xref: /netbsd-src/crypto/dist/ipsec-tools/src/racoon/session.c (revision 165b31ce969841b1b96165ce3c8c8b91653ed8df)
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 
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 init_signal __P((void));
115 static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
116 static void check_sigreq __P((void));
117 static int close_sockets __P((void));
118 
119 static fd_set preset_mask, active_mask;
120 static struct fd_monitor fd_monitors[FD_SETSIZE];
121 static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
122 static int nfds = 0;
123 
124 static volatile sig_atomic_t sigreq[NSIG + 1];
125 
126 void
monitor_fd(int fd,int (* callback)(void *,int),void * ctx,int priority)127 monitor_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 
150 void
unmonitor_fd(int fd)151 unmonitor_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 
169 int
session(void)170 session(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. */
336 static void
close_session()337 close_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 
353 static 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  */
367 RETSIGTYPE
signal_handler(sig)368 signal_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  */
reload_conf(void)377 static 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 
436 static void
check_sigreq()437 check_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 
488 static void
init_signal()489 init_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 
508 static int
set_signal(sig,func)509 set_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 
528 static int
close_sockets()529 close_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