Home | History | Annotate | Line # | Download | only in racoon
      1 /*	$NetBSD: session.c,v 1.36 2025/03/07 15:55:29 christos Exp $	*/
      2 
      3 /*	$KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $	*/
      4 
      5 /*
      6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     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.
     20  *
     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
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #include "config.h"
     35 
     36 #include <sys/types.h>
     37 #include <sys/param.h>
     38 #include <sys/time.h>
     39 #include <sys/socket.h>
     40 #if HAVE_SYS_WAIT_H
     41 # include <sys/wait.h>
     42 #endif
     43 #ifndef WEXITSTATUS
     44 # define WEXITSTATUS(s)	((unsigned)(s) >> 8)
     45 #endif
     46 #ifndef WIFEXITED
     47 # define WIFEXITED(s)	(((s) & 255) == 0)
     48 #endif
     49 
     50 #include PATH_IPSEC_H
     51 
     52 #include <stdlib.h>
     53 #include <stdio.h>
     54 #include <string.h>
     55 #include <errno.h>
     56 #ifdef HAVE_UNISTD_H
     57 #include <unistd.h>
     58 #endif
     59 #include <signal.h>
     60 #include <sys/stat.h>
     61 #include <paths.h>
     62 #include <err.h>
     63 
     64 #include <netinet/in.h>
     65 #include <resolv.h>
     66 
     67 #include "libpfkey.h"
     68 
     69 #include "var.h"
     70 #include "misc.h"
     71 #include "vmbuf.h"
     72 #include "plog.h"
     73 #include "debug.h"
     74 
     75 #include "schedule.h"
     76 #include "session.h"
     77 #include "grabmyaddr.h"
     78 #include "evt.h"
     79 #include "cfparse_proto.h"
     80 #include "isakmp_var.h"
     81 #include "isakmp.h"
     82 #include "isakmp_var.h"
     83 #include "isakmp_xauth.h"
     84 #include "isakmp_cfg.h"
     85 #include "admin_var.h"
     86 #include "admin.h"
     87 #include "privsep.h"
     88 #include "oakley.h"
     89 #include "pfkey.h"
     90 #include "handler.h"
     91 #include "localconf.h"
     92 #include "remoteconf.h"
     93 #include "backupsa.h"
     94 #include "remoteconf.h"
     95 #ifdef ENABLE_NATT
     96 #include "nattraversal.h"
     97 #endif
     98 
     99 #include "algorithm.h" /* XXX ??? */
    100 
    101 #include "sainfo.h"
    102 
    103 struct fd_monitor {
    104 	int (*callback)(void *ctx, int fd);
    105 	void *ctx;
    106 	int prio;
    107 	int fd;
    108 	TAILQ_ENTRY(fd_monitor) chain;
    109 };
    110 
    111 #define NUM_PRIORITIES 2
    112 
    113 static void close_session(void);
    114 static void init_signal(void);
    115 static int set_signal(int sig, RETSIGTYPE (*func)(int));
    116 static void check_sigreq(void);
    117 static int close_sockets(void);
    118 
    119 static fd_set preset_mask, active_mask;
    120 static struct fd_monitor fd_monitors[FD_SETSIZE];
    121 static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
    122 static int nfds = 0;
    123 
    124 static volatile sig_atomic_t sigreq[NSIG + 1];
    125 
    126 void
    127 monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
    128 {
    129 	if (fd < 0 || fd >= FD_SETSIZE) {
    130 		plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
    131 		exit(1);
    132 	}
    133 
    134 	FD_SET(fd, &preset_mask);
    135 	if (fd > nfds)
    136 		nfds = fd;
    137 	if (priority <= 0)
    138 		priority = 0;
    139 	if (priority >= NUM_PRIORITIES)
    140 		priority = NUM_PRIORITIES - 1;
    141 
    142 	fd_monitors[fd].callback = callback;
    143 	fd_monitors[fd].ctx = ctx;
    144 	fd_monitors[fd].prio = priority;
    145 	fd_monitors[fd].fd = fd;
    146 	TAILQ_INSERT_TAIL(&fd_monitor_tree[priority],
    147 			  &fd_monitors[fd], chain);
    148 }
    149 
    150 void
    151 unmonitor_fd(int fd)
    152 {
    153 	if (fd < 0 || fd >= FD_SETSIZE) {
    154 		plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
    155 		exit(1);
    156 	}
    157 
    158 	if (fd_monitors[fd].callback == NULL)
    159 		return;
    160 
    161 	FD_CLR(fd, &preset_mask);
    162 	FD_CLR(fd, &active_mask);
    163 	fd_monitors[fd].callback = NULL;
    164 	fd_monitors[fd].ctx = NULL;
    165 	TAILQ_REMOVE(&fd_monitor_tree[fd_monitors[fd].prio],
    166 		     &fd_monitors[fd], chain);
    167 }
    168 
    169 int
    170 session(void)
    171 {
    172 	struct timeval *timeout;
    173 	int error;
    174 	char pid_file[MAXPATHLEN];
    175 	FILE *fp;
    176 	pid_t racoon_pid = 0;
    177 	int i, count;
    178 	struct fd_monitor *fdm;
    179 
    180 	nfds = 0;
    181 	FD_ZERO(&preset_mask);
    182 
    183 	for (i = 0; i < NUM_PRIORITIES; i++)
    184 		TAILQ_INIT(&fd_monitor_tree[i]);
    185 
    186 	/* initialize schedular */
    187 	sched_init();
    188 	init_signal();
    189 
    190 	if (pfkey_init() < 0)
    191 		errx(1, "failed to initialize pfkey socket");
    192 
    193 	if (isakmp_init() < 0)
    194 		errx(1, "failed to initialize ISAKMP structures");
    195 
    196 #ifdef ENABLE_HYBRID
    197 	if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
    198 		errx(1, "could not initialize ISAKMP mode config structures");
    199 #endif
    200 
    201 #ifdef HAVE_LIBLDAP
    202 	if (xauth_ldap_init_conf() != 0)
    203 		errx(1, "could not initialize ldap config");
    204 #endif
    205 
    206 #ifdef HAVE_LIBRADIUS
    207 	if (xauth_radius_init_conf(0) != 0)
    208 		errx(1, "could not initialize radius config");
    209 #endif
    210 
    211 	myaddr_init_lists();
    212 
    213 	/*
    214 	 * in order to prefer the parameters by command line,
    215 	 * saving some parameters before parsing configuration file.
    216 	 */
    217 	save_params();
    218 	if (cfparse() != 0)
    219 		errx(1, "failed to parse configuration file.");
    220 	restore_params();
    221 
    222 #ifdef ENABLE_ADMINPORT
    223 	if (admin_init() < 0)
    224 		errx(1, "failed to initialize admin port socket");
    225 #endif
    226 
    227 
    228 #ifdef ENABLE_HYBRID
    229 	if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
    230 		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
    231 			return error;
    232 #endif
    233 
    234 	if (dump_config)
    235 		dumprmconf();
    236 
    237 #ifdef HAVE_LIBRADIUS
    238 	if (xauth_radius_init() != 0)
    239 		errx(1, "could not initialize libradius");
    240 #endif
    241 
    242 	if (myaddr_init() != 0)
    243 		errx(1, "failed to listen to configured addresses");
    244 	myaddr_sync();
    245 
    246 #ifdef ENABLE_NATT
    247 	natt_keepalive_init ();
    248 #endif
    249 
    250 	/* write .pid file */
    251 	if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
    252 		strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
    253 	else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
    254 		strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
    255 	else {
    256 		strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
    257 		strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
    258 	}
    259 	fp = fopen(pid_file, "w");
    260 	if (fp) {
    261 		if (fchmod(fileno(fp),
    262 			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
    263 			syslog(LOG_ERR, "%s", strerror(errno));
    264 			fclose(fp);
    265 			exit(1);
    266 		}
    267 	} else {
    268 		plog(LLV_ERROR, LOCATION, NULL,
    269 			"cannot open %s", pid_file);
    270 	}
    271 
    272 	if (privsep_init() != 0)
    273 		exit(1);
    274 
    275 	/*
    276 	 * The fork()'ed privileged side will close its copy of fp.  We wait
    277 	 * until here to get the correct child pid.
    278 	 */
    279 	racoon_pid = getpid();
    280 	fprintf(fp, "%ld\n", (long)racoon_pid);
    281 	fclose(fp);
    282 
    283 	for (i = 0; i <= NSIG; i++)
    284 		sigreq[i] = 0;
    285 
    286 	for (;;) {
    287 		/*
    288 		 * asynchronous requests via signal.
    289 		 * make sure to reset sigreq to 0.
    290 		 */
    291 		check_sigreq();
    292 
    293 		/* scheduling */
    294 		timeout = schedular();
    295 
    296 		/* schedular can change select() mask, so we reset
    297 		 * the working copy here */
    298 		active_mask = preset_mask;
    299 
    300 		error = select(nfds + 1, &active_mask, NULL, NULL, timeout);
    301 		if (error < 0) {
    302 			switch (errno) {
    303 			case EINTR:
    304 				continue;
    305 			default:
    306 				plog(LLV_ERROR, LOCATION, NULL,
    307 					"failed to select (%s)\n",
    308 					strerror(errno));
    309 				return -1;
    310 			}
    311 			/*NOTREACHED*/
    312 		}
    313 
    314 		count = 0;
    315 		for (i = 0; i < NUM_PRIORITIES; i++) {
    316 			TAILQ_FOREACH(fdm, &fd_monitor_tree[i], chain) {
    317 				if (!FD_ISSET(fdm->fd, &active_mask))
    318 					continue;
    319 
    320 				FD_CLR(fdm->fd, &active_mask);
    321 				if (fdm->callback != NULL) {
    322 					fdm->callback(fdm->ctx, fdm->fd);
    323 					count++;
    324 				} else
    325 					plog(LLV_ERROR, LOCATION, NULL,
    326 					"fd %d set, but no active callback\n", i);
    327 			}
    328 			if (count != 0)
    329 				break;
    330 		}
    331 
    332 	}
    333 }
    334 
    335 /* clear all status and exit program. */
    336 static void
    337 close_session()
    338 {
    339 	evt_generic(EVT_RACOON_QUIT, NULL);
    340 	pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
    341 	flushph2();
    342 	flushph1();
    343 	flushrmconf();
    344 	flushsainfo();
    345 	close_sockets();
    346 	backupsa_clean();
    347 
    348 	plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid());
    349 
    350 	exit(0);
    351 }
    352 
    353 static int signals[] = {
    354 	SIGHUP,
    355 	SIGINT,
    356 	SIGTERM,
    357 	SIGUSR1,
    358 	SIGUSR2,
    359 	SIGCHLD,
    360 	0
    361 };
    362 
    363 /*
    364  * asynchronous requests will actually dispatched in the
    365  * main loop in session().
    366  */
    367 RETSIGTYPE
    368 signal_handler(int sig)
    369 {
    370 	sigreq[sig] = 1;
    371 }
    372 
    373 
    374 /* XXX possible mem leaks and no way to go back for now !!!
    375  */
    376 static void reload_conf(void)
    377 {
    378 	int error;
    379 
    380 #ifdef ENABLE_HYBRID
    381 	if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
    382 		plog(LLV_ERROR, LOCATION, NULL,
    383 		    "ISAKMP mode config structure reset failed, "
    384 		    "not reloading\n");
    385 		return;
    386 	}
    387 #endif
    388 
    389 	sainfo_start_reload();
    390 
    391 	/* TODO: save / restore / flush old lcconf (?) / rmtree
    392 	 */
    393 	rmconf_start_reload();
    394 
    395 #ifdef HAVE_LIBRADIUS
    396 	/* free and init radius configuration */
    397 	xauth_radius_init_conf(1);
    398 #endif
    399 
    400 	pfkey_reload();
    401 
    402 	save_params();
    403 	flushlcconf();
    404 	error = cfparse();
    405 	if (error != 0){
    406 		plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
    407 		/* We are probably in an inconsistant state... */
    408 		return;
    409 	}
    410 	restore_params();
    411 
    412 #if 0
    413 	if (dump_config)
    414 		dumprmconf ();
    415 #endif
    416 
    417 	myaddr_sync();
    418 
    419 #ifdef HAVE_LIBRADIUS
    420 	/* re-initialize radius state */
    421 	xauth_radius_init();
    422 #endif
    423 
    424 	/* Revalidate ph1 / ph2tree !!!
    425 	 * update ctdtree if removing some ph1 !
    426 	 */
    427 	revalidate_ph12();
    428 	/* Update ctdtree ?
    429 	 */
    430 
    431 	sainfo_finish_reload();
    432 	rmconf_finish_reload();
    433 }
    434 
    435 static void
    436 check_sigreq()
    437 {
    438 	int sig, s;
    439 
    440 	for (sig = 0; sig <= NSIG; sig++) {
    441 		if (sigreq[sig] == 0)
    442 			continue;
    443 		sigreq[sig] = 0;
    444 
    445 		switch(sig) {
    446 		case 0:
    447 			return;
    448 
    449 		case SIGCHLD:
    450 			/* Reap all pending children */
    451 			while (waitpid(-1, &s, WNOHANG) > 0)
    452 				;
    453 			break;
    454 
    455 #ifdef DEBUG_RECORD_MALLOCATION
    456 		/*
    457 		 * XXX This operation is signal handler unsafe and may lead to
    458 		 * crashes and security breaches: See Henning Brauer talk at
    459 		 * EuroBSDCon 2005. Do not run in production with this option
    460 		 * enabled.
    461 		 */
    462 		case SIGUSR2:
    463 			DRM_dump();
    464 			break;
    465 #endif
    466 
    467 		case SIGHUP:
    468 			/* Save old configuration, load new one...  */
    469 			reload_conf();
    470 			break;
    471 
    472 		case SIGINT:
    473 		case SIGTERM:
    474 			plog(LLV_INFO, LOCATION, NULL,
    475 			    "caught signal %d\n", sig);
    476 			close_session();
    477 			break;
    478 
    479 		default:
    480 			plog(LLV_INFO, LOCATION, NULL,
    481 			    "caught signal %d\n", sig);
    482 			break;
    483 		}
    484 	}
    485 }
    486 
    487 static void
    488 init_signal()
    489 {
    490 	int i;
    491 
    492 	/*
    493 	 * Ignore SIGPIPE as we check the return value of system calls
    494 	 * that write to pipe-like fds.
    495 	 */
    496 	signal(SIGPIPE, SIG_IGN);
    497 
    498 	for (i = 0; signals[i] != 0; i++)
    499 		if (set_signal(signals[i], signal_handler) < 0) {
    500 			plog(LLV_ERROR, LOCATION, NULL,
    501 				"failed to set_signal (%s)\n",
    502 				strerror(errno));
    503 			exit(1);
    504 		}
    505 }
    506 
    507 static int
    508 set_signal(int sig, RETSIGTYPE (*func)(int))
    509 {
    510 	struct sigaction sa;
    511 
    512 	memset((caddr_t)&sa, 0, sizeof(sa));
    513 	sa.sa_handler = func;
    514 	sa.sa_flags = SA_RESTART;
    515 
    516 	if (sigemptyset(&sa.sa_mask) < 0)
    517 		return -1;
    518 
    519 	if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
    520 		return(-1);
    521 
    522 	return 0;
    523 }
    524 
    525 static int
    526 close_sockets(void)
    527 {
    528 	myaddr_close();
    529 	pfkey_close(lcconf->sock_pfkey);
    530 #ifdef ENABLE_ADMINPORT
    531 	(void)admin_close();
    532 #endif
    533 	return 0;
    534 }
    535 
    536