Annotation of embedaddon/strongswan/src/charon/charon.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2006-2017 Tobias Brunner
                      3:  * Copyright (C) 2005-2009 Martin Willi
                      4:  * Copyright (C) 2006 Daniel Roethlisberger
                      5:  * Copyright (C) 2005 Jan Hutter
                      6:  * HSR Hochschule fuer Technik Rapperswil
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include <stdio.h>
                     20: #include <signal.h>
                     21: #include <pthread.h>
                     22: #include <sys/stat.h>
                     23: #include <sys/types.h>
                     24: #include <sys/utsname.h>
                     25: #include <unistd.h>
                     26: #include <getopt.h>
                     27: #include <fcntl.h>
                     28: #include <errno.h>
                     29: 
                     30: #include <daemon.h>
                     31: 
                     32: #include <library.h>
                     33: #include <utils/backtrace.h>
                     34: #include <threading/thread.h>
                     35: 
                     36: #ifdef ANDROID
                     37: #include <private/android_filesystem_config.h> /* for AID_VPN */
                     38: #endif
                     39: 
                     40: /**
                     41:  * PID file, in which charon stores its process id
                     42:  */
                     43: #define PID_FILE IPSEC_PIDDIR "/charon.pid"
                     44: 
                     45: /**
                     46:  * Default user and group
                     47:  */
                     48: #ifndef IPSEC_USER
                     49: #define IPSEC_USER NULL
                     50: #endif
                     51: 
                     52: #ifndef IPSEC_GROUP
                     53: #define IPSEC_GROUP NULL
                     54: #endif
                     55: 
                     56: /**
                     57:  * Global reference to PID file (required to truncate, if undeletable)
                     58:  */
                     59: static FILE *pidfile = NULL;
                     60: 
                     61: /**
                     62:  * hook in library for debugging messages
                     63:  */
                     64: extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
                     65: 
                     66: /**
                     67:  * Logging hook for library logs, using stderr output
                     68:  */
                     69: static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
                     70: {
                     71:        va_list args;
                     72: 
                     73:        if (level <= 1)
                     74:        {
                     75:                va_start(args, fmt);
                     76:                fprintf(stderr, "00[%N] ", debug_names, group);
                     77:                vfprintf(stderr, fmt, args);
                     78:                fprintf(stderr, "\n");
                     79:                va_end(args);
                     80:        }
                     81: }
                     82: 
                     83: /**
                     84:  * Run the daemon and handle unix signals
                     85:  */
                     86: static void run()
                     87: {
                     88:        sigset_t set;
                     89: 
                     90:        /* handle SIGINT, SIGHUP and SIGTERM in this handler */
                     91:        sigemptyset(&set);
                     92:        sigaddset(&set, SIGINT);
                     93:        sigaddset(&set, SIGHUP);
                     94:        sigaddset(&set, SIGTERM);
                     95:        sigprocmask(SIG_BLOCK, &set, NULL);
                     96: 
                     97:        while (TRUE)
                     98:        {
                     99:                int sig;
                    100: 
                    101:                sig = sigwaitinfo(&set, NULL);
                    102:                if (sig == -1)
                    103:                {
                    104:                        if (errno == EINTR)
                    105:                        {       /* ignore signals we didn't wait for */
                    106:                                continue;
                    107:                        }
                    108:                        DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno));
                    109:                        return;
                    110:                }
                    111:                switch (sig)
                    112:                {
                    113:                        case SIGHUP:
                    114:                        {
                    115:                                DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading "
                    116:                                         "configuration");
                    117:                                if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
                    118:                                {
                    119:                                        charon->load_loggers(charon);
                    120:                                        lib->plugins->reload(lib->plugins, NULL);
                    121:                                }
                    122:                                else
                    123:                                {
                    124:                                        DBG1(DBG_DMN, "reloading config failed, keeping old");
                    125:                                }
                    126:                                break;
                    127:                        }
                    128:                        case SIGINT:
                    129:                        {
                    130:                                DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down");
                    131:                                charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
                    132:                                return;
                    133:                        }
                    134:                        case SIGTERM:
                    135:                        {
                    136:                                DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down");
                    137:                                charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
                    138:                                return;
                    139:                        }
                    140:                }
                    141:        }
                    142: }
                    143: 
                    144: /**
                    145:  * lookup UID and GID
                    146:  */
                    147: static bool lookup_uid_gid()
                    148: {
                    149:        char *name;
                    150: 
                    151:        name = lib->settings->get_str(lib->settings, "charon.user", IPSEC_USER);
                    152:        if (name && !lib->caps->resolve_uid(lib->caps, name))
                    153:        {
                    154:                return FALSE;
                    155:        }
                    156:        name = lib->settings->get_str(lib->settings, "charon.group", IPSEC_GROUP);
                    157:        if (name && !lib->caps->resolve_gid(lib->caps, name))
                    158:        {
                    159:                return FALSE;
                    160:        }
                    161: #ifdef ANDROID
                    162:        lib->caps->set_uid(lib->caps, AID_VPN);
                    163: #endif
                    164:        return TRUE;
                    165: }
                    166: 
                    167: /**
                    168:  * Handle SIGSEGV/SIGILL signals raised by threads
                    169:  */
                    170: #ifndef DISABLE_SIGNAL_HANDLER
                    171: static void segv_handler(int signal)
                    172: {
                    173:        backtrace_t *backtrace;
                    174: 
                    175:        DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
                    176:        backtrace = backtrace_create(2);
                    177:        backtrace->log(backtrace, NULL, TRUE);
                    178:        backtrace->log(backtrace, stderr, TRUE);
                    179:        backtrace->destroy(backtrace);
                    180: 
                    181:        DBG1(DBG_DMN, "killing ourself, received critical signal");
                    182:        abort();
                    183: }
                    184: #endif /* DISABLE_SIGNAL_HANDLER */
                    185: 
                    186: /**
                    187:  * Check/create PID file, return TRUE if already running
                    188:  */
                    189: static bool check_pidfile()
                    190: {
                    191:        struct stat stb;
                    192: 
                    193:        if (stat(PID_FILE, &stb) == 0)
                    194:        {
                    195:                pidfile = fopen(PID_FILE, "r");
                    196:                if (pidfile)
                    197:                {
                    198:                        char buf[64];
                    199:                        pid_t pid = 0;
                    200: 
                    201:                        memset(buf, 0, sizeof(buf));
                    202:                        if (fread(buf, 1, sizeof(buf), pidfile))
                    203:                        {
                    204:                                buf[sizeof(buf) - 1] = '\0';
                    205:                                pid = atoi(buf);
                    206:                        }
                    207:                        fclose(pidfile);
                    208:                        pidfile = NULL;
                    209:                        if (pid && pid != getpid() && kill(pid, 0) == 0)
                    210:                        {
                    211:                                DBG1(DBG_DMN, "charon already running ('"PID_FILE"' exists)");
                    212:                                return TRUE;
                    213:                        }
                    214:                }
                    215:                DBG1(DBG_DMN, "removing pidfile '"PID_FILE"', process not running");
                    216:                unlink(PID_FILE);
                    217:        }
                    218: 
                    219:        /* create new pidfile */
                    220:        pidfile = fopen(PID_FILE, "w");
                    221:        if (pidfile)
                    222:        {
                    223:                int fd;
                    224: 
                    225:                fd = fileno(pidfile);
                    226:                if (fd == -1)
                    227:                {
                    228:                        DBG1(DBG_DMN, "unable to determine fd for '"PID_FILE"'");
                    229:                        return TRUE;
                    230:                }
                    231:                if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
                    232:                {
                    233:                        DBG1(DBG_LIB, "setting FD_CLOEXEC for '"PID_FILE"' failed: %s",
                    234:                                 strerror(errno));
                    235:                }
                    236:                /* Only change owner of the pidfile if we have CAP_CHOWN. Otherwise,
                    237:                 * attempt to change group of pidfile to group under which charon
                    238:                 * runs after dropping caps. This requires the user that charon
                    239:                 * starts as to:
                    240:                 * a) Have write access to the socket dir.
                    241:                 * b) Belong to the group that charon will run under after dropping
                    242:                 *    caps. */
                    243:                if (lib->caps->check(lib->caps, CAP_CHOWN))
                    244:                {
                    245:                        ignore_result(fchown(fd,
                    246:                                                                 lib->caps->get_uid(lib->caps),
                    247:                                                                 lib->caps->get_gid(lib->caps)));
                    248:                }
                    249:                else
                    250:                {
                    251:                        ignore_result(fchown(fd, -1,
                    252:                                                                 lib->caps->get_gid(lib->caps)));
                    253:                }
                    254:                fprintf(pidfile, "%d\n", getpid());
                    255:                fflush(pidfile);
                    256:                return FALSE;
                    257:        }
                    258:        else
                    259:        {
                    260:                DBG1(DBG_DMN, "unable to create pidfile '"PID_FILE"'");
                    261:                return TRUE;
                    262:        }
                    263: }
                    264: 
                    265: /**
                    266:  * Delete/truncate the PID file
                    267:  */
                    268: static void unlink_pidfile()
                    269: {
                    270:        /* because unlinking the PID file may fail, we truncate it to ensure the
                    271:         * daemon can be properly restarted.  one probable cause for this is the
                    272:         * combination of not running as root and the effective user lacking
                    273:         * permissions on the parent dir(s) of the PID file */
                    274:        if (pidfile)
                    275:        {
                    276:                ignore_result(ftruncate(fileno(pidfile), 0));
                    277:                fclose(pidfile);
                    278:                unlink(PID_FILE);
                    279:        }
                    280: }
                    281: 
                    282: /**
                    283:  * print command line usage and exit
                    284:  */
                    285: static void usage(const char *msg)
                    286: {
                    287:        if (msg != NULL && *msg != '\0')
                    288:        {
                    289:                fprintf(stderr, "%s\n", msg);
                    290:        }
                    291:        fprintf(stderr, "Usage: charon\n"
                    292:                                        "         [--help]\n"
                    293:                                        "         [--version]\n"
                    294:                                        "         [--use-syslog]\n"
                    295:                                        "         [--debug-<type> <level>]\n"
                    296:                                        "           <type>:  log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n"
                    297:                                        "           <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
                    298:                                        "                                    2 = controlmore, 3 = raw, 4 = private)\n"
                    299:                                        "\n"
                    300:                   );
                    301: }
                    302: 
                    303: /**
                    304:  * Main function, starts the daemon.
                    305:  */
                    306: int main(int argc, char *argv[])
                    307: {
                    308:        struct sigaction action;
                    309:        int group, status = SS_RC_INITIALIZATION_FAILED;
                    310:        struct utsname utsname;
                    311:        level_t levels[DBG_MAX];
                    312:        bool use_syslog = FALSE;
                    313: 
                    314:        /* logging for library during initialization, as we have no bus yet */
                    315:        dbg = dbg_stderr;
                    316: 
                    317:        /* initialize library */
                    318:        if (!library_init(NULL, "charon"))
                    319:        {
                    320:                library_deinit();
                    321:                exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
                    322:        }
                    323: 
                    324:        if (lib->integrity &&
                    325:                !lib->integrity->check_file(lib->integrity, "charon", argv[0]))
                    326:        {
                    327:                dbg_stderr(DBG_DMN, 1, "integrity check of charon failed");
                    328:                library_deinit();
                    329:                exit(SS_RC_DAEMON_INTEGRITY);
                    330:        }
                    331: 
                    332:        if (!libcharon_init())
                    333:        {
                    334:                dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
                    335:                goto deinit;
                    336:        }
                    337: 
                    338:        /* use CTRL loglevel for default */
                    339:        for (group = 0; group < DBG_MAX; group++)
                    340:        {
                    341:                levels[group] = LEVEL_CTRL;
                    342:        }
                    343: 
                    344:        /* handle arguments */
                    345:        for (;;)
                    346:        {
                    347:                struct option long_opts[] = {
                    348:                        { "help", no_argument, NULL, 'h' },
                    349:                        { "version", no_argument, NULL, 'v' },
                    350:                        { "use-syslog", no_argument, NULL, 'l' },
                    351:                        /* TODO: handle "debug-all" */
                    352:                        { "debug-dmn", required_argument, &group, DBG_DMN },
                    353:                        { "debug-mgr", required_argument, &group, DBG_MGR },
                    354:                        { "debug-ike", required_argument, &group, DBG_IKE },
                    355:                        { "debug-chd", required_argument, &group, DBG_CHD },
                    356:                        { "debug-job", required_argument, &group, DBG_JOB },
                    357:                        { "debug-cfg", required_argument, &group, DBG_CFG },
                    358:                        { "debug-knl", required_argument, &group, DBG_KNL },
                    359:                        { "debug-net", required_argument, &group, DBG_NET },
                    360:                        { "debug-asn", required_argument, &group, DBG_ASN },
                    361:                        { "debug-enc", required_argument, &group, DBG_ENC },
                    362:                        { "debug-tnc", required_argument, &group, DBG_TNC },
                    363:                        { "debug-imc", required_argument, &group, DBG_IMC },
                    364:                        { "debug-imv", required_argument, &group, DBG_IMV },
                    365:                        { "debug-pts", required_argument, &group, DBG_PTS },
                    366:                        { "debug-tls", required_argument, &group, DBG_TLS },
                    367:                        { "debug-esp", required_argument, &group, DBG_ESP },
                    368:                        { "debug-lib", required_argument, &group, DBG_LIB },
                    369:                        { 0,0,0,0 }
                    370:                };
                    371: 
                    372:                int c = getopt_long(argc, argv, "", long_opts, NULL);
                    373:                switch (c)
                    374:                {
                    375:                        case EOF:
                    376:                                break;
                    377:                        case 'h':
                    378:                                usage(NULL);
                    379:                                status = 0;
                    380:                                goto deinit;
                    381:                        case 'v':
                    382:                                printf("FreeBSD strongSwan %s\n", VERSION);
                    383:                                status = 0;
                    384:                                goto deinit;
                    385:                        case 'l':
                    386:                                use_syslog = TRUE;
                    387:                                continue;
                    388:                        case 0:
                    389:                                /* option is in group */
                    390:                                levels[group] = atoi(optarg);
                    391:                                continue;
                    392:                        default:
                    393:                                usage("");
                    394:                                status = 1;
                    395:                                goto deinit;
                    396:                }
                    397:                break;
                    398:        }
                    399: 
                    400:        if (!lookup_uid_gid())
                    401:        {
                    402:                dbg_stderr(DBG_DMN, 1, "invalid uid/gid - aborting charon");
                    403:                goto deinit;
                    404:        }
                    405: 
                    406:        charon->set_default_loggers(charon, levels, !use_syslog);
                    407:        charon->load_loggers(charon);
                    408: 
                    409:        if (uname(&utsname) != 0)
                    410:        {
                    411:                memset(&utsname, 0, sizeof(utsname));
                    412:        }
                    413:        DBG1(DBG_DMN, "Starting IKE charon daemon (strongSwan "VERSION", %s %s, %s)",
                    414:                  utsname.sysname, utsname.release, utsname.machine);
                    415:        if (lib->integrity)
                    416:        {
                    417:                DBG1(DBG_DMN, "integrity tests enabled:");
                    418:                DBG1(DBG_DMN, "lib    'libstrongswan': passed file and segment integrity tests");
                    419:                DBG1(DBG_DMN, "lib    'libcharon': passed file and segment integrity tests");
                    420:                DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
                    421:        }
                    422: 
                    423:        /* initialize daemon */
                    424:        if (!charon->initialize(charon,
                    425:                                lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
                    426:        {
                    427:                DBG1(DBG_DMN, "initialization failed - aborting charon");
                    428:                goto deinit;
                    429:        }
                    430:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
                    431: 
                    432:        if (check_pidfile())
                    433:        {
                    434:                goto deinit;
                    435:        }
                    436: 
                    437:        if (!lib->caps->drop(lib->caps))
                    438:        {
                    439:                DBG1(DBG_DMN, "capability dropping failed - aborting charon");
                    440:                goto deinit;
                    441:        }
                    442: 
                    443:        /* add handler for fatal signals,
                    444:         * INT, TERM and HUP are handled by sigwaitinfo() in run() */
                    445:        action.sa_flags = 0;
                    446:        sigemptyset(&action.sa_mask);
                    447:        sigaddset(&action.sa_mask, SIGINT);
                    448:        sigaddset(&action.sa_mask, SIGTERM);
                    449:        sigaddset(&action.sa_mask, SIGHUP);
                    450: 
                    451:        /* optionally let the external system handle fatal signals */
                    452: #ifndef DISABLE_SIGNAL_HANDLER
                    453:        action.sa_handler = segv_handler;
                    454:        sigaction(SIGSEGV, &action, NULL);
                    455:        sigaction(SIGILL, &action, NULL);
                    456:        sigaction(SIGBUS, &action, NULL);
                    457: #endif /* DISABLE_SIGNAL_HANDLER */
                    458: 
                    459:        action.sa_handler = SIG_IGN;
                    460:        sigaction(SIGPIPE, &action, NULL);
                    461: 
                    462:        pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
                    463: 
                    464:        /* start daemon (i.e. the threads in the thread-pool) */
                    465:        charon->start(charon);
                    466: 
                    467:        /* main thread goes to run loop */
                    468:        run();
                    469: 
                    470:        status = 0;
                    471: 
                    472: deinit:
                    473:        libcharon_deinit();
                    474:        unlink_pidfile();
                    475:        library_deinit();
                    476:        return status;
                    477: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>