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;
48 static unsigned char *skey = NULL;
49 static unsigned char bbuf[MAXPARAMLEN];
50 static unsigned char saltbuf[MAXSALTLEN];
51 static char *username = NULL;
52 static char password[MAXPARAMLEN] = "";
53 static char pw_md5[MD5_OUT_BUFSIZE];
54 static char pw_salt[MAXSALTLEN];
56 static struct t_client *tc = NULL;
57 static struct t_num salt = { .data = saltbuf };
58 static struct t_num *A, B;
59 static struct t_preconf *tcp;
60 static int auth_type = EAD_AUTH_DEFAULT;
61 static int timeout = EAD_TIMEOUT;
64 set_nonblock(int enable)
66 if (enable == !!(sockflags & O_NONBLOCK));
69 sockflags ^= O_NONBLOCK;
70 fcntl(s, F_SETFL, sockflags);
74 send_packet(int type, bool (*handler)(void), unsigned int max)
84 sendto(s, msgbuf, sizeof(struct ead_msg) + ntohl(msg->len), 0, (struct sockaddr *) &remote, sizeof(remote));
87 tv.tv_sec = timeout / 1000;
88 tv.tv_usec = (timeout % 1000) * 1000;
93 nfds = select(s + 1, &fds, NULL, NULL, &tv);
98 if (!FD_ISSET(s, &fds))
101 len = read(s, msgbuf, sizeof(msgbuf));
105 if (len < sizeof(struct ead_msg))
108 if (len < sizeof(struct ead_msg) + ntohl(msg->len))
111 if (msg->magic != htonl(EAD_MAGIC))
114 if ((nid != 0xffff) && (ntohs(msg->nid) != nid))
117 if (msg->type != type)
123 if ((max > 0) && (res >= max))
131 prepare_password(void)
134 case EAD_AUTH_DEFAULT:
137 md5_crypt(pw_md5, (unsigned char *) password, (unsigned char *) pw_salt);
138 strncpy(password, pw_md5, sizeof(password));
146 struct ead_msg_pong *pong = EAD_DATA(msg, pong);
147 int len = ntohl(msg->len) - sizeof(struct ead_msg_pong);
153 auth_type = ntohs(pong->auth_type);
155 printf("%04x: %s\n", ntohs(msg->nid), pong->name);
162 struct ead_msg_salt *sb = EAD_DATA(msg, salt);
165 memcpy(salt.data, sb->salt, salt.len);
167 if (auth_type == EAD_AUTH_MD5) {
168 memcpy(pw_salt, sb->ext_salt, MAXSALTLEN);
169 pw_salt[MAXSALTLEN - 1] = 0;
172 tcp = t_getpreparam(sb->prime);
173 tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
175 fprintf(stderr, "Client open failed\n");
185 struct ead_msg_number *num = EAD_DATA(msg, number);
186 int len = ntohl(msg->len) - sizeof(struct ead_msg_number);
190 memcpy(bbuf, num->data, len);
201 handle_done_auth(void)
203 struct ead_msg_auth *auth = EAD_DATA(msg, auth);
204 if (t_clientverify(tc, auth->data) != 0) {
205 fprintf(stderr, "Client auth verify failed\n");
212 handle_cmd_data(void)
214 struct ead_msg_cmd_data *cmd = EAD_ENC_DATA(msg, cmd_data);
215 int datalen = ead_decrypt_message(msg) - sizeof(struct ead_msg_cmd_data);
221 write(1, cmd->data, datalen);
229 msg->type = htonl(EAD_TYPE_PING);
231 return send_packet(EAD_TYPE_PONG, handle_pong, (nid == 0xffff ? 0 : 1));
237 msg->type = htonl(EAD_TYPE_SET_USERNAME);
238 msg->len = htonl(sizeof(struct ead_msg_user));
239 strcpy(EAD_DATA(msg, user)->username, username);
240 return send_packet(EAD_TYPE_ACK_USERNAME, handle_none, 1);
246 msg->type = htonl(EAD_TYPE_GET_PRIME);
248 return send_packet(EAD_TYPE_PRIME, handle_prime, 1);
254 struct ead_msg_number *num = EAD_DATA(msg, number);
255 A = t_clientgenexp(tc);
256 msg->type = htonl(EAD_TYPE_SEND_A);
257 msg->len = htonl(sizeof(struct ead_msg_number) + A->len);
258 memcpy(num->data, A->data, A->len);
259 return send_packet(EAD_TYPE_SEND_B, handle_b, 1);
265 struct ead_msg_auth *auth = EAD_DATA(msg, auth);
268 t_clientpasswd(tc, password);
269 skey = t_clientgetkey(tc, &B);
274 msg->type = htonl(EAD_TYPE_SEND_AUTH);
275 msg->len = htonl(sizeof(struct ead_msg_auth));
276 memcpy(auth->data, t_clientresponse(tc), sizeof(auth->data));
277 return send_packet(EAD_TYPE_DONE_AUTH, handle_done_auth, 1);
281 send_command(const char *command)
283 struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
285 msg->type = htonl(EAD_TYPE_SEND_CMD);
286 cmd->type = htons(EAD_CMD_NORMAL);
287 cmd->timeout = htons(10);
288 strncpy((char *)cmd->data, command, 1024);
289 ead_encrypt_message(msg, sizeof(struct ead_msg_cmd) + strlen(command) + 1);
290 return send_packet(EAD_TYPE_RESULT_CMD, handle_cmd_data, 1);
295 usage(const char *prog)
297 fprintf(stderr, "Usage: %s [-b <addr>] <node> <username>[:<password>] <command>\n"
299 "\t-b <addr>: Set the broadcast address to <addr>\n"
300 "\t<node>: Node ID (4 digits hex)\n"
301 "\t<username>: Username to authenticate with\n"
303 "\tPassing no arguments shows a list of active nodes on the network\n"
309 int main(int argc, char **argv)
313 const char *command = NULL;
314 const char *prog = argv[0];
317 msg->magic = htonl(EAD_MAGIC);
320 memset(&local, 0, sizeof(local));
321 memset(&remote, 0, sizeof(remote));
323 remote.sin_family = AF_INET;
324 remote.sin_addr.s_addr = 0xffffffff;
325 remote.sin_port = htons(EAD_PORT);
327 local.sin_family = AF_INET;
328 local.sin_addr.s_addr = INADDR_ANY;
331 while ((ch = getopt(argc, argv, "b:")) != -1) {
334 inet_aton(optarg, &remote.sin_addr);
347 st = strchr(username, ':');
351 strncpy(password, st, sizeof(password));
352 password[sizeof(password) - 1] = 0;
353 /* hide command line password */
354 memset(st, 0, strlen(st));
358 nid = strtoul(argv[0], &st, 16);
359 if (st && st[0] != 0)
368 msg->nid = htons(nid);
369 s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
375 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
377 if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) {
381 sockflags = fcntl(s, F_GETFL);
384 fprintf(stderr, "No devices found\n");
391 if (!username || !password[0])
394 if (!send_username()) {
395 fprintf(stderr, "Device did not accept user name\n");
399 fprintf(stderr, "Failed to get user password info\n");
403 timeout = EAD_TIMEOUT_LONG;
405 fprintf(stderr, "Failed to send local authentication data\n");
409 fprintf(stderr, "Authentication failed\n");
413 fprintf(stderr, "Authentication succesful\n");
416 if (!send_command(command)) {
417 fprintf(stderr, "Command failed\n");