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