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