Return to library.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan |
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: }