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 * Number of words we write and memwipe() in memwipe check
156 #define MEMWIPE_WIPE_WORDS 16
159 * Number of words we check stack for memwiped magic
161 #define MEMWIPE_CHECK_WORDS (MEMWIPE_WIPE_WORDS * 2)
164 * Write magic to memory, and try to clear it with memwipe()
166 __attribute__((noinline
))
167 static void do_magic(int magic
, int **stack
)
169 int buf
[MEMWIPE_WIPE_WORDS
], i
;
171 /* tell caller where callee stack is (but don't point to buf) */
173 for (i
= 0; i
< countof(buf
); i
++)
177 /* passing buf to dbg should make sure the compiler can't optimize out buf.
178 * we use directly dbg(3), as DBG3() might be stripped with DEBUG_LEVEL. */
179 dbg(DBG_LIB
, 3, "memwipe() pre: %b", buf
, sizeof(buf
));
180 memwipe(buf
, sizeof(buf
));
184 * Check if memwipe works as expected
186 static bool check_memwipe()
188 int magic
= 0xCAFEBABE, *ptr
, *deeper
, i
, stackdir
= 1;
190 do_magic(magic
, &deeper
);
194 { /* stack grows down */
197 for (i
= 0; i
< MEMWIPE_CHECK_WORDS
; i
++)
199 ptr
= ptr
+ stackdir
;
202 ptr
= &magic
+ stackdir
;
205 ptr
-= MEMWIPE_CHECK_WORDS
;
207 DBG1(DBG_LIB
, "memwipe() check failed: stackdir: %d %b",
208 stackdir
, ptr
, (u_int
)(MEMWIPE_CHECK_WORDS
* sizeof(int)));
218 bool library_init(char *settings
)
220 private_library_t
*this;
224 { /* already initialized, increase refcount */
225 this = (private_library_t
*)lib
;
227 return !this->integrity_failed
;
242 #ifdef LEAK_DETECTIVE
243 lib
->leak_detective
= leak_detective_create();
244 #endif /* LEAK_DETECTIVE */
246 pfh
= printf_hook_create();
247 this->public.printf_hook
= pfh
;
249 pfh
->add_handler(pfh
, 'b', mem_printf_hook
,
250 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_INT
,
251 PRINTF_HOOK_ARGTYPE_END
);
252 pfh
->add_handler(pfh
, 'B', chunk_printf_hook
,
253 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
254 pfh
->add_handler(pfh
, 'H', host_printf_hook
,
255 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
256 pfh
->add_handler(pfh
, 'N', enum_printf_hook
,
257 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_INT
,
258 PRINTF_HOOK_ARGTYPE_END
);
259 pfh
->add_handler(pfh
, 'T', time_printf_hook
,
260 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_INT
,
261 PRINTF_HOOK_ARGTYPE_END
);
262 pfh
->add_handler(pfh
, 'V', time_delta_printf_hook
,
263 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_POINTER
,
264 PRINTF_HOOK_ARGTYPE_END
);
265 pfh
->add_handler(pfh
, 'Y', identification_printf_hook
,
266 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
267 pfh
->add_handler(pfh
, 'R', traffic_selector_printf_hook
,
268 PRINTF_HOOK_ARGTYPE_POINTER
, PRINTF_HOOK_ARGTYPE_END
);
270 this->objects
= hashtable_create((hashtable_hash_t
)hash
,
271 (hashtable_equals_t
)equals
, 4);
272 this->public.settings
= settings_create(settings
);
273 this->public.hosts
= host_resolver_create();
274 this->public.proposal
= proposal_keywords_create();
275 this->public.crypto
= crypto_factory_create();
276 this->public.creds
= credential_factory_create();
277 this->public.credmgr
= credential_manager_create();
278 this->public.encoding
= cred_encoding_create();
279 this->public.fetcher
= fetcher_manager_create();
280 this->public.resolver
= resolver_manager_create();
281 this->public.db
= database_factory_create();
282 this->public.processor
= processor_create();
283 this->public.scheduler
= scheduler_create();
284 this->public.plugins
= plugin_loader_create();
286 if (!check_memwipe())
291 if (lib
->settings
->get_bool(lib
->settings
,
292 "libstrongswan.integrity_test", FALSE
))
294 #ifdef INTEGRITY_TEST
295 this->public.integrity
= integrity_checker_create(CHECKSUM_LIBRARY
);
296 if (!lib
->integrity
->check(lib
->integrity
, "libstrongswan", library_init
))
298 DBG1(DBG_LIB
, "integrity check of libstrongswan failed");
299 this->integrity_failed
= TRUE
;
301 #else /* !INTEGRITY_TEST */
302 DBG1(DBG_LIB
, "integrity test enabled, but not supported");
303 this->integrity_failed
= TRUE
;
304 #endif /* INTEGRITY_TEST */
307 return !this->integrity_failed
;