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