Annotation of embedaddon/strongswan/src/libstrongswan/library.c, revision 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>