1/*	$NetBSD: session.c,v 1.35 2018/05/19 20:14:56 maxv 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 init_signal __P((void));
115static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
116static void check_sigreq __P((void));
117static int close_sockets __P((void));
118
119static fd_set preset_mask, active_mask;
120static struct fd_monitor fd_monitors[FD_SETSIZE];
121static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
122static int nfds = 0;
123
124static volatile sig_atomic_t sigreq[NSIG + 1];
125
126void
127monitor_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
150void
151unmonitor_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
169int
170session(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	while (1) {
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. */
336static void
337close_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
353static 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 */
367RETSIGTYPE
368signal_handler(sig)
369	int sig;
370{
371	sigreq[sig] = 1;
372}
373
374
375/* XXX possible mem leaks and no way to go back for now !!!
376 */
377static void reload_conf(void)
378{
379	int error;
380
381#ifdef ENABLE_HYBRID
382	if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
383		plog(LLV_ERROR, LOCATION, NULL,
384		    "ISAKMP mode config structure reset failed, "
385		    "not reloading\n");
386		return;
387	}
388#endif
389
390	sainfo_start_reload();
391
392	/* TODO: save / restore / flush old lcconf (?) / rmtree
393	 */
394	rmconf_start_reload();
395
396#ifdef HAVE_LIBRADIUS
397	/* free and init radius configuration */
398	xauth_radius_init_conf(1);
399#endif
400
401	pfkey_reload();
402
403	save_params();
404	flushlcconf();
405	error = cfparse();
406	if (error != 0){
407		plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n");
408		/* We are probably in an inconsistant state... */
409		return;
410	}
411	restore_params();
412
413#if 0
414	if (dump_config)
415		dumprmconf ();
416#endif
417
418	myaddr_sync();
419
420#ifdef HAVE_LIBRADIUS
421	/* re-initialize radius state */
422	xauth_radius_init();
423#endif
424
425	/* Revalidate ph1 / ph2tree !!!
426	 * update ctdtree if removing some ph1 !
427	 */
428	revalidate_ph12();
429	/* Update ctdtree ?
430	 */
431
432	sainfo_finish_reload();
433	rmconf_finish_reload();
434}
435
436static void
437check_sigreq()
438{
439	int sig, s;
440
441	for (sig = 0; sig <= NSIG; sig++) {
442		if (sigreq[sig] == 0)
443			continue;
444		sigreq[sig] = 0;
445
446		switch(sig) {
447		case 0:
448			return;
449
450		case SIGCHLD:
451			/* Reap all pending children */
452			while (waitpid(-1, &s, WNOHANG) > 0)
453				;
454			break;
455
456#ifdef DEBUG_RECORD_MALLOCATION
457		/*
458		 * XXX This operation is signal handler unsafe and may lead to
459		 * crashes and security breaches: See Henning Brauer talk at
460		 * EuroBSDCon 2005. Do not run in production with this option
461		 * enabled.
462		 */
463		case SIGUSR2:
464			DRM_dump();
465			break;
466#endif
467
468		case SIGHUP:
469			/* Save old configuration, load new one...  */
470			reload_conf();
471			break;
472
473		case SIGINT:
474		case SIGTERM:
475			plog(LLV_INFO, LOCATION, NULL,
476			    "caught signal %d\n", sig);
477			close_session();
478			break;
479
480		default:
481			plog(LLV_INFO, LOCATION, NULL,
482			    "caught signal %d\n", sig);
483			break;
484		}
485	}
486}
487
488static void
489init_signal()
490{
491	int i;
492
493	/*
494	 * Ignore SIGPIPE as we check the return value of system calls
495	 * that write to pipe-like fds.
496	 */
497	signal(SIGPIPE, SIG_IGN);
498
499	for (i = 0; signals[i] != 0; i++)
500		if (set_signal(signals[i], signal_handler) < 0) {
501			plog(LLV_ERROR, LOCATION, NULL,
502				"failed to set_signal (%s)\n",
503				strerror(errno));
504			exit(1);
505		}
506}
507
508static int
509set_signal(sig, func)
510	int sig;
511	RETSIGTYPE (*func) __P((int));
512{
513	struct sigaction sa;
514
515	memset((caddr_t)&sa, 0, sizeof(sa));
516	sa.sa_handler = func;
517	sa.sa_flags = SA_RESTART;
518
519	if (sigemptyset(&sa.sa_mask) < 0)
520		return -1;
521
522	if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
523		return(-1);
524
525	return 0;
526}
527
528static int
529close_sockets()
530{
531	myaddr_close();
532	pfkey_close(lcconf->sock_pfkey);
533#ifdef ENABLE_ADMINPORT
534	(void)admin_close();
535#endif
536	return 0;
537}
538
539