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