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