File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / library.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:43 2020 UTC (4 years, 4 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    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>