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>