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

1.1       misho       1: /*
                      2:  * Copyright (C) 2010 Martin Willi
                      3:  * Copyright (C) 2010 revosec AG
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #define _GNU_SOURCE
                     17: #include <unistd.h>
                     18: #include <stdio.h>
                     19: #include <errno.h>
                     20: #include <signal.h>
                     21: #include <getopt.h>
                     22: #include <dlfcn.h>
                     23: #include <libgen.h>
                     24: 
                     25: #include "conftest.h"
                     26: #include "config.h"
                     27: #include "hooks/hook.h"
                     28: 
                     29: #include <bus/listeners/file_logger.h>
                     30: #include <threading/thread.h>
                     31: #include <credentials/certificates/x509.h>
                     32: 
                     33: /**
                     34:  * Conftest globals struct
                     35:  */
                     36: conftest_t *conftest;
                     37: 
                     38: /**
                     39:  * Print usage information
                     40:  */
                     41: static void usage(FILE *out)
                     42: {
                     43:        fprintf(out, "Usage:\n");
                     44:        fprintf(out, "  --help           show usage information\n");
                     45:        fprintf(out, "  --version        show conftest version\n");
                     46:        fprintf(out, "  --suite <file>   global testsuite configuration "
                     47:                                                                         "(default: ./suite.conf)\n");
                     48:        fprintf(out, "  --test <file>    test specific configuration\n");
                     49: }
                     50: 
                     51: /**
                     52:  * Handle SIGSEGV/SIGILL signals raised by threads
                     53:  */
                     54: static void segv_handler(int signal)
                     55: {
                     56:        fprintf(stderr, "thread %u received %d\n", thread_current_id(), signal);
                     57:        abort();
                     58: }
                     59: 
                     60: /**
                     61:  * Load suite and test specific configurations
                     62:  */
                     63: static bool load_configs(char *suite_file, char *test_file)
                     64: {
                     65:        if (!test_file)
                     66:        {
                     67:                fprintf(stderr, "Missing test configuration file.\n");
                     68:                return FALSE;
                     69:        }
                     70:        if (access(suite_file, R_OK) != 0)
                     71:        {
                     72:                fprintf(stderr, "Reading suite configuration file '%s' failed: %s.\n",
                     73:                                suite_file, strerror(errno));
                     74:                return FALSE;
                     75:        }
                     76:        if (access(test_file, R_OK) != 0)
                     77:        {
                     78:                fprintf(stderr, "Reading test configuration file '%s' failed: %s.\n",
                     79:                                test_file, strerror(errno));
                     80:                return FALSE;
                     81:        }
                     82:        conftest->test = settings_create(suite_file);
                     83:        conftest->test->load_files(conftest->test, test_file, TRUE);
                     84:        conftest->suite_dir = path_dirname(suite_file);
                     85:        return TRUE;
                     86: }
                     87: 
                     88: /**
                     89:  * Load trusted/untrusted certificates
                     90:  */
                     91: static bool load_cert(settings_t *settings, bool trusted)
                     92: {
                     93:        enumerator_t *enumerator;
                     94:        char *key, *value;
                     95: 
                     96:        enumerator = settings->create_key_value_enumerator(settings,
                     97:                                                                trusted ? "certs.trusted" : "certs.untrusted");
                     98:        while (enumerator->enumerate(enumerator, &key, &value))
                     99:        {
                    100:                certificate_t *cert = NULL;
                    101: 
                    102:                if (strncaseeq(key, "x509", strlen("x509")))
                    103:                {
                    104:                        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                    105:                                                        CERT_X509, BUILD_FROM_FILE, value, BUILD_END);
                    106:                }
                    107:                else if (strncaseeq(key, "crl", strlen("crl")))
                    108:                {
                    109:                        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                    110:                                                        CERT_X509_CRL, BUILD_FROM_FILE, value, BUILD_END);
                    111:                }
                    112:                else
                    113:                {
                    114:                        fprintf(stderr, "certificate type '%s' not supported\n", key);
                    115:                        enumerator->destroy(enumerator);
                    116:                        return FALSE;
                    117:                }
                    118:                if (!cert)
                    119:                {
                    120:                        fprintf(stderr, "loading %strusted certificate '%s' from '%s' "
                    121:                                        "failed\n", trusted ? "" : "un", key, value);
                    122:                        enumerator->destroy(enumerator);
                    123:                        return FALSE;
                    124:                }
                    125:                conftest->creds->add_cert(conftest->creds, trusted, cert);
                    126:        }
                    127:        enumerator->destroy(enumerator);
                    128:        return TRUE;
                    129: }
                    130: 
                    131: /**
                    132:  * Load certificates from the configuration file
                    133:  */
                    134: static bool load_certs(settings_t *settings, char *dir)
                    135: {
                    136:        char wd[PATH_MAX];
                    137: 
                    138:        if (getcwd(wd, sizeof(wd)) == NULL)
                    139:        {
                    140:                fprintf(stderr, "getting cwd failed: %s\n", strerror(errno));
                    141:                return FALSE;
                    142:        }
                    143:        if (chdir(dir) != 0)
                    144:        {
                    145:                fprintf(stderr, "opening directory '%s' failed: %s\n",
                    146:                                dir, strerror(errno));
                    147:                return FALSE;
                    148:        }
                    149: 
                    150:        if (!load_cert(settings, TRUE) ||
                    151:                !load_cert(settings, FALSE))
                    152:        {
                    153:                return FALSE;
                    154:        }
                    155: 
                    156:        if (chdir(wd) != 0)
                    157:        {
                    158:                fprintf(stderr, "opening directory '%s' failed: %s\n",
                    159:                                wd, strerror(errno));
                    160:                return FALSE;
                    161:        }
                    162:        return TRUE;
                    163: }
                    164: 
                    165: /**
                    166:  * Load private keys from the configuration file
                    167:  */
                    168: static bool load_keys(settings_t *settings, char *dir)
                    169: {
                    170:        enumerator_t *enumerator;
                    171:        char *type, *value, wd[PATH_MAX];
                    172:        private_key_t *key;
                    173:        key_type_t key_type;
                    174: 
                    175:        if (getcwd(wd, sizeof(wd)) == NULL)
                    176:        {
                    177:                fprintf(stderr, "getting cwd failed: %s\n", strerror(errno));
                    178:                return FALSE;
                    179:        }
                    180:        if (chdir(dir) != 0)
                    181:        {
                    182:                fprintf(stderr, "opening directory '%s' failed: %s\n",
                    183:                                dir, strerror(errno));
                    184:                return FALSE;
                    185:        }
                    186: 
                    187:        enumerator = settings->create_key_value_enumerator(settings, "keys");
                    188:        while (enumerator->enumerate(enumerator, &type, &value))
                    189:        {
                    190:                if (strncaseeq(type, "ecdsa", strlen("ecdsa")))
                    191:                {
                    192:                        key_type = KEY_ECDSA;
                    193:                }
                    194:                else if (strncaseeq(type, "rsa", strlen("rsa")))
                    195:                {
                    196:                        key_type = KEY_RSA;
                    197:                }
                    198:                else
                    199:                {
                    200:                        fprintf(stderr, "unknown key type: '%s'\n", type);
                    201:                        enumerator->destroy(enumerator);
                    202:                        return FALSE;
                    203:                }
                    204:                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, key_type,
                    205:                                                                 BUILD_FROM_FILE, value, BUILD_END);
                    206:                if (!key)
                    207:                {
                    208:                        fprintf(stderr, "loading %s key from '%s' failed\n", type, value);
                    209:                        enumerator->destroy(enumerator);
                    210:                        return FALSE;
                    211:                }
                    212:                conftest->creds->add_key(conftest->creds, key);
                    213:        }
                    214:        enumerator->destroy(enumerator);
                    215: 
                    216:        if (chdir(wd) != 0)
                    217:        {
                    218:                fprintf(stderr, "opening directory '%s' failed: %s\n",
                    219:                                wd, strerror(errno));
                    220:                return FALSE;
                    221:        }
                    222:        return TRUE;
                    223: }
                    224: 
                    225: /**
                    226:  * Load certificate distribution points
                    227:  */
                    228: static void load_cdps(settings_t *settings)
                    229: {
                    230:        enumerator_t *enumerator;
                    231:        identification_t *id;
                    232:        char *ca, *uri, *section;
                    233:        certificate_type_t type;
                    234:        x509_t *x509;
                    235: 
                    236:        enumerator = settings->create_section_enumerator(settings, "cdps");
                    237:        while (enumerator->enumerate(enumerator, &section))
                    238:        {
                    239:                if (strncaseeq(section, "crl", strlen("crl")))
                    240:                {
                    241:                        type = CERT_X509_CRL;
                    242:                }
                    243:                else if (strncaseeq(section, "ocsp", strlen("ocsp")))
                    244:                {
                    245:                        type = CERT_X509_OCSP_RESPONSE;
                    246:                }
                    247:                else
                    248:                {
                    249:                        fprintf(stderr, "unknown cdp type '%s', ignored\n", section);
                    250:                        continue;
                    251:                }
                    252: 
                    253:                uri = settings->get_str(settings, "cdps.%s.uri", NULL, section);
                    254:                ca = settings->get_str(settings, "cdps.%s.ca", NULL, section);
                    255:                if (!ca || !uri)
                    256:                {
                    257:                        fprintf(stderr, "cdp '%s' misses ca/uri, ignored\n", section);
                    258:                        continue;
                    259:                }
                    260:                x509 = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                    261:                                                        CERT_X509, BUILD_FROM_FILE, ca, BUILD_END);
                    262:                if (!x509)
                    263:                {
                    264:                        fprintf(stderr, "loading cdp '%s' ca failed, ignored\n", section);
                    265:                        continue;
                    266:                }
                    267:                id = identification_create_from_encoding(ID_KEY_ID,
                    268:                                                                        x509->get_subjectKeyIdentifier(x509));
                    269:                conftest->creds->add_cdp(conftest->creds, type, id, uri);
                    270:                DESTROY_IF((certificate_t*)x509);
                    271:                id->destroy(id);
                    272:        }
                    273:        enumerator->destroy(enumerator);
                    274: }
                    275: 
                    276: /**
                    277:  * Load configured hooks
                    278:  */
                    279: static bool load_hooks()
                    280: {
                    281:        enumerator_t *enumerator;
                    282:        char *name, *pos, buf[64];
                    283:        hook_t *(*create)(char*);
                    284:        hook_t *hook;
                    285: 
                    286:        enumerator = conftest->test->create_section_enumerator(conftest->test,
                    287:                                                                                                                   "hooks");
                    288:        while (enumerator->enumerate(enumerator, &name))
                    289:        {
                    290:                pos = strchr(name, '-');
                    291:                if (pos)
                    292:                {
                    293:                        snprintf(buf, sizeof(buf), "%.*s_hook_create", (int)(pos - name),
                    294:                                         name);
                    295:                }
                    296:                else
                    297:                {
                    298:                        snprintf(buf, sizeof(buf), "%s_hook_create", name);
                    299:                }
                    300:                create = dlsym(RTLD_DEFAULT, buf);
                    301:                if (create)
                    302:                {
                    303:                        hook = create(name);
                    304:                        if (hook)
                    305:                        {
                    306:                                conftest->hooks->insert_last(conftest->hooks, hook);
                    307:                                charon->bus->add_listener(charon->bus, &hook->listener);
                    308:                        }
                    309:                }
                    310:                else
                    311:                {
                    312:                        fprintf(stderr, "dlsym() for hook '%s' failed: %s\n", name, dlerror());
                    313:                        enumerator->destroy(enumerator);
                    314:                        return FALSE;
                    315:                }
                    316:        }
                    317:        enumerator->destroy(enumerator);
                    318:        return TRUE;
                    319: }
                    320: 
                    321: /**
                    322:  * atexit() cleanup handler
                    323:  */
                    324: static void cleanup()
                    325: {
                    326:        file_logger_t *logger;
                    327:        hook_t *hook;
                    328: 
                    329:        DESTROY_IF(conftest->test);
                    330:        lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set);
                    331:        conftest->creds->destroy(conftest->creds);
                    332:        DESTROY_IF(conftest->actions);
                    333:        while (conftest->hooks->remove_last(conftest->hooks,
                    334:                                                                                (void**)&hook) == SUCCESS)
                    335:        {
                    336:                charon->bus->remove_listener(charon->bus, &hook->listener);
                    337:                hook->destroy(hook);
                    338:        }
                    339:        conftest->hooks->destroy(conftest->hooks);
                    340:        if (conftest->config)
                    341:        {
                    342:                if (charon->backends)
                    343:                {
                    344:                        charon->backends->remove_backend(charon->backends,
                    345:                                                                                         &conftest->config->backend);
                    346:                }
                    347:                conftest->config->destroy(conftest->config);
                    348:        }
                    349:        while (conftest->loggers->remove_last(conftest->loggers,
                    350:                                                                                  (void**)&logger) == SUCCESS)
                    351:        {
                    352:                charon->bus->remove_logger(charon->bus, &logger->logger);
                    353:                logger->destroy(logger);
                    354:        }
                    355:        conftest->loggers->destroy(conftest->loggers);
                    356:        free(conftest->suite_dir);
                    357:        free(conftest);
                    358:        libcharon_deinit();
                    359:        library_deinit();
                    360: }
                    361: 
                    362: /**
                    363:  * Load log levels for a logger from section
                    364:  */
                    365: static void load_log_levels(file_logger_t *logger, char *section)
                    366: {
                    367:        debug_t group;
                    368:        level_t  def;
                    369: 
                    370:        def = conftest->test->get_int(conftest->test, "log.%s.default", 1, section);
                    371:        for (group = 0; group < DBG_MAX; group++)
                    372:        {
                    373:                logger->set_level(logger, group,
                    374:                                        conftest->test->get_int(conftest->test, "log.%s.%N", def,
                    375:                                                                                        section, debug_lower_names, group));
                    376:        }
                    377: }
                    378: 
                    379: /**
                    380:  * Load logger options for a logger from section
                    381:  */
                    382: static void load_logger_options(file_logger_t *logger, char *section)
                    383: {
                    384:        char *time_format;
1.1.1.2 ! misho     385:        bool add_ms, ike_name, log_level;
1.1       misho     386: 
                    387:        time_format = conftest->test->get_str(conftest->test,
                    388:                                        "log.%s.time_format", NULL, section);
                    389:        add_ms = conftest->test->get_bool(conftest->test,
                    390:                                        "log.%s.time_add_ms", FALSE, section);
                    391:        ike_name = conftest->test->get_bool(conftest->test,
                    392:                                        "log.%s.ike_name", FALSE, section);
1.1.1.2 ! misho     393:        log_level = conftest->test->get_bool(conftest->test,
        !           394:                                        "log.%s.log_level", FALSE, section);
1.1       misho     395: 
1.1.1.2 ! misho     396:        logger->set_options(logger, time_format, add_ms, ike_name, log_level);
1.1       misho     397: }
                    398: 
                    399: /**
                    400:  * Load logger configuration
                    401:  */
                    402: static void load_loggers(file_logger_t *logger)
                    403: {
                    404:        enumerator_t *enumerator;
                    405:        char *section;
                    406: 
                    407:        load_log_levels(logger, "stdout");
                    408:        load_logger_options(logger, "stdout");
                    409:        /* Re-add the logger to propagate configuration changes to the
                    410:         * logging system */
                    411:        charon->bus->add_logger(charon->bus, &logger->logger);
                    412: 
                    413:        enumerator = conftest->test->create_section_enumerator(conftest->test, "log");
                    414:        while (enumerator->enumerate(enumerator, &section))
                    415:        {
                    416:                if (!streq(section, "stdout"))
                    417:                {
                    418:                        logger = file_logger_create(section);
                    419:                        load_logger_options(logger, section);
                    420:                        logger->open(logger, FALSE, FALSE);
                    421:                        load_log_levels(logger, section);
                    422:                        charon->bus->add_logger(charon->bus, &logger->logger);
                    423:                        conftest->loggers->insert_last(conftest->loggers, logger);
                    424:                }
                    425:        }
                    426:        enumerator->destroy(enumerator);
                    427: }
                    428: 
                    429: /**
                    430:  * Main function, starts the conftest daemon.
                    431:  */
                    432: int main(int argc, char *argv[])
                    433: {
                    434:        struct sigaction action;
                    435:        int status = 0;
                    436:        sigset_t set;
                    437:        int sig;
                    438:        char *suite_file = "suite.conf", *test_file = NULL, *preload, *plugins;
                    439:        file_logger_t *logger;
                    440: 
                    441:        if (!library_init(NULL, "conftest"))
                    442:        {
                    443:                library_deinit();
                    444:                return SS_RC_LIBSTRONGSWAN_INTEGRITY;
                    445:        }
                    446:        if (!libcharon_init())
                    447:        {
                    448:                libcharon_deinit();
                    449:                library_deinit();
                    450:                return SS_RC_INITIALIZATION_FAILED;
                    451:        }
                    452: 
                    453:        INIT(conftest,
                    454:                .creds = mem_cred_create(),
                    455:                .config = config_create(),
                    456:                .hooks = linked_list_create(),
                    457:                .loggers = linked_list_create(),
                    458:        );
                    459:        lib->credmgr->add_set(lib->credmgr, &conftest->creds->set);
                    460: 
                    461:        logger = file_logger_create("stdout");
1.1.1.2 ! misho     462:        logger->set_options(logger, NULL, FALSE, FALSE, FALSE);
1.1       misho     463:        logger->open(logger, FALSE, FALSE);
                    464:        logger->set_level(logger, DBG_ANY, LEVEL_CTRL);
                    465:        charon->bus->add_logger(charon->bus, &logger->logger);
                    466:        conftest->loggers->insert_last(conftest->loggers, logger);
                    467: 
                    468:        atexit(cleanup);
                    469: 
                    470:        while (TRUE)
                    471:        {
                    472:                struct option long_opts[] = {
                    473:                        { "help", no_argument, NULL, 'h' },
                    474:                        { "version", no_argument, NULL, 'v' },
                    475:                        { "suite", required_argument, NULL, 's' },
                    476:                        { "test", required_argument, NULL, 't' },
                    477:                        { 0,0,0,0 }
                    478:                };
                    479:                switch (getopt_long(argc, argv, "", long_opts, NULL))
                    480:                {
                    481:                        case EOF:
                    482:                                break;
                    483:                        case 'h':
                    484:                                usage(stdout);
                    485:                                return 0;
                    486:                        case 'v':
                    487:                                printf("strongSwan %s conftest\n", VERSION);
                    488:                                return 0;
                    489:                        case 's':
                    490:                                suite_file = optarg;
                    491:                                continue;
                    492:                        case 't':
                    493:                                test_file = optarg;
                    494:                                continue;
                    495:                        default:
                    496:                                usage(stderr);
                    497:                                return 1;
                    498:                }
                    499:                break;
                    500:        }
                    501: 
                    502:        if (!load_configs(suite_file, test_file))
                    503:        {
                    504:                return 1;
                    505:        }
                    506:        load_loggers(logger);
                    507: 
                    508:        preload = conftest->test->get_str(conftest->test, "preload", "");
                    509:        if (asprintf(&plugins, "%s %s", preload, PLUGINS) < 0)
                    510:        {
                    511:                return 1;
                    512:        }
                    513:        if (!charon->initialize(charon, plugins))
                    514:        {
                    515:                free(plugins);
                    516:                return 1;
                    517:        }
                    518:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
                    519:        free(plugins);
                    520: 
                    521:        if (!load_certs(conftest->test, conftest->suite_dir))
                    522:        {
                    523:                return 1;
                    524:        }
                    525:        if (!load_keys(conftest->test, conftest->suite_dir))
                    526:        {
                    527:                return 1;
                    528:        }
                    529:        load_cdps(conftest->test);
                    530:        if (!load_hooks())
                    531:        {
                    532:                return 1;
                    533:        }
                    534:        charon->backends->add_backend(charon->backends, &conftest->config->backend);
                    535:        conftest->config->load(conftest->config, conftest->test);
                    536:        conftest->actions = actions_create();
                    537: 
                    538:        /* set up thread specific handlers */
                    539:        action.sa_handler = segv_handler;
                    540:        action.sa_flags = 0;
                    541:        sigemptyset(&action.sa_mask);
                    542:        sigaddset(&action.sa_mask, SIGINT);
                    543:        sigaddset(&action.sa_mask, SIGTERM);
                    544:        sigaddset(&action.sa_mask, SIGHUP);
                    545:        sigaction(SIGSEGV, &action, NULL);
                    546:        sigaction(SIGILL, &action, NULL);
                    547:        sigaction(SIGBUS, &action, NULL);
                    548:        action.sa_handler = SIG_IGN;
                    549:        sigaction(SIGPIPE, &action, NULL);
                    550:        pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
                    551: 
                    552:        /* start thread pool */
                    553:        charon->start(charon);
                    554: 
                    555:        /* handle SIGINT/SIGTERM in main thread */
                    556:        sigemptyset(&set);
                    557:        sigaddset(&set, SIGINT);
                    558:        sigaddset(&set, SIGHUP);
                    559:        sigaddset(&set, SIGTERM);
                    560:        sigprocmask(SIG_BLOCK, &set, NULL);
                    561: 
                    562:        while ((sig = sigwaitinfo(&set, NULL)) != -1 || errno == EINTR)
                    563:        {
                    564:                switch (sig)
                    565:                {
                    566:                        case SIGINT:
                    567:                        case SIGTERM:
                    568:                                fprintf(stderr, "\nshutting down...\n");
                    569:                                break;
                    570:                        default:
                    571:                                continue;
                    572:                }
                    573:                break;
                    574:        }
                    575:        return status;
                    576: }

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