1 /* $NetBSD: session.c,v 1.7.6.2 2007/08/01 11:52:22 vanhu Exp $ */
3 /* $KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $ */
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/types.h>
37 #include <sys/param.h>
39 #include <sys/socket.h>
41 # include <sys/wait.h>
44 # define WEXITSTATUS(s) ((unsigned)(s) >> 8)
47 # define WIFEXITED(s) (((s) & 255) == 0)
50 #ifndef HAVE_NETINET6_IPSEC
51 #include <netinet/ipsec.h>
53 #include <netinet6/ipsec.h>
67 #include <netinet/in.h>
68 #include <netinet/ip.h>
69 #include <netinet/ip_icmp.h>
72 #include <TargetConditionals.h>
73 #include <vproc_priv.h>
85 #include "grabmyaddr.h"
87 #include "cfparse_proto.h"
88 #include "isakmp_var.h"
89 #include "isakmp_xauth.h"
90 #include "isakmp_cfg.h"
91 #include "admin_var.h"
97 #include "localconf.h"
98 #include "remoteconf.h"
101 #include "nattraversal.h"
103 #include "vpn_control_var.h"
105 #include "algorithm.h" /* XXX ??? */
108 #include "power_mgmt.h"
112 extern pid_t racoon_pid
;
113 extern char logFileStr
[];
114 extern int launchedbylaunchd(void);
115 static void close_session
__P((void));
116 static void check_rtsock
__P((void *));
117 static void initfds
__P((void));
118 static void init_signal
__P((void));
119 static int set_signal
__P((int sig
, RETSIGTYPE (*func
) __P((int, siginfo_t
*, void *))));
120 static void check_sigreq
__P((void));
121 static void check_flushsa_stub
__P((void *));
122 static void check_flushsa
__P((void));
123 static void auto_exit_do
__P((void *));
124 static int close_sockets
__P((void));
127 static fd_set maskdying
;
129 static volatile sig_atomic_t sigreq
[NSIG
+ 1];
130 static int dying
= 0;
131 static struct sched
*check_rtsock_sched
= NULL
;
134 #define HANDLE_TENTATIVE_INTF_FAILURES() do { \
135 if (tentative_failures) { \
136 plog(LLV_ERROR, LOCATION, NULL, \
137 "detected tentative interface/address issues: will retry later.\n"); \
138 if (check_rtsock_sched == NULL) { \
139 /* only schedule if not already done */ \
140 check_rtsock_sched = sched_new(5, check_rtsock, NULL); \
148 int tentative_failures
;
151 close(lcconf
->rtsock
);
153 if (isakmp_open(&tentative_failures
) < 0) {
154 plog(LLV_ERROR2
, LOCATION
, NULL
,
155 "failed to reopen isakmp sockets\n");
158 HANDLE_TENTATIVE_INTF_FAILURES();
161 static int64_t racoon_keepalive
= -1;
164 * This is used to (manually) update racoon's launchd keepalive, which is needed because racoon is (mostly)
165 * launched on demand and for <rdar://problem/8768510> requires a keepalive on dirty/failure exits.
166 * The launchd plist can't be used for this because RunOnLoad is required to have keepalive on a failure exit.
169 launchd_update_racoon_keepalive (Boolean enabled
)
171 if (launchedbylaunchd()) {
172 vproc_t vp
= vprocmgr_lookup_vproc("com.apple.racoon");
174 int64_t val
= (__typeof__(val
))enabled
;
175 if (vproc_swap_integer(vp
,
176 VPROC_GSK_BASIC_KEEPALIVE
,
178 &racoon_keepalive
)) {
179 plog(LLV_ERROR2
, LOCATION
, NULL
,
180 "failed to swap launchd keepalive integer %d\n", enabled
);
185 return racoon_keepalive
;
192 struct timeval
*timeout
;
195 char pid_file
[MAXPATHLEN
];
198 int tentative_failures
;
200 /* initialize schedular */
203 /* needs to be called after schedular */
204 if (init_power_mgmt() < 0) {
205 errx(1, "failed to initialize power-mgmt.");
210 if (isakmp_init(false, &tentative_failures
) < 0) {
211 plog(LLV_ERROR2
, LOCATION
, NULL
,
212 "failed to initialize isakmp");
215 HANDLE_TENTATIVE_INTF_FAILURES();
217 #ifdef ENABLE_ADMINPORT
218 if (admin_init() < 0) {
219 plog(LLV_ERROR2
, LOCATION
, NULL
,
220 "failed to initialize admin port");
224 #ifdef ENABLE_VPNCONTROL_PORT
225 if (vpncontrol_init() < 0) {
226 plog(LLV_ERROR2
, LOCATION
, NULL
,
227 "failed to initialize vpn control port");
237 if (privsep_init() != 0) {
238 plog(LLV_ERROR2
, LOCATION
, NULL
,
239 "failed to initialize privsep");
244 for (i
= 0; i
<= NSIG
; i
++)
247 /* write .pid file */
249 racoon_pid
= getpid();
250 if (lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
] == NULL
)
251 strlcpy(pid_file
, _PATH_VARRUN
"racoon.pid", sizeof(pid_file
));
252 else if (lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
][0] == '/')
253 strlcpy(pid_file
, lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
], sizeof(pid_file
));
255 strlcat(pid_file
, _PATH_VARRUN
, sizeof(pid_file
));
256 strlcat(pid_file
, lcconf
->pathinfo
[LC_PATHTYPE_PIDFILE
], sizeof(pid_file
));
258 fp
= fopen(pid_file
, "w");
260 if (fchmod(fileno(fp
),
261 S_IRUSR
| S_IWUSR
| S_IRGRP
| S_IROTH
) == -1) {
262 syslog(LOG_ERR
, "%s", strerror(errno
));
266 fprintf(fp
, "%ld\n", (long)racoon_pid
);
269 plog(LLV_ERROR
, LOCATION
, NULL
,
270 "cannot open %s", pid_file
);
274 #if !TARGET_OS_EMBEDDED
275 // enable keepalive for recovery (from crashes and bad exits... after init)
276 (void)launchd_update_racoon_keepalive(true);
277 #endif // !TARGET_OS_EMBEDDED
280 if (!TAILQ_EMPTY(&lcconf
->saved_msg_queue
))
281 pfkey_post_handler();
284 * asynchronous requests via signal.
285 * make sure to reset sigreq to 0.
292 timeout
= schedular();
293 // <rdar://problem/7650111> Workaround: make sure timeout is playing nice
295 if (timeout
->tv_usec
< 0 || timeout
->tv_usec
> SELECT_USEC_MAX
) {
296 timeout
->tv_sec
+= ((__typeof__(timeout
->tv_sec
))timeout
->tv_usec
)/SELECT_USEC_MAX
;
297 timeout
->tv_usec
%= SELECT_USEC_MAX
;
299 if (timeout
->tv_sec
> SELECT_SEC_MAX
/* tv_sec is unsigned */) {
300 timeout
->tv_sec
= SELECT_SEC_MAX
;
302 if (!timeout
->tv_sec
&& !timeout
->tv_usec
) {
311 error
= select(nfds
, &rfds
, (fd_set
*)0, (fd_set
*)0, timeout
);
317 plog(LLV_ERROR2
, LOCATION
, NULL
,
318 "failed select (%s) nfds %d\n",
319 strerror(errno
), nfds
);
327 #ifdef ENABLE_ADMINPORT
328 if ((lcconf
->sock_admin
!= -1) &&
329 (FD_ISSET(lcconf
->sock_admin
, &rfds
)))
332 #ifdef ENABLE_VPNCONTROL_PORT
334 struct vpnctl_socket_elem
*elem
;
335 struct vpnctl_socket_elem
*t_elem
;
337 if ((lcconf
->sock_vpncontrol
!= -1) &&
338 (FD_ISSET(lcconf
->sock_vpncontrol
, &rfds
))) {
339 vpncontrol_handler();
340 update_fds
= 1; // in case new socket created - update mask
342 /* The handler may close and remove the list element
343 * so we can't rely on it being valid after calling
346 LIST_FOREACH_SAFE(elem
, &lcconf
->vpnctl_comm_socks
, chain
, t_elem
) {
347 if ((elem
->sock
!= -1) &&
348 (FD_ISSET(elem
->sock
, &rfds
)))
349 if (vpncontrol_comm_handler(elem
))
350 update_fds
= 1; // socket closed by peer - update mask
355 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
358 if ((p
->sock
!= -1) &&
359 (FD_ISSET(p
->sock
, &rfds
)))
360 if ((error
= isakmp_handler(p
->sock
)) == -2)
364 plog(LLV_ERROR2
, LOCATION
, NULL
,
365 "failed to process isakmp port\n");
371 if (FD_ISSET(lcconf
->sock_pfkey
, &rfds
))
374 if (lcconf
->rtsock
>= 0 && FD_ISSET(lcconf
->rtsock
, &rfds
)) {
375 if (update_myaddrs() && lcconf
->autograbaddr
)
376 if (check_rtsock_sched
== NULL
) /* only schedule if not already done */
377 check_rtsock_sched
= sched_new(1, check_rtsock
, NULL
);
379 // force reinit if schedule is too far off (3 seconds or more)
380 time_t too_far
= current_time() + 3;
381 if (check_rtsock_sched
->dead
||
382 check_rtsock_sched
->xtime
>= too_far
) {
383 plog(LLV_DEBUG
, LOCATION
, NULL
,
384 "forced reinit of addrs\n");
389 // initfds(); //%%% BUG FIX - not needed here
399 /* clear all status and exit program. */
409 #if !TARGET_OS_EMBEDDED
410 // a clean exit, so disable launchd keepalive
411 (void)launchd_update_racoon_keepalive(false);
412 #endif // !TARGET_OS_EMBEDDED
414 plog(LLV_INFO
, LOCATION
, NULL
, "racoon shutdown\n");
422 int tentative_failures
;
424 check_rtsock_sched
= NULL
;
426 isakmp_close_unused();
428 autoconf_myaddrsport();
429 isakmp_open(&tentative_failures
);
431 /* initialize socket list again */
433 HANDLE_TENTATIVE_INTF_FAILURES();
446 #ifdef ENABLE_ADMINPORT
447 if (lcconf
->sock_admin
!= -1) {
448 if (lcconf
->sock_admin
>= FD_SETSIZE
) {
449 plog(LLV_ERROR2
, LOCATION
, NULL
, "fd_set overrun - admin socket\n");
452 FD_SET(lcconf
->sock_admin
, &mask0
);
453 /* XXX should we listen on admin socket when dying ?
456 FD_SET(lcconf
->sock_admin
, &maskdying
);
458 nfds
= (nfds
> lcconf
->sock_admin
? nfds
: lcconf
->sock_admin
);
461 #ifdef ENABLE_VPNCONTROL_PORT
463 struct vpnctl_socket_elem
*elem
;
465 if (lcconf
->sock_vpncontrol
!= -1) {
466 if (lcconf
->sock_vpncontrol
>= FD_SETSIZE
) {
467 plog(LLV_ERROR2
, LOCATION
, NULL
, "fd_set overrun - vpncontrol socket\n");
470 FD_SET(lcconf
->sock_vpncontrol
, &mask0
);
471 nfds
= (nfds
> lcconf
->sock_vpncontrol
? nfds
: lcconf
->sock_vpncontrol
);
474 LIST_FOREACH(elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
475 if (elem
->sock
!= -1) {
476 if (elem
->sock
>= FD_SETSIZE
) {
477 plog(LLV_ERROR2
, LOCATION
, NULL
, "fd_set overrun vpnctl_comm socket\n");
480 FD_SET(elem
->sock
, &mask0
);
481 nfds
= (nfds
> elem
->sock
? nfds
: elem
->sock
);
487 if (lcconf
->sock_pfkey
>= FD_SETSIZE
) {
488 plog(LLV_ERROR2
, LOCATION
, NULL
, "fd_set overrun - pfkey socket\n");
491 FD_SET(lcconf
->sock_pfkey
, &mask0
);
492 FD_SET(lcconf
->sock_pfkey
, &maskdying
);
493 nfds
= (nfds
> lcconf
->sock_pfkey
? nfds
: lcconf
->sock_pfkey
);
494 if (lcconf
->rtsock
>= 0) {
495 if (lcconf
->rtsock
>= FD_SETSIZE
) {
496 plog(LLV_ERROR2
, LOCATION
, NULL
, "fd_set overrun - rt socket\n");
499 FD_SET(lcconf
->rtsock
, &mask0
);
500 nfds
= (nfds
> lcconf
->rtsock
? nfds
: lcconf
->rtsock
);
503 for (p
= lcconf
->myaddrs
; p
; p
= p
->next
) {
508 if (p
->sock
>= FD_SETSIZE
) {
509 plog(LLV_ERROR2
, LOCATION
, NULL
, "fd_set overrun - isakmp socket\n");
512 FD_SET(p
->sock
, &mask0
);
513 nfds
= (nfds
> p
->sock
? nfds
: p
->sock
);
519 static int signals
[] = {
531 * asynchronous requests will actually dispatched in the
532 * main loop in session().
535 signal_handler(sig
, sigi
, ctx
)
541 plog(LLV_DEBUG
, LOCATION
, NULL
,
542 "%s received signal %d from pid %d uid %d\n\n",
543 __FUNCTION__
, sig
, sigi
->si_pid
, sigi
->si_uid
);
546 /* Do not just set it to 1, because we may miss some signals by just setting
550 if ( sig
== SIGTERM
){
559 int tentative_failures
;
562 * XXX We are not able to tell if we got
563 * several time the same signal. This is
564 * not a problem for the current code,
565 * but we shall remember this limitation.
567 for (sig
= 0; sig
<= NSIG
; sig
++) {
568 if (sigreq
[sig
] == 0)
576 /* Catch up childs, mainly scripts.
587 #ifdef DEBUG_RECORD_MALLOCATION
589 * XXX This operation is signal handler unsafe and may lead to
590 * crashes and security breaches: See Henning Brauer talk at
591 * EuroBSDCon 2005. Do not run in production with this option
602 if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM
)) != 0) {
603 plog(LLV_ERROR
, LOCATION
, NULL
,
604 "ISAKMP mode config structure reset failed, "
613 * if we got a HUP... try graceful teardown of sessions before we close and reopen sockets...
614 * so that info-deletes notifications can make it to the peer.
620 /* Save old configuration, load new one... */
622 close(lcconf
->rtsock
);
623 if (cfreparse(sig
)) {
624 plog(LLV_ERROR2
, LOCATION
, NULL
,
625 "configuration read failed\n");
628 if (lcconf
->logfile_param
== NULL
&& logFileStr
[0] == 0)
629 plogreset(lcconf
->pathinfo
[LC_PATHTYPE_LOGFILE
]);
633 isakmp_init(true, &tentative_failures
);
634 HANDLE_TENTATIVE_INTF_FAILURES();
636 #if TARGET_OS_EMBEDDED
637 if (no_remote_configs(TRUE
)) {
638 EVT_PUSH(NULL
, NULL
, EVTT_RACOON_QUIT
, NULL
);
639 pfkey_send_flush(lcconf
->sock_pfkey
, SADB_SATYPE_UNSPEC
);
640 #ifdef ENABLE_FASTQUIT
643 sched_new(1, check_flushsa_stub
, NULL
);
652 plog(LLV_INFO
, LOCATION
, NULL
,
653 "caught signal %d\n", sig
);
654 EVT_PUSH(NULL
, NULL
, EVTT_RACOON_QUIT
, NULL
);
655 pfkey_send_flush(lcconf
->sock_pfkey
,
657 if ( sig
== SIGTERM
){
658 terminated
= 1; /* in case if it hasn't been set yet */
662 sched_new(1, check_flushsa_stub
, NULL
);
668 plog(LLV_INFO
, LOCATION
, NULL
,
669 "caught signal %d\n", sig
);
676 * waiting the termination of processing until sending DELETE message
677 * for all inbound SA will complete.
680 check_flushsa_stub(p
)
691 struct sadb_msg
*msg
, *end
, *next
;
693 caddr_t mhp
[SADB_EXT_MAX
+ 1];
696 buf
= pfkey_dump_sadb(SADB_SATYPE_UNSPEC
);
698 plog(LLV_DEBUG
, LOCATION
, NULL
,
699 "pfkey_dump_sadb: returned nothing.\n");
703 msg
= (struct sadb_msg
*)buf
->v
;
704 end
= (struct sadb_msg
*)(buf
->v
+ buf
->l
);
706 /* counting SA except of dead one. */
709 if (PFKEY_UNUNIT64(msg
->sadb_msg_len
) < sizeof(*msg
))
711 next
= (struct sadb_msg
*)((caddr_t
)msg
+ PFKEY_UNUNIT64(msg
->sadb_msg_len
));
712 if (msg
->sadb_msg_type
!= SADB_DUMP
) {
717 if (pfkey_align(msg
, mhp
) || pfkey_check(mhp
)) {
718 plog(LLV_ERROR
, LOCATION
, NULL
,
719 "pfkey_check (%s)\n", ipsec_strerror());
724 sa
= (struct sadb_sa
*)(mhp
[SADB_EXT_SA
]);
730 if (sa
->sadb_sa_state
!= SADB_SASTATE_DEAD
) {
743 sched_new(1, check_flushsa_stub
, NULL
);
748 #if !TARGET_OS_EMBEDDED
750 vproc_transaction_end(NULL
, lcconf
->vt
);
755 auto_exit_do(void *p
)
757 EVT_PUSH(NULL
, NULL
, EVTT_RACOON_QUIT
, NULL
);
758 plog(LLV_DEBUG
, LOCATION
, NULL
,
759 "performing auto exit\n");
760 pfkey_send_flush(lcconf
->sock_pfkey
, SADB_SATYPE_UNSPEC
);
761 sched_new(1, check_flushsa_stub
, NULL
);
766 check_auto_exit(void)
768 if (lcconf
->auto_exit_sched
!= NULL
) { /* exit scheduled? */
769 if (lcconf
->auto_exit_state
!= LC_AUTOEXITSTATE_ENABLED
770 || vpn_control_connected() /* vpn control connected */
771 || policies_installed() /* policies installed in kernel */
772 || !no_remote_configs(FALSE
)) /* remote or anonymous configs */
773 SCHED_KILL(lcconf
->auto_exit_sched
);
774 } else { /* exit not scheduled */
775 if (lcconf
->auto_exit_state
== LC_AUTOEXITSTATE_ENABLED
776 && !vpn_control_connected()
777 && !policies_installed()
778 && no_remote_configs(FALSE
))
779 if (lcconf
->auto_exit_delay
== 0)
780 auto_exit_do(NULL
); /* immediate exit */
782 lcconf
->auto_exit_sched
= sched_new(lcconf
->auto_exit_delay
, auto_exit_do
, NULL
);
792 for (i
= 0; signals
[i
] != 0; i
++)
793 if (set_signal(signals
[i
], signal_handler
) < 0) {
794 plog(LLV_ERROR2
, LOCATION
, NULL
,
795 "failed to set_signal (%s)\n",
802 set_signal(sig
, func
)
804 RETSIGTYPE (*func
) __P((int, siginfo_t
*, void *));
808 memset((caddr_t
)&sa
, 0, sizeof(sa
));
809 sa
.sa_handler
= func
;
810 sa
.sa_flags
= SA_RESTART
| SA_SIGINFO
;
812 if (sigemptyset(&sa
.sa_mask
) < 0)
815 if (sigaction(sig
, &sa
, (struct sigaction
*)0) < 0)
825 pfkey_close(lcconf
->sock_pfkey
);
826 #ifdef ENABLE_ADMINPORT
829 #ifdef ENABLE_VPNCONTROL_PORT