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

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:                        case SIGTERM:
                    130:                        {
1.1.1.2 ! misho     131:                                DBG1(DBG_DMN, "%s received, shutting down",
        !           132:                                         sig == SIGINT ? "SIGINT" : "SIGTERM");
1.1       misho     133:                                charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
                    134:                                return;
                    135:                        }
                    136:                }
                    137:        }
                    138: }
                    139: 
                    140: /**
                    141:  * lookup UID and GID
                    142:  */
                    143: static bool lookup_uid_gid()
                    144: {
                    145:        char *name;
                    146: 
                    147:        name = lib->settings->get_str(lib->settings, "charon.user", IPSEC_USER);
                    148:        if (name && !lib->caps->resolve_uid(lib->caps, name))
                    149:        {
                    150:                return FALSE;
                    151:        }
                    152:        name = lib->settings->get_str(lib->settings, "charon.group", IPSEC_GROUP);
                    153:        if (name && !lib->caps->resolve_gid(lib->caps, name))
                    154:        {
                    155:                return FALSE;
                    156:        }
                    157: #ifdef ANDROID
                    158:        lib->caps->set_uid(lib->caps, AID_VPN);
                    159: #endif
                    160:        return TRUE;
                    161: }
                    162: 
                    163: /**
                    164:  * Handle SIGSEGV/SIGILL signals raised by threads
                    165:  */
                    166: #ifndef DISABLE_SIGNAL_HANDLER
                    167: static void segv_handler(int signal)
                    168: {
                    169:        backtrace_t *backtrace;
                    170: 
                    171:        DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
                    172:        backtrace = backtrace_create(2);
                    173:        backtrace->log(backtrace, NULL, TRUE);
                    174:        backtrace->log(backtrace, stderr, TRUE);
                    175:        backtrace->destroy(backtrace);
                    176: 
                    177:        DBG1(DBG_DMN, "killing ourself, received critical signal");
                    178:        abort();
                    179: }
                    180: #endif /* DISABLE_SIGNAL_HANDLER */
                    181: 
                    182: /**
                    183:  * Check/create PID file, return TRUE if already running
                    184:  */
                    185: static bool check_pidfile()
                    186: {
                    187:        struct stat stb;
                    188: 
                    189:        if (stat(PID_FILE, &stb) == 0)
                    190:        {
                    191:                pidfile = fopen(PID_FILE, "r");
                    192:                if (pidfile)
                    193:                {
                    194:                        char buf[64];
                    195:                        pid_t pid = 0;
                    196: 
                    197:                        memset(buf, 0, sizeof(buf));
                    198:                        if (fread(buf, 1, sizeof(buf), pidfile))
                    199:                        {
                    200:                                buf[sizeof(buf) - 1] = '\0';
                    201:                                pid = atoi(buf);
                    202:                        }
                    203:                        fclose(pidfile);
                    204:                        pidfile = NULL;
                    205:                        if (pid && pid != getpid() && kill(pid, 0) == 0)
                    206:                        {
                    207:                                DBG1(DBG_DMN, "charon already running ('"PID_FILE"' exists)");
                    208:                                return TRUE;
                    209:                        }
                    210:                }
                    211:                DBG1(DBG_DMN, "removing pidfile '"PID_FILE"', process not running");
                    212:                unlink(PID_FILE);
                    213:        }
                    214: 
                    215:        /* create new pidfile */
                    216:        pidfile = fopen(PID_FILE, "w");
                    217:        if (pidfile)
                    218:        {
                    219:                int fd;
                    220: 
                    221:                fd = fileno(pidfile);
                    222:                if (fd == -1)
                    223:                {
                    224:                        DBG1(DBG_DMN, "unable to determine fd for '"PID_FILE"'");
                    225:                        return TRUE;
                    226:                }
                    227:                if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
                    228:                {
                    229:                        DBG1(DBG_LIB, "setting FD_CLOEXEC for '"PID_FILE"' failed: %s",
                    230:                                 strerror(errno));
                    231:                }
                    232:                /* Only change owner of the pidfile if we have CAP_CHOWN. Otherwise,
                    233:                 * attempt to change group of pidfile to group under which charon
                    234:                 * runs after dropping caps. This requires the user that charon
                    235:                 * starts as to:
                    236:                 * a) Have write access to the socket dir.
                    237:                 * b) Belong to the group that charon will run under after dropping
                    238:                 *    caps. */
                    239:                if (lib->caps->check(lib->caps, CAP_CHOWN))
                    240:                {
                    241:                        ignore_result(fchown(fd,
                    242:                                                                 lib->caps->get_uid(lib->caps),
                    243:                                                                 lib->caps->get_gid(lib->caps)));
                    244:                }
                    245:                else
                    246:                {
                    247:                        ignore_result(fchown(fd, -1,
                    248:                                                                 lib->caps->get_gid(lib->caps)));
                    249:                }
                    250:                fprintf(pidfile, "%d\n", getpid());
                    251:                fflush(pidfile);
                    252:                return FALSE;
                    253:        }
                    254:        else
                    255:        {
                    256:                DBG1(DBG_DMN, "unable to create pidfile '"PID_FILE"'");
                    257:                return TRUE;
                    258:        }
                    259: }
                    260: 
                    261: /**
                    262:  * Delete/truncate the PID file
                    263:  */
                    264: static void unlink_pidfile()
                    265: {
                    266:        /* because unlinking the PID file may fail, we truncate it to ensure the
                    267:         * daemon can be properly restarted.  one probable cause for this is the
                    268:         * combination of not running as root and the effective user lacking
                    269:         * permissions on the parent dir(s) of the PID file */
                    270:        if (pidfile)
                    271:        {
                    272:                ignore_result(ftruncate(fileno(pidfile), 0));
                    273:                fclose(pidfile);
                    274:                unlink(PID_FILE);
                    275:        }
                    276: }
                    277: 
                    278: /**
                    279:  * print command line usage and exit
                    280:  */
                    281: static void usage(const char *msg)
                    282: {
                    283:        if (msg != NULL && *msg != '\0')
                    284:        {
                    285:                fprintf(stderr, "%s\n", msg);
                    286:        }
                    287:        fprintf(stderr, "Usage: charon\n"
                    288:                                        "         [--help]\n"
                    289:                                        "         [--version]\n"
                    290:                                        "         [--use-syslog]\n"
                    291:                                        "         [--debug-<type> <level>]\n"
                    292:                                        "           <type>:  log context type (dmn|mgr|ike|chd|job|cfg|knl|net|asn|enc|tnc|imc|imv|pts|tls|esp|lib)\n"
                    293:                                        "           <level>: log verbosity (-1 = silent, 0 = audit, 1 = control,\n"
                    294:                                        "                                    2 = controlmore, 3 = raw, 4 = private)\n"
                    295:                                        "\n"
                    296:                   );
                    297: }
                    298: 
                    299: /**
                    300:  * Main function, starts the daemon.
                    301:  */
                    302: int main(int argc, char *argv[])
                    303: {
                    304:        struct sigaction action;
                    305:        int group, status = SS_RC_INITIALIZATION_FAILED;
                    306:        struct utsname utsname;
                    307:        level_t levels[DBG_MAX];
                    308:        bool use_syslog = FALSE;
                    309: 
                    310:        /* logging for library during initialization, as we have no bus yet */
                    311:        dbg = dbg_stderr;
                    312: 
                    313:        /* initialize library */
                    314:        if (!library_init(NULL, "charon"))
                    315:        {
                    316:                library_deinit();
                    317:                exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
                    318:        }
                    319: 
                    320:        if (lib->integrity &&
                    321:                !lib->integrity->check_file(lib->integrity, "charon", argv[0]))
                    322:        {
                    323:                dbg_stderr(DBG_DMN, 1, "integrity check of charon failed");
                    324:                library_deinit();
                    325:                exit(SS_RC_DAEMON_INTEGRITY);
                    326:        }
                    327: 
                    328:        if (!libcharon_init())
                    329:        {
                    330:                dbg_stderr(DBG_DMN, 1, "initialization failed - aborting charon");
                    331:                goto deinit;
                    332:        }
                    333: 
                    334:        /* use CTRL loglevel for default */
                    335:        for (group = 0; group < DBG_MAX; group++)
                    336:        {
                    337:                levels[group] = LEVEL_CTRL;
                    338:        }
                    339: 
                    340:        /* handle arguments */
                    341:        for (;;)
                    342:        {
                    343:                struct option long_opts[] = {
                    344:                        { "help", no_argument, NULL, 'h' },
                    345:                        { "version", no_argument, NULL, 'v' },
                    346:                        { "use-syslog", no_argument, NULL, 'l' },
                    347:                        /* TODO: handle "debug-all" */
                    348:                        { "debug-dmn", required_argument, &group, DBG_DMN },
                    349:                        { "debug-mgr", required_argument, &group, DBG_MGR },
                    350:                        { "debug-ike", required_argument, &group, DBG_IKE },
                    351:                        { "debug-chd", required_argument, &group, DBG_CHD },
                    352:                        { "debug-job", required_argument, &group, DBG_JOB },
                    353:                        { "debug-cfg", required_argument, &group, DBG_CFG },
                    354:                        { "debug-knl", required_argument, &group, DBG_KNL },
                    355:                        { "debug-net", required_argument, &group, DBG_NET },
                    356:                        { "debug-asn", required_argument, &group, DBG_ASN },
                    357:                        { "debug-enc", required_argument, &group, DBG_ENC },
                    358:                        { "debug-tnc", required_argument, &group, DBG_TNC },
                    359:                        { "debug-imc", required_argument, &group, DBG_IMC },
                    360:                        { "debug-imv", required_argument, &group, DBG_IMV },
                    361:                        { "debug-pts", required_argument, &group, DBG_PTS },
                    362:                        { "debug-tls", required_argument, &group, DBG_TLS },
                    363:                        { "debug-esp", required_argument, &group, DBG_ESP },
                    364:                        { "debug-lib", required_argument, &group, DBG_LIB },
                    365:                        { 0,0,0,0 }
                    366:                };
                    367: 
                    368:                int c = getopt_long(argc, argv, "", long_opts, NULL);
                    369:                switch (c)
                    370:                {
                    371:                        case EOF:
                    372:                                break;
                    373:                        case 'h':
                    374:                                usage(NULL);
                    375:                                status = 0;
                    376:                                goto deinit;
                    377:                        case 'v':
1.1.1.2 ! misho     378:                                printf("Linux strongSwan %s\n", VERSION);
1.1       misho     379:                                status = 0;
                    380:                                goto deinit;
                    381:                        case 'l':
                    382:                                use_syslog = TRUE;
                    383:                                continue;
                    384:                        case 0:
                    385:                                /* option is in group */
                    386:                                levels[group] = atoi(optarg);
                    387:                                continue;
                    388:                        default:
                    389:                                usage("");
                    390:                                status = 1;
                    391:                                goto deinit;
                    392:                }
                    393:                break;
                    394:        }
                    395: 
                    396:        if (!lookup_uid_gid())
                    397:        {
                    398:                dbg_stderr(DBG_DMN, 1, "invalid uid/gid - aborting charon");
                    399:                goto deinit;
                    400:        }
                    401: 
                    402:        charon->set_default_loggers(charon, levels, !use_syslog);
                    403:        charon->load_loggers(charon);
                    404: 
                    405:        if (uname(&utsname) != 0)
                    406:        {
                    407:                memset(&utsname, 0, sizeof(utsname));
                    408:        }
                    409:        DBG1(DBG_DMN, "Starting IKE charon daemon (strongSwan "VERSION", %s %s, %s)",
                    410:                  utsname.sysname, utsname.release, utsname.machine);
                    411:        if (lib->integrity)
                    412:        {
                    413:                DBG1(DBG_DMN, "integrity tests enabled:");
                    414:                DBG1(DBG_DMN, "lib    'libstrongswan': passed file and segment integrity tests");
                    415:                DBG1(DBG_DMN, "lib    'libcharon': passed file and segment integrity tests");
                    416:                DBG1(DBG_DMN, "daemon 'charon': passed file integrity test");
                    417:        }
                    418: 
                    419:        /* initialize daemon */
                    420:        if (!charon->initialize(charon,
                    421:                                lib->settings->get_str(lib->settings, "charon.load", PLUGINS)))
                    422:        {
                    423:                DBG1(DBG_DMN, "initialization failed - aborting charon");
                    424:                goto deinit;
                    425:        }
                    426:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
                    427: 
                    428:        if (check_pidfile())
                    429:        {
                    430:                goto deinit;
                    431:        }
                    432: 
                    433:        if (!lib->caps->drop(lib->caps))
                    434:        {
                    435:                DBG1(DBG_DMN, "capability dropping failed - aborting charon");
                    436:                goto deinit;
                    437:        }
                    438: 
                    439:        /* add handler for fatal signals,
                    440:         * INT, TERM and HUP are handled by sigwaitinfo() in run() */
                    441:        action.sa_flags = 0;
                    442:        sigemptyset(&action.sa_mask);
                    443:        sigaddset(&action.sa_mask, SIGINT);
                    444:        sigaddset(&action.sa_mask, SIGTERM);
                    445:        sigaddset(&action.sa_mask, SIGHUP);
                    446: 
                    447:        /* optionally let the external system handle fatal signals */
                    448: #ifndef DISABLE_SIGNAL_HANDLER
                    449:        action.sa_handler = segv_handler;
                    450:        sigaction(SIGSEGV, &action, NULL);
                    451:        sigaction(SIGILL, &action, NULL);
                    452:        sigaction(SIGBUS, &action, NULL);
                    453: #endif /* DISABLE_SIGNAL_HANDLER */
                    454: 
                    455:        action.sa_handler = SIG_IGN;
                    456:        sigaction(SIGPIPE, &action, NULL);
                    457: 
                    458:        pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
                    459: 
                    460:        /* start daemon (i.e. the threads in the thread-pool) */
                    461:        charon->start(charon);
                    462: 
                    463:        /* main thread goes to run loop */
                    464:        run();
                    465: 
                    466:        status = 0;
                    467: 
                    468: deinit:
                    469:        libcharon_deinit();
                    470:        unlink_pidfile();
                    471:        library_deinit();
                    472:        return status;
                    473: }

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