Annotation of embedaddon/ipsec-tools/src/racoon/session.c, revision 1.1.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>