]>
Commit | Line | Data |
---|---|---|
6b3292da | 1 | /* |
d25ce370 | 2 | * Copyright (C) 2009 Tobias Brunner |
552cc11b | 3 | * Copyright (C) 2008 Martin Willi |
6b3292da MW |
4 | * 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 | ||
60356f33 | 17 | #include "library.h" |
6b3292da | 18 | |
552cc11b | 19 | #include <stdlib.h> |
db7ef624 | 20 | |
f05b4272 | 21 | #include <utils/debug.h> |
5493ffde MW |
22 | #include <threading/thread.h> |
23 | #include <utils/identification.h> | |
2e7cc07e | 24 | #include <networking/host.h> |
12642a68 | 25 | #include <collections/hashtable.h> |
4c6c9346 | 26 | #include <utils/backtrace.h> |
5493ffde | 27 | #include <selectors/traffic_selector.h> |
db7ef624 | 28 | |
60d62b9e | 29 | #define CHECKSUM_LIBRARY IPSEC_LIB_DIR"/libchecksum.so" |
0179d468 | 30 | |
552cc11b | 31 | typedef struct private_library_t private_library_t; |
db7ef624 | 32 | |
f27f6296 | 33 | /** |
552cc11b | 34 | * private data of library |
f27f6296 | 35 | */ |
552cc11b | 36 | struct private_library_t { |
f27f6296 | 37 | |
552cc11b MW |
38 | /** |
39 | * public functions | |
40 | */ | |
41 | library_t public; | |
2ce569cc MW |
42 | |
43 | /** | |
44 | * Hashtable with registered objects (name => object) | |
45 | */ | |
46 | hashtable_t *objects; | |
1e5e1fb6 MW |
47 | |
48 | /** | |
49 | * Integrity check failed? | |
50 | */ | |
51 | bool integrity_failed; | |
52 | ||
53 | /** | |
54 | * Number of times we have been initialized | |
55 | */ | |
56 | refcount_t ref; | |
552cc11b | 57 | }; |
60356f33 | 58 | |
db7ef624 | 59 | /** |
552cc11b | 60 | * library instance |
db7ef624 | 61 | */ |
1e5e1fb6 | 62 | library_t *lib = NULL; |
db7ef624 MW |
63 | |
64 | /** | |
2ce569cc | 65 | * Deinitialize library |
db7ef624 | 66 | */ |
552cc11b | 67 | void library_deinit() |
db7ef624 | 68 | { |
552cc11b | 69 | private_library_t *this = (private_library_t*)lib; |
091d1780 MW |
70 | bool detailed; |
71 | ||
1e5e1fb6 MW |
72 | if (!this || !ref_put(&this->ref)) |
73 | { /* have more users */ | |
74 | return; | |
75 | } | |
76 | ||
091d1780 MW |
77 | detailed = lib->settings->get_bool(lib->settings, |
78 | "libstrongswan.leak_detective.detailed", TRUE); | |
552cc11b | 79 | |
a5951a28 TB |
80 | /* make sure the cache is clear before unloading plugins */ |
81 | lib->credmgr->flush_cache(lib->credmgr, CERT_ANY); | |
82 | ||
e18556e9 TB |
83 | this->public.scheduler->destroy(this->public.scheduler); |
84 | this->public.processor->destroy(this->public.processor); | |
552cc11b | 85 | this->public.plugins->destroy(this->public.plugins); |
292d8f41 | 86 | this->public.hosts->destroy(this->public.hosts); |
552cc11b | 87 | this->public.settings->destroy(this->public.settings); |
2ccc02a4 | 88 | this->public.credmgr->destroy(this->public.credmgr); |
552cc11b | 89 | this->public.creds->destroy(this->public.creds); |
d9b24887 | 90 | this->public.encoding->destroy(this->public.encoding); |
552cc11b | 91 | this->public.crypto->destroy(this->public.crypto); |
4c57c630 | 92 | this->public.proposal->destroy(this->public.proposal); |
552cc11b | 93 | this->public.fetcher->destroy(this->public.fetcher); |
b1505b34 | 94 | this->public.resolver->destroy(this->public.resolver); |
552cc11b MW |
95 | this->public.db->destroy(this->public.db); |
96 | this->public.printf_hook->destroy(this->public.printf_hook); | |
8fde0b66 | 97 | this->objects->destroy(this->objects); |
960e0c10 MW |
98 | if (this->public.integrity) |
99 | { | |
100 | this->public.integrity->destroy(this->public.integrity); | |
101 | } | |
7daf5226 | 102 | |
f37e8252 | 103 | if (lib->leak_detective) |
db7ef624 | 104 | { |
f37e8252 MW |
105 | lib->leak_detective->report(lib->leak_detective, detailed); |
106 | lib->leak_detective->destroy(lib->leak_detective); | |
db7ef624 | 107 | } |
4a5a5dd2 TB |
108 | |
109 | threads_deinit(); | |
4c6c9346 | 110 | backtrace_deinit(); |
4a5a5dd2 | 111 | |
552cc11b MW |
112 | free(this); |
113 | lib = NULL; | |
db7ef624 MW |
114 | } |
115 | ||
2ce569cc MW |
116 | METHOD(library_t, get, void*, |
117 | private_library_t *this, char *name) | |
118 | { | |
119 | return this->objects->get(this->objects, name); | |
120 | } | |
121 | ||
122 | METHOD(library_t, set, bool, | |
123 | private_library_t *this, char *name, void *object) | |
124 | { | |
125 | if (object) | |
126 | { | |
127 | if (this->objects->get(this->objects, name)) | |
128 | { | |
129 | return FALSE; | |
130 | } | |
131 | this->objects->put(this->objects, name, object); | |
132 | return TRUE; | |
133 | } | |
134 | return this->objects->remove(this->objects, name) != NULL; | |
135 | } | |
136 | ||
137 | /** | |
138 | * Hashtable hash function | |
139 | */ | |
140 | static u_int hash(char *key) | |
141 | { | |
142 | return chunk_hash(chunk_create(key, strlen(key))); | |
143 | } | |
144 | ||
145 | /** | |
146 | * Hashtable equals function | |
147 | */ | |
148 | static bool equals(char *a, char *b) | |
149 | { | |
150 | return streq(a, b); | |
151 | } | |
152 | ||
1657b4ef MW |
153 | /** |
154 | * Number of words we write and memwipe() in memwipe check | |
155 | */ | |
156 | #define MEMWIPE_WIPE_WORDS 16 | |
157 | ||
158 | /** | |
159 | * Number of words we check stack for memwiped magic | |
160 | */ | |
161 | #define MEMWIPE_CHECK_WORDS (MEMWIPE_WIPE_WORDS * 2) | |
162 | ||
e6ba688a MW |
163 | /** |
164 | * Write magic to memory, and try to clear it with memwipe() | |
165 | */ | |
166 | __attribute__((noinline)) | |
167 | static void do_magic(int magic, int **stack) | |
168 | { | |
1657b4ef | 169 | int buf[MEMWIPE_WIPE_WORDS], i; |
e6ba688a MW |
170 | |
171 | /* tell caller where callee stack is (but don't point to buf) */ | |
172 | *stack = &i; | |
173 | for (i = 0; i < countof(buf); i++) | |
174 | { | |
175 | buf[i] = magic; | |
176 | } | |
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)); | |
181 | } | |
182 | ||
183 | /** | |
184 | * Check if memwipe works as expected | |
185 | */ | |
186 | static bool check_memwipe() | |
187 | { | |
188 | int magic = 0xCAFEBABE, *ptr, *deeper, i, stackdir = 1; | |
189 | ||
190 | do_magic(magic, &deeper); | |
191 | ||
192 | ptr = &magic; | |
193 | if (deeper < ptr) | |
194 | { /* stack grows down */ | |
195 | stackdir = -1; | |
196 | } | |
1657b4ef | 197 | for (i = 0; i < MEMWIPE_CHECK_WORDS; i++) |
e6ba688a MW |
198 | { |
199 | ptr = ptr + stackdir; | |
200 | if (*ptr == magic) | |
201 | { | |
1657b4ef MW |
202 | ptr = &magic + stackdir; |
203 | if (stackdir == -1) | |
204 | { | |
205 | ptr -= MEMWIPE_CHECK_WORDS; | |
206 | } | |
207 | DBG1(DBG_LIB, "memwipe() check failed: stackdir: %d %b", | |
208 | stackdir, ptr, (u_int)(MEMWIPE_CHECK_WORDS * sizeof(int))); | |
e6ba688a MW |
209 | return FALSE; |
210 | } | |
211 | } | |
212 | return TRUE; | |
213 | } | |
214 | ||
552cc11b MW |
215 | /* |
216 | * see header file | |
db7ef624 | 217 | */ |
a0fc8979 | 218 | bool library_init(char *settings) |
db7ef624 | 219 | { |
2ce569cc | 220 | private_library_t *this; |
552cc11b | 221 | printf_hook_t *pfh; |
2ce569cc | 222 | |
1e5e1fb6 MW |
223 | if (lib) |
224 | { /* already initialized, increase refcount */ | |
225 | this = (private_library_t*)lib; | |
226 | ref_get(&this->ref); | |
227 | return !this->integrity_failed; | |
228 | } | |
229 | ||
2ce569cc MW |
230 | INIT(this, |
231 | .public = { | |
232 | .get = _get, | |
233 | .set = _set, | |
234 | }, | |
1e5e1fb6 | 235 | .ref = 1, |
2ce569cc | 236 | ); |
552cc11b | 237 | lib = &this->public; |
7daf5226 | 238 | |
4c6c9346 | 239 | backtrace_init(); |
4a5a5dd2 TB |
240 | threads_init(); |
241 | ||
552cc11b | 242 | #ifdef LEAK_DETECTIVE |
f37e8252 | 243 | lib->leak_detective = leak_detective_create(); |
552cc11b | 244 | #endif /* LEAK_DETECTIVE */ |
2f5914a3 | 245 | |
552cc11b MW |
246 | pfh = printf_hook_create(); |
247 | this->public.printf_hook = pfh; | |
7daf5226 | 248 | |
d25ce370 TB |
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); | |
d25ce370 TB |
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); | |
d24a74c5 TB |
265 | pfh->add_handler(pfh, 'Y', identification_printf_hook, |
266 | PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END); | |
5493ffde MW |
267 | pfh->add_handler(pfh, 'R', traffic_selector_printf_hook, |
268 | PRINTF_HOOK_ARGTYPE_POINTER, PRINTF_HOOK_ARGTYPE_END); | |
7daf5226 | 269 | |
2ce569cc MW |
270 | this->objects = hashtable_create((hashtable_hash_t)hash, |
271 | (hashtable_equals_t)equals, 4); | |
28a0728b | 272 | this->public.settings = settings_create(settings); |
b4f6c39e | 273 | this->public.hosts = host_resolver_create(); |
4c57c630 | 274 | this->public.proposal = proposal_keywords_create(); |
552cc11b MW |
275 | this->public.crypto = crypto_factory_create(); |
276 | this->public.creds = credential_factory_create(); | |
2ccc02a4 | 277 | this->public.credmgr = credential_manager_create(); |
da9724e6 | 278 | this->public.encoding = cred_encoding_create(); |
552cc11b | 279 | this->public.fetcher = fetcher_manager_create(); |
b1505b34 | 280 | this->public.resolver = resolver_manager_create(); |
552cc11b | 281 | this->public.db = database_factory_create(); |
e18556e9 TB |
282 | this->public.processor = processor_create(); |
283 | this->public.scheduler = scheduler_create(); | |
552cc11b | 284 | this->public.plugins = plugin_loader_create(); |
7daf5226 | 285 | |
e6ba688a MW |
286 | if (!check_memwipe()) |
287 | { | |
e6ba688a MW |
288 | return FALSE; |
289 | } | |
290 | ||
960e0c10 MW |
291 | if (lib->settings->get_bool(lib->settings, |
292 | "libstrongswan.integrity_test", FALSE)) | |
293 | { | |
bef50875 | 294 | #ifdef INTEGRITY_TEST |
0179d468 | 295 | this->public.integrity = integrity_checker_create(CHECKSUM_LIBRARY); |
6a8c8815 | 296 | if (!lib->integrity->check(lib->integrity, "libstrongswan", library_init)) |
059c479a | 297 | { |
8b0e0910 | 298 | DBG1(DBG_LIB, "integrity check of libstrongswan failed"); |
1e5e1fb6 | 299 | this->integrity_failed = TRUE; |
059c479a | 300 | } |
bef50875 | 301 | #else /* !INTEGRITY_TEST */ |
8b0e0910 | 302 | DBG1(DBG_LIB, "integrity test enabled, but not supported"); |
1e5e1fb6 | 303 | this->integrity_failed = TRUE; |
bef50875 | 304 | #endif /* INTEGRITY_TEST */ |
960e0c10 | 305 | } |
4c6c9346 | 306 | |
1e5e1fb6 | 307 | return !this->integrity_failed; |
db7ef624 | 308 | } |