Advertisement
Guest User

Untitled

a guest
Jul 18th, 2019
141
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.37 KB | None | 0 0
  1. /*
  2. * Client for the Emergency Access Daemon
  3. * Copyright (C) 2008 Felix Fietkau <nbd@nbd.name>
  4. *
  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
  8. *
  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.
  13. */
  14.  
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <sys/time.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <stdio.h>
  21. #include <stddef.h>
  22. #include <stdint.h>
  23. #include <stdlib.h>
  24. #include <stdbool.h>
  25. #include <string.h>
  26. #include <fcntl.h>
  27. #include <unistd.h>
  28. #include <t_pwd.h>
  29. #include <t_read.h>
  30. #include <t_sha.h>
  31. #include <t_defines.h>
  32. #include <t_client.h>
  33. #include "ead.h"
  34. #include "ead-crypt.h"
  35.  
  36. #include "pw_encrypt_md5.c"
  37.  
  38. #define EAD_TIMEOUT 400
  39. #define EAD_TIMEOUT_LONG 2000
  40.  
  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;
  45. static int s = 0;
  46. static int sockflags;
  47. static struct in_addr serverip = {
  48. .s_addr = 0x01010101 /* dummy */
  49. };
  50.  
  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];
  58.  
  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;
  66.  
  67. static void
  68. set_nonblock(int enable)
  69. {
  70. if (enable == !!(sockflags & O_NONBLOCK))
  71. return;
  72.  
  73. sockflags ^= O_NONBLOCK;
  74. fcntl(s, F_SETFL, sockflags);
  75. }
  76.  
  77. static int
  78. send_packet(int type, bool (*handler)(void), unsigned int max)
  79. {
  80. struct timeval tv;
  81. fd_set fds;
  82. int nfds;
  83. int len;
  84. int res = 0;
  85.  
  86. type = htonl(type);
  87. memcpy(&msg->ip, &serverip.s_addr, sizeof(msg->ip));
  88. set_nonblock(0);
  89. sendto(s, msgbuf, sizeof(struct ead_msg) + ntohl(msg->len), 0, (struct sockaddr *) &remote, sizeof(remote));
  90. set_nonblock(1);
  91.  
  92. tv.tv_sec = timeout / 1000;
  93. tv.tv_usec = (timeout % 1000) * 1000;
  94.  
  95. FD_ZERO(&fds);
  96. do {
  97. FD_SET(s, &fds);
  98. nfds = select(s + 1, &fds, NULL, NULL, &tv);
  99.  
  100. if (nfds <= 0)
  101. break;
  102.  
  103. if (!FD_ISSET(s, &fds))
  104. break;
  105.  
  106. len = read(s, msgbuf, sizeof(msgbuf));
  107. if (len < 0)
  108. break;
  109.  
  110. if (len < sizeof(struct ead_msg))
  111. continue;
  112.  
  113. if (len < sizeof(struct ead_msg) + ntohl(msg->len))
  114. continue;
  115.  
  116. if (msg->magic != htonl(EAD_MAGIC))
  117. continue;
  118.  
  119. if ((nid != 0xffff) && (ntohs(msg->nid) != nid))
  120. continue;
  121.  
  122. if (msg->type != type)
  123. continue;
  124.  
  125. if (handler())
  126. res++;
  127.  
  128. if ((max > 0) && (res >= max))
  129. break;
  130. } while (1);
  131.  
  132. return res;
  133. }
  134.  
  135. static void
  136. prepare_password(void)
  137. {
  138. switch(auth_type) {
  139. case EAD_AUTH_DEFAULT:
  140. break;
  141. case EAD_AUTH_MD5:
  142. md5_crypt(pw_md5, (unsigned char *) password, (unsigned char *) pw_salt);
  143. strncpy(password, pw_md5, sizeof(password));
  144. break;
  145. }
  146. }
  147.  
  148. static bool
  149. handle_pong(void)
  150. {
  151. struct ead_msg_pong *pong = EAD_DATA(msg, pong);
  152. int len = ntohl(msg->len) - sizeof(struct ead_msg_pong);
  153.  
  154. if (len <= 0)
  155. return false;
  156.  
  157. pong->name[len] = 0;
  158. auth_type = ntohs(pong->auth_type);
  159. if (nid == 0xffff)
  160. printf("%04x: %s\n", ntohs(msg->nid), pong->name);
  161. sid = msg->sid;
  162. return true;
  163. }
  164.  
  165. static bool
  166. handle_prime(void)
  167. {
  168. struct ead_msg_salt *sb = EAD_DATA(msg, salt);
  169.  
  170. salt.len = sb->len;
  171. memcpy(salt.data, sb->salt, salt.len);
  172.  
  173. if (auth_type == EAD_AUTH_MD5) {
  174. memcpy(pw_salt, sb->ext_salt, MAXSALTLEN);
  175. pw_salt[MAXSALTLEN - 1] = 0;
  176. }
  177.  
  178. tcp = t_getpreparam(sb->prime);
  179. tc = t_clientopen(username, &tcp->modulus, &tcp->generator, &salt);
  180. if (!tc) {
  181. fprintf(stderr, "Client open failed\n");
  182. return false;
  183. }
  184.  
  185. return true;
  186. }
  187.  
  188. static bool
  189. handle_b(void)
  190. {
  191. struct ead_msg_number *num = EAD_DATA(msg, number);
  192. int len = ntohl(msg->len) - sizeof(struct ead_msg_number);
  193.  
  194. B.data = bbuf;
  195. B.len = len;
  196. memcpy(bbuf, num->data, len);
  197. return true;
  198. }
  199.  
  200. static bool
  201. handle_none(void)
  202. {
  203. return true;
  204. }
  205.  
  206. static bool
  207. handle_done_auth(void)
  208. {
  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");
  212. return false;
  213. }
  214. return true;
  215. }
  216.  
  217. static bool
  218. handle_cmd_data(void)
  219. {
  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);
  222.  
  223. if (datalen < 0)
  224. return false;
  225.  
  226. if (datalen > 0) {
  227. write(1, cmd->data, datalen);
  228. }
  229.  
  230. return !!cmd->done;
  231. }
  232. static int
  233. send_ping(void)
  234. {
  235. msg->type = htonl(EAD_TYPE_PING);
  236. msg->len = 0;
  237. return send_packet(EAD_TYPE_PONG, handle_pong, (nid == 0xffff ? 0 : 1));
  238. }
  239.  
  240. static int
  241. send_username(void)
  242. {
  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);
  247. }
  248.  
  249. static int
  250. get_prime(void)
  251. {
  252. msg->type = htonl(EAD_TYPE_GET_PRIME);
  253. msg->len = 0;
  254. return send_packet(EAD_TYPE_PRIME, handle_prime, 1);
  255. }
  256.  
  257. static int
  258. send_a(void)
  259. {
  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);
  266. }
  267.  
  268. static int
  269. send_auth(void)
  270. {
  271. struct ead_msg_auth *auth = EAD_DATA(msg, auth);
  272.  
  273. prepare_password();
  274. t_clientpasswd(tc, password);
  275. skey = t_clientgetkey(tc, &B);
  276. if (!skey)
  277. return 0;
  278.  
  279. ead_set_key(skey);
  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);
  284. }
  285.  
  286. static int
  287. send_command(const char *command)
  288. {
  289. struct ead_msg_cmd *cmd = EAD_ENC_DATA(msg, cmd);
  290.  
  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);
  297. }
  298.  
  299.  
  300. static int
  301. usage(const char *prog)
  302. {
  303. fprintf(stderr, "Usage: %s [-s <addr>] [-b <addr>] <node> <username>[:<password>] <command>\n"
  304. "\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"
  309. "\n"
  310. "\tPassing no arguments shows a list of active nodes on the network\n"
  311. "\n", prog);
  312. return -1;
  313. }
  314.  
  315.  
  316. int main(int argc, char **argv)
  317. {
  318. int val = 1;
  319. char *st = NULL;
  320. const char *command = NULL;
  321. const char *prog = argv[0];
  322. int ch;
  323.  
  324. msg->magic = htonl(EAD_MAGIC);
  325. msg->sid = 0;
  326.  
  327. memset(&local, 0, sizeof(local));
  328. memset(&remote, 0, sizeof(remote));
  329.  
  330. remote.sin_family = AF_INET;
  331. remote.sin_addr.s_addr = 0xffffffff;
  332. remote.sin_port = htons(EAD_PORT);
  333.  
  334. local.sin_family = AF_INET;
  335. local.sin_addr.s_addr = INADDR_ANY;
  336. local.sin_port = 0;
  337.  
  338. while ((ch = getopt(argc, argv, "b:s:h")) != -1) {
  339. switch(ch) {
  340. case 's':
  341. inet_aton(optarg, &serverip);
  342. break;
  343. case 'b':
  344. inet_aton(optarg, &remote.sin_addr);
  345. break;
  346. case 'h':
  347. return usage(prog);
  348. }
  349. }
  350. argv += optind;
  351. argc -= optind;
  352.  
  353. switch(argc) {
  354. case 3:
  355. command = argv[2];
  356. /* fall through */
  357. case 2:
  358. username = argv[1];
  359. st = strchr(username, ':');
  360. if (st) {
  361. *st = 0;
  362. st++;
  363. strncpy(password, st, sizeof(password));
  364. password[sizeof(password) - 1] = 0;
  365. /* hide command line password */
  366. memset(st, 0, strlen(st));
  367. }
  368. /* fall through */
  369. case 1:
  370. nid = strtoul(argv[0], &st, 16);
  371. if (st && st[0] != 0)
  372. return usage(prog);
  373. /* fall through */
  374. case 0:
  375. break;
  376. default:
  377. return usage(prog);
  378. }
  379.  
  380. msg->nid = htons(nid);
  381. s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  382. if (s < 0) {
  383. perror("socket");
  384. return -1;
  385. }
  386.  
  387. setsockopt(s, SOL_SOCKET, SO_BROADCAST, &val, sizeof(val));
  388.  
  389. if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0) {
  390. perror("bind");
  391. return -1;
  392. }
  393. sockflags = fcntl(s, F_GETFL);
  394.  
  395. if (!send_ping()) {
  396. fprintf(stderr, "No devices found\n");
  397. return 1;
  398. }
  399.  
  400. if (nid == 0xffff)
  401. return 0;
  402.  
  403. if (!username || !password[0])
  404. return 0;
  405.  
  406. if (!send_username()) {
  407. fprintf(stderr, "Device did not accept user name\n");
  408. return 1;
  409. }
  410. timeout = EAD_TIMEOUT_LONG;
  411. if (!get_prime()) {
  412. fprintf(stderr, "Failed to get user password info\n");
  413. return 1;
  414. }
  415. if (!send_a()) {
  416. fprintf(stderr, "Failed to send local authentication data\n");
  417. return 1;
  418. }
  419. if (!send_auth()) {
  420. fprintf(stderr, "Authentication failed\n");
  421. return 1;
  422. }
  423. if (!command) {
  424. fprintf(stderr, "Authentication succesful\n");
  425. return 0;
  426. }
  427. if (!send_command(command)) {
  428. fprintf(stderr, "Command failed\n");
  429. return 1;
  430. }
  431.  
  432. return 0;
  433. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement