1/* $NetBSD: session.c,v 1.32 2011/03/02 15:09:16 vanhu 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 initfds __P((void)); 115static void init_signal __P((void)); 116static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int)))); 117static void check_sigreq __P((void)); 118static void check_flushsa __P((void)); 119static int close_sockets __P((void)); 120 121static fd_set preset_mask, active_mask; 122static struct fd_monitor fd_monitors[FD_SETSIZE]; 123static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES]; 124static int nfds = 0; 125 126static volatile sig_atomic_t sigreq[NSIG + 1]; 127static struct sched scflushsa = SCHED_INITIALIZER(); 128 129void 130monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority) 131{ 132 if (fd < 0 || fd >= FD_SETSIZE) { 133 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun"); 134 exit(1); 135 } 136 137 FD_SET(fd, &preset_mask); 138 if (fd > nfds) 139 nfds = fd; 140 if (priority <= 0) 141 priority = 0; 142 if (priority >= NUM_PRIORITIES) 143 priority = NUM_PRIORITIES - 1; 144 145 fd_monitors[fd].callback = callback; 146 fd_monitors[fd].ctx = ctx; 147 fd_monitors[fd].prio = priority; 148 fd_monitors[fd].fd = fd; 149 TAILQ_INSERT_TAIL(&fd_monitor_tree[priority], 150 &fd_monitors[fd], chain); 151} 152 153void 154unmonitor_fd(int fd) 155{ 156 if (fd < 0 || fd >= FD_SETSIZE) { 157 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun"); 158 exit(1); 159 } 160 161 if (fd_monitors[fd].callback == NULL) 162 return; 163 164 FD_CLR(fd, &preset_mask); 165 FD_CLR(fd, &active_mask); 166 fd_monitors[fd].callback = NULL; 167 fd_monitors[fd].ctx = NULL; 168 TAILQ_REMOVE(&fd_monitor_tree[fd_monitors[fd].prio], 169 &fd_monitors[fd], chain); 170} 171 172int 173session(void) 174{ 175 struct timeval *timeout; 176 int error; 177 char pid_file[MAXPATHLEN]; 178 FILE *fp; 179 pid_t racoon_pid = 0; 180 int i, count; 181 struct fd_monitor *fdm; 182 183 nfds = 0; 184 FD_ZERO(&preset_mask); 185 186 for (i = 0; i < NUM_PRIORITIES; i++) 187 TAILQ_INIT(&fd_monitor_tree[i]); 188 189 /* initialize schedular */ 190 sched_init(); 191 init_signal(); 192 193 if (pfkey_init() < 0) 194 errx(1, "failed to initialize pfkey socket"); 195 196 if (isakmp_init() < 0) 197 errx(1, "failed to initialize ISAKMP structures"); 198 199#ifdef ENABLE_HYBRID 200 if (isakmp_cfg_init(ISAKMP_CFG_INIT_COLD)) 201 errx(1, "could not initialize ISAKMP mode config structures"); 202#endif 203 204#ifdef HAVE_LIBLDAP 205 if (xauth_ldap_init_conf() != 0) 206 errx(1, "could not initialize ldap config"); 207#endif 208 209#ifdef HAVE_LIBRADIUS 210 if (xauth_radius_init_conf(0) != 0) 211 errx(1, "could not initialize radius config"); 212#endif 213 214 myaddr_init_lists(); 215 216 /* 217 * in order to prefer the parameters by command line, 218 * saving some parameters before parsing configuration file. 219 */ 220 save_params(); 221 if (cfparse() != 0) 222 errx(1, "failed to parse configuration file."); 223 restore_params(); 224 225#ifdef ENABLE_ADMINPORT 226 if (admin_init() < 0) 227 errx(1, "failed to initialize admin port socket"); 228#endif 229 230 231#ifdef ENABLE_HYBRID 232 if(isakmp_cfg_config.network4 && isakmp_cfg_config.pool_size == 0) 233 if ((error = isakmp_cfg_resize_pool(ISAKMP_CFG_MAX_CNX)) != 0) 234 return error; 235#endif 236 237 if (dump_config) 238 dumprmconf(); 239 240#ifdef HAVE_LIBRADIUS 241 if (xauth_radius_init() != 0) 242 errx(1, "could not initialize libradius"); 243#endif 244 245 if (myaddr_init() != 0) 246 errx(1, "failed to listen to configured addresses"); 247 myaddr_sync(); 248 249#ifdef ENABLE_NATT 250 natt_keepalive_init (); 251#endif 252 253 /* write .pid file */ 254 if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL) 255 strlcpy(pid_file, _PATH_VARRUN "racoon.pid", MAXPATHLEN); 256 else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/') 257 strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN); 258 else { 259 strlcat(pid_file, _PATH_VARRUN, MAXPATHLEN); 260 strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], MAXPATHLEN); 261 } 262 fp = fopen(pid_file, "w"); 263 if (fp) { 264 if (fchmod(fileno(fp), 265 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) { 266 syslog(LOG_ERR, "%s", strerror(errno)); 267 fclose(fp); 268 exit(1); 269 } 270 } else { 271 plog(LLV_ERROR, LOCATION, NULL, 272 "cannot open %s", pid_file); 273 } 274 275 if (privsep_init() != 0) 276 exit(1); 277 278 /* 279 * The fork()'ed privileged side will close its copy of fp. We wait 280 * until here to get the correct child pid. 281 */ 282 racoon_pid = getpid(); 283 fprintf(fp, "%ld\n", (long)racoon_pid); 284 fclose(fp); 285 286 for (i = 0; i <= NSIG; i++) 287 sigreq[i] = 0; 288 289 while (1) { 290 /* 291 * asynchronous requests via signal. 292 * make sure to reset sigreq to 0. 293 */ 294 check_sigreq(); 295 296 /* scheduling */ 297 timeout = schedular(); 298 299 /* schedular can change select() mask, so we reset 300 * the working copy here */ 301 active_mask = preset_mask; 302 303 error = select(nfds + 1, &active_mask, NULL, NULL, timeout); 304 if (error < 0) { 305 switch (errno) { 306 case EINTR: 307 continue; 308 default: 309 plog(LLV_ERROR, LOCATION, NULL, 310 "failed to select (%s)\n", 311 strerror(errno)); 312 return -1; 313 } 314 /*NOTREACHED*/ 315 } 316 317 count = 0; 318 for (i = 0; i < NUM_PRIORITIES; i++) { 319 TAILQ_FOREACH(fdm, &fd_monitor_tree[i], chain) { 320 if (!FD_ISSET(fdm->fd, &active_mask)) 321 continue; 322 323 FD_CLR(fdm->fd, &active_mask); 324 if (fdm->callback != NULL) { 325 fdm->callback(fdm->ctx, fdm->fd); 326 count++; 327 } else 328 plog(LLV_ERROR, LOCATION, NULL, 329 "fd %d set, but no active callback\n", i); 330 } 331 if (count != 0) 332 break; 333 } 334 335 } 336} 337 338/* clear all status and exit program. */ 339static void 340close_session() 341{ 342 evt_generic(EVT_RACOON_QUIT, NULL); 343 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC); 344 flushph2(); 345 flushph1(); 346 flushrmconf(); 347 flushsainfo(); 348 close_sockets(); 349 backupsa_clean(); 350 351 plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid()); 352 353 exit(0); 354} 355 356static int signals[] = { 357 SIGHUP, 358 SIGINT, 359 SIGTERM, 360 SIGUSR1, 361 SIGUSR2, 362 SIGCHLD, 363 0 364}; 365 366/* 367 * asynchronous requests will actually dispatched in the 368 * main loop in session(). 369 */ 370RETSIGTYPE 371signal_handler(sig) 372 int sig; 373{ 374 sigreq[sig] = 1; 375} 376 377 378/* XXX possible mem leaks and no way to go back for now !!! 379 */ 380static void reload_conf(){ 381 int error; 382 383#ifdef ENABLE_HYBRID 384 if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) { 385 plog(LLV_ERROR, LOCATION, NULL, 386 "ISAKMP mode config structure reset failed, " 387 "not reloading\n"); 388 return; 389 } 390#endif 391 392 sainfo_start_reload(); 393 394 /* TODO: save / restore / flush old lcconf (?) / rmtree 395 */ 396 rmconf_start_reload(); 397 398#ifdef HAVE_LIBRADIUS 399 /* free and init radius configuration */ 400 xauth_radius_init_conf(1); 401#endif 402 403 pfkey_reload(); 404 405 save_params(); 406 flushlcconf(); 407 error = cfparse(); 408 if (error != 0){ 409 plog(LLV_ERROR, LOCATION, NULL, "config reload failed\n"); 410 /* We are probably in an inconsistant state... */ 411 return; 412 } 413 restore_params(); 414 415#if 0 416 if (dump_config) 417 dumprmconf (); 418#endif 419 420 myaddr_sync(); 421 422#ifdef HAVE_LIBRADIUS 423 /* re-initialize radius state */ 424 xauth_radius_init(); 425#endif 426 427 /* Revalidate ph1 / ph2tree !!! 428 * update ctdtree if removing some ph1 ! 429 */ 430 revalidate_ph12(); 431 /* Update ctdtree ? 432 */ 433 434 sainfo_finish_reload(); 435 rmconf_finish_reload(); 436} 437 438static void 439check_sigreq() 440{ 441 int sig, s; 442 443 for (sig = 0; sig <= NSIG; sig++) { 444 if (sigreq[sig] == 0) 445 continue; 446 sigreq[sig] = 0; 447 448 switch(sig) { 449 case 0: 450 return; 451 452 case SIGCHLD: 453 /* Reap all pending children */ 454 while (waitpid(-1, &s, WNOHANG) > 0) 455 ; 456 break; 457 458#ifdef DEBUG_RECORD_MALLOCATION 459 /* 460 * XXX This operation is signal handler unsafe and may lead to 461 * crashes and security breaches: See Henning Brauer talk at 462 * EuroBSDCon 2005. Do not run in production with this option 463 * enabled. 464 */ 465 case SIGUSR2: 466 DRM_dump(); 467 break; 468#endif 469 470 case SIGHUP: 471 /* Save old configuration, load new one... */ 472 reload_conf(); 473 break; 474 475 case SIGINT: 476 case SIGTERM: 477 plog(LLV_INFO, LOCATION, NULL, 478 "caught signal %d\n", sig); 479 close_session(); 480 break; 481 482 default: 483 plog(LLV_INFO, LOCATION, NULL, 484 "caught signal %d\n", sig); 485 break; 486 } 487 } 488} 489 490static void 491init_signal() 492{ 493 int i; 494 495 /* 496 * Ignore SIGPIPE as we check the return value of system calls 497 * that write to pipe-like fds. 498 */ 499 signal(SIGPIPE, SIG_IGN); 500 501 for (i = 0; signals[i] != 0; i++) 502 if (set_signal(signals[i], signal_handler) < 0) { 503 plog(LLV_ERROR, LOCATION, NULL, 504 "failed to set_signal (%s)\n", 505 strerror(errno)); 506 exit(1); 507 } 508} 509 510static int 511set_signal(sig, func) 512 int sig; 513 RETSIGTYPE (*func) __P((int)); 514{ 515 struct sigaction sa; 516 517 memset((caddr_t)&sa, 0, sizeof(sa)); 518 sa.sa_handler = func; 519 sa.sa_flags = SA_RESTART; 520 521 if (sigemptyset(&sa.sa_mask) < 0) 522 return -1; 523 524 if (sigaction(sig, &sa, (struct sigaction *)0) < 0) 525 return(-1); 526 527 return 0; 528} 529 530static int 531close_sockets() 532{ 533 myaddr_close(); 534 pfkey_close(lcconf->sock_pfkey); 535#ifdef ENABLE_ADMINPORT 536 (void)admin_close(); 537#endif 538 return 0; 539} 540 541