File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon / session.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 22:39:10 2012 UTC (12 years, 5 months ago) by misho
Branches: ipsec-tools, MAIN
CVS tags: v0_8_2p2, v0_8_1p0, v0_8_1, v0_8_0p0, v0_8_0, HEAD
ipsec-tools

    1: /*	$NetBSD: session.c,v 1.32 2011/03/02 15:09:16 vanhu 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 __P((void));
  114: static void initfds __P((void));
  115: static void init_signal __P((void));
  116: static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
  117: static void check_sigreq __P((void));
  118: static void check_flushsa __P((void));
  119: static int close_sockets __P((void));
  120: 
  121: static fd_set preset_mask, active_mask;
  122: static struct fd_monitor fd_monitors[FD_SETSIZE];
  123: static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
  124: static int nfds = 0;
  125: 
  126: static volatile sig_atomic_t sigreq[NSIG + 1];
  127: static struct sched scflushsa = SCHED_INITIALIZER();
  128: 
  129: void
  130: monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
  131: {
  132: 	if (fd < 0 || fd >= FD_SETSIZE) {
  133: 		plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
  134: 		exit(1);
  135: 	}
  136: 
  137: 	FD_SET(fd, &preset_mask);
  138: 	if (fd > nfds)
  139: 		nfds = fd;
  140: 	if (priority <= 0)
  141: 		priority = 0;
  142: 	if (priority >= NUM_PRIORITIES)
  143: 		priority = NUM_PRIORITIES - 1;
  144: 
  145: 	fd_monitors[fd].callback = callback;
  146: 	fd_monitors[fd].ctx = ctx;
  147: 	fd_monitors[fd].prio = priority;
  148: 	fd_monitors[fd].fd = fd;
  149: 	TAILQ_INSERT_TAIL(&fd_monitor_tree[priority],
  150: 			  &fd_monitors[fd], chain);
  151: }
  152: 
  153: void
  154: unmonitor_fd(int fd)
  155: {
  156: 	if (fd < 0 || fd >= FD_SETSIZE) {
  157: 		plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
  158: 		exit(1);
  159: 	}
  160: 
  161: 	if (fd_monitors[fd].callback == NULL)
  162: 		return;
  163: 
  164: 	FD_CLR(fd, &preset_mask);
  165: 	FD_CLR(fd, &active_mask);
  166: 	fd_monitors[fd].callback = NULL;
  167: 	fd_monitors[fd].ctx = NULL;
  168: 	TAILQ_REMOVE(&fd_monitor_tree[fd_monitors[fd].prio],
  169: 		     &fd_monitors[fd], chain);
  170: }
  171: 
  172: int
  173: session(void)
  174: {
  175: 	struct timeval *timeout;
  176: 	int error;
  177: 	char pid_file[MAXPATHLEN];
  178: 	FILE *fp;
  179: 	pid_t racoon_pid = 0;
  180: 	int i, count;
  181: 	struct fd_monitor *fdm;
  182: 
  183: 	nfds = 0;
  184: 	FD_ZERO(&preset_mask);
  185: 
  186: 	for (i = 0; i < NUM_PRIORITIES; i++)
  187: 		TAILQ_INIT(&fd_monitor_tree[i]);
  188: 
  189: 	/* initialize schedular */
  190: 	sched_init();
  191: 	init_signal();
  192: 
  193: 	if (pfkey_init() < 0)
  194: 		errx(1, "failed to initialize pfkey socket");
  195: 
  196: 	if (isakmp_init() < 0)
  197: 		errx(1, "failed to initialize ISAKMP structures");
  198: 
  199: #ifdef ENABLE_HYBRID
  200: 	if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD))
  201: 		errx(1, "could not initialize ISAKMP mode config structures");
  202: #endif
  203: 
  204: #ifdef HAVE_LIBLDAP
  205: 	if (xauth_ldap_init_conf() != 0)
  206: 		errx(1, "could not initialize ldap config");
  207: #endif
  208: 
  209: #ifdef HAVE_LIBRADIUS
  210: 	if (xauth_radius_init_conf(0) != 0)
  211: 		errx(1, "could not initialize radius config");
  212: #endif
  213: 
  214: 	myaddr_init_lists();
  215: 
  216: 	/*
  217: 	 * in order to prefer the parameters by command line,
  218: 	 * saving some parameters before parsing configuration file.
  219: 	 */
  220: 	save_params();
  221: 	if (cfparse() != 0)
  222: 		errx(1, "failed to parse configuration file.");
  223: 	restore_params();
  224: 
  225: #ifdef ENABLE_ADMINPORT
  226: 	if (admin_init() < 0)
  227: 		errx(1, "failed to initialize admin port socket");
  228: #endif
  229: 
  230: 
  231: #ifdef ENABLE_HYBRID
  232: 	if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0)
  233: 		if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0)
  234: 			return error;
  235: #endif
  236: 
  237: 	if (dump_config)
  238: 		dumprmconf();
  239: 
  240: #ifdef HAVE_LIBRADIUS
  241: 	if (xauth_radius_init() != 0)
  242: 		errx(1, "could not initialize libradius");
  243: #endif
  244: 
  245: 	if (myaddr_init() != 0)
  246: 		errx(1, "failed to listen to configured addresses");
  247: 	myaddr_sync();
  248: 
  249: #ifdef ENABLE_NATT
  250: 	natt_keepalive_init ();
  251: #endif
  252: 
  253: 	/* write .pid file */
  254: 	if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
  255: 		strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
  256: 	else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
  257: 		strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
  258: 	else {
  259: 		strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
  260: 		strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
  261: 	}
  262: 	fp = fopen(pid_file, "w");
  263: 	if (fp) {
  264: 		if (fchmod(fileno(fp),
  265: 			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
  266: 			syslog(LOG_ERR, "%s", strerror(errno));
  267: 			fclose(fp);
  268: 			exit(1);
  269: 		}
  270: 	} else {
  271: 		plog(LLV_ERROR, LOCATION, NULL,
  272: 			"cannot open %s", pid_file);
  273: 	}
  274: 
  275: 	if (privsep_init() != 0)
  276: 		exit(1);
  277: 
  278: 	/*
  279: 	 * The fork()'ed privileged side will close its copy of fp.  We wait
  280: 	 * until here to get the correct child pid.
  281: 	 */
  282: 	racoon_pid = getpid();
  283: 	fprintf(fp, "%ld\n", (long)racoon_pid);
  284: 	fclose(fp);
  285: 
  286: 	for (i = 0; i <= NSIG; i++)
  287: 		sigreq[i] = 0;
  288: 
  289: 	while (1) {
  290: 		/*
  291: 		 * asynchronous requests via signal.
  292: 		 * make sure to reset sigreq to 0.
  293: 		 */
  294: 		check_sigreq();
  295: 
  296: 		/* scheduling */
  297: 		timeout = schedular();
  298: 
  299: 		/* schedular can change select() mask, so we reset
  300: 		 * the working copy here */
  301: 		active_mask = preset_mask;
  302: 
  303: 		error = select(nfds + 1, &active_mask, NULL, NULL, timeout);
  304: 		if (error < 0) {
  305: 			switch (errno) {
  306: 			case EINTR:
  307: 				continue;
  308: 			default:
  309: 				plog(LLV_ERROR, LOCATION, NULL,
  310: 					"failed to select (%s)\n",
  311: 					strerror(errno));
  312: 				return -1;
  313: 			}
  314: 			/*NOTREACHED*/
  315: 		}
  316: 
  317: 		count = 0;
  318: 		for (i = 0; i < NUM_PRIORITIES; i++) {
  319: 			TAILQ_FOREACH(fdm, &fd_monitor_tree[i], chain) {
  320: 				if (!FD_ISSET(fdm->fd, &active_mask))
  321: 					continue;
  322: 
  323: 				FD_CLR(fdm->fd, &active_mask);
  324: 				if (fdm->callback != NULL) {
  325: 					fdm->callback(fdm->ctx, fdm->fd);
  326: 					count++;
  327: 				} else
  328: 					plog(LLV_ERROR, LOCATION, NULL,
  329: 					"fd %d set, but no active callback\n", i);
  330: 			}
  331: 			if (count != 0)
  332: 				break;
  333: 		}
  334: 
  335: 	}
  336: }
  337: 
  338: /* clear all status and exit program. */
  339: static void
  340: close_session()
  341: {
  342: 	evt_generic(EVT_RACOON_QUIT, NULL);
  343: 	pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
  344: 	flushph2();
  345: 	flushph1();
  346: 	flushrmconf();
  347: 	flushsainfo();
  348: 	close_sockets();
  349: 	backupsa_clean();
  350: 
  351: 	plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid());
  352: 
  353: 	exit(0);
  354: }
  355: 
  356: static int signals[] = {
  357: 	SIGHUP,
  358: 	SIGINT,
  359: 	SIGTERM,
  360: 	SIGUSR1,
  361: 	SIGUSR2,
  362: 	SIGCHLD,
  363: 	0
  364: };
  365: 
  366: /*
  367:  * asynchronous requests will actually dispatched in the
  368:  * main loop in session().
  369:  */
  370: RETSIGTYPE
  371: signal_handler(sig)
  372: 	int sig;
  373: {
  374: 	sigreq[sig] = 1;
  375: }
  376: 
  377: 
  378: /* XXX possible mem leaks and no way to go back for now !!!
  379:  */
  380: static void reload_conf(){
  381: 	int error;
  382: 
  383: #ifdef ENABLE_HYBRID
  384: 	if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
  385: 		plog(LLV_ERROR, LOCATION, NULL,
  386: 		    "ISAKMP mode config structure reset failed, "
  387: 		    "not reloading\n");
  388: 		return;
  389: 	}
  390: #endif
  391: 
  392: 	sainfo_start_reload();
  393: 
  394: 	/* TODO: save / restore / flush old lcconf (?) / rmtree
  395: 	 */
  396: 	rmconf_start_reload();
  397: 
  398: #ifdef HAVE_LIBRADIUS
  399: 	/* free and init radius configuration */
  400: 	xauth_radius_init_conf(1);
  401: #endif
  402: 
  403: 	pfkey_reload();
  404: 
  405: 	save_params();
  406: 	flushlcconf();
  407: 	error = cfparse();
  408: 	if (error != 0){
  409: 		plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
  410: 		/* We are probably in an inconsistant state... */
  411: 		return;
  412: 	}
  413: 	restore_params();
  414: 
  415: #if 0
  416: 	if (dump_config)
  417: 		dumprmconf ();
  418: #endif
  419: 
  420: 	myaddr_sync();
  421: 
  422: #ifdef HAVE_LIBRADIUS
  423: 	/* re-initialize radius state */
  424: 	xauth_radius_init();
  425: #endif
  426: 
  427: 	/* Revalidate ph1 / ph2tree !!!
  428: 	 * update ctdtree if removing some ph1 !
  429: 	 */
  430: 	revalidate_ph12();
  431: 	/* Update ctdtree ?
  432: 	 */
  433: 
  434: 	sainfo_finish_reload();
  435: 	rmconf_finish_reload();
  436: }
  437: 
  438: static void
  439: check_sigreq()
  440: {
  441: 	int sig, s;
  442: 
  443: 	for (sig = 0; sig <= NSIG; sig++) {
  444: 		if (sigreq[sig] == 0)
  445: 			continue;
  446: 		sigreq[sig] = 0;
  447: 
  448: 		switch(sig) {
  449: 		case 0:
  450: 			return;
  451: 
  452: 		case SIGCHLD:
  453: 			/* Reap all pending children */
  454: 			while (waitpid(-1, &s, WNOHANG) > 0)
  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: 			reload_conf();
  473: 			break;
  474: 
  475: 		case SIGINT:
  476: 		case SIGTERM:
  477: 			plog(LLV_INFO, LOCATION, NULL,
  478: 			    "caught signal %d\n", sig);
  479: 			close_session();
  480: 			break;
  481: 
  482: 		default:
  483: 			plog(LLV_INFO, LOCATION, NULL,
  484: 			    "caught signal %d\n", sig);
  485: 			break;
  486: 		}
  487: 	}
  488: }
  489: 
  490: static void
  491: init_signal()
  492: {
  493: 	int i;
  494: 
  495: 	/*
  496: 	 * Ignore SIGPIPE as we check the return value of system calls
  497: 	 * that write to pipe-like fds.
  498: 	 */
  499: 	signal(SIGPIPE, SIG_IGN);
  500: 
  501: 	for (i = 0; signals[i] != 0; i++)
  502: 		if (set_signal(signals[i], signal_handler) < 0) {
  503: 			plog(LLV_ERROR, LOCATION, NULL,
  504: 				"failed to set_signal (%s)\n",
  505: 				strerror(errno));
  506: 			exit(1);
  507: 		}
  508: }
  509: 
  510: static int
  511: set_signal(sig, func)
  512: 	int sig;
  513: 	RETSIGTYPE (*func) __P((int));
  514: {
  515: 	struct sigaction sa;
  516: 
  517: 	memset((caddr_t)&sa, 0, sizeof(sa));
  518: 	sa.sa_handler = func;
  519: 	sa.sa_flags = SA_RESTART;
  520: 
  521: 	if (sigemptyset(&sa.sa_mask) < 0)
  522: 		return -1;
  523: 
  524: 	if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
  525: 		return(-1);
  526: 
  527: 	return 0;
  528: }
  529: 
  530: static int
  531: close_sockets()
  532: {
  533: 	myaddr_close();
  534: 	pfkey_close(lcconf->sock_pfkey);
  535: #ifdef ENABLE_ADMINPORT
  536: 	(void)admin_close();
  537: #endif
  538: 	return 0;
  539: }
  540: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>