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
103struct 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
113static void close_session __P((void));
114static void initfds __P((void));
115static void init_signal __P((void));
116static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
117static void check_sigreq __P((void));
118static void check_flushsa __P((void));
119static int close_sockets __P((void));
120
121static fd_set preset_mask, active_mask;
122static struct fd_monitor fd_monitors[FD_SETSIZE];
123static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
124static int nfds = 0;
125
126static volatile sig_atomic_t sigreq[NSIG + 1];
127static struct sched scflushsa = SCHED_INITIALIZER();
128
129void
130monitor_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
153void
154unmonitor_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
172int
173session(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. */
339static void
340close_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
356static 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 */
370RETSIGTYPE
371signal_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 */
380static 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
438static void
439check_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
490static void
491init_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
510static int
511set_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
530static int
531close_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
541