Annotation of embedaddon/strongswan/src/libstrongswan/library.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2009-2018 Tobias Brunner
                      3:  * Copyright (C) 2008 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #include "library.h"
                     18: 
                     19: #include <stdlib.h>
                     20: 
                     21: #include <utils/debug.h>
                     22: #include <threading/thread.h>
                     23: #include <utils/identification.h>
                     24: #include <networking/host.h>
                     25: #include <collections/array.h>
                     26: #include <collections/hashtable.h>
                     27: #include <utils/backtrace.h>
                     28: #include <selectors/traffic_selector.h>
                     29: #include <crypto/proposal/proposal.h>
                     30: 
                     31: #define CHECKSUM_LIBRARY IPSEC_LIB_DIR"/libchecksum.so"
                     32: 
                     33: #ifndef STRONGSWAN_CONF
                     34: #define STRONGSWAN_CONF NULL
                     35: #endif
                     36: 
                     37: typedef struct private_library_t private_library_t;
                     38: 
                     39: /**
                     40:  * private data of library
                     41:  */
                     42: struct private_library_t {
                     43: 
                     44:        /**
                     45:         * public functions
                     46:         */
                     47:        library_t public;
                     48: 
                     49:        /**
                     50:         * Hashtable with registered objects (name => object)
                     51:         */
                     52:        hashtable_t *objects;
                     53: 
                     54:        /**
                     55:         * Integrity check failed?
                     56:         */
                     57:        bool init_failed;
                     58: 
                     59: #ifdef LEAK_DETECTIVE
                     60:        /**
                     61:         * Where to write leak detective output to
                     62:         */
                     63:        FILE *ld_out;
                     64: #endif
                     65: 
                     66:        /**
                     67:         * Number of times we have been initialized
                     68:         */
                     69:        refcount_t ref;
                     70: };
                     71: 
                     72: #define MAX_NAMESPACES 5
                     73: 
                     74: /**
                     75:  * Additional namespaces registered using __attribute__((constructor))
                     76:  */
                     77: static char *namespaces[MAX_NAMESPACES];
                     78: static int ns_count;
                     79: 
                     80: /**
                     81:  * Described in header
                     82:  */
                     83: void library_add_namespace(char *ns)
                     84: {
                     85:        if (ns_count < MAX_NAMESPACES - 1)
                     86:        {
                     87:                namespaces[ns_count] = ns;
                     88:                ns_count++;
                     89:        }
                     90:        else
                     91:        {
                     92:                fprintf(stderr, "failed to register additional namespace alias, please "
                     93:                                "increase MAX_NAMESPACES");
                     94:        }
                     95: }
                     96: 
                     97: /**
                     98:  * Register plugins if built statically
                     99:  */
                    100: #ifdef STATIC_PLUGIN_CONSTRUCTORS
                    101: #include "plugin_constructors.c"
                    102: #endif
                    103: 
                    104: /**
                    105:  * library instance
                    106:  */
                    107: library_t *lib = NULL;
                    108: 
                    109: #ifdef LEAK_DETECTIVE
                    110: /**
                    111:  * Default leak report callback
                    112:  */
                    113: CALLBACK(report_leaks, void,
                    114:        private_library_t *this, int count, size_t bytes, backtrace_t *bt,
                    115:        bool detailed)
                    116: {
                    117:        fprintf(this->ld_out, "%zu bytes total, %d allocations, %zu bytes average:\n",
                    118:                        bytes, count, bytes / count);
                    119:        bt->log(bt, this->ld_out, detailed);
                    120: }
                    121: 
                    122: /**
                    123:  * Default leak report summary callback
                    124:  */
                    125: CALLBACK(sum_leaks, void,
                    126:        private_library_t *this, int count, size_t bytes, int whitelisted)
                    127: {
                    128:        switch (count)
                    129:        {
                    130:                case 0:
                    131:                        fprintf(this->ld_out, "No leaks detected");
                    132:                        break;
                    133:                case 1:
                    134:                        fprintf(this->ld_out, "One leak detected");
                    135:                        break;
                    136:                default:
                    137:                        fprintf(this->ld_out, "%d leaks detected, %zu bytes", count, bytes);
                    138:                        break;
                    139:        }
                    140:        fprintf(this->ld_out, ", %d suppressed by whitelist\n", whitelisted);
                    141: }
                    142: #endif /* LEAK_DETECTIVE */
                    143: 
                    144: /**
                    145:  * Deinitialize library
                    146:  */
                    147: void library_deinit()
                    148: {
                    149:        private_library_t *this = (private_library_t*)lib;
                    150:        bool detailed;
                    151: 
                    152:        if (!this || !ref_put(&this->ref))
                    153:        {       /* have more users */
                    154:                return;
                    155:        }
                    156: 
                    157:        detailed = lib->settings->get_bool(lib->settings,
                    158:                                                                "%s.leak_detective.detailed", TRUE, lib->ns);
                    159: 
                    160:        /* make sure the cache is clear before unloading plugins */
                    161:        lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
                    162: 
                    163:        this->public.streams->destroy(this->public.streams);
                    164:        this->public.watcher->destroy(this->public.watcher);
                    165:        this->public.scheduler->destroy(this->public.scheduler);
                    166:        this->public.processor->destroy(this->public.processor);
                    167:        this->public.plugins->destroy(this->public.plugins);
                    168:        this->public.hosts->destroy(this->public.hosts);
                    169:        this->public.settings->destroy(this->public.settings);
                    170:        this->public.credmgr->destroy(this->public.credmgr);
                    171:        this->public.creds->destroy(this->public.creds);
                    172:        this->public.encoding->destroy(this->public.encoding);
                    173:        this->public.crypto->destroy(this->public.crypto);
                    174:        this->public.caps->destroy(this->public.caps);
                    175:        this->public.proposal->destroy(this->public.proposal);
                    176:        this->public.fetcher->destroy(this->public.fetcher);
                    177:        this->public.resolver->destroy(this->public.resolver);
                    178:        this->public.db->destroy(this->public.db);
                    179:        this->public.printf_hook->destroy(this->public.printf_hook);
                    180:        this->objects->destroy(this->objects);
                    181:        if (this->public.integrity)
                    182:        {
                    183:                this->public.integrity->destroy(this->public.integrity);
                    184:        }
                    185: 
                    186:        if (lib->leak_detective)
                    187:        {
                    188:                lib->leak_detective->report(lib->leak_detective, detailed);
                    189:                lib->leak_detective->destroy(lib->leak_detective);
                    190:                lib->leak_detective = NULL;
                    191:        }
                    192: #ifdef LEAK_DETECTIVE
                    193:        if (this->ld_out && this->ld_out != stderr)
                    194:        {
                    195:                fclose(this->ld_out);
                    196:        }
                    197: #endif /* LEAK_DETECTIVE */
                    198: 
                    199:        backtrace_deinit();
                    200:        arrays_deinit();
                    201:        utils_deinit();
                    202:        threads_deinit();
                    203: 
                    204:        free(this->public.conf);
                    205:        free((void*)this->public.ns);
                    206:        free(this);
                    207:        lib = NULL;
                    208: }
                    209: 
                    210: METHOD(library_t, get, void*,
                    211:        private_library_t *this, char *name)
                    212: {
                    213:        return this->objects->get(this->objects, name);
                    214: }
                    215: 
                    216: METHOD(library_t, set, bool,
                    217:        private_library_t *this, char *name, void *object)
                    218: {
                    219:        if (object)
                    220:        {
                    221:                if (this->objects->get(this->objects, name))
                    222:                {
                    223:                        return FALSE;
                    224:                }
                    225:                this->objects->put(this->objects, name, object);
                    226:                return TRUE;
                    227:        }
                    228:        return this->objects->remove(this->objects, name) != NULL;
                    229: }
                    230: 
                    231: /**
                    232:  * Hashtable hash function
                    233:  */
                    234: static u_int hash(char *key)
                    235: {
                    236:        return chunk_hash(chunk_create(key, strlen(key)));
                    237: }
                    238: 
                    239: /**
                    240:  * Hashtable equals function
                    241:  */
                    242: static bool equals(char *a, char *b)
                    243: {
                    244:        return streq(a, b);
                    245: }
                    246: 
                    247: /**
                    248:  * Number of words we write and memwipe() in memwipe check
                    249:  */
                    250: #define MEMWIPE_WIPE_WORDS 16
                    251: 
                    252: #ifndef NO_CHECK_MEMWIPE
                    253: 
                    254: /**
                    255:  * Write magic to memory, and try to clear it with memwipe()
                    256:  */
                    257: __attribute__((noinline))
                    258: static void do_magic(int *magic, int **out)
                    259: {
                    260:        int buf[MEMWIPE_WIPE_WORDS], i;
                    261: 
                    262:        *out = buf;
                    263:        for (i = 0; i < countof(buf); i++)
                    264:        {
                    265:                buf[i] = *magic;
                    266:        }
                    267:        /* passing buf to dbg should make sure the compiler can't optimize out buf.
                    268:         * we use directly dbg(3), as DBG3() might be stripped with DEBUG_LEVEL. */
                    269:        dbg(DBG_LIB, 3, "memwipe() pre: %b", buf, sizeof(buf));
                    270:        memwipe(buf, sizeof(buf));
                    271: }
                    272: 
                    273: /**
                    274:  * Check if memwipe works as expected
                    275:  */
                    276: static bool check_memwipe()
                    277: {
                    278:        int magic = 0xCAFEBABE, *buf, i;
                    279: 
                    280:        do_magic(&magic, &buf);
                    281: 
                    282:        for (i = 0; i < MEMWIPE_WIPE_WORDS; i++)
                    283:        {
                    284:                if (buf[i] == magic)
                    285:                {
                    286:                        DBG1(DBG_LIB, "memwipe() check failed: stackdir: %b",
                    287:                                 buf, MEMWIPE_WIPE_WORDS * sizeof(int));
                    288:                        return FALSE;
                    289:                }
                    290:        }
                    291:        return TRUE;
                    292: }
                    293: 
                    294: #endif
                    295: 
                    296: /*
                    297:  * see header file
                    298:  */
                    299: bool library_init(char *settings, const char *namespace)
                    300: {
                    301:        private_library_t *this;
                    302:        printf_hook_t *pfh;
                    303:        int i;
                    304: 
                    305:        if (lib)
                    306:        {       /* already initialized, increase refcount */
                    307:                this = (private_library_t*)lib;
                    308:                ref_get(&this->ref);
                    309:                return !this->init_failed;
                    310:        }
                    311: 
                    312:        chunk_hash_seed();
                    313: 
                    314:        INIT(this,
                    315:                .public = {
                    316:                        .get = _get,
                    317:                        .set = _set,
                    318:                        .ns = strdup(namespace ?: "libstrongswan"),
                    319:                        .conf = strdupnull(settings ?: (getenv("STRONGSWAN_CONF") ?: STRONGSWAN_CONF)),
                    320:                },
                    321:                .ref = 1,
                    322:        );
                    323:        lib = &this->public;
                    324: 
                    325:        threads_init();
                    326:        utils_init();
                    327:        arrays_init();
                    328:        backtrace_init();
                    329: 
                    330: #ifdef LEAK_DETECTIVE
                    331:        {
                    332:                FILE *out = NULL;
                    333:                char *log;
                    334: 
                    335:                log = getenv("LEAK_DETECTIVE_LOG");
                    336:                if (log)
                    337:                {
                    338:                        out = fopen(log, "a");
                    339:                }
                    340:                this->ld_out = out ?: stderr;
                    341:        }
                    342:        lib->leak_detective = leak_detective_create();
                    343:        if (lib->leak_detective)
                    344:        {
                    345:                lib->leak_detective->set_report_cb(lib->leak_detective,
                    346:                                                                                   report_leaks, sum_leaks, this);
                    347:        }
                    348: #endif /* LEAK_DETECTIVE */
                    349: 
                    350:        pfh = printf_hook_create();
                    351:        this->public.printf_hook = pfh;
                    352: 
                    353:        pfh->add_handler(pfh, 'b', mem_printf_hook,
                    354:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT,
                    355:                                         PRINTF_HOOK_ARGTYPE_END);
                    356:        pfh->add_handler(pfh, 'B', chunk_printf_hook,
                    357:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
                    358:        pfh->add_handler(pfh, 'H', host_printf_hook,
                    359:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
                    360:        pfh->add_handler(pfh, 'N', enum_printf_hook,
                    361:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT,
                    362:                                         PRINTF_HOOK_ARGTYPE_END);
                    363:        pfh->add_handler(pfh, 'T', time_printf_hook,
                    364:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_INT,
                    365:                                         PRINTF_HOOK_ARGTYPE_END);
                    366:        pfh->add_handler(pfh, 'V', time_delta_printf_hook,
                    367:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_POINTER,
                    368:                                         PRINTF_HOOK_ARGTYPE_END);
                    369:        pfh->add_handler(pfh, 'Y', identification_printf_hook,
                    370:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
                    371:        pfh->add_handler(pfh, 'R', traffic_selector_printf_hook,
                    372:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
                    373:        pfh->add_handler(pfh, 'P', proposal_printf_hook,
                    374:                                         PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END);
                    375: 
                    376:        this->objects = hashtable_create((hashtable_hash_t)hash,
                    377:                                                                         (hashtable_equals_t)equals, 4);
                    378: 
                    379:        this->public.settings = settings_create(NULL);
                    380:        if (!this->public.settings->load_files(this->public.settings,
                    381:                                                                                   this->public.conf, FALSE))
                    382:        {
                    383:                DBG1(DBG_LIB, "abort initialization due to invalid configuration");
                    384:                this->init_failed = TRUE;
                    385:        }
                    386: 
                    387:        /* add registered aliases */
                    388:        for (i = 0; i < ns_count; ++i)
                    389:        {
                    390:                lib->settings->add_fallback(lib->settings, lib->ns, namespaces[i]);
                    391:        }
                    392:        /* all namespace settings may fall back to libstrongswan */
                    393:        lib->settings->add_fallback(lib->settings, lib->ns, "libstrongswan");
                    394: 
                    395:        this->public.hosts = host_resolver_create();
                    396:        this->public.proposal = proposal_keywords_create();
                    397:        this->public.caps = capabilities_create();
                    398:        this->public.crypto = crypto_factory_create();
                    399:        this->public.creds = credential_factory_create();
                    400:        this->public.credmgr = credential_manager_create();
                    401:        this->public.encoding = cred_encoding_create();
                    402:        this->public.fetcher = fetcher_manager_create();
                    403:        this->public.resolver = resolver_manager_create();
                    404:        this->public.db = database_factory_create();
                    405:        this->public.processor = processor_create();
                    406:        this->public.scheduler = scheduler_create();
                    407:        this->public.watcher = watcher_create();
                    408:        this->public.streams = stream_manager_create();
                    409:        this->public.plugins = plugin_loader_create();
                    410: 
                    411: #ifndef NO_CHECK_MEMWIPE
                    412:        if (!check_memwipe())
                    413:        {
                    414:                return FALSE;
                    415:        }
                    416: #endif
                    417: 
                    418:        if (lib->settings->get_bool(lib->settings,
                    419:                                                                "%s.integrity_test", FALSE, lib->ns))
                    420:        {
                    421: #ifdef INTEGRITY_TEST
                    422:                this->public.integrity = integrity_checker_create(CHECKSUM_LIBRARY);
                    423:                if (!lib->integrity->check(lib->integrity, "libstrongswan", library_init))
                    424:                {
                    425:                        DBG1(DBG_LIB, "integrity check of libstrongswan failed");
                    426:                        this->init_failed = TRUE;
                    427:                }
                    428: #else /* !INTEGRITY_TEST */
                    429:                DBG1(DBG_LIB, "integrity test enabled, but not supported");
                    430:                this->init_failed = TRUE;
                    431: #endif /* INTEGRITY_TEST */
                    432:        }
                    433: 
                    434:        diffie_hellman_init();
                    435: 
                    436:        return !this->init_failed;
                    437: }

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