Renamed mem_cred_t clear function internally to clear_, fixes potential name conflict
[strongswan.git] / src / libstrongswan / credentials / sets / mem_cred.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "mem_cred.h"
17
18 #include <threading/rwlock.h>
19 #include <utils/linked_list.h>
20
21 typedef struct private_mem_cred_t private_mem_cred_t;
22
23 /**
24 * Private data of an mem_cred_t object.
25 */
26 struct private_mem_cred_t {
27
28 /**
29 * Public mem_cred_t interface.
30 */
31 mem_cred_t public;
32
33 /**
34 * Lock for this set
35 */
36 rwlock_t *lock;
37
38 /**
39 * List of trusted certificates, certificate_t
40 */
41 linked_list_t *trusted;
42
43 /**
44 * List of trusted and untrusted certificates, certificate_t
45 */
46 linked_list_t *untrusted;
47
48 /**
49 * List of private keys, private_key_t
50 */
51 linked_list_t *keys;
52
53 /**
54 * List of shared keys, as shared_entry_t
55 */
56 linked_list_t *shared;
57 };
58
59 /**
60 * Data for the certificate enumerator
61 */
62 typedef struct {
63 rwlock_t *lock;
64 certificate_type_t cert;
65 key_type_t key;
66 identification_t *id;
67 } cert_data_t;
68
69 /**
70 * destroy cert_data
71 */
72 static void cert_data_destroy(cert_data_t *data)
73 {
74 data->lock->unlock(data->lock);
75 free(data);
76 }
77
78 /**
79 * filter function for certs enumerator
80 */
81 static bool certs_filter(cert_data_t *data, certificate_t **in, certificate_t **out)
82 {
83 public_key_t *public;
84 certificate_t *cert = *in;
85
86 if (data->cert == CERT_ANY || data->cert == cert->get_type(cert))
87 {
88 public = cert->get_public_key(cert);
89 if (public)
90 {
91 if (data->key == KEY_ANY || data->key == public->get_type(public))
92 {
93 if (data->id && public->has_fingerprint(public,
94 data->id->get_encoding(data->id)))
95 {
96 public->destroy(public);
97 *out = *in;
98 return TRUE;
99 }
100 }
101 public->destroy(public);
102 }
103 else if (data->key != KEY_ANY)
104 {
105 return FALSE;
106 }
107 if (data->id == NULL || cert->has_subject(cert, data->id))
108 {
109 *out = *in;
110 return TRUE;
111 }
112 }
113 return FALSE;
114 }
115
116 METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
117 private_mem_cred_t *this, certificate_type_t cert, key_type_t key,
118 identification_t *id, bool trusted)
119 {
120 cert_data_t *data;
121 enumerator_t *enumerator;
122
123 INIT(data,
124 .lock = this->lock,
125 .cert = cert,
126 .key = key,
127 .id = id,
128 );
129 this->lock->read_lock(this->lock);
130 if (trusted)
131 {
132 enumerator = this->trusted->create_enumerator(this->trusted);
133 }
134 else
135 {
136 enumerator = this->untrusted->create_enumerator(this->untrusted);
137 }
138 return enumerator_create_filter(enumerator, (void*)certs_filter, data,
139 (void*)cert_data_destroy);
140 }
141
142 static bool certificate_equals(certificate_t *item, certificate_t *cert)
143 {
144 return item->equals(item, cert);
145 }
146
147 METHOD(mem_cred_t, add_cert, void,
148 private_mem_cred_t *this, bool trusted, certificate_t *cert)
149 {
150 this->lock->write_lock(this->lock);
151 if (this->untrusted->find_last(this->untrusted,
152 (linked_list_match_t)certificate_equals, NULL, cert) != SUCCESS)
153 {
154 if (trusted)
155 {
156 this->trusted->insert_last(this->trusted, cert->get_ref(cert));
157 }
158 this->untrusted->insert_last(this->untrusted, cert->get_ref(cert));
159 }
160 cert->destroy(cert);
161 this->lock->unlock(this->lock);
162 }
163
164 /**
165 * Data for key enumerator
166 */
167 typedef struct {
168 rwlock_t *lock;
169 key_type_t type;
170 identification_t *id;
171 } key_data_t;
172
173 /**
174 * Destroy key enumerator data
175 */
176 static void key_data_destroy(key_data_t *data)
177 {
178 data->lock->unlock(data->lock);
179 free(data);
180 }
181
182 /**
183 * filter function for private key enumerator
184 */
185 static bool key_filter(key_data_t *data, private_key_t **in, private_key_t **out)
186 {
187 private_key_t *key;
188
189 key = *in;
190 if (data->type == KEY_ANY || data->type == key->get_type(key))
191 {
192 if (data->id == NULL ||
193 key->has_fingerprint(key, data->id->get_encoding(data->id)))
194 {
195 *out = key;
196 return TRUE;
197 }
198 }
199 return FALSE;
200 }
201
202 METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
203 private_mem_cred_t *this, key_type_t type, identification_t *id)
204 {
205 key_data_t *data;
206
207 INIT(data,
208 .lock = this->lock,
209 .type = type,
210 .id = id,
211 );
212 this->lock->read_lock(this->lock);
213 return enumerator_create_filter(this->keys->create_enumerator(this->keys),
214 (void*)key_filter, data, (void*)key_data_destroy);
215 }
216
217 METHOD(mem_cred_t, add_key, void,
218 private_mem_cred_t *this, private_key_t *key)
219 {
220 this->lock->write_lock(this->lock);
221 this->keys->insert_last(this->keys, key);
222 this->lock->unlock(this->lock);
223 }
224
225 /**
226 * Shared key entry
227 */
228 typedef struct {
229 /* shared key */
230 shared_key_t *shared;
231 /* list of owners, identification_t */
232 linked_list_t *owners;
233 } shared_entry_t;
234
235 /**
236 * Clean up a shared entry
237 */
238 static void shared_entry_destroy(shared_entry_t *entry)
239 {
240 entry->owners->destroy_offset(entry->owners,
241 offsetof(identification_t, destroy));
242 entry->shared->destroy(entry->shared);
243 free(entry);
244 }
245
246 /**
247 * Data for the shared_key enumerator
248 */
249 typedef struct {
250 rwlock_t *lock;
251 identification_t *me;
252 identification_t *other;
253 shared_key_type_t type;
254 } shared_data_t;
255
256 /**
257 * free shared key enumerator data and unlock list
258 */
259 static void shared_data_destroy(shared_data_t *data)
260 {
261 data->lock->unlock(data->lock);
262 free(data);
263 }
264
265 /**
266 * Get the best match of an owner in an entry.
267 */
268 static id_match_t has_owner(shared_entry_t *entry, identification_t *owner)
269 {
270 enumerator_t *enumerator;
271 id_match_t match, best = ID_MATCH_NONE;
272 identification_t *current;
273
274 enumerator = entry->owners->create_enumerator(entry->owners);
275 while (enumerator->enumerate(enumerator, &current))
276 {
277 match = owner->matches(owner, current);
278 if (match > best)
279 {
280 best = match;
281 }
282 }
283 enumerator->destroy(enumerator);
284 return best;
285 }
286
287 /**
288 * enumerator filter function for shared entries
289 */
290 static bool shared_filter(shared_data_t *data,
291 shared_entry_t **in, shared_key_t **out,
292 void **unused1, id_match_t *me,
293 void **unused2, id_match_t *other)
294 {
295 id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE;
296 shared_entry_t *entry = *in;
297
298 if (data->type != SHARED_ANY &&
299 entry->shared->get_type(entry->shared) != data->type)
300 {
301 return FALSE;
302 }
303 if (data->me)
304 {
305 my_match = has_owner(entry, data->me);
306 }
307 if (data->other)
308 {
309 other_match = has_owner(entry, data->other);
310 }
311 if ((data->me || data->other) && (!my_match && !other_match))
312 {
313 return FALSE;
314 }
315 *out = entry->shared;
316 if (me)
317 {
318 *me = my_match;
319 }
320 if (other)
321 {
322 *other = other_match;
323 }
324 return TRUE;
325 }
326
327 METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
328 private_mem_cred_t *this, shared_key_type_t type,
329 identification_t *me, identification_t *other)
330 {
331 shared_data_t *data;
332
333 INIT(data,
334 .lock = this->lock,
335 .me = me,
336 .other = other,
337 .type = type,
338 );
339 data->lock->read_lock(data->lock);
340 return enumerator_create_filter(
341 this->shared->create_enumerator(this->shared),
342 (void*)shared_filter, data, (void*)shared_data_destroy);
343 }
344
345 METHOD(mem_cred_t, add_shared, void,
346 private_mem_cred_t *this, shared_key_t *shared, ...)
347 {
348 shared_entry_t *entry;
349 identification_t *id;
350 va_list args;
351
352 INIT(entry,
353 .shared = shared,
354 .owners = linked_list_create(),
355 );
356
357 va_start(args, shared);
358 do
359 {
360 id = va_arg(args, identification_t*);
361 if (id)
362 {
363 entry->owners->insert_last(entry->owners, id);
364 }
365 }
366 while (id);
367 va_end(args);
368
369 this->lock->write_lock(this->lock);
370 this->shared->insert_last(this->shared, entry);
371 this->lock->unlock(this->lock);
372 }
373
374 METHOD(mem_cred_t, clear_, void,
375 private_mem_cred_t *this)
376 {
377 this->lock->write_lock(this->lock);
378 this->trusted->destroy_offset(this->trusted,
379 offsetof(certificate_t, destroy));
380 this->untrusted->destroy_offset(this->untrusted,
381 offsetof(certificate_t, destroy));
382 this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
383 this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
384 this->trusted = linked_list_create();
385 this->untrusted = linked_list_create();
386 this->keys = linked_list_create();
387 this->shared = linked_list_create();
388 this->lock->unlock(this->lock);
389 }
390
391 METHOD(mem_cred_t, destroy, void,
392 private_mem_cred_t *this)
393 {
394 clear_(this);
395 this->trusted->destroy(this->trusted);
396 this->untrusted->destroy(this->untrusted);
397 this->keys->destroy(this->keys);
398 this->shared->destroy(this->shared);
399 this->lock->destroy(this->lock);
400 free(this);
401 }
402
403 /**
404 * See header
405 */
406 mem_cred_t *mem_cred_create()
407 {
408 private_mem_cred_t *this;
409
410 INIT(this,
411 .public = {
412 .set = {
413 .create_shared_enumerator = _create_shared_enumerator,
414 .create_private_enumerator = _create_private_enumerator,
415 .create_cert_enumerator = _create_cert_enumerator,
416 .create_cdp_enumerator = (void*)return_null,
417 .cache_cert = (void*)nop,
418 },
419 .add_cert = _add_cert,
420 .add_key = _add_key,
421 .add_shared = _add_shared,
422 .clear = _clear_,
423 .destroy = _destroy,
424 },
425 .trusted = linked_list_create(),
426 .untrusted = linked_list_create(),
427 .keys = linked_list_create(),
428 .shared = linked_list_create(),
429 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
430 );
431
432 return &this->public;
433 }