Annotation of embedaddon/ipsec-tools/src/racoon/session.c, revision 1.1
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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>