]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/session.c
ipsec-34.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / session.c
1 /* $KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include "config.h"
33
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/time.h>
37 #include <sys/socket.h>
38 #if HAVE_SYS_WAIT_H
39 # include <sys/wait.h>
40 #endif
41 #ifndef WEXITSTATUS
42 # define WEXITSTATUS(s) ((unsigned)(s) >> 8)
43 #endif
44 #ifndef WIFEXITED
45 # define WIFEXITED(s) (((s) & 255) == 0)
46 #endif
47
48 #ifndef HAVE_NETINET6_IPSEC
49 #include <netinet/ipsec.h>
50 #else
51 #include <netinet6/ipsec.h>
52 #endif
53
54 #include <stdlib.h>
55 #include <stdio.h>
56 #include <string.h>
57 #include <errno.h>
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
61 #include <signal.h>
62 #include <sys/stat.h>
63 #include <paths.h>
64
65 #include "libpfkey.h"
66
67 #include "var.h"
68 #include "misc.h"
69 #include "vmbuf.h"
70 #include "plog.h"
71 #include "debug.h"
72
73 #include "schedule.h"
74 #include "session.h"
75 #include "grabmyaddr.h"
76 #include "evt.h"
77 #include "cfparse_proto.h"
78 #include "isakmp_var.h"
79 #include "admin_var.h"
80 #include "admin.h"
81 #include "privsep.h"
82 #include "oakley.h"
83 #include "pfkey.h"
84 #include "handler.h"
85 #include "localconf.h"
86 #include "remoteconf.h"
87 #include "backupsa.h"
88 #ifdef ENABLE_NATT
89 #include "nattraversal.h"
90 #endif
91 #include "vpn_control_var.h"
92 #include "policy.h"
93
94 extern pid_t racoon_pid;
95 static void close_session __P((void));
96 static void check_rtsock __P((void *));
97 static void initfds __P((void));
98 static void init_signal __P((void));
99 static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
100 static void check_sigreq __P((void));
101 static void check_flushsa_stub __P((void *));
102 static void check_flushsa __P((void));
103 static void auto_exit_do __P((void *));
104 static int close_sockets __P((void));
105
106 static fd_set mask0;
107 static fd_set maskdying;
108 static int nfds = 0;
109 static volatile sig_atomic_t sigreq[NSIG + 1];
110 static int dying = 0;
111 static struct sched *check_rtsock_sched = NULL;
112
113 int
114 session(void)
115 {
116 fd_set rfds;
117 struct timeval *timeout;
118 int error;
119 struct myaddrs *p;
120 char pid_file[MAXPATHLEN];
121 FILE *fp;
122 int i, update_fds;
123
124 /* initialize schedular */
125 sched_init();
126
127 initmyaddr();
128
129 if (isakmp_init() < 0) {
130 plog(LLV_ERROR2, LOCATION, NULL,
131 "failed to initialize isakmp");
132 exit(1);
133 }
134
135 #ifdef ENABLE_ADMINPORT
136 if (admin_init() < 0) {
137 plog(LLV_ERROR2, LOCATION, NULL,
138 "failed to initialize admin port");
139 exit(1);
140 }
141 #endif
142 #ifdef ENABLE_VPNCONTROL_PORT
143 if (vpncontrol_init() < 0) {
144 plog(LLV_ERROR2, LOCATION, NULL,
145 "failed to initialize vpn control port");
146 exit(1);
147 }
148 #endif
149
150 init_signal();
151 initfds();
152
153 #ifndef __APPLE__
154 #ifdef ENABLE_NATT
155 natt_keepalive_init ();
156 #endif
157 #endif
158
159 if (privsep_init() != 0) {
160 plog(LLV_ERROR2, LOCATION, NULL,
161 "failed to initialize privsep");
162 exit(1);
163 }
164
165 for (i = 0; i <= NSIG; i++)
166 sigreq[i] = 0;
167
168 /* write .pid file */
169 if (!f_foreground) {
170 racoon_pid = getpid();
171 if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
172 strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
173 else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
174 strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
175 else {
176 strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
177 strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
178 }
179 fp = fopen(pid_file, "w");
180 if (fp) {
181 if (fchmod(fileno(fp),
182 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
183 syslog(LOG_ERR, "%s", strerror(errno));
184 fclose(fp);
185 exit(1);
186 }
187 fprintf(fp, "%ld\n", (long)racoon_pid);
188 fclose(fp);
189 } else {
190 plog(LLV_ERROR, LOCATION, NULL,
191 "cannot open %s", pid_file);
192 }
193 }
194
195 while (1) {
196 update_fds = 0;
197 /*
198 * asynchronous requests via signal.
199 * make sure to reset sigreq to 0.
200 */
201 check_sigreq();
202
203 /* scheduling */
204 timeout = schedular();
205
206 if (dying)
207 rfds = maskdying;
208 else
209 rfds = mask0;
210 error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
211 if (error < 0) {
212 switch (errno) {
213 case EINTR:
214 continue;
215 default:
216 plog(LLV_ERROR2, LOCATION, NULL,
217 "failed select (%s)\n",
218 strerror(errno));
219 exit(1);
220 }
221 /*NOTREACHED*/
222 }
223
224 #ifdef ENABLE_ADMINPORT
225 if ((lcconf->sock_admin != -1) &&
226 (FD_ISSET(lcconf->sock_admin, &rfds)))
227 admin_handler();
228 #endif
229 #ifdef ENABLE_VPNCONTROL_PORT
230 {
231 struct vpnctl_socket_elem *elem;
232 struct vpnctl_socket_elem *t_elem;
233
234 if ((lcconf->sock_vpncontrol != -1) &&
235 (FD_ISSET(lcconf->sock_vpncontrol, &rfds))) {
236 vpncontrol_handler();
237 update_fds = 1; // in case new socket created - update mask
238 }
239 /* The handler may close and remove the list element
240 * so we can't rely on it being valid after calling
241 * the handler.
242 */
243 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem) {
244 if ((elem->sock != -1) &&
245 (FD_ISSET(elem->sock, &rfds)))
246 if (vpncontrol_comm_handler(elem))
247 update_fds = 1; // socket closed by peer - update mask
248 }
249 }
250 #endif
251
252 for (p = lcconf->myaddrs; p; p = p->next) {
253 if (!p->addr)
254 continue;
255 if (FD_ISSET(p->sock, &rfds))
256 if ((error = isakmp_handler(p->sock)) == -2)
257 break;
258 }
259 if (error == -2) {
260 if (lcconf->autograbaddr) {
261 /* serious socket problem - close all listening sockets and re-open */
262 isakmp_close();
263 initfds();
264 sched_new(5, check_rtsock, NULL);
265 continue;
266 } else {
267 isakmp_close_sockets();
268 isakmp_open();
269 initfds();
270 continue;
271 }
272 }
273
274 if (FD_ISSET(lcconf->sock_pfkey, &rfds))
275 pfkey_handler();
276
277 if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds)) {
278 if (update_myaddrs() && lcconf->autograbaddr)
279 if (check_rtsock_sched == NULL) /* only schedule if not already done */
280 check_rtsock_sched = sched_new(5, check_rtsock, NULL);
281 // initfds(); //%%% BUG FIX - not needed here
282 }
283 if (update_fds) {
284 initfds();
285 update_fds = 0;
286 }
287 }
288 }
289
290
291 /* clear all status and exit program. */
292 static void
293 close_session()
294 {
295 flushph1();
296 close_sockets();
297 backupsa_clean();
298
299 plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
300 exit(0);
301 }
302
303 static void
304 check_rtsock(p)
305 void *p;
306 {
307
308 check_rtsock_sched = NULL;
309 grab_myaddrs();
310 isakmp_close_unused();
311
312 autoconf_myaddrsport();
313 isakmp_open();
314
315 /* initialize socket list again */
316 initfds();
317 }
318
319 static void
320 initfds()
321 {
322 struct myaddrs *p;
323
324 nfds = 0;
325
326 FD_ZERO(&mask0);
327 FD_ZERO(&maskdying);
328
329 #ifdef ENABLE_ADMINPORT
330 if (lcconf->sock_admin != -1) {
331 if (lcconf->sock_admin >= FD_SETSIZE) {
332 plog(LLV_ERROR2, LOCATION, NULL, "fd_set overrun - admin socket\n");
333 exit(1);
334 }
335 FD_SET(lcconf->sock_admin, &mask0);
336 /* XXX should we listen on admin socket when dying ?
337 */
338 #if 0
339 FD_SET(lcconf->sock_admin, &maskdying);
340 #endif
341 nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
342 }
343 #endif
344 #ifdef ENABLE_VPNCONTROL_PORT
345 {
346 struct vpnctl_socket_elem *elem;
347
348 if (lcconf->sock_vpncontrol != -1) {
349 if (lcconf->sock_vpncontrol >= FD_SETSIZE) {
350 plog(LLV_ERROR2, LOCATION, NULL, "fd_set overrun - vpncontrol socket\n");
351 exit(1);
352 }
353 FD_SET(lcconf->sock_vpncontrol, &mask0);
354 nfds = (nfds > lcconf->sock_vpncontrol ? nfds : lcconf->sock_vpncontrol);
355 }
356
357 LIST_FOREACH(elem, &lcconf->vpnctl_comm_socks, chain) {
358 if (elem->sock != -1) {
359 if (elem->sock >= FD_SETSIZE) {
360 plog(LLV_ERROR2, LOCATION, NULL, "fd_set overrun vpnctl_comm socket\n");
361 exit(1);
362 }
363 FD_SET(elem->sock, &mask0);
364 nfds = (nfds > elem->sock ? nfds : elem->sock);
365 }
366 }
367 }
368
369 #endif
370
371 if (lcconf->sock_pfkey >= FD_SETSIZE) {
372 plog(LLV_ERROR2, LOCATION, NULL, "fd_set overrun - pfkey socket\n");
373 exit(1);
374 }
375 FD_SET(lcconf->sock_pfkey, &mask0);
376 FD_SET(lcconf->sock_pfkey, &maskdying);
377 nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
378 if (lcconf->rtsock >= 0) {
379 if (lcconf->rtsock >= FD_SETSIZE) {
380 plog(LLV_ERROR2, LOCATION, NULL, "fd_set overrun - rt socket\n");
381 exit(1);
382 }
383 FD_SET(lcconf->rtsock, &mask0);
384 nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
385 }
386
387 for (p = lcconf->myaddrs; p; p = p->next) {
388 if (!p->addr)
389 continue;
390 if (p->sock < 0)
391 continue;
392 if (p->sock >= FD_SETSIZE) {
393 plog(LLV_ERROR2, LOCATION, NULL, "fd_set overrun - isakmp socket\n");
394 exit(1);
395 }
396 FD_SET(p->sock, &mask0);
397 nfds = (nfds > p->sock ? nfds : p->sock);
398 }
399 nfds++;
400 }
401
402 static int signals[] = {
403 SIGHUP,
404 SIGINT,
405 SIGTERM,
406 SIGUSR1,
407 SIGUSR2,
408 SIGCHLD,
409 SIGPIPE,
410 0
411 };
412
413 /*
414 * asynchronous requests will actually dispatched in the
415 * main loop in session().
416 */
417 RETSIGTYPE
418 signal_handler(sig)
419 int sig;
420 {
421 /* Do not just set it to 1, because we may miss some signals by just setting
422 * values to 0/1
423 */
424 sigreq[sig]++;
425 }
426
427 static void
428 check_sigreq()
429 {
430 int sig;
431
432 /*
433 * XXX We are not able to tell if we got
434 * several time the same signal. This is
435 * not a problem for the current code,
436 * but we shall remember this limitation.
437 */
438 for (sig = 0; sig <= NSIG; sig++) {
439 if (sigreq[sig] == 0)
440 continue;
441
442 sigreq[sig]--;
443 switch(sig) {
444 case 0:
445 return;
446
447 /* Catch up childs, mainly scripts.
448 */
449 case SIGCHLD:
450 {
451 pid_t pid;
452 int s;
453
454 pid = wait(&s);
455 }
456 break;
457
458 #ifdef DEBUG_RECORD_MALLOCATION
459 /*
460 * XXX This operation is signal handler unsafe and may lead to
461 * crashes and security breaches: See Henning Brauer talk at
462 * EuroBSDCon 2005. Do not run in production with this option
463 * enabled.
464 */
465 case SIGUSR2:
466 DRM_dump();
467 break;
468 #endif
469
470 case SIGHUP:
471 /* Save old configuration, load new one... */
472 isakmp_close();
473 close(lcconf->rtsock);
474 if (cfreparse()) {
475 plog(LLV_ERROR2, LOCATION, NULL,
476 "configuration read failed\n");
477 exit(1);
478 }
479 if (lcconf->logfile_param == NULL)
480 plogreset(lcconf->pathinfo[LC_PATHTYPE_LOGFILE]);
481
482 initmyaddr();
483 isakmp_cleanup();
484 isakmp_init();
485 initfds();
486 break;
487
488 case SIGINT:
489 case SIGTERM:
490 plog(LLV_INFO, LOCATION, NULL,
491 "caught signal %d\n", sig);
492 EVT_PUSH(NULL, NULL, EVTT_RACOON_QUIT, NULL);
493 pfkey_send_flush(lcconf->sock_pfkey,
494 SADB_SATYPE_UNSPEC);
495 sched_new(1, check_flushsa_stub, NULL);
496 dying = 1;
497 break;
498
499 default:
500 plog(LLV_INFO, LOCATION, NULL,
501 "caught signal %d\n", sig);
502 break;
503 }
504 }
505 }
506
507 /*
508 * waiting the termination of processing until sending DELETE message
509 * for all inbound SA will complete.
510 */
511 static void
512 check_flushsa_stub(p)
513 void *p;
514 {
515
516 check_flushsa();
517 }
518
519 static void
520 check_flushsa()
521 {
522 vchar_t *buf;
523 struct sadb_msg *msg, *end, *next;
524 struct sadb_sa *sa;
525 caddr_t mhp[SADB_EXT_MAX + 1];
526 int n;
527
528 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
529 if (buf == NULL) {
530 plog(LLV_DEBUG, LOCATION, NULL,
531 "pfkey_dump_sadb: returned nothing.\n");
532 return;
533 }
534
535 msg = (struct sadb_msg *)buf->v;
536 end = (struct sadb_msg *)(buf->v + buf->l);
537
538 /* counting SA except of dead one. */
539 n = 0;
540 while (msg < end) {
541 if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
542 break;
543 next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
544 if (msg->sadb_msg_type != SADB_DUMP) {
545 msg = next;
546 continue;
547 }
548
549 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
550 plog(LLV_ERROR, LOCATION, NULL,
551 "pfkey_check (%s)\n", ipsec_strerror());
552 msg = next;
553 continue;
554 }
555
556 sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
557 if (!sa) {
558 msg = next;
559 continue;
560 }
561
562 if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
563 n++;
564 msg = next;
565 continue;
566 }
567
568 msg = next;
569 }
570
571 if (buf != NULL)
572 vfree(buf);
573
574 if (n) {
575 sched_new(1, check_flushsa_stub, NULL);
576 return;
577 }
578
579 close_session();
580 }
581
582 void
583 auto_exit_do(void *p)
584 {
585 EVT_PUSH(NULL, NULL, EVTT_RACOON_QUIT, NULL);
586 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
587 sched_new(1, check_flushsa_stub, NULL);
588 dying = 1;
589 }
590
591 void
592 check_auto_exit(void)
593 {
594
595 if (lcconf->auto_exit_sched != NULL) { /* exit scheduled? */
596 if (lcconf->auto_exit_state != LC_AUTOEXITSTATE_ENABLED
597 || vpn_control_connected() /* vpn control connected */
598 || policies_installed()) /* policies installed in kernel */
599 SCHED_KILL(lcconf->auto_exit_sched);
600 } else { /* exit not scheduled */
601 if (lcconf->auto_exit_state == LC_AUTOEXITSTATE_ENABLED
602 && !vpn_control_connected()
603 && !policies_installed())
604 if (lcconf->auto_exit_delay == 0)
605 auto_exit_do(NULL); /* immediate exit */
606 else
607 lcconf->auto_exit_sched = sched_new(lcconf->auto_exit_delay, auto_exit_do, NULL);
608 }
609 }
610
611
612 static void
613 init_signal()
614 {
615 int i;
616
617 for (i = 0; signals[i] != 0; i++)
618 if (set_signal(signals[i], signal_handler) < 0) {
619 plog(LLV_ERROR2, LOCATION, NULL,
620 "failed to set_signal (%s)\n",
621 strerror(errno));
622 exit(1);
623 }
624 }
625
626 static int
627 set_signal(sig, func)
628 int sig;
629 RETSIGTYPE (*func) __P((int));
630 {
631 struct sigaction sa;
632
633 memset((caddr_t)&sa, 0, sizeof(sa));
634 sa.sa_handler = func;
635 sa.sa_flags = SA_RESTART;
636
637 if (sigemptyset(&sa.sa_mask) < 0)
638 return -1;
639
640 if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
641 return(-1);
642
643 return 0;
644 }
645
646 static int
647 close_sockets()
648 {
649 isakmp_close();
650 pfkey_close(lcconf->sock_pfkey);
651 #ifdef ENABLE_ADMINPORT
652 (void)admin_close();
653 #endif
654 #ifdef ENABLE_VPNCONTROL_PORT
655 vpncontrol_close();
656 #endif
657 return 0;
658 }
659