xref: /openbsd/usr.sbin/sasyncd/net.c (revision 6668a736)
1 /*	$OpenBSD: net.c,v 1.24 2022/01/28 06:33:27 guenther Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 H�kan Olsson.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * This code was written under funding by Multicom Security AB.
30  */
31 
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <ifaddrs.h>
38 #include <netdb.h>
39 #include <signal.h>
40 
41 #include <openssl/aes.h>
42 #include <openssl/sha.h>
43 
44 #include <errno.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <unistd.h>
49 
50 #include "sasyncd.h"
51 #include "net.h"
52 
53 struct msg {
54 	u_int8_t	*buf;
55 	u_int32_t	 len;
56 	int		 refcnt;
57 };
58 
59 struct qmsg {
60 	SIMPLEQ_ENTRY(qmsg)	next;
61 	struct msg	*msg;
62 };
63 
64 int	*listeners;
65 AES_KEY	aes_key[2];
66 #define AES_IV_LEN	AES_BLOCK_SIZE
67 
68 /* We never send (or expect to receive) messages smaller/larger than this. */
69 #define MSG_MINLEN	12
70 #define MSG_MAXLEN	4096
71 
72 /* Local prototypes. */
73 static u_int8_t *net_read(struct syncpeer *, u_int32_t *, u_int32_t *);
74 static int	 net_set_sa(struct sockaddr *, char *, in_port_t);
75 static void	 net_check_peers(void *);
76 
77 /* Pretty-print a buffer. */
78 void
dump_buf(int lvl,u_int8_t * b,u_int32_t len,char * title)79 dump_buf(int lvl, u_int8_t *b, u_int32_t len, char *title)
80 {
81 	u_int32_t	i, off, blen;
82 	u_int8_t	*buf;
83 	const char	def[] = "Buffer:";
84 
85 	if (cfgstate.verboselevel < lvl)
86 		return;
87 
88 	blen = 2 * (len + len / 36) + 3 + (title ? strlen(title) : sizeof def);
89 	if (!(buf = calloc(1, blen)))
90 		return;
91 
92 	snprintf(buf, blen, "%s\n ", title ? title : def);
93 	off = strlen(buf);
94 	for (i = 0; i < len; i++, off+=2) {
95 		snprintf(buf + off, blen - off, "%02x", b[i]);
96 		if ((i+1) % 36 == 0) {
97 			off += 2;
98 			snprintf(buf + off, blen - off, "\n ");
99 		}
100 	}
101 	log_msg(lvl, "%s", buf);
102 	free(buf);
103 }
104 
105 /* Add a listening socket. */
106 static int
net_add_listener(struct sockaddr * sa)107 net_add_listener(struct sockaddr *sa)
108 {
109 	char	host[NI_MAXHOST], port[NI_MAXSERV];
110 	int	r, s;
111 
112 	s = socket(sa->sa_family, SOCK_STREAM, 0);
113 	if (s < 0) {
114 		perror("net_add_listener: socket()");
115 		close(s);
116 		return -1;
117 	}
118 
119 	r = 1;
120 	if (setsockopt(s, SOL_SOCKET,
121 		cfgstate.listen_on ? SO_REUSEADDR : SO_REUSEPORT, (void *)&r,
122 		sizeof r)) {
123 		perror("net_add_listener: setsockopt()");
124 		close(s);
125 		return -1;
126 	}
127 
128 	if (bind(s, sa, sa->sa_family == AF_INET ? sizeof(struct sockaddr_in) :
129 		sizeof (struct sockaddr_in6))) {
130 		perror("net_add_listener: bind()");
131 		close(s);
132 		return -1;
133 	}
134 
135 	if (listen(s, 3)) {
136 		perror("net_add_listener: listen()");
137 		close(s);
138 		return -1;
139 	}
140 
141 	if (getnameinfo(sa, sa->sa_len, host, sizeof host, port, sizeof port,
142 		NI_NUMERICHOST | NI_NUMERICSERV))
143 		log_msg(2, "listening on port %u fd %d", cfgstate.listen_port,
144 		    s);
145 	else
146 		log_msg(2, "listening on %s port %s fd %d", host, port, s);
147 
148 	return s;
149 }
150 
151 /* Allocate and fill in listeners array. */
152 static int
net_setup_listeners(void)153 net_setup_listeners(void)
154 {
155 	struct sockaddr_storage	 sa_storage;
156 	struct sockaddr		*sa = (struct sockaddr *)&sa_storage;
157 	struct sockaddr_in	*sin = (struct sockaddr_in *)sa;
158 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)sa;
159 	struct ifaddrs		*ifap = 0, *ifa;
160 	int			 i, count;
161 
162 	/* Setup listening sockets.  */
163 	memset(&sa_storage, 0, sizeof sa_storage);
164 	if (net_set_sa(sa, cfgstate.listen_on, cfgstate.listen_port) == 0) {
165 		listeners = calloc(2, sizeof(int));
166 		if (!listeners) {
167 			perror("net_setup_listeners: calloc()");
168 			goto errout;
169 		}
170 		listeners[1] = -1;
171 		listeners[0] = net_add_listener(sa);
172 		if (listeners[0] == -1) {
173 			log_msg(0, "net_setup_listeners: could not find "
174 			    "listen address (%s)", cfgstate.listen_on);
175 			goto errout;
176 		}
177 		return 0;
178 	}
179 
180 	/*
181 	 * If net_set_sa() failed, cfgstate.listen_on is probably an
182 	 * interface name, so we should listen on all its addresses.
183 	 */
184 
185 	if (getifaddrs(&ifap) != 0) {
186 		perror("net_setup_listeners: getifaddrs()");
187 		goto errout;
188 	}
189 
190 	/* How many addresses matches? */
191 	for (count = 0, ifa = ifap; ifa; ifa = ifa->ifa_next) {
192 		if (!ifa->ifa_name || !ifa->ifa_addr ||
193 		    (ifa->ifa_addr->sa_family != AF_INET &&
194 			ifa->ifa_addr->sa_family != AF_INET6))
195 			continue;
196 		if (cfgstate.listen_family &&
197 		    cfgstate.listen_family != ifa->ifa_addr->sa_family)
198 			continue;
199 		if (strcmp(ifa->ifa_name, cfgstate.listen_on) != 0)
200 			continue;
201 		count++;
202 	}
203 
204 	if (!count) {
205 		log_msg(0, "net_setup_listeners: no listeners found for %s",
206 		    cfgstate.listen_on);
207 		goto errout;
208 	}
209 
210 	/* Allocate one extra slot and set to -1, marking end of array. */
211 	listeners = calloc(count + 1, sizeof(int));
212 	if (!listeners) {
213 		perror("net_setup_listeners: calloc()");
214 		goto errout;
215 	}
216 	for (i = 0; i <= count; i++)
217 		listeners[i] = -1;
218 
219 	/* Create listening sockets */
220 	for (count = 0, ifa = ifap; ifa; ifa = ifa->ifa_next) {
221 		if (!ifa->ifa_name || !ifa->ifa_addr ||
222 		    (ifa->ifa_addr->sa_family != AF_INET &&
223 			ifa->ifa_addr->sa_family != AF_INET6))
224 			continue;
225 		if (cfgstate.listen_family &&
226 		    cfgstate.listen_family != ifa->ifa_addr->sa_family)
227 			continue;
228 		if (strcmp(ifa->ifa_name, cfgstate.listen_on) != 0)
229 			continue;
230 
231 		memset(&sa_storage, 0, sizeof sa_storage);
232 		sa->sa_family = ifa->ifa_addr->sa_family;
233 		switch (sa->sa_family) {
234 		case AF_INET:
235 			sin->sin_port = htons(cfgstate.listen_port);
236 			sin->sin_len = sizeof *sin;
237 			memcpy(&sin->sin_addr,
238 			    &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr,
239 			    sizeof sin->sin_addr);
240 			break;
241 		case AF_INET6:
242 			sin6->sin6_port = htons(cfgstate.listen_port);
243 			sin6->sin6_len = sizeof *sin6;
244 			memcpy(&sin6->sin6_addr,
245 			    &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr,
246 			    sizeof sin6->sin6_addr);
247 			break;
248 		}
249 
250 		listeners[count] = net_add_listener(sa);
251 		if (listeners[count] == -1) {
252 			log_msg(2, "net_setup_listeners(setup): failed to "
253 			    "add listener, count = %d", count);
254 			goto errout;
255 		}
256 		count++;
257 	}
258 	freeifaddrs(ifap);
259 	return 0;
260 
261   errout:
262 	if (ifap)
263 		freeifaddrs(ifap);
264 	if (listeners) {
265 		for (i = 0; listeners[i] != -1; i++)
266 			close(listeners[i]);
267 		free(listeners);
268 	}
269 	return -1;
270 }
271 
272 int
net_init(void)273 net_init(void)
274 {
275 	struct syncpeer *p;
276 
277 	if (AES_set_encrypt_key(cfgstate.sharedkey, cfgstate.sharedkey_len,
278 	    &aes_key[0]) ||
279 	    AES_set_decrypt_key(cfgstate.sharedkey, cfgstate.sharedkey_len,
280 	    &aes_key[1])) {
281 		fprintf(stderr, "Bad AES shared key\n");
282 		return -1;
283 	}
284 
285 	if (net_setup_listeners())
286 		return -1;
287 
288 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
289 		p->socket = -1;
290 		SIMPLEQ_INIT(&p->msgs);
291 	}
292 
293 	net_check_peers(0);
294 	return 0;
295 }
296 
297 static void
net_enqueue(struct syncpeer * p,struct msg * m)298 net_enqueue(struct syncpeer *p, struct msg *m)
299 {
300 	struct qmsg	*qm;
301 
302 	if (p->socket < 0)
303 		return;
304 
305 	qm = calloc(1, sizeof *qm);
306 	if (!qm) {
307 		log_err("net_enqueue: calloc()");
308 		return;
309 	}
310 
311 	qm->msg = m;
312 	m->refcnt++;
313 
314 	SIMPLEQ_INSERT_TAIL(&p->msgs, qm, next);
315 	return;
316 }
317 
318 /*
319  * Queue a message for transmission to a particular peer,
320  * or to all peers if no peer is specified.
321  */
322 int
net_queue(struct syncpeer * p0,u_int32_t msgtype,u_int8_t * buf,u_int32_t len)323 net_queue(struct syncpeer *p0, u_int32_t msgtype, u_int8_t *buf, u_int32_t len)
324 {
325 	struct syncpeer *p = p0;
326 	struct msg	*m;
327 	SHA_CTX		 ctx;
328 	u_int8_t	 hash[SHA_DIGEST_LENGTH];
329 	u_int8_t	 iv[AES_IV_LEN], tmp_iv[AES_IV_LEN];
330 	u_int32_t	 v, padlen = 0;
331 	int		 i, offset;
332 
333 	m = calloc(1, sizeof *m);
334 	if (!m) {
335 		log_err("net_queue: calloc()");
336 		free(buf);
337 		return -1;
338 	}
339 
340 	/* Generate hash */
341 	SHA1_Init(&ctx);
342 	SHA1_Update(&ctx, buf, len);
343 	SHA1_Final(hash, &ctx);
344 	dump_buf(2, hash, sizeof hash, "net_queue: computed hash");
345 
346 	/* Padding required? */
347 	i = len % AES_IV_LEN;
348 	if (i) {
349 		u_int8_t *pbuf;
350 		i = AES_IV_LEN - i;
351 		pbuf = realloc(buf, len + i);
352 		if (!pbuf) {
353 			log_err("net_queue: realloc()");
354 			free(buf);
355 			free(m);
356 			return -1;
357 		}
358 		padlen = i;
359 		while (i > 0)
360 			pbuf[len++] = (u_int8_t)i--;
361 		buf = pbuf;
362 	}
363 
364 	/* Get random IV */
365 	for (i = 0; (size_t)i <= sizeof iv - sizeof v; i += sizeof v) {
366 		v = arc4random();
367 		memcpy(&iv[i], &v, sizeof v);
368 	}
369 	dump_buf(2, iv, sizeof iv, "net_queue: IV");
370 	memcpy(tmp_iv, iv, sizeof tmp_iv);
371 
372 	/* Encrypt */
373 	dump_buf(2, buf, len, "net_queue: pre encrypt");
374 	AES_cbc_encrypt(buf, buf, len, &aes_key[0], tmp_iv, AES_ENCRYPT);
375 	dump_buf(2, buf, len, "net_queue: post encrypt");
376 
377 	/* Allocate send buffer */
378 	m->len = len + sizeof iv + sizeof hash + 3 * sizeof(u_int32_t);
379 	m->buf = malloc(m->len);
380 	if (!m->buf) {
381 		free(m);
382 		free(buf);
383 		log_err("net_queue: calloc()");
384 		return -1;
385 	}
386 	offset = 0;
387 
388 	/* Fill it (order must match parsing code in net_read()) */
389 	v = htonl(m->len - sizeof(u_int32_t));
390 	memcpy(m->buf + offset, &v, sizeof v);
391 	offset += sizeof v;
392 	v = htonl(msgtype);
393 	memcpy(m->buf + offset, &v, sizeof v);
394 	offset += sizeof v;
395 	v = htonl(padlen);
396 	memcpy(m->buf + offset, &v, sizeof v);
397 	offset += sizeof v;
398 	memcpy(m->buf + offset, hash, sizeof hash);
399 	offset += sizeof hash;
400 	memcpy(m->buf + offset, iv, sizeof iv);
401 	offset += sizeof iv;
402 	memcpy(m->buf + offset, buf, len);
403 	free(buf);
404 
405 	if (p)
406 		net_enqueue(p, m);
407 	else
408 		for (p = LIST_FIRST(&cfgstate.peerlist); p;
409 		     p = LIST_NEXT(p, link))
410 			net_enqueue(p, m);
411 
412 	if (!m->refcnt) {
413 		free(m->buf);
414 		free(m);
415 	}
416 
417 	return 0;
418 }
419 
420 /* Set all write pending filedescriptors. */
421 int
net_set_pending_wfds(fd_set * fds)422 net_set_pending_wfds(fd_set *fds)
423 {
424 	struct syncpeer *p;
425 	int		max_fd = -1;
426 
427 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link))
428 		if (p->socket > -1 && SIMPLEQ_FIRST(&p->msgs)) {
429 			FD_SET(p->socket, fds);
430 			if (p->socket > max_fd)
431 				max_fd = p->socket;
432 		}
433 	return max_fd + 1;
434 }
435 
436 /*
437  * Set readable filedescriptors. They are basically the same as for write,
438  * plus the listening socket.
439  */
440 int
net_set_rfds(fd_set * fds)441 net_set_rfds(fd_set *fds)
442 {
443 	struct syncpeer *p;
444 	int		i, max_fd = -1;
445 
446 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
447 		if (p->socket > -1)
448 			FD_SET(p->socket, fds);
449 		if (p->socket > max_fd)
450 			max_fd = p->socket;
451 	}
452 	for (i = 0; listeners[i] != -1; i++) {
453 		FD_SET(listeners[i], fds);
454 		if (listeners[i] > max_fd)
455 			max_fd = listeners[i];
456 	}
457 	return max_fd + 1;
458 }
459 
460 static void
net_accept(int accept_socket)461 net_accept(int accept_socket)
462 {
463 	struct sockaddr_storage	 sa_storage, sa_storage2;
464 	struct sockaddr		*sa = (struct sockaddr *)&sa_storage;
465 	struct sockaddr		*sa2 = (struct sockaddr *)&sa_storage2;
466 	struct sockaddr_in	*sin, *sin2;
467 	struct sockaddr_in6	*sin6, *sin62;
468 	struct syncpeer		*p;
469 	socklen_t		 socklen;
470 	int			 s, found;
471 
472 	/* Accept a new incoming connection */
473 	socklen = sizeof sa_storage;
474 	memset(&sa_storage, 0, socklen);
475 	memset(&sa_storage2, 0, socklen);
476 	s = accept(accept_socket, sa, &socklen);
477 	if (s > -1) {
478 		/* Setup the syncpeer structure */
479 		found = 0;
480 		for (p = LIST_FIRST(&cfgstate.peerlist); p && !found;
481 		     p = LIST_NEXT(p, link)) {
482 
483 			/* Match? */
484 			if (net_set_sa(sa2, p->name, 0))
485 				continue;
486 			if (sa->sa_family != sa2->sa_family)
487 				continue;
488 			if (sa->sa_family == AF_INET) {
489 				sin = (struct sockaddr_in *)sa;
490 				sin2 = (struct sockaddr_in *)sa2;
491 				if (memcmp(&sin->sin_addr, &sin2->sin_addr,
492 					sizeof(struct in_addr)))
493 					continue;
494 			} else {
495 				sin6 = (struct sockaddr_in6 *)sa;
496 				sin62 = (struct sockaddr_in6 *)sa2;
497 				if (memcmp(&sin6->sin6_addr, &sin62->sin6_addr,
498 					sizeof(struct in6_addr)))
499 					continue;
500 			}
501 			/* Match! */
502 			found++;
503 			p->socket = s;
504 			log_msg(1, "net: peer \"%s\" connected", p->name);
505 			if (cfgstate.runstate == MASTER)
506 				timer_add("pfkey_snap", 2, pfkey_snapshot, p);
507 		}
508 		if (!found) {
509 			log_msg(1, "net: found no matching peer for accepted "
510 			    "socket, closing.");
511 			close(s);
512 		}
513 	} else if (errno != EWOULDBLOCK && errno != EINTR &&
514 	    errno != ECONNABORTED)
515 		log_err("net: accept()");
516 }
517 
518 void
net_handle_messages(fd_set * fds)519 net_handle_messages(fd_set *fds)
520 {
521 	struct syncpeer *p;
522 	u_int8_t	*msg;
523 	u_int32_t	 msgtype, msglen;
524 	int		 i;
525 
526 	for (i = 0; listeners[i] != -1; i++)
527 		if (FD_ISSET(listeners[i], fds))
528 			net_accept(listeners[i]);
529 
530 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
531 		if (p->socket < 0 || !FD_ISSET(p->socket, fds))
532 			continue;
533 		msg = net_read(p, &msgtype, &msglen);
534 		if (!msg)
535 			continue;
536 
537 		log_msg(2, "net_handle_messages: got msg type %u len %u from "
538 		    "peer %s", msgtype, msglen, p->name);
539 
540 		switch (msgtype) {
541 		case MSG_SYNCCTL:
542 			net_ctl_handle_msg(p, msg, msglen);
543 			free(msg);
544 			break;
545 
546 		case MSG_PFKEYDATA:
547 			if (p->runstate != MASTER ||
548 			    cfgstate.runstate == MASTER) {
549 				log_msg(1, "net: got PFKEY message from "
550 				    "non-MASTER peer");
551 				free(msg);
552 				if (cfgstate.runstate == MASTER)
553 					net_ctl_send_state(p);
554 				else
555 					net_ctl_send_error(p, 0);
556 			} else if (pfkey_queue_message(msg, msglen))
557 				free(msg);
558 			break;
559 
560 		default:
561 			log_msg(0, "net: got unknown message type %u len %u "
562 			    "from peer %s", msgtype, msglen, p->name);
563 			free(msg);
564 			net_ctl_send_error(p, 0);
565 		}
566 	}
567 }
568 
569 void
net_send_messages(fd_set * fds)570 net_send_messages(fd_set *fds)
571 {
572 	struct syncpeer *p;
573 	struct qmsg	*qm;
574 	struct msg	*m;
575 	ssize_t		 r;
576 
577 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
578 		if (p->socket < 0 || !FD_ISSET(p->socket, fds))
579 			continue;
580 		qm = SIMPLEQ_FIRST(&p->msgs);
581 		if (!qm) {
582 			/* XXX Log */
583 			continue;
584 		}
585 		m = qm->msg;
586 
587 		log_msg(2, "net_send_messages: msg %p len %u ref %d "
588 		    "to peer %s", m, m->len, m->refcnt, p->name);
589 
590 		/* write message */
591 		r = write(p->socket, m->buf, m->len);
592 		if (r == -1) {
593 			net_disconnect_peer(p);
594 			log_msg(0, "net_send_messages: write() failed, "
595 			    "peer disconnected");
596 		} else if (r < (ssize_t)m->len) {
597 			/* retransmit later */
598 			continue;
599 		}
600 
601 		/* cleanup */
602 		SIMPLEQ_REMOVE_HEAD(&p->msgs, next);
603 		free(qm);
604 
605 		if (--m->refcnt < 1) {
606 			log_msg(2, "net_send_messages: freeing msg %p", m);
607 			free(m->buf);
608 			free(m);
609 		}
610 	}
611 	return;
612 }
613 
614 void
net_disconnect_peer(struct syncpeer * p)615 net_disconnect_peer(struct syncpeer *p)
616 {
617 	if (p->socket > -1) {
618 		log_msg(1, "net_disconnect_peer: peer \"%s\" removed",
619 		    p->name);
620 		close(p->socket);
621 	}
622 	p->socket = -1;
623 }
624 
625 void
net_shutdown(void)626 net_shutdown(void)
627 {
628 	struct syncpeer *p;
629 	struct qmsg	*qm;
630 	struct msg	*m;
631 	int		 i;
632 
633 	while ((p = LIST_FIRST(&cfgstate.peerlist))) {
634 		while ((qm = SIMPLEQ_FIRST(&p->msgs))) {
635 			SIMPLEQ_REMOVE_HEAD(&p->msgs, next);
636 			m = qm->msg;
637 			if (--m->refcnt < 1) {
638 				free(m->buf);
639 				free(m);
640 			}
641 			free(qm);
642 		}
643 		net_disconnect_peer(p);
644 		free(p->sa);
645 		free(p->name);
646 		LIST_REMOVE(p, link);
647 		cfgstate.peercnt--;
648 		free(p);
649 	}
650 
651 	if (listeners) {
652 		for (i = 0; listeners[i] != -1; i++)
653 			close(listeners[i]);
654 		free(listeners);
655 		listeners = 0;
656 	}
657 }
658 
659 /*
660  * Helper functions (local) below here.
661  */
662 
663 static u_int8_t *
net_read(struct syncpeer * p,u_int32_t * msgtype,u_int32_t * msglen)664 net_read(struct syncpeer *p, u_int32_t *msgtype, u_int32_t *msglen)
665 {
666 	u_int8_t	*msg, *blob, *rhash, *iv, hash[SHA_DIGEST_LENGTH];
667 	u_int32_t	 v, blob_len, pos = 0;
668 	int		 padlen = 0, offset = 0;
669 	ssize_t 	 r;
670 	SHA_CTX		 ctx;
671 
672 	/* Read blob length */
673 	r = read(p->socket, &v, sizeof v);
674 	if (r != (ssize_t)sizeof v) {
675 		if (r < 1)
676 			net_disconnect_peer(p);
677 		return NULL;
678 	}
679 
680 	blob_len = ntohl(v);
681 	if (blob_len < sizeof hash + AES_IV_LEN + 2 * sizeof(u_int32_t))
682 		return NULL;
683 	*msglen = blob_len - sizeof hash - AES_IV_LEN - 2 * sizeof(u_int32_t);
684 	if (*msglen < MSG_MINLEN || *msglen > MSG_MAXLEN)
685 		return NULL;
686 
687 	/* Read message blob */
688 	blob = malloc(blob_len);
689 	if (!blob) {
690 		log_err("net_read: malloc()");
691 		return NULL;
692 	}
693 
694 	while (blob_len > pos) {
695 		switch (r = read(p->socket, blob + pos, blob_len - pos)) {
696 		case -1:
697 			if (errno == EINTR || errno == EAGAIN)
698 				continue;
699                         /* FALLTHROUGH */
700 		case 0:
701 			net_disconnect_peer(p);
702 			free(blob);
703 			return NULL;
704                         /* NOTREACHED */
705 		default:
706 			pos += r;
707 		}
708 	}
709 
710 	offset = 0;
711 	memcpy(&v, blob + offset, sizeof v);
712 	*msgtype = ntohl(v);
713 	offset += sizeof v;
714 
715 	if (*msgtype > MSG_MAXTYPE) {
716 		free(blob);
717 		return NULL;
718 	}
719 
720 	memcpy(&v, blob + offset, sizeof v);
721 	padlen = ntohl(v);
722 	offset += sizeof v;
723 
724 	rhash = blob + offset;
725 	iv    = rhash + sizeof hash;
726 	msg = malloc(*msglen);
727 	if (!msg) {
728 		free(blob);
729 		return NULL;
730 	}
731 	memcpy(msg, iv + AES_IV_LEN, *msglen);
732 
733 	dump_buf(2, rhash, sizeof hash, "net_read: got hash");
734 	dump_buf(2, iv, AES_IV_LEN, "net_read: got IV");
735 	dump_buf(2, msg, *msglen, "net_read: pre decrypt");
736 	AES_cbc_encrypt(msg, msg, *msglen, &aes_key[1], iv, AES_DECRYPT);
737 	dump_buf(2, msg, *msglen, "net_read: post decrypt");
738 	*msglen -= padlen;
739 
740 	SHA1_Init(&ctx);
741 	SHA1_Update(&ctx, msg, *msglen);
742 	SHA1_Final(hash, &ctx);
743 	dump_buf(2, hash, sizeof hash, "net_read: computed hash");
744 
745 	if (memcmp(hash, rhash, sizeof hash) != 0) {
746 		free(blob);
747 		free(msg);
748 		log_msg(0, "net_read: got bad message (typo in shared key?)");
749 		return NULL;
750 	}
751 	free(blob);
752 	return msg;
753 }
754 
755 static int
net_set_sa(struct sockaddr * sa,char * name,in_port_t port)756 net_set_sa(struct sockaddr *sa, char *name, in_port_t port)
757 {
758 	struct sockaddr_in	*sin = (struct sockaddr_in *)sa;
759 	struct sockaddr_in6	*sin6 = (struct sockaddr_in6 *)sa;
760 
761 	if (!name) {
762 		/* XXX Assume IPv4 */
763 		sa->sa_family = AF_INET;
764 		sin->sin_port = htons(port);
765 		sin->sin_len = sizeof *sin;
766 		return 0;
767 	}
768 
769 	if (inet_pton(AF_INET, name, &sin->sin_addr) == 1) {
770 		sa->sa_family = AF_INET;
771 		sin->sin_port = htons(port);
772 		sin->sin_len = sizeof *sin;
773 		return 0;
774 	}
775 
776 	if (inet_pton(AF_INET6, name, &sin6->sin6_addr) == 1) {
777 		sa->sa_family = AF_INET6;
778 		sin6->sin6_port = htons(port);
779 		sin6->sin6_len = sizeof *sin6;
780 		return 0;
781 	}
782 
783 	return -1;
784 }
785 
786 static void
got_sigalrm(int s)787 got_sigalrm(int s)
788 {
789 	return;
790 }
791 
792 void
net_connect(void)793 net_connect(void)
794 {
795 	struct itimerval	iv;
796 	struct syncpeer		*p;
797 
798 	signal(SIGALRM, got_sigalrm);
799 	memset(&iv, 0, sizeof iv);
800 	iv.it_value.tv_sec = 5;
801 	iv.it_interval.tv_sec = 5;
802 	setitimer(ITIMER_REAL, &iv, NULL);
803 
804 	for (p = LIST_FIRST(&cfgstate.peerlist); p; p = LIST_NEXT(p, link)) {
805 		if (p->socket > -1)
806 			continue;
807 		if (!p->sa) {
808 			p->sa = calloc(1, sizeof(struct sockaddr_storage));
809 			if (!p->sa)
810 				return;
811 			if (net_set_sa(p->sa, p->name, cfgstate.listen_port))
812 				continue;
813 		}
814 		p->socket = socket(p->sa->sa_family, SOCK_STREAM, 0);
815 		if (p->socket < 0) {
816 			log_err("peer \"%s\": socket()", p->name);
817 			continue;
818 		}
819 		if (connect(p->socket, p->sa, p->sa->sa_len)) {
820 			log_msg(1, "net_connect: peer \"%s\" not ready yet",
821 			    p->name);
822 			net_disconnect_peer(p);
823 			continue;
824 		}
825 		if (net_ctl_send_state(p)) {
826 			log_msg(0, "net_connect: peer \"%s\" failed", p->name);
827 			net_disconnect_peer(p);
828 			continue;
829 		}
830 		log_msg(1, "net_connect: peer \"%s\" connected, fd %d",
831 		    p->name, p->socket);
832 
833 		/* Schedule a pfkey sync to the newly connected peer. */
834 		if (cfgstate.runstate == MASTER)
835 			timer_add("pfkey_snapshot", 2, pfkey_snapshot, p);
836 	}
837 
838 	timerclear(&iv.it_value);
839 	timerclear(&iv.it_interval);
840 	setitimer(ITIMER_REAL, &iv, NULL);
841 	signal(SIGALRM, SIG_IGN);
842 
843 	return;
844 }
845 
846 static void
net_check_peers(void * arg)847 net_check_peers(void *arg)
848 {
849 	net_connect();
850 	(void)timer_add("peer recheck", 600, net_check_peers, 0);
851 }
852