library.c 11 KB

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