1 /*
2 * Copyright (C) 2014 - David Goulet <dgoulet@ev0ke.net>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18 #define _GNU_SOURCE
19 #include <assert.h>
20 #include <ctype.h>
21 #include <gcrypt.h>
22 #include <getopt.h>
23 #include <inttypes.h>
24 #include <pthread.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <syscall.h>
28 #include <sys/epoll.h>
29 #include <sys/types.h>
30 #include <sys/un.h>
31 #include <unistd.h>
32
33 #include <context.h>
34 #include <privkey.h>
35 #include <proto.h>
36 #include <message.h>
37
38 #include <tap/tap.h>
39
40 #define zmalloc(x) calloc(1, x)
41
42 GCRY_THREAD_OPTION_PTHREAD_IMPL;
43
44 /* Global OTR user state. */
45 static OtrlUserState user_state;
46
47 /* Getopt options. */
48 static struct option long_opts[] = {
49 { "load-instag", 1, NULL, 'i' },
50 { "load-key", 1, NULL, 'k' },
51 { "load-fp", 1, NULL, 'f' },
52 { "timeout", 1, NULL, 't' },
53 { "max-msg", 1, NULL, 'm' },
54 { "disconnect", 0, NULL, 'd' },
55 { "auth", 0, NULL, 'a' },
56 { "fragment", 0, NULL, 'F' },
57
58 /* Closure. */
59 { NULL, 0, NULL, 0 }
60 };
61
62 static char *opt_instag_path;
63 static char *opt_key_path;
64 static char *opt_key_fp_path;
65 static unsigned int opt_max_num_msg;
66 static int opt_disconnect;
67 static int opt_auth;
68 static int opt_fragment;
69
70 /* Currently, the message size sent is between 1 and 600 len so 100 is a good
71 * middle ground. */
72 static const int fragment_size = 100;
73 /* By default, don't send frag. */
74 static OtrlFragmentPolicy fragPolicy = OTRL_FRAGMENT_SEND_SKIP;
75
76 static const char *protocol = "otr-test";
77 static const char *alice_name = "alice";
78 static const char *bob_name = "bob";
79
80 static const char *unix_sock_bob_path = "/tmp/otr-test-bob.sock";
81 static const char *unix_sock_alice_path = "/tmp/otr-test-alice.sock";
82
83 static const char *auth_question = "What is NSA?";
84 static const char *auth_secret = "No Sugar Added";
85
86 /* Alice and Bob thread's socket. */
87 static int alice_sock;
88 static int bob_sock;
89 /* Declare it global because we use it multiple times. */
90 static struct sockaddr_un alice_sun;
91 static struct sockaddr_un bob_sun;
92
93 static int timeout_max = 1000;
94 static unsigned int num_recv_msg;
95 static unsigned int session_disconnected;
96
97 static int quit_pipe[2] = { -1, -1 };
98
99 /*
100 * For now not really do much more but if we want to use the OK condition at
101 * some point to do something else, that will ease our life :).
102 */
103 #define OK(cond, fmt, args...) \
104 do { \
105 ok(cond, fmt, ## args); \
106 } while (0)
107
108 /*
109 * Used to pass OTR message between threads. This contains the cipher and
110 * plaintext so we are able to validate what's expected in both threads.
111 */
112 struct otr_msg {
113 size_t plaintext_len;
114 size_t ciphertext_len;
115 char *plaintext;
116 char *ciphertext;
117 };
118
119 struct otr_info {
120 const char *user;
121 int sock;
122 unsigned int gone_secure;
123 unsigned int auth_done;
124 };
125
126 /* Stub */
127 static int send_otr_msg(int sock, const char *to, const char *from,
128 struct otr_info *oinfo, const char *message);
129
ops_policy(void * opdata,ConnContext * context)130 static OtrlPolicy ops_policy(void *opdata, ConnContext *context)
131 {
132 return OTRL_POLICY_DEFAULT;
133 }
134
ops_inject_msg(void * opdata,const char * accountname,const char * protocol,const char * recipient,const char * message)135 static void ops_inject_msg(void *opdata, const char *accountname,
136 const char *protocol, const char *recipient, const char *message)
137 {
138 ssize_t ret;
139 struct otr_info *oinfo = opdata;
140 struct otr_msg *msg;
141
142 msg = zmalloc(sizeof(*msg));
143 if (!msg) {
144 perror("zmalloc inject");
145 return;
146 }
147
148 msg->ciphertext = strdup(message);
149 msg->ciphertext_len = strlen(message);
150
151 ret = send(oinfo->sock, &msg, sizeof(msg), 0);
152 if (ret < 0) {
153 perror("send msg");
154 }
155 }
156
ops_gone_secure(void * opdata,ConnContext * context)157 static void ops_gone_secure(void *opdata, ConnContext *context)
158 {
159 struct otr_info *oinfo = opdata;
160
161 session_disconnected = 0;
162 oinfo->gone_secure = 1;
163 /* XXX: gone_insecure is never called ref bug #40 so this will always be
164 * true. */
165 OK(oinfo->gone_secure, "Gone secure for %s",
166 oinfo->user);
167 }
168
ops_gone_insecure(void * opdata,ConnContext * context)169 static void ops_gone_insecure(void *opdata, ConnContext *context)
170 {
171 struct otr_info *oinfo = opdata;
172
173 OK(oinfo->gone_secure, "Gone insecure for %s",
174 oinfo->user);
175 oinfo->gone_secure = 0;
176 }
177
ops_max_message_size(void * opdata,ConnContext * context)178 static int ops_max_message_size(void *opdata, ConnContext *context)
179 {
180 if (opt_fragment) {
181 return fragment_size;
182 }
183 return 0;
184 }
185
ops_otr_error_message(void * opdata,ConnContext * context,OtrlErrorCode code)186 static const char *ops_otr_error_message(void *opdata, ConnContext *context,
187 OtrlErrorCode code)
188 {
189 char *msg = NULL;
190
191 switch (code) {
192 case OTRL_ERRCODE_NONE:
193 break;
194 case OTRL_ERRCODE_ENCRYPTION_ERROR:
195 msg = strdup("OTRL_ERRCODE_ENCRYPTION_ERROR");
196 break;
197 case OTRL_ERRCODE_MSG_NOT_IN_PRIVATE:
198 msg = strdup("OTRL_ERRCODE_MSG_NOT_IN_PRIVATE");
199 break;
200 case OTRL_ERRCODE_MSG_UNREADABLE:
201 msg = strdup("OTRL_ERRCODE_MSG_UNREADABLE");
202 break;
203 case OTRL_ERRCODE_MSG_MALFORMED:
204 msg = strdup("OTRL_ERRCODE_MSG_MALFORMED");
205 break;
206 }
207
208 return msg;
209 }
210
ops_otr_error_message_free(void * opdata,const char * err_msg)211 static void ops_otr_error_message_free(void *opdata, const char *err_msg)
212 {
213 free((char *) err_msg);
214 }
215
ops_handle_msg_event(void * opdata,OtrlMessageEvent msg_event,ConnContext * context,const char * message,gcry_error_t err)216 static void ops_handle_msg_event(void *opdata, OtrlMessageEvent msg_event,
217 ConnContext *context, const char *message, gcry_error_t err)
218 {
219 //char* msg = "";
220 struct otr_info *oinfo = opdata;
221
222 switch(msg_event) {
223 case OTRL_MSGEVENT_NONE:
224 //msg = "OTRL_MSGEVENT_NONE";
225 break;
226 case OTRL_MSGEVENT_ENCRYPTION_REQUIRED:
227 //msg = "OTRL_MSGEVENT_ENCRYPTION_REQUIRED";
228 break;
229 case OTRL_MSGEVENT_ENCRYPTION_ERROR:
230 //msg = "OTRL_MSGEVENT_ENCRYPTION_ERROR";
231 break;
232 case OTRL_MSGEVENT_CONNECTION_ENDED:
233 //msg = "OTRL_MSGEVENT_CONNECTION_ENDED";
234 oinfo->gone_secure = 0;
235 break;
236 case OTRL_MSGEVENT_SETUP_ERROR:
237 //msg = "OTRL_MSGEVENT_SETUP_ERROR";
238 break;
239 case OTRL_MSGEVENT_MSG_REFLECTED:
240 //msg = "OTRL_MSGEVENT_MSG_REFLECTED";
241 break;
242 case OTRL_MSGEVENT_MSG_RESENT:
243 //msg = "OTRL_MSGEVENT_MSG_RESENT";
244 break;
245 case OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE:
246 //msg = "OTRL_MSGEVENT_RCVDMSG_NOT_IN_PRIVATE";
247 break;
248 case OTRL_MSGEVENT_RCVDMSG_UNREADABLE:
249 //msg = "OTRL_MSGEVENT_RCVDMSG_UNREADABLE";
250 break;
251 case OTRL_MSGEVENT_RCVDMSG_MALFORMED:
252 //msg = "OTRL_MSGEVENT_RCVDMSG_MALFORMED";
253 break;
254 case OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD:
255 //msg = "OTRL_MSGEVENT_LOG_HEARTBEAT_RCVD";
256 break;
257 case OTRL_MSGEVENT_LOG_HEARTBEAT_SENT:
258 //msg = "OTRL_MSGEVENT_LOG_HEARTBEAT_SENT";
259 break;
260 case OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR:
261 //msg = "OTRL_MSGEVENT_RCVDMSG_GENERAL_ERR";
262 break;
263 case OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED:
264 //msg = "OTRL_MSGEVENT_RCVDMSG_UNENCRYPTED";
265 break;
266 case OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED:
267 //msg = "OTRL_MSGEVENT_RCVDMSG_UNRECOGNIZED";
268 break;
269 case OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE:
270 //msg = "OTRL_MSGEVENT_RCVDMSG_FOR_OTHER_INSTANCE";
271 break;
272 default:
273 //msg = "Unknown OTRL message event";
274 break;
275 }
276 }
277
ops_create_instag(void * opdata,const char * accountname,const char * protocol)278 static void ops_create_instag(void *opdata, const char *accountname,
279 const char *protocol)
280 {
281 otrl_instag_generate(user_state, "/dev/null", accountname,
282 protocol);
283 }
284
ops_is_logged_in(void * opdata,const char * accountname,const char * protocol,const char * recipient)285 static int ops_is_logged_in(void *opdata, const char *accountname,
286 const char *protocol, const char *recipient)
287 {
288 /* Always logged in or else we don't receive a disconnected TLV. */
289 return 1;
290 }
291
ops_create_privkey(void * opdata,const char * accountname,const char * protocol)292 static void ops_create_privkey(void *opdata, const char *accountname,
293 const char *protocol)
294 {
295 /* XXX: We should gen. our own key each time at some point? */
296 return;
297 }
298
ops_update_context_list(void * opdata)299 static void ops_update_context_list(void *opdata)
300 {
301 return;
302 }
303
ops_new_fingerprint(void * opdata,OtrlUserState us,const char * accountname,const char * protocol,const char * username,unsigned char fingerprint[20])304 static void ops_new_fingerprint(void *opdata, OtrlUserState us,
305 const char *accountname, const char *protocol,
306 const char *username, unsigned char fingerprint[20])
307 {
308 return;
309 }
310
ops_write_fingerprints(void * opdata)311 static void ops_write_fingerprints(void *opdata)
312 {
313 return;
314 }
315
ops_still_secure(void * opdata,ConnContext * context,int is_reply)316 static void ops_still_secure(void *opdata, ConnContext *context, int is_reply)
317 {
318 struct otr_info *oinfo = opdata;
319
320 OK(oinfo->gone_secure, "OP still secure");
321 }
322
ops_received_symkey(void * opdata,ConnContext * context,unsigned int use,const unsigned char * usedata,size_t usedatalen,const unsigned char * symkey)323 static void ops_received_symkey(void *opdata, ConnContext *context,
324 unsigned int use, const unsigned char *usedata,
325 size_t usedatalen, const unsigned char *symkey)
326 {
327 return;
328 }
329
ops_resent_msg_prefix(void * opdata,ConnContext * context)330 static const char *ops_resent_msg_prefix(void *opdata, ConnContext *context)
331 {
332 /* Just so we can test resent_msg_prefix_free */
333 char *prefix = zmalloc(32);
334 strncpy(prefix, "[such resent]", 32);
335
336 return prefix;
337 }
338
ops_resent_msg_prefix_free(void * opdata,const char * prefix)339 static void ops_resent_msg_prefix_free(void *opdata, const char *prefix)
340 {
341 free((char *) prefix);
342 }
343
ops_convert_msg(void * opdata,ConnContext * context,OtrlConvertType convert_type,char ** dest,const char * src)344 static void ops_convert_msg(void *opdata, ConnContext *context,
345 OtrlConvertType convert_type, char ** dest, const char *src)
346 {
347 switch (convert_type) {
348 case OTRL_CONVERT_SENDING:
349 case OTRL_CONVERT_RECEIVING:
350 break;
351 default:
352 OK(0, "OP convert_msg, got a unknown type %d", convert_type);
353 break;
354 }
355
356 *dest = NULL;
357 }
358
ops_convert_free(void * opdata,ConnContext * context,char * dest)359 static void ops_convert_free(void *opdata, ConnContext *context, char *dest)
360 {
361 return;
362 }
363
364 /* Stub */
365 static void ops_handle_smp_event(void *opdata, OtrlSMPEvent smp_event,
366 ConnContext *context, unsigned short progress_percent, char *question);
367 static void ops_timer_control(void *opdata, unsigned int interval);
368
369 /* OTR message operations. */
370 static OtrlMessageAppOps ops = {
371 ops_policy,
372 ops_create_privkey,
373 ops_is_logged_in,
374 ops_inject_msg,
375 ops_update_context_list,
376 ops_new_fingerprint,
377 ops_write_fingerprints,
378 ops_gone_secure,
379 ops_gone_insecure,
380 ops_still_secure,
381 ops_max_message_size,
382 NULL, /* account_name - NOT USED */
383 NULL, /* account_name_free - NOT USED */
384 ops_received_symkey,
385 ops_otr_error_message,
386 ops_otr_error_message_free,
387 ops_resent_msg_prefix,
388 ops_resent_msg_prefix_free,
389 ops_handle_smp_event,
390 ops_handle_msg_event,
391 ops_create_instag,
392 ops_convert_msg,
393 ops_convert_free,
394 ops_timer_control,
395 };
396
397
ops_timer_control(void * opdata,unsigned int interval)398 static void ops_timer_control(void *opdata, unsigned int interval)
399 {
400 otrl_message_poll(user_state, &ops, NULL);
401 }
402
ops_handle_smp_event(void * opdata,OtrlSMPEvent smp_event,ConnContext * context,unsigned short progress_percent,char * question)403 static void ops_handle_smp_event(void *opdata, OtrlSMPEvent smp_event,
404 ConnContext *context, unsigned short progress_percent, char *question)
405 {
406 struct otr_info *oinfo = opdata;
407
408 switch (smp_event) {
409 case OTRL_SMPEVENT_ASK_FOR_SECRET:
410 OK(!oinfo->auth_done &&
411 !strncmp(oinfo->user, alice_name, strlen(alice_name)),
412 "SMP Event, %s asking for secret", alice_name);
413 break;
414 case OTRL_SMPEVENT_ASK_FOR_ANSWER:
415 OK(!oinfo->auth_done &&
416 !strncmp(oinfo->user, bob_name, strlen(bob_name)) &&
417 !strncmp(auth_question, question, strlen(auth_question)),
418 "SMP Event, %s asking for answer", bob_name);
419 /*
420 * Directly respond to the SMP auth here. Much more easy instead of in
421 * bob's thread.
422 */
423 otrl_message_respond_smp(user_state, &ops, opdata, context,
424 (unsigned char *) auth_secret, strlen(auth_secret));
425 break;
426 case OTRL_SMPEVENT_IN_PROGRESS:
427 OK(!oinfo->auth_done &&
428 !strncmp(oinfo->user, alice_name, strlen(alice_name)),
429 "SMP Event, %s asking for secret", alice_name);
430 break;
431 case OTRL_SMPEVENT_SUCCESS:
432 oinfo->auth_done = 1;
433 OK(oinfo->auth_done, "SMP authentication success for %s", oinfo->user);
434 break;
435 case OTRL_SMPEVENT_ABORT:
436 case OTRL_SMPEVENT_FAILURE:
437 case OTRL_SMPEVENT_CHEATED:
438 case OTRL_SMPEVENT_ERROR:
439 default:
440 OK(0, "SMP auth failed with event %d", smp_event);
441 break;
442 }
443 }
444
cleanup(void)445 static void cleanup(void)
446 {
447 ssize_t ret;
448
449 /* Wake up threads. */
450 ret = write(quit_pipe[1], "42", 2);
451 if (ret < 0) {
452 perror("write quit pipe");
453 }
454
455 /* Cleanup residual Unix socket path. */
456 unlink(alice_sun.sun_path);
457 unlink(bob_sun.sun_path);
458 }
459
update_msg_counter(void)460 static void update_msg_counter(void)
461 {
462 num_recv_msg++;
463 if (num_recv_msg == opt_max_num_msg) {
464 cleanup();
465 }
466 }
467
468 /*
469 * Generate random string and stores it in out of size len.
470 */
gen_random_string(char * out,size_t len)471 static void gen_random_string(char *out, size_t len)
472 {
473 size_t i;
474 static const char alphanum[] =
475 "0123456789"
476 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
477 "abcdefghijklmnopqrstuvwxyz";
478
479 for (i = 0; i < len; i++) {
480 out[i] = alphanum[rand() % (sizeof(alphanum) - 1)];
481 }
482 out[len - 1] = '\0';
483 }
484
send_otr_msg(int sock,const char * to,const char * from,struct otr_info * oinfo,const char * message)485 static int send_otr_msg(int sock, const char *to, const char *from,
486 struct otr_info *oinfo, const char *message)
487 {
488 char *new_msg = NULL;
489 ssize_t ret;
490 gcry_error_t err;
491 struct otr_msg *omsg;
492
493 omsg = zmalloc(sizeof(*omsg));
494 if (!omsg) {
495 perror("zmalloc send otr msg");
496 goto error;
497 }
498
499 if (!message) {
500 size_t len = rand() % 600;
501 char *msg = zmalloc(len);
502 if (!msg) {
503 perror("random msg");
504 goto error;
505 }
506 gen_random_string(msg, len);
507 omsg->plaintext = msg;
508 omsg->plaintext_len = strlen(msg);
509 } else {
510 omsg->plaintext = strdup(message);
511 omsg->plaintext_len = strlen(message);
512 }
513
514 err = otrl_message_sending(user_state, &ops, oinfo, from, protocol, to,
515 OTRL_INSTAG_BEST, omsg->plaintext, NULL, &new_msg,
516 fragPolicy, NULL, NULL, NULL);
517 if (err) {
518 goto error;
519 }
520 if (new_msg) {
521 free(omsg->ciphertext);
522 omsg->ciphertext = strdup(new_msg);
523 omsg->ciphertext_len = strlen(omsg->ciphertext);
524 otrl_message_free(new_msg);
525 }
526
527 ret = send(sock, &omsg, sizeof(omsg), 0);
528 if (ret < 0) {
529 perror("send OTR msg");
530 goto error;
531 }
532
533 return 0;
534
535 error:
536 if(omsg){
537 free(omsg->plaintext);
538 free(omsg->ciphertext);
539 free(omsg);
540 }
541 return -1;
542 }
543
recv_otr_msg(int sock,const char * to,const char * from,struct otr_info * oinfo)544 static int recv_otr_msg(int sock, const char *to, const char *from,
545 struct otr_info *oinfo)
546 {
547 int err;
548 ssize_t ret;
549 char *new_msg = NULL;
550 struct otr_msg *omsg;
551 OtrlTLV *tlvs = NULL;
552
553 ret = recv(sock, &omsg, sizeof(omsg), 0);
554 if (ret < 0) {
555 goto error;
556 }
557
558 err = otrl_message_receiving(user_state, &ops, oinfo, to, protocol, from,
559 omsg->ciphertext, &new_msg, &tlvs, NULL, NULL, NULL);
560 if (!err) {
561 if (new_msg) {
562 OK(strncmp(omsg->plaintext, new_msg, omsg->plaintext_len) == 0,
563 "Message exchanged is valid");
564 update_msg_counter();
565 }
566 } else {
567 OK(err == 1, "Internal OTR message valid");
568 }
569
570 free(omsg->plaintext);
571 free(omsg->ciphertext);
572 free(omsg);
573
574 OtrlTLV *tlv = otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED);
575 /*
576 * XXX: Somehow you can end up with a disconnected TLV in a gone secure
577 * session (see #54). This is probably a bug but since the gone_insecure is
578 * never called (see bug #48) we have no reliable way of knowing the state
579 * of the session at this point.
580 */
581 if (tlv && !oinfo->gone_secure) {
582 OK(session_disconnected, "Disconnected TLV confirmed");
583 }
584
585 otrl_tlv_free(tlvs);
586
587 return 0;
588
589 error:
590 return -1;
591 }
592
add_sock_to_pollset(int epfd,int sock,uint32_t req_ev)593 static int add_sock_to_pollset(int epfd, int sock, uint32_t req_ev)
594 {
595 int ret;
596 struct epoll_event ev;
597
598 memset(&ev, 0, sizeof(ev));
599 ev.events = req_ev;
600 ev.data.fd = sock;
601
602 ret = epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);
603 if (ret < 0) {
604 perror("epoll_ctl add");
605 }
606 return ret;
607 }
608
alice_thread(void * data)609 static void *alice_thread(void *data)
610 {
611 int sock_to_bob, sock_from_bob = 0, epfd, ret;
612 unsigned int auth_started = 0;
613 struct otr_info oinfo;
614
615 memset(&oinfo, 0, sizeof(oinfo));
616
617 /* Poll size is ignored since 2.6.8 */
618 epfd = epoll_create(42);
619 if (epfd < 0) {
620 perror("epoll_create Bob");
621 goto error;
622 }
623
624 sock_to_bob = socket(PF_UNIX, SOCK_STREAM, 0);
625 if (sock_to_bob < 0) {
626 perror("Bob socket to Alice");
627 goto sock_error;
628 }
629 oinfo.sock = sock_to_bob;
630 oinfo.user = alice_name;
631 if (!opt_auth) {
632 /* We are not going to SMP auth for this session so indicate it's
633 * completed so we can go forward with random disconnect.
634 */
635 oinfo.auth_done = 1;
636 }
637
638 ret = connect(sock_to_bob, (struct sockaddr *) &bob_sun,
639 sizeof(bob_sun));
640 if (ret < 0) {
641 perror("connect to Alice");
642 goto end;
643 }
644
645 /* Add quit pipe to pollset trigger by a cleanup. */
646 ret = add_sock_to_pollset(epfd, quit_pipe[0], EPOLLIN);
647 if (ret < 0) {
648 goto end;
649 }
650
651 /* Add our socket to epoll set. */
652 ret = add_sock_to_pollset(epfd, alice_sock,
653 EPOLLIN | EPOLLRDHUP);
654 if (ret < 0) {
655 goto end;
656 }
657
658 while (1) {
659 int i, nb_fd, timeout;
660 struct epoll_event ev[3];
661 memset(ev, 0, sizeof(ev));
662
663 /*
664 * Set random timeout and when we do timeout, use that to send message
665 * to Alice.
666 */
667 timeout = (rand() % (timeout_max - 1));
668
669 ret = epoll_wait(epfd, ev, sizeof(ev), timeout);
670 if (ret < 0) {
671 perror("epoll_wait Alice");
672 goto end;
673 }
674 nb_fd = ret;
675
676 /* Each timeout to 10 finishes the OTR session. */
677 if (!(timeout % 3) && opt_disconnect && oinfo.auth_done) {
678 session_disconnected = 1;
679 oinfo.gone_secure = 0;
680 otrl_message_disconnect(user_state, &ops, &oinfo,
681 alice_name, protocol, bob_name, OTRL_INSTAG_BEST);
682 OK(!oinfo.gone_secure, "OTR message disconnect");
683 }
684
685 /* Start authentication with Bob. */
686 if (opt_auth && !auth_started && oinfo.gone_secure) {
687 ConnContext *ctx;
688
689 /* We have to find our context before auth. */
690 ctx = otrl_context_find(user_state, bob_name, alice_name,
691 protocol, OTRL_INSTAG_BEST, 0, NULL, NULL, &oinfo);
692 OK(ctx, "Alice context found for SMP auth");
693
694 otrl_message_initiate_smp_q(user_state, &ops, &oinfo, ctx,
695 auth_question, (unsigned char *) auth_secret,
696 strlen(auth_secret));
697 auth_started = 1;
698 }
699
700 /* No event thus timeout, send message to Alice. */
701 if (nb_fd == 0) {
702 (void) send_otr_msg(sock_to_bob, bob_name, alice_name, &oinfo,
703 NULL);
704 continue;
705 }
706
707 for (i = 0; i < nb_fd; i++) {
708 int fd;
709 uint32_t event;
710
711 fd = ev[i].data.fd;
712 event = ev[i].events;
713
714 if (fd == quit_pipe[0]) {
715 /* Time to leave. */
716 goto end;
717 } else if (fd == alice_sock) {
718 if (event & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
719 goto end;
720 } else if (event & EPOLLIN) {
721 socklen_t len;
722 struct sockaddr_un sun;
723
724 /* Connection from Bob, accept it so we can handle it. */
725 sock_from_bob = accept(fd, (struct sockaddr *) &sun,
726 &len);
727 ret = add_sock_to_pollset(epfd, sock_from_bob,
728 EPOLLIN | EPOLLERR | EPOLLHUP);
729 if (ret < 0) {
730 goto end;
731 }
732 }
733 continue;
734 } else if (fd == sock_from_bob) {
735 if (event & (EPOLLERR | EPOLLHUP)) {
736 /* Stop since Bob's thread just shut us down. */
737 goto end;
738 } else if (event & EPOLLIN) {
739 (void) recv_otr_msg(sock_from_bob, alice_name, bob_name,
740 &oinfo);
741 }
742 continue;
743 } else {
744 goto end;
745 }
746 }
747 }
748
749 end:
750 if (sock_from_bob) {
751 (void) close(sock_from_bob);
752 }
753 (void) close(sock_to_bob);
754 sock_error:
755 (void) close(epfd);
756 error:
757 (void) close(alice_sock);
758
759 return NULL;
760 }
761
bob_thread(void * data)762 static void *bob_thread(void *data)
763 {
764 int sock_to_alice, sock_from_alice = 0, epfd, ret;
765 struct otr_info oinfo;
766
767 memset(&oinfo, 0, sizeof(oinfo));
768
769 /* Poll size is ignored since 2.6.8 */
770 epfd = epoll_create(42);
771 if (epfd < 0) {
772 perror("epoll_create Bob");
773 goto error;
774 }
775
776 sock_to_alice = socket(PF_UNIX, SOCK_STREAM, 0);
777 if (sock_to_alice < 0) {
778 perror("Bob socket to Alice");
779 goto sock_error;
780 }
781 oinfo.sock = sock_to_alice;
782 oinfo.user = bob_name;
783
784 ret = connect(sock_to_alice, (struct sockaddr *) &alice_sun,
785 sizeof(alice_sun));
786 if (ret < 0) {
787 perror("connect to Alice");
788 goto end;
789 }
790
791 /* Add quit pipe to pollset trigger by a cleanup. */
792 ret = add_sock_to_pollset(epfd, quit_pipe[0], EPOLLIN);
793 if (ret < 0) {
794 goto end;
795 }
796
797 /* Add our socket to epoll set. */
798 ret = add_sock_to_pollset(epfd, bob_sock,
799 EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLRDHUP);
800 if (ret < 0) {
801 goto end;
802 }
803
804 while (1) {
805 int i, timeout = 500, nb_fd;
806 struct epoll_event ev[3];
807 memset(ev, 0, sizeof(ev));
808
809 /*
810 * Set random timeout and when we do timeout, use that to send message
811 * to Alice.
812 */
813 timeout = (rand() % (timeout_max - 1));
814
815 ret = epoll_wait(epfd, ev, sizeof(ev), timeout);
816 if (ret < 0) {
817 perror("epoll_wait Bob");
818 goto end;
819 }
820 nb_fd = ret;
821
822 /* No event thus timeout, send message to Alice. */
823 if (nb_fd == 0) {
824 (void) send_otr_msg(sock_to_alice, alice_name, bob_name, &oinfo,
825 NULL);
826 continue;
827 }
828
829 for (i = 0; i < nb_fd; i++) {
830 int fd;
831 uint32_t event;
832
833 fd = ev[i].data.fd;
834 event = ev[i].events;
835
836 if (fd == quit_pipe[0]) {
837 /* Time to leave. */
838 goto end;
839 } else if (fd == bob_sock) {
840 if (event & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) {
841 goto end;
842 } else if (event & (EPOLLIN | EPOLLHUP)) {
843 socklen_t len;
844 struct sockaddr_un sun;
845
846 /* Connection from Alice, accept it so we can handle it. */
847 sock_from_alice = accept(fd, (struct sockaddr *) &sun,
848 &len);
849 ret = add_sock_to_pollset(epfd, sock_from_alice,
850 EPOLLIN | EPOLLERR | EPOLLHUP);
851 if (ret < 0) {
852 goto end;
853 }
854 }
855 continue;
856 } else if (fd == sock_from_alice) {
857 if (event & (EPOLLERR | EPOLLHUP)) {
858 goto end;
859 } else if (event & EPOLLIN) {
860 (void) recv_otr_msg(sock_from_alice, bob_name,
861 alice_name, &oinfo);
862 }
863 continue;
864 } else {
865 goto end;
866 }
867 }
868 }
869
870 end:
871 if (sock_from_alice) {
872 (void) close(sock_from_alice);
873 }
874 (void) close(sock_to_alice);
875 sock_error:
876 (void) close(epfd);
877 error:
878 (void) close(bob_sock);
879 return NULL;
880 }
881
run(void)882 static void run(void)
883 {
884 int ret;
885 void *status;
886 pthread_t alice_th, bob_th;
887
888 /* Init quit pipe. */
889 ret = pipe(quit_pipe);
890 if (ret < 0) {
891 perror("pipe quit pipe");
892 goto end;
893 }
894
895 ret = pthread_create(&alice_th, NULL, alice_thread, NULL);
896 if (ret) {
897 fail("pthread_create sender thread failed (errno: %d)", errno);
898 goto end;
899 }
900
901 ret = pthread_create(&bob_th, NULL, bob_thread, NULL);
902 if (ret) {
903 fail("pthread_create receiver thread failed (errno: %d)", errno);
904 goto exit_receiver;
905 }
906
907 (void) pthread_join(bob_th, &status);
908
909 exit_receiver:
910 (void) pthread_join(alice_th, &status);
911 end:
912 /* Get rid of the quit pipe. */
913 close(quit_pipe[0]);
914 close(quit_pipe[1]);
915 return;
916 }
917
918 /*
919 * Load OTR instag using the given opt argument.
920 */
load_instag(void)921 static void load_instag(void)
922 {
923 int ret;
924 gcry_error_t err;
925
926 ret = access(opt_instag_path, R_OK);
927 if (ret < 0) {
928 fail("Instag file %s is not readable", opt_instag_path);
929 return;
930 }
931
932 err = otrl_instag_read(user_state, opt_instag_path);
933 OK(err == GPG_ERR_NO_ERROR, "Loading instag from given file");
934 }
935
936 /*
937 * Load private key file using the given opt argument.
938 */
load_key(void)939 static void load_key(void)
940 {
941 int ret;
942 gcry_error_t err;
943
944 ret = access(opt_key_path, R_OK);
945 if (ret < 0) {
946 fail("Key file %s is not readable", opt_key_path);
947 return;
948 }
949
950 err = otrl_privkey_read(user_state, opt_key_path);
951 OK(err == GPG_ERR_NO_ERROR, "Loading key from given file");
952 }
953
954 /*
955 * Load private key fingerprint file using the given opt argument.
956 */
load_key_fp(void)957 static void load_key_fp(void)
958 {
959 int ret;
960 gcry_error_t err;
961
962 ret = access(opt_key_fp_path, R_OK);
963 if (ret < 0) {
964 fail("Key fingerprints file %s is not readable", opt_key_fp_path);
965 return;
966 }
967
968 err = otrl_privkey_read_fingerprints(user_state, opt_key_fp_path, NULL,
969 NULL);
970 OK(err == GPG_ERR_NO_ERROR, "Loading key fingerprints from given file");
971 }
972
create_unix_socket(const char * pathname,struct sockaddr_un * sun)973 static int create_unix_socket(const char *pathname,
974 struct sockaddr_un *sun)
975 {
976 int sock, ret;
977
978 /* Create both Unix socket. */
979 if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
980 ret = -errno;
981 perror("Unix socket");
982 goto error;
983 }
984
985 memset(sun, 0, sizeof(struct sockaddr_un));
986 sun->sun_family = AF_UNIX;
987 strncpy(sun->sun_path, pathname, sizeof(sun->sun_path));
988 sun->sun_path[sizeof(sun->sun_path) - 1] = '\0';
989
990 ret = bind(sock, (struct sockaddr *) sun, sizeof(struct sockaddr_un));
991 if (ret < 0) {
992 perror("bind unix sock");
993 goto error;
994 }
995
996 ret = listen(sock, 10);
997 if (ret < 0) {
998 perror("listen unix sock");
999 goto error;
1000 }
1001
1002 return sock;
1003 error:
1004 return ret;
1005 }
1006
1007 /*
1008 * Bootstrap client by initializing the OTR library and creating an OTR user
1009 * state.
1010 *
1011 * Return 0 on success else a negative value on error.
1012 */
init_client(void)1013 static int init_client(void)
1014 {
1015 int ret;
1016
1017 /* Init libgcrypt threading system. */
1018 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
1019
1020 /* Init OTR library. */
1021 OTRL_INIT;
1022 OK(1, "OTR library initialization done.");
1023
1024 user_state = otrl_userstate_create();
1025 OK(user_state, "OTR userstate creation done.");
1026 if (!user_state) {
1027 fail("Out of memory on userstate create");
1028 ret = -ENOMEM;
1029 goto error;
1030 }
1031
1032 /* Seed the prng. */
1033 srand(time(NULL));
1034
1035 /* Cleanup Unix socket file before creating them. */
1036 unlink(unix_sock_alice_path);
1037 unlink(unix_sock_bob_path);
1038
1039 alice_sock = create_unix_socket(unix_sock_alice_path, &alice_sun);
1040 bob_sock = create_unix_socket(unix_sock_bob_path, &bob_sun);
1041 if (alice_sock < 0 || bob_sock < 0) {
1042 ret = -EINVAL;
1043 goto error;
1044 }
1045
1046 if (opt_fragment) {
1047 fragPolicy = OTRL_FRAGMENT_SEND_ALL;
1048 }
1049
1050 return 0;
1051
1052 error:
1053 return ret;
1054 }
1055
sighandler(int sig)1056 static void sighandler(int sig)
1057 {
1058 switch (sig) {
1059 case SIGPIPE:
1060 case SIGINT:
1061 case SIGTERM:
1062 cleanup();
1063 break;
1064 default:
1065 break;
1066 }
1067 }
1068
1069 /*
1070 * main entry point.
1071 */
main(int argc,char ** argv)1072 int main(int argc, char **argv)
1073 {
1074 int ret, opt;
1075 struct sigaction sa;
1076 sigset_t sigset;
1077
1078 plan_no_plan();
1079
1080 if ((ret = sigemptyset(&sigset)) < 0) {
1081 perror("sigemptyset");
1082 goto error;
1083 }
1084
1085 sa.sa_handler = sighandler;
1086 sa.sa_mask = sigset;
1087 sa.sa_flags = 0;
1088
1089 if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
1090 perror("sigaction");
1091 goto error;
1092 }
1093 if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) {
1094 perror("sigaction");
1095 goto error;
1096 }
1097 if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) {
1098 perror("sigaction");
1099 goto error;
1100 }
1101
1102 while ((opt = getopt_long(argc, argv, "+i:k:f:t:m:daF", long_opts, NULL)) != -1) {
1103 switch (opt) {
1104 case 'i':
1105 opt_instag_path = strdup(optarg);
1106 break;
1107 case 'k':
1108 opt_key_path = strdup(optarg);
1109 break;
1110 case 'f':
1111 opt_key_fp_path = strdup(optarg);
1112 break;
1113 case 't':
1114 timeout_max = atoi(optarg);
1115 break;
1116 case 'm':
1117 opt_max_num_msg = atoi(optarg);
1118 break;
1119 case 'd':
1120 opt_disconnect = 1;
1121 break;
1122 case 'a':
1123 opt_auth = 1;
1124 break;
1125 case 'F':
1126 opt_fragment = 1;
1127 break;
1128 default:
1129 goto error;
1130 }
1131 }
1132
1133 if (!opt_key_path) {
1134 fail("No key file, failing");
1135 goto error;
1136 }
1137
1138 /* Running OTR tests. */
1139 ret = init_client();
1140 if (ret < 0) {
1141 goto error;
1142 }
1143
1144 if (opt_instag_path) {
1145 load_instag();
1146 }
1147 if (opt_key_fp_path) {
1148 load_key_fp();
1149 }
1150 load_key();
1151
1152 run();
1153
1154 return exit_status();
1155
1156 error:
1157 return -1;
1158 }
1159