Return to session.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipsec-tools / src / racoon |
1.1 ! misho 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: ! 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 __P((void)); ! 114: static void initfds __P((void)); ! 115: static void init_signal __P((void)); ! 116: static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int)))); ! 117: static void check_sigreq __P((void)); ! 118: static void check_flushsa __P((void)); ! 119: static int close_sockets __P((void)); ! 120: ! 121: static fd_set preset_mask, active_mask; ! 122: static struct fd_monitor fd_monitors[FD_SETSIZE]; ! 123: static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES]; ! 124: static int nfds = 0; ! 125: ! 126: static volatile sig_atomic_t sigreq[NSIG + 1]; ! 127: static struct sched scflushsa = SCHED_INITIALIZER(); ! 128: ! 129: void ! 130: monitor_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: ! 153: void ! 154: unmonitor_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: ! 172: int ! 173: session(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. */ ! 339: static void ! 340: close_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: ! 356: static 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: */ ! 370: RETSIGTYPE ! 371: signal_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: */ ! 380: static 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: ! 438: static void ! 439: check_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: ! 490: static void ! 491: init_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: ! 510: static int ! 511: set_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: ! 530: static int ! 531: close_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: