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 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 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 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 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 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 */ 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 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 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 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 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