2 * Copyright (C) 2009 Tobias Brunner
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
21 #include <utils/debug.h>
22 #include <threading/thread.h>
23 #include <utils/identification.h>
24 #include <networking/host.h>
25 #include <collections/hashtable.h>
26 #include <utils/backtrace.h>
27 #include <selectors/traffic_selector.h>
29 #define CHECKSUM_LIBRARY IPSEC_LIB_DIR"/libchecksum.so"
31 typedef struct private_library_t private_library_t
;
34 * private data of library
36 struct private_library_t
{
44 * Hashtable with registered objects (name => object)
49 * Integrity check failed?
51 bool integrity_failed
;
54 * Number of times we have been initialized
62 library_t
*lib
= NULL
;
65 * Deinitialize library
69 private_library_t
*this = (private_library_t
*)lib
;
72 if (!this || !ref_put(&this->ref
))
73 { /* have more users */
77 detailed
= lib
->settings
->get_bool(lib
->settings
,
78 "libstrongswan.leak_detective.detailed", TRUE
);
80 /* make sure the cache is clear before unloading plugins */
81 lib
->credmgr
->flush_cache(lib
->credmgr
, CERT_ANY
);
83 this->public.scheduler
->destroy(this->public.scheduler
);
84 this->public.processor
->destroy(this->public.processor
);
85 this->public.plugins
->destroy(this->public.plugins
);
86 this->public.hosts
->destroy(this->public.hosts
);
87 this->public.settings
->destroy(this->public.settings
);
88 this->public.credmgr
->destroy(this->public.credmgr
);
89 this->public.creds
->destroy(this->public.creds
);
90 this->public.encoding
->destroy(this->public.encoding
);
91 this->public.crypto
->destroy(this->public.crypto
);
92 this->public.proposal
->destroy(this->public.proposal
);
93 this->public.fetcher
->destroy(this->public.fetcher
);
94 this->public.resolver
->destroy(this->public.resolver
);
95 this->public.db
->destroy(this->public.db
);
96 this->public.printf_hook
->destroy(this->public.printf_hook
);
97 this->objects
->destroy(this->objects
);
98 if (this->public.integrity
)
100 this->public.integrity
->destroy(this->public.integrity
);
103 if (lib
->leak_detective
)
105 lib
->leak_detective
->report(lib
->leak_detective
, detailed
);
106 lib
->leak_detective
->destroy(lib
->leak_detective
);
116 METHOD(library_t
, get
, void*,
117 private_library_t
*this, char *name
)
119 return this->objects
->get(this->objects
, name
);
122 METHOD(library_t
, set
, bool,
123 private_library_t
*this, char *name
, void *object
)
127 if (this->objects
->get(this->objects
, name
))
131 this->objects
->put(this->objects
, name
, object
);
134 return this->objects
->remove(this->objects
, name
) != NULL
;
138 * Hashtable hash function
140 static u_int
hash(char *key
)
142 return chunk_hash(chunk_create(key
, strlen(key
)));
146 * Hashtable equals function
148 static bool equals(char *a
, char *b
)
154 * Write magic to memory, and try to clear it with memwipe()
156 __attribute__((noinline
))
157 static void do_magic(int magic
, int **stack
)
161 /* tell caller where callee stack is (but don't point to buf) */
163 for (i
= 0; i
< countof(buf
); i
++)
167 /* passing buf to dbg should make sure the compiler can't optimize out buf.
168 * we use directly dbg(3), as DBG3() might be stripped with DEBUG_LEVEL. */
169 dbg(DBG_LIB
, 3, "memwipe() pre: %b", buf
, sizeof(buf
));
170 memwipe(buf
, sizeof(buf
));
174 * Check if memwipe works as expected
176 static bool check_memwipe()
178 int magic
= 0xCAFEBABE, *ptr
, *deeper
, i
, stackdir
= 1;
180 do_magic(magic
, &deeper
);
184 { /* stack grows down */
187 for (i
= 0; i
< 128; i
++)
189 ptr
= ptr
+ stackdir
;
201 bool library_init(char *settings
)
203 private_library_t
*this;
207 { /* already initialized, increase refcount */
208 this = (private_library_t
*)lib
;
210 return !this->integrity_failed
;
225 #ifdef LEAK_DETECTIVE
226 lib
->leak_detective
= leak_detective_create();
227 #endif /* LEAK_DETECTIVE */
229 pfh
= printf_hook_create();
230 this->public.printf_hook
= pfh
;
232 pfh
->add_handler(pfh
, 'b', mem_printf_hook
,
233 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_INT
,
234 PRINTF_HOOK_ARGTYPE_END
);
235 pfh
->add_handler(pfh
, 'B', chunk_printf_hook
,
236 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
237 pfh
->add_handler(pfh
, 'H', host_printf_hook
,
238 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
239 pfh
->add_handler(pfh
, 'N', enum_printf_hook
,
240 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_INT
,
241 PRINTF_HOOK_ARGTYPE_END
);
242 pfh
->add_handler(pfh
, 'T', time_printf_hook
,
243 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_INT
,
244 PRINTF_HOOK_ARGTYPE_END
);
245 pfh
->add_handler(pfh
, 'V', time_delta_printf_hook
,
246 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_POINTER
,
247 PRINTF_HOOK_ARGTYPE_END
);
248 pfh
->add_handler(pfh
, 'Y', identification_printf_hook
,
249 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
250 pfh
->add_handler(pfh
, 'R', traffic_selector_printf_hook
,
251 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
253 this->objects
= hashtable_create((hashtable_hash_t
)hash
,
254 (hashtable_equals_t
)equals
, 4);
255 this->public.settings
= settings_create(settings
);
256 this->public.hosts
= host_resolver_create();
257 this->public.proposal
= proposal_keywords_create();
258 this->public.crypto
= crypto_factory_create();
259 this->public.creds
= credential_factory_create();
260 this->public.credmgr
= credential_manager_create();
261 this->public.encoding
= cred_encoding_create();
262 this->public.fetcher
= fetcher_manager_create();
263 this->public.resolver
= resolver_manager_create();
264 this->public.db
= database_factory_create();
265 this->public.processor
= processor_create();
266 this->public.scheduler
= scheduler_create();
267 this->public.plugins
= plugin_loader_create();
269 if (!check_memwipe())
271 DBG1(DBG_LIB
, "memwipe() check failed");
275 if (lib
->settings
->get_bool(lib
->settings
,
276 "libstrongswan.integrity_test", FALSE
))
278 #ifdef INTEGRITY_TEST
279 this->public.integrity
= integrity_checker_create(CHECKSUM_LIBRARY
);
280 if (!lib
->integrity
->check(lib
->integrity
, "libstrongswan", library_init
))
282 DBG1(DBG_LIB
, "integrity check of libstrongswan failed");
283 this->integrity_failed
= TRUE
;
285 #else /* !INTEGRITY_TEST */
286 DBG1(DBG_LIB
, "integrity test enabled, but not supported");
287 this->integrity_failed
= TRUE
;
288 #endif /* INTEGRITY_TEST */
291 return !this->integrity_failed
;