2 * Client for the Emergency Access Daemon
3 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2
7 * as published by the Free Software Foundation
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <sys/types.h>
16 #include <sys/socket.h>
18 #include <netinet/in.h>
19 #include <arpa/inet.h>
31 #include <t_defines.h>
34 #include "ead-crypt.h"
36 #include "pw_encrypt_md5.c"
38 #define EAD_TIMEOUT 400
39 #define EAD_TIMEOUT_LONG 2000
41 static char msgbuf
[1500];
42 static struct ead_msg
*msg
= (struct ead_msg
*) msgbuf
;
43 static uint16_t nid
= 0xffff;
44 struct sockaddr_in local
, remote
;
47 static struct in_addr serverip
= {
48 .s_addr
= 0x01010101 /* dummy */
51 static unsigned char *skey
= NULL
;
52 static unsigned char bbuf
[MAXPARAMLEN
];
53 static unsigned char saltbuf
[MAXSALTLEN
];
54 static char *username
= NULL
;
55 static char password
[MAXPARAMLEN
] = "";
56 static char pw_md5
[MD5_OUT_BUFSIZE
];
57 static char pw_salt
[MAXSALTLEN
];
59 static struct t_client
*tc
= NULL
;
60 static struct t_num salt
= { .data
= saltbuf
};
61 static struct t_num
*A
, B
;
62 static struct t_preconf
*tcp
;
63 static int auth_type
= EAD_AUTH_DEFAULT
;
64 static int timeout
= EAD_TIMEOUT
;
65 static uint16_t sid
= 0;
68 set_nonblock(int enable
)
70 if (enable
== !!(sockflags
& O_NONBLOCK
));
73 sockflags
^= O_NONBLOCK
;
74 fcntl(s
, F_SETFL
, sockflags
);
78 send_packet(int type
, bool (*handler
)(void), unsigned int max
)
87 memcpy(&msg
->ip
, &serverip
.s_addr
, sizeof(msg
->ip
));
89 sendto(s
, msgbuf
, sizeof(struct ead_msg
) + ntohl(msg
->len
), 0, (struct sockaddr
*) &remote
, sizeof(remote
));
92 tv
.tv_sec
= timeout
/ 1000;
93 tv
.tv_usec
= (timeout
% 1000) * 1000;
98 nfds
= select(s
+ 1, &fds
, NULL
, NULL
, &tv
);
103 if (!FD_ISSET(s
, &fds
))
106 len
= read(s
, msgbuf
, sizeof(msgbuf
));
110 if (len
< sizeof(struct ead_msg
))
113 if (len
< sizeof(struct ead_msg
) + ntohl(msg
->len
))
116 if (msg
->magic
!= htonl(EAD_MAGIC
))
119 if ((nid
!= 0xffff) && (ntohs(msg
->nid
) != nid
))
122 if (msg
->type
!= type
)
128 if ((max
> 0) && (res
>= max
))
136 prepare_password(void)
139 case EAD_AUTH_DEFAULT
:
142 md5_crypt(pw_md5
, (unsigned char *) password
, (unsigned char *) pw_salt
);
143 strncpy(password
, pw_md5
, sizeof(password
));
151 struct ead_msg_pong
*pong
= EAD_DATA(msg
, pong
);
152 int len
= ntohl(msg
->len
) - sizeof(struct ead_msg_pong
);
158 auth_type
= ntohs(pong
->auth_type
);
160 printf("%04x: %s\n", ntohs(msg
->nid
), pong
->name
);
168 struct ead_msg_salt
*sb
= EAD_DATA(msg
, salt
);
171 memcpy(salt
.data
, sb
->salt
, salt
.len
);
173 if (auth_type
== EAD_AUTH_MD5
) {
174 memcpy(pw_salt
, sb
->ext_salt
, MAXSALTLEN
);
175 pw_salt
[MAXSALTLEN
- 1] = 0;
178 tcp
= t_getpreparam(sb
->prime
);
179 tc
= t_clientopen(username
, &tcp
->modulus
, &tcp
->generator
, &salt
);
181 fprintf(stderr
, "Client open failed\n");
191 struct ead_msg_number
*num
= EAD_DATA(msg
, number
);
192 int len
= ntohl(msg
->len
) - sizeof(struct ead_msg_number
);
196 memcpy(bbuf
, num
->data
, len
);
207 handle_done_auth(void)
209 struct ead_msg_auth
*auth
= EAD_DATA(msg
, auth
);
210 if (t_clientverify(tc
, auth
->data
) != 0) {
211 fprintf(stderr
, "Client auth verify failed\n");
218 handle_cmd_data(void)
220 struct ead_msg_cmd_data
*cmd
= EAD_ENC_DATA(msg
, cmd_data
);
221 int datalen
= ead_decrypt_message(msg
) - sizeof(struct ead_msg_cmd_data
);
227 write(1, cmd
->data
, datalen
);
235 msg
->type
= htonl(EAD_TYPE_PING
);
237 return send_packet(EAD_TYPE_PONG
, handle_pong
, (nid
== 0xffff ? 0 : 1));
243 msg
->type
= htonl(EAD_TYPE_SET_USERNAME
);
244 msg
->len
= htonl(sizeof(struct ead_msg_user
));
245 strcpy(EAD_DATA(msg
, user
)->username
, username
);
246 return send_packet(EAD_TYPE_ACK_USERNAME
, handle_none
, 1);
252 msg
->type
= htonl(EAD_TYPE_GET_PRIME
);
254 return send_packet(EAD_TYPE_PRIME
, handle_prime
, 1);
260 struct ead_msg_number
*num
= EAD_DATA(msg
, number
);
261 A
= t_clientgenexp(tc
);
262 msg
->type
= htonl(EAD_TYPE_SEND_A
);
263 msg
->len
= htonl(sizeof(struct ead_msg_number
) + A
->len
);
264 memcpy(num
->data
, A
->data
, A
->len
);
265 return send_packet(EAD_TYPE_SEND_B
, handle_b
, 1);
271 struct ead_msg_auth
*auth
= EAD_DATA(msg
, auth
);
274 t_clientpasswd(tc
, password
);
275 skey
= t_clientgetkey(tc
, &B
);
280 msg
->type
= htonl(EAD_TYPE_SEND_AUTH
);
281 msg
->len
= htonl(sizeof(struct ead_msg_auth
));
282 memcpy(auth
->data
, t_clientresponse(tc
), sizeof(auth
->data
));
283 return send_packet(EAD_TYPE_DONE_AUTH
, handle_done_auth
, 1);
287 send_command(const char *command
)
289 struct ead_msg_cmd
*cmd
= EAD_ENC_DATA(msg
, cmd
);
291 msg
->type
= htonl(EAD_TYPE_SEND_CMD
);
292 cmd
->type
= htons(EAD_CMD_NORMAL
);
293 cmd
->timeout
= htons(10);
294 strncpy((char *)cmd
->data
, command
, 1024);
295 ead_encrypt_message(msg
, sizeof(struct ead_msg_cmd
) + strlen(command
) + 1);
296 return send_packet(EAD_TYPE_RESULT_CMD
, handle_cmd_data
, 1);
301 usage(const char *prog
)
303 fprintf(stderr
, "Usage: %s [-s <addr>] [-b <addr>] <node> <username>[:<password>] <command>\n"
305 "\t-s <addr>: Set the server's source address to <addr>\n"
306 "\t-b <addr>: Set the broadcast address to <addr>\n"
307 "\t<node>: Node ID (4 digits hex)\n"
308 "\t<username>: Username to authenticate with\n"
310 "\tPassing no arguments shows a list of active nodes on the network\n"
316 int main(int argc
, char **argv
)
320 const char *command
= NULL
;
321 const char *prog
= argv
[0];
324 msg
->magic
= htonl(EAD_MAGIC
);
327 memset(&local
, 0, sizeof(local
));
328 memset(&remote
, 0, sizeof(remote
));
330 remote
.sin_family
= AF_INET
;
331 remote
.sin_addr
.s_addr
= 0xffffffff;
332 remote
.sin_port
= htons(EAD_PORT
);
334 local
.sin_family
= AF_INET
;
335 local
.sin_addr
.s_addr
= INADDR_ANY
;
338 while ((ch
= getopt(argc
, argv
, "b:s:h")) != -1) {
341 inet_aton(optarg
, &serverip
);
344 inet_aton(optarg
, &remote
.sin_addr
);
359 st
= strchr(username
, ':');
363 strncpy(password
, st
, sizeof(password
));
364 password
[sizeof(password
) - 1] = 0;
365 /* hide command line password */
366 memset(st
, 0, strlen(st
));
370 nid
= strtoul(argv
[0], &st
, 16);
371 if (st
&& st
[0] != 0)
380 msg
->nid
= htons(nid
);
381 s
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
387 setsockopt(s
, SOL_SOCKET
, SO_BROADCAST
, &val
, sizeof(val
));
389 if (bind(s
, (struct sockaddr
*)&local
, sizeof(local
)) < 0) {
393 sockflags
= fcntl(s
, F_GETFL
);
396 fprintf(stderr
, "No devices found\n");
403 if (!username
|| !password
[0])
406 if (!send_username()) {
407 fprintf(stderr
, "Device did not accept user name\n");
410 timeout
= EAD_TIMEOUT_LONG
;
412 fprintf(stderr
, "Failed to get user password info\n");
416 fprintf(stderr
, "Failed to send local authentication data\n");
420 fprintf(stderr
, "Authentication failed\n");
424 fprintf(stderr
, "Authentication succesful\n");
427 if (!send_command(command
)) {
428 fprintf(stderr
, "Command failed\n");
This page took 0.076825 seconds and 5 git commands to generate.