1/*	$NetBSD: session.c,v 1.7.6.2 2007/08/01 11:52:22 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
63#include <netinet/in.h>
64#include <resolv.h>
65
66#include "libpfkey.h"
67
68#include "var.h"
69#include "misc.h"
70#include "vmbuf.h"
71#include "plog.h"
72#include "debug.h"
73
74#include "schedule.h"
75#include "session.h"
76#include "grabmyaddr.h"
77#include "evt.h"
78#include "cfparse_proto.h"
79#include "isakmp_var.h"
80#include "isakmp_xauth.h"
81#include "isakmp_cfg.h"
82#include "admin_var.h"
83#include "admin.h"
84#include "privsep.h"
85#include "oakley.h"
86#include "pfkey.h"
87#include "handler.h"
88#include "localconf.h"
89#include "remoteconf.h"
90#include "backupsa.h"
91#ifdef ENABLE_NATT
92#include "nattraversal.h"
93#endif
94
95
96#include "algorithm.h" /* XXX ??? */
97
98#include "sainfo.h"
99
100static void close_session __P((void));
101static void check_rtsock __P((void *));
102static void initfds __P((void));
103static void init_signal __P((void));
104static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
105static void check_sigreq __P((void));
106static void check_flushsa_stub __P((void *));
107static void check_flushsa __P((void));
108static int close_sockets __P((void));
109
110static fd_set mask0;
111static fd_set maskdying;
112static int nfds = 0;
113static volatile sig_atomic_t sigreq[NSIG + 1];
114static int dying = 0;
115
116int
117session(void)
118{
119	fd_set rfds;
120	struct timeval *timeout;
121	int error;
122	struct myaddrs *p;
123	char pid_file[MAXPATHLEN];
124	FILE *fp;
125	pid_t racoon_pid = 0;
126	int i;
127
128	/* initialize schedular */
129	sched_init();
130
131	init_signal();
132
133#ifdef ENABLE_ADMINPORT
134	if (admin_init() < 0)
135		exit(1);
136#endif
137
138	initmyaddr();
139
140	if (isakmp_init() < 0)
141		exit(1);
142
143	initfds();
144
145#ifdef ENABLE_NATT
146	natt_keepalive_init ();
147#endif
148
149	if (privsep_init() != 0)
150		exit(1);
151
152	for (i = 0; i <= NSIG; i++)
153		sigreq[i] = 0;
154
155	/* write .pid file */
156	racoon_pid = getpid();
157	if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
158		strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN);
159	else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
160		strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
161	else {
162		strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN);
163		strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN);
164	}
165	fp = fopen(pid_file, "w");
166	if (fp) {
167		if (fchmod(fileno(fp),
168			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
169			syslog(LOG_ERR, "%s", strerror(errno));
170			fclose(fp);
171			exit(1);
172		}
173		fprintf(fp, "%ld\n", (long)racoon_pid);
174		fclose(fp);
175	} else {
176		plog(LLV_ERROR, LOCATION, NULL,
177			"cannot open %s", pid_file);
178	}
179
180	while (1) {
181		if (dying)
182			rfds = maskdying;
183		else
184			rfds = mask0;
185
186		/*
187		 * asynchronous requests via signal.
188		 * make sure to reset sigreq to 0.
189		 */
190		check_sigreq();
191
192		/* scheduling */
193		timeout = schedular();
194
195		error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
196		if (error < 0) {
197			switch (errno) {
198			case EINTR:
199				continue;
200			default:
201				plog(LLV_ERROR, LOCATION, NULL,
202					"failed to select (%s)\n",
203					strerror(errno));
204				return -1;
205			}
206			/*NOTREACHED*/
207		}
208
209#ifdef ENABLE_ADMINPORT
210		if ((lcconf->sock_admin != -1) &&
211		    (FD_ISSET(lcconf->sock_admin, &rfds)))
212			admin_handler();
213#endif
214
215		for (p = lcconf->myaddrs; p; p = p->next) {
216			if (!p->addr)
217				continue;
218			if (FD_ISSET(p->sock, &rfds))
219				isakmp_handler(p->sock);
220		}
221
222		if (FD_ISSET(lcconf->sock_pfkey, &rfds))
223			pfkey_handler();
224
225		if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds)) {
226			if (update_myaddrs() && lcconf->autograbaddr)
227				check_rtsock(NULL);
228			else
229				initfds();
230		}
231	}
232}
233
234/* clear all status and exit program. */
235static void
236close_session()
237{
238#ifdef ENABLE_FASTQUIT
239	flushph2();
240#endif
241	flushph1();
242	close_sockets();
243	backupsa_clean();
244
245	plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
246	exit(0);
247}
248
249static void
250check_rtsock(unused)
251	void *unused;
252{
253	isakmp_close();
254	grab_myaddrs();
255	autoconf_myaddrsport();
256	isakmp_open();
257
258	/* initialize socket list again */
259	initfds();
260}
261
262static void
263initfds()
264{
265	struct myaddrs *p;
266
267	nfds = 0;
268
269	FD_ZERO(&mask0);
270	FD_ZERO(&maskdying);
271
272#ifdef ENABLE_ADMINPORT
273	if (lcconf->sock_admin != -1) {
274		if (lcconf->sock_admin >= FD_SETSIZE) {
275			plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
276			exit(1);
277		}
278		FD_SET(lcconf->sock_admin, &mask0);
279		/* XXX should we listen on admin socket when dying ?
280		 */
281#if 0
282		FD_SET(lcconf->sock_admin, &maskdying);
283#endif
284		nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
285	}
286#endif
287	if (lcconf->sock_pfkey >= FD_SETSIZE) {
288		plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
289		exit(1);
290	}
291	FD_SET(lcconf->sock_pfkey, &mask0);
292	FD_SET(lcconf->sock_pfkey, &maskdying);
293	nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
294	if (lcconf->rtsock >= 0) {
295		if (lcconf->rtsock >= FD_SETSIZE) {
296			plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
297			exit(1);
298		}
299		FD_SET(lcconf->rtsock, &mask0);
300		nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
301	}
302
303	for (p = lcconf->myaddrs; p; p = p->next) {
304		if (!p->addr)
305			continue;
306		if (p->sock >= FD_SETSIZE) {
307			plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
308			exit(1);
309		}
310		FD_SET(p->sock, &mask0);
311		nfds = (nfds > p->sock ? nfds : p->sock);
312	}
313	nfds++;
314}
315
316static int signals[] = {
317	SIGHUP,
318	SIGINT,
319	SIGTERM,
320	SIGUSR1,
321	SIGUSR2,
322	SIGCHLD,
323	0
324};
325
326/*
327 * asynchronous requests will actually dispatched in the
328 * main loop in session().
329 */
330RETSIGTYPE
331signal_handler(sig)
332	int sig;
333{
334	/* Do not just set it to 1, because we may miss some signals by just setting
335	 * values to 0/1
336	 */
337	sigreq[sig]++;
338}
339
340
341/* XXX possible mem leaks and no way to go back for now !!!
342 */
343static void reload_conf(){
344	int error;
345
346#ifdef ENABLE_HYBRID
347	if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
348		plog(LLV_ERROR, LOCATION, NULL,
349		    "ISAKMP mode config structure reset failed, "
350		    "not reloading\n");
351		return;
352	}
353#endif
354
355	save_sainfotree();
356
357	/* TODO: save / restore / flush old lcconf (?) / rmtree
358	 */
359/*	initlcconf();*/ /* racoon_conf ? ! */
360
361	save_rmconf();
362	initrmconf();
363
364	/* Do a part of pfkey_init() ?
365	 * SPD reload ?
366	 */
367
368	save_params();
369	error = cfparse();
370	if (error != 0){
371		plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
372		/* We are probably in an inconsistant state... */
373		return;
374	}
375	restore_params();
376
377#if 0
378	if (dump_config)
379		dumprmconf ();
380#endif
381
382	/*
383	 * init_myaddr() ?
384	 * If running in privilege separation, do not reinitialize
385	 * the IKE listener, as we will not have the right to
386	 * setsockopt(IP_IPSEC_POLICY).
387	 */
388	if (geteuid() == 0)
389		check_rtsock(NULL);
390
391	/* Revalidate ph1 / ph2tree !!!
392	 * update ctdtree if removing some ph1 !
393	 */
394	revalidate_ph12();
395	/* Update ctdtree ?
396	 */
397
398	save_sainfotree_flush();
399	save_rmconf_flush();
400}
401
402static void
403check_sigreq()
404{
405	int sig;
406
407	/*
408	 * XXX We are not able to tell if we got
409	 * several time the same signal. This is
410	 * not a problem for the current code,
411	 * but we shall remember this limitation.
412	 */
413	for (sig = 0; sig <= NSIG; sig++) {
414		if (sigreq[sig] == 0)
415			continue;
416
417		sigreq[sig]--;
418		switch(sig) {
419		case 0:
420			return;
421
422			/* Catch up childs, mainly scripts.
423			 */
424		case SIGCHLD:
425	    {
426			pid_t pid;
427			int s;
428
429			pid = wait(&s);
430	    }
431		break;
432
433#ifdef DEBUG_RECORD_MALLOCATION
434		/*
435		 * XXX This operation is signal handler unsafe and may lead to
436		 * crashes and security breaches: See Henning Brauer talk at
437		 * EuroBSDCon 2005. Do not run in production with this option
438		 * enabled.
439		 */
440		case SIGUSR2:
441			DRM_dump();
442			break;
443#endif
444
445		case SIGHUP:
446			/* Save old configuration, load new one...  */
447			reload_conf();
448			break;
449
450		case SIGINT:
451		case SIGTERM:
452			plog(LLV_INFO, LOCATION, NULL,
453			    "caught signal %d\n", sig);
454			EVT_PUSH(NULL, NULL, EVTT_RACOON_QUIT, NULL);
455			pfkey_send_flush(lcconf->sock_pfkey,
456			    SADB_SATYPE_UNSPEC);
457#ifdef ENABLE_FASTQUIT
458			close_session();
459#else
460			sched_new(1, check_flushsa_stub, NULL);
461#endif
462			dying = 1;
463			break;
464
465		default:
466			plog(LLV_INFO, LOCATION, NULL,
467			    "caught signal %d\n", sig);
468			break;
469		}
470	}
471}
472
473/*
474 * waiting the termination of processing until sending DELETE message
475 * for all inbound SA will complete.
476 */
477static void
478check_flushsa_stub(p)
479	void *p;
480{
481
482	check_flushsa();
483}
484
485static void
486check_flushsa()
487{
488	vchar_t *buf;
489	struct sadb_msg *msg, *end, *next;
490	struct sadb_sa *sa;
491	caddr_t mhp[SADB_EXT_MAX + 1];
492	int n;
493
494	buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
495	if (buf == NULL) {
496		plog(LLV_DEBUG, LOCATION, NULL,
497		    "pfkey_dump_sadb: returned nothing.\n");
498		return;
499	}
500
501	msg = (struct sadb_msg *)buf->v;
502	end = (struct sadb_msg *)(buf->v + buf->l);
503
504	/* counting SA except of dead one. */
505	n = 0;
506	while (msg < end) {
507		if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
508			break;
509		next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
510		if (msg->sadb_msg_type != SADB_DUMP) {
511			msg = next;
512			continue;
513		}
514
515		if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
516			plog(LLV_ERROR, LOCATION, NULL,
517				"pfkey_check (%s)\n", ipsec_strerror());
518			msg = next;
519			continue;
520		}
521
522		sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
523		if (!sa) {
524			msg = next;
525			continue;
526		}
527
528		if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
529			n++;
530			msg = next;
531			continue;
532		}
533
534		msg = next;
535	}
536
537	if (buf != NULL)
538		vfree(buf);
539
540	if (n) {
541		sched_new(1, check_flushsa_stub, NULL);
542		return;
543	}
544
545	close_session();
546}
547
548static void
549init_signal()
550{
551	int i;
552
553	for (i = 0; signals[i] != 0; i++)
554		if (set_signal(signals[i], signal_handler) < 0) {
555			plog(LLV_ERROR, LOCATION, NULL,
556				"failed to set_signal (%s)\n",
557				strerror(errno));
558			exit(1);
559		}
560}
561
562static int
563set_signal(sig, func)
564	int sig;
565	RETSIGTYPE (*func) __P((int));
566{
567	struct sigaction sa;
568
569	memset((caddr_t)&sa, 0, sizeof(sa));
570	sa.sa_handler = func;
571	sa.sa_flags = SA_RESTART;
572
573	if (sigemptyset(&sa.sa_mask) < 0)
574		return -1;
575
576	if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
577		return(-1);
578
579	return 0;
580}
581
582static int
583close_sockets()
584{
585	isakmp_close();
586	pfkey_close(lcconf->sock_pfkey);
587#ifdef ENABLE_ADMINPORT
588	(void)admin_close();
589#endif
590	return 0;
591}
592
593