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