Avoid enumerating certificates with non-matching key type
[strongswan.git] / src / libstrongswan / credentials / sets / mem_cred.c
1 /*
2 * Copyright (C) 2010-2016 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2010 Martin Willi
6 * Copyright (C) 2010 revosec AG
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "mem_cred.h"
20
21 #include <threading/rwlock.h>
22 #include <collections/linked_list.h>
23
24 typedef struct private_mem_cred_t private_mem_cred_t;
25
26 /**
27 * Private data of an mem_cred_t object.
28 */
29 struct private_mem_cred_t {
30
31 /**
32 * Public mem_cred_t interface.
33 */
34 mem_cred_t public;
35
36 /**
37 * Lock for this set
38 */
39 rwlock_t *lock;
40
41 /**
42 * List of trusted certificates, certificate_t
43 */
44 linked_list_t *trusted;
45
46 /**
47 * List of trusted and untrusted certificates, certificate_t
48 */
49 linked_list_t *untrusted;
50
51 /**
52 * List of private keys, private_key_t
53 */
54 linked_list_t *keys;
55
56 /**
57 * List of shared keys, as shared_entry_t
58 */
59 linked_list_t *shared;
60
61 /**
62 * List of CDPs, as cdp_t
63 */
64 linked_list_t *cdps;
65 };
66
67 /**
68 * Data for the certificate enumerator
69 */
70 typedef struct {
71 rwlock_t *lock;
72 certificate_type_t cert;
73 key_type_t key;
74 identification_t *id;
75 } cert_data_t;
76
77 CALLBACK(cert_data_destroy, void,
78 cert_data_t *data)
79 {
80 data->lock->unlock(data->lock);
81 free(data);
82 }
83
84 CALLBACK(certs_filter, bool,
85 cert_data_t *data, enumerator_t *orig, va_list args)
86 {
87 public_key_t *public;
88 certificate_t *cert, **out;
89
90 VA_ARGS_VGET(args, out);
91
92 while (orig->enumerate(orig, &cert))
93 {
94 if (data->cert != CERT_ANY && data->cert != cert->get_type(cert))
95 {
96 continue;
97 }
98 public = cert->get_public_key(cert);
99 if (public)
100 {
101 if (data->key == KEY_ANY || data->key == public->get_type(public))
102 {
103 if (data->id && public->has_fingerprint(public,
104 data->id->get_encoding(data->id)))
105 {
106 public->destroy(public);
107 *out = cert;
108 return TRUE;
109 }
110 }
111 else
112 {
113 public->destroy(public);
114 continue;
115 }
116 public->destroy(public);
117 }
118 else if (data->key != KEY_ANY)
119 {
120 continue;
121 }
122 if (!data->id || cert->has_subject(cert, data->id))
123 {
124 *out = cert;
125 return TRUE;
126 }
127 }
128 return FALSE;
129 }
130
131 METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
132 private_mem_cred_t *this, certificate_type_t cert, key_type_t key,
133 identification_t *id, bool trusted)
134 {
135 cert_data_t *data;
136 enumerator_t *enumerator;
137
138 INIT(data,
139 .lock = this->lock,
140 .cert = cert,
141 .key = key,
142 .id = id,
143 );
144 this->lock->read_lock(this->lock);
145 if (trusted)
146 {
147 enumerator = this->trusted->create_enumerator(this->trusted);
148 }
149 else
150 {
151 enumerator = this->untrusted->create_enumerator(this->untrusted);
152 }
153 return enumerator_create_filter(enumerator, certs_filter, data,
154 cert_data_destroy);
155 }
156
157 CALLBACK(certificate_equals, bool,
158 certificate_t *item, va_list args)
159 {
160 certificate_t *cert;
161
162 VA_ARGS_VGET(args, cert);
163 return item->equals(item, cert);
164 }
165
166 /**
167 * Add a certificate the the cache. Returns a reference to "cert" or a
168 * previously cached certificate that equals "cert".
169 */
170 static certificate_t *add_cert_internal(private_mem_cred_t *this, bool trusted,
171 certificate_t *cert)
172 {
173 certificate_t *cached;
174 this->lock->write_lock(this->lock);
175 if (this->untrusted->find_first(this->untrusted, certificate_equals,
176 (void**)&cached, cert))
177 {
178 cert->destroy(cert);
179 cert = cached->get_ref(cached);
180 }
181 else
182 {
183 if (trusted)
184 {
185 this->trusted->insert_first(this->trusted, cert->get_ref(cert));
186 }
187 this->untrusted->insert_first(this->untrusted, cert->get_ref(cert));
188 }
189 this->lock->unlock(this->lock);
190 return cert;
191 }
192
193 METHOD(mem_cred_t, add_cert, void,
194 private_mem_cred_t *this, bool trusted, certificate_t *cert)
195 {
196 certificate_t *cached = add_cert_internal(this, trusted, cert);
197 cached->destroy(cached);
198 }
199
200 METHOD(mem_cred_t, add_cert_ref, certificate_t*,
201 private_mem_cred_t *this, bool trusted, certificate_t *cert)
202 {
203 return add_cert_internal(this, trusted, cert);
204 }
205
206 METHOD(mem_cred_t, get_cert_ref, certificate_t*,
207 private_mem_cred_t *this, certificate_t *cert)
208 {
209 certificate_t *cached;
210
211 this->lock->read_lock(this->lock);
212 if (this->untrusted->find_first(this->untrusted, certificate_equals,
213 (void**)&cached, cert))
214 {
215 cert->destroy(cert);
216 cert = cached->get_ref(cached);
217 }
218 this->lock->unlock(this->lock);
219
220 return cert;
221 }
222
223 METHOD(mem_cred_t, add_crl, bool,
224 private_mem_cred_t *this, crl_t *crl)
225 {
226 certificate_t *current, *cert = &crl->certificate;
227 enumerator_t *enumerator;
228 bool new = TRUE;
229
230 this->lock->write_lock(this->lock);
231 enumerator = this->untrusted->create_enumerator(this->untrusted);
232 while (enumerator->enumerate(enumerator, (void**)&current))
233 {
234 if (current->get_type(current) == CERT_X509_CRL)
235 {
236 chunk_t base;
237 bool found = FALSE;
238 crl_t *crl_c = (crl_t*)current;
239 chunk_t authkey = crl->get_authKeyIdentifier(crl);
240 chunk_t authkey_c = crl_c->get_authKeyIdentifier(crl_c);
241
242 /* compare authorityKeyIdentifiers if available */
243 if (chunk_equals(authkey, authkey_c))
244 {
245 found = TRUE;
246 }
247 else
248 {
249 identification_t *issuer = cert->get_issuer(cert);
250 identification_t *issuer_c = current->get_issuer(current);
251
252 /* otherwise compare issuer distinguished names */
253 if (issuer->equals(issuer, issuer_c))
254 {
255 found = TRUE;
256 }
257 }
258 if (found)
259 {
260 /* we keep at most one delta CRL for each base CRL */
261 if (crl->is_delta_crl(crl, &base))
262 {
263 if (!crl_c->is_delta_crl(crl_c, NULL))
264 {
265 if (chunk_equals(base, crl_c->get_serial(crl_c)))
266 { /* keep the added delta and the existing base CRL
267 * but check if this is the newest delta CRL for
268 * the same base */
269 continue;
270 }
271 }
272 }
273 else if (crl_c->is_delta_crl(crl_c, &base))
274 {
275 if (chunk_equals(base, crl->get_serial(crl)))
276 { /* keep the existing delta and the added base CRL,
277 * but check if we don't store it already */
278 continue;
279 }
280 }
281 new = crl_is_newer(crl, crl_c);
282 if (!new)
283 {
284 cert->destroy(cert);
285 break;
286 }
287 /* we remove the existing older CRL but there might be other
288 * delta or base CRLs we can replace */
289 this->untrusted->remove_at(this->untrusted, enumerator);
290 current->destroy(current);
291 }
292 }
293 }
294 enumerator->destroy(enumerator);
295
296 if (new)
297 {
298 this->untrusted->insert_first(this->untrusted, cert);
299 }
300 this->lock->unlock(this->lock);
301 return new;
302 }
303
304 /**
305 * Data for key enumerator
306 */
307 typedef struct {
308 rwlock_t *lock;
309 key_type_t type;
310 identification_t *id;
311 } key_data_t;
312
313 CALLBACK(key_data_destroy, void,
314 key_data_t *data)
315 {
316 data->lock->unlock(data->lock);
317 free(data);
318 }
319
320 CALLBACK(key_filter, bool,
321 key_data_t *data, enumerator_t *orig, va_list args)
322 {
323 private_key_t *key, **out;
324
325 VA_ARGS_VGET(args, out);
326
327 while (orig->enumerate(orig, &key))
328 {
329 if (data->type == KEY_ANY || data->type == key->get_type(key))
330 {
331 if (data->id == NULL ||
332 key->has_fingerprint(key, data->id->get_encoding(data->id)))
333 {
334 *out = key;
335 return TRUE;
336 }
337 }
338 }
339 return FALSE;
340 }
341
342 METHOD(credential_set_t, create_private_enumerator, enumerator_t*,
343 private_mem_cred_t *this, key_type_t type, identification_t *id)
344 {
345 key_data_t *data;
346
347 INIT(data,
348 .lock = this->lock,
349 .type = type,
350 .id = id,
351 );
352 this->lock->read_lock(this->lock);
353 return enumerator_create_filter(this->keys->create_enumerator(this->keys),
354 key_filter, data, key_data_destroy);
355 }
356
357 METHOD(mem_cred_t, add_key, void,
358 private_mem_cred_t *this, private_key_t *key)
359 {
360 enumerator_t *enumerator;
361 private_key_t *current;
362
363 this->lock->write_lock(this->lock);
364
365 enumerator = this->keys->create_enumerator(this->keys);
366 while (enumerator->enumerate(enumerator, &current))
367 {
368 if (current->equals(current, key))
369 {
370 this->keys->remove_at(this->keys, enumerator);
371 current->destroy(current);
372 break;
373 }
374 }
375 enumerator->destroy(enumerator);
376
377 this->keys->insert_first(this->keys, key);
378
379 this->lock->unlock(this->lock);
380 }
381
382 METHOD(mem_cred_t, remove_key, bool,
383 private_mem_cred_t *this, chunk_t fp)
384 {
385 enumerator_t *enumerator;
386 private_key_t *current;
387 bool found = FALSE;
388
389 this->lock->write_lock(this->lock);
390
391 enumerator = this->keys->create_enumerator(this->keys);
392 while (enumerator->enumerate(enumerator, &current))
393 {
394 if (current->has_fingerprint(current, fp))
395 {
396 this->keys->remove_at(this->keys, enumerator);
397 current->destroy(current);
398 found = TRUE;
399 break;
400 }
401 }
402 enumerator->destroy(enumerator);
403
404 this->lock->unlock(this->lock);
405 return found;
406 }
407
408 /**
409 * Shared key entry
410 */
411 typedef struct {
412 /** shared key */
413 shared_key_t *shared;
414 /** list of owners, identification_t */
415 linked_list_t *owners;
416 /** optional unique identifier */
417 char *id;
418 } shared_entry_t;
419
420 /**
421 * Clean up a shared entry
422 */
423 static void shared_entry_destroy(shared_entry_t *entry)
424 {
425 entry->owners->destroy_offset(entry->owners,
426 offsetof(identification_t, destroy));
427 entry->shared->destroy(entry->shared);
428 free(entry->id);
429 free(entry);
430 }
431
432 /**
433 * Check if two shared key entries are equal (ignoring the unique identifier)
434 */
435 static bool shared_entry_equals(shared_entry_t *a, shared_entry_t *b)
436 {
437 enumerator_t *e1, *e2;
438 identification_t *id1, *id2;
439 bool equals = TRUE;
440
441 if (a->shared->get_type(a->shared) != b->shared->get_type(b->shared))
442 {
443 return FALSE;
444 }
445 if (!chunk_equals(a->shared->get_key(a->shared),
446 b->shared->get_key(b->shared)))
447 {
448 return FALSE;
449 }
450 if (a->owners->get_count(a->owners) != b->owners->get_count(b->owners))
451 {
452 return FALSE;
453 }
454 e1 = a->owners->create_enumerator(a->owners);
455 e2 = b->owners->create_enumerator(b->owners);
456 while (e1->enumerate(e1, &id1) && e2->enumerate(e2, &id2))
457 {
458 if (!id1->equals(id1, id2))
459 {
460 equals = FALSE;
461 break;
462 }
463 }
464 e1->destroy(e1);
465 e2->destroy(e2);
466
467 return equals;
468 }
469
470 /**
471 * Data for the shared_key enumerator
472 */
473 typedef struct {
474 rwlock_t *lock;
475 identification_t *me;
476 identification_t *other;
477 shared_key_type_t type;
478 } shared_data_t;
479
480 CALLBACK(shared_data_destroy, void,
481 shared_data_t *data)
482 {
483 data->lock->unlock(data->lock);
484 free(data);
485 }
486
487 /**
488 * Get the best match of an owner in an entry.
489 */
490 static id_match_t has_owner(shared_entry_t *entry, identification_t *owner)
491 {
492 enumerator_t *enumerator;
493 id_match_t match, best = ID_MATCH_NONE;
494 identification_t *current;
495
496 enumerator = entry->owners->create_enumerator(entry->owners);
497 while (enumerator->enumerate(enumerator, &current))
498 {
499 match = owner->matches(owner, current);
500 if (match > best)
501 {
502 best = match;
503 }
504 }
505 enumerator->destroy(enumerator);
506 return best;
507 }
508
509 CALLBACK(shared_filter, bool,
510 shared_data_t *data, enumerator_t *orig, va_list args)
511 {
512 id_match_t my_match = ID_MATCH_NONE, other_match = ID_MATCH_NONE;
513 shared_entry_t *entry;
514 shared_key_t **out;
515 id_match_t *me, *other;
516
517 VA_ARGS_VGET(args, out, me, other);
518
519 while (orig->enumerate(orig, &entry))
520 {
521 if (data->type != SHARED_ANY &&
522 entry->shared->get_type(entry->shared) != data->type)
523 {
524 continue;
525 }
526 if (data->me)
527 {
528 my_match = has_owner(entry, data->me);
529 }
530 if (data->other)
531 {
532 other_match = has_owner(entry, data->other);
533 }
534 if ((data->me || data->other) && (!my_match && !other_match))
535 {
536 continue;
537 }
538 *out = entry->shared;
539 if (me)
540 {
541 *me = my_match;
542 }
543 if (other)
544 {
545 *other = other_match;
546 }
547 return TRUE;
548 }
549 return FALSE;
550 }
551
552 METHOD(credential_set_t, create_shared_enumerator, enumerator_t*,
553 private_mem_cred_t *this, shared_key_type_t type,
554 identification_t *me, identification_t *other)
555 {
556 shared_data_t *data;
557
558 INIT(data,
559 .lock = this->lock,
560 .me = me,
561 .other = other,
562 .type = type,
563 );
564 data->lock->read_lock(data->lock);
565 return enumerator_create_filter(
566 this->shared->create_enumerator(this->shared),
567 shared_filter, data, shared_data_destroy);
568 }
569
570 METHOD(mem_cred_t, add_shared_unique, void,
571 private_mem_cred_t *this, char *id, shared_key_t *shared,
572 linked_list_t* owners)
573 {
574 shared_entry_t *current, *new;
575 enumerator_t *enumerator;
576
577 INIT(new,
578 .shared = shared,
579 .owners = owners,
580 .id = strdupnull(id),
581 );
582
583 this->lock->write_lock(this->lock);
584
585 enumerator = this->shared->create_enumerator(this->shared);
586 while (enumerator->enumerate(enumerator, &current))
587 {
588 /* always replace keys with the same unique identifier, only compare
589 * them if both have no unique id assigned */
590 if ((id && streq(id, current->id)) ||
591 (!id && !current->id && shared_entry_equals(current, new)))
592 {
593 this->shared->remove_at(this->shared, enumerator);
594 shared_entry_destroy(current);
595 break;
596 }
597 }
598 enumerator->destroy(enumerator);
599
600 this->shared->insert_first(this->shared, new);
601
602 this->lock->unlock(this->lock);
603 }
604
605 METHOD(mem_cred_t, add_shared_list, void,
606 private_mem_cred_t *this, shared_key_t *shared, linked_list_t* owners)
607 {
608 add_shared_unique(this, NULL, shared, owners);
609 }
610
611 METHOD(mem_cred_t, add_shared, void,
612 private_mem_cred_t *this, shared_key_t *shared, ...)
613 {
614 identification_t *id;
615 linked_list_t *owners = linked_list_create();
616 va_list args;
617
618 va_start(args, shared);
619 do
620 {
621 id = va_arg(args, identification_t*);
622 if (id)
623 {
624 owners->insert_first(owners, id);
625 }
626 }
627 while (id);
628 va_end(args);
629
630 add_shared_list(this, shared, owners);
631 }
632
633 METHOD(mem_cred_t, remove_shared_unique, void,
634 private_mem_cred_t *this, char *id)
635 {
636 enumerator_t *enumerator;
637 shared_entry_t *current;
638
639 if (!id)
640 {
641 return;
642 }
643
644 this->lock->write_lock(this->lock);
645
646 enumerator = this->shared->create_enumerator(this->shared);
647 while (enumerator->enumerate(enumerator, &current))
648 {
649 if (streq(id, current->id))
650 {
651 this->shared->remove_at(this->shared, enumerator);
652 shared_entry_destroy(current);
653 break;
654 }
655 }
656 enumerator->destroy(enumerator);
657
658 this->lock->unlock(this->lock);
659 }
660
661 CALLBACK(unique_filter, bool,
662 void *unused, enumerator_t *orig, va_list args)
663 {
664 shared_entry_t *entry;
665 char **id;
666
667 VA_ARGS_VGET(args, id);
668
669 while (orig->enumerate(orig, &entry))
670 {
671 if (!entry->id)
672 {
673 continue;
674 }
675 if (id)
676 {
677 *id = entry->id;
678 }
679 return TRUE;
680 }
681 return FALSE;
682 }
683
684 METHOD(mem_cred_t, create_unique_shared_enumerator, enumerator_t*,
685 private_mem_cred_t *this)
686 {
687 this->lock->read_lock(this->lock);
688 return enumerator_create_filter(
689 this->shared->create_enumerator(this->shared),
690 unique_filter, this->lock,
691 (void*)this->lock->unlock);
692 }
693
694 /**
695 * Certificate distribution point
696 */
697 typedef struct {
698 certificate_type_t type;
699 identification_t *id;
700 char *uri;
701 } cdp_t;
702
703 /**
704 * Destroy a CDP entry
705 */
706 static void cdp_destroy(cdp_t *this)
707 {
708 this->id->destroy(this->id);
709 free(this->uri);
710 free(this);
711 }
712
713 METHOD(mem_cred_t, add_cdp, void,
714 private_mem_cred_t *this, certificate_type_t type,
715 identification_t *id, char *uri)
716 {
717 cdp_t *cdp;
718
719 INIT(cdp,
720 .type = type,
721 .id = id->clone(id),
722 .uri = strdup(uri),
723 );
724 this->lock->write_lock(this->lock);
725 this->cdps->insert_last(this->cdps, cdp);
726 this->lock->unlock(this->lock);
727 }
728
729 /**
730 * CDP enumerator data
731 */
732 typedef struct {
733 certificate_type_t type;
734 identification_t *id;
735 rwlock_t *lock;
736 } cdp_data_t;
737
738 CALLBACK(cdp_data_destroy, void,
739 cdp_data_t *data)
740 {
741 data->lock->unlock(data->lock);
742 free(data);
743 }
744
745 CALLBACK(cdp_filter, bool,
746 cdp_data_t *data, enumerator_t *orig, va_list args)
747 {
748 cdp_t *cdp;
749 char **uri;
750
751 VA_ARGS_VGET(args, uri);
752
753 while (orig->enumerate(orig, &cdp))
754 {
755 if (data->type != CERT_ANY && data->type != cdp->type)
756 {
757 continue;
758 }
759 if (data->id && !cdp->id->matches(cdp->id, data->id))
760 {
761 continue;
762 }
763 *uri = cdp->uri;
764 return TRUE;
765 }
766 return FALSE;
767 }
768
769 METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
770 private_mem_cred_t *this, certificate_type_t type, identification_t *id)
771 {
772 cdp_data_t *data;
773
774 INIT(data,
775 .type = type,
776 .id = id,
777 .lock = this->lock,
778 );
779 this->lock->read_lock(this->lock);
780 return enumerator_create_filter(this->cdps->create_enumerator(this->cdps),
781 cdp_filter, data, cdp_data_destroy);
782
783 }
784
785 static void reset_certs(private_mem_cred_t *this)
786 {
787 this->trusted->destroy_offset(this->trusted,
788 offsetof(certificate_t, destroy));
789 this->untrusted->destroy_offset(this->untrusted,
790 offsetof(certificate_t, destroy));
791 this->trusted = linked_list_create();
792 this->untrusted = linked_list_create();
793 }
794
795 static void copy_certs(linked_list_t *dst, linked_list_t *src, bool clone)
796 {
797 enumerator_t *enumerator;
798 certificate_t *cert;
799
800 enumerator = src->create_enumerator(src);
801 while (enumerator->enumerate(enumerator, &cert))
802 {
803 if (clone)
804 {
805 cert = cert->get_ref(cert);
806 }
807 else
808 {
809 src->remove_at(src, enumerator);
810 }
811 dst->insert_last(dst, cert);
812 }
813 enumerator->destroy(enumerator);
814 }
815
816 METHOD(mem_cred_t, replace_certs, void,
817 private_mem_cred_t *this, mem_cred_t *other_set, bool clone)
818 {
819 private_mem_cred_t *other = (private_mem_cred_t*)other_set;
820
821 this->lock->write_lock(this->lock);
822 reset_certs(this);
823 copy_certs(this->untrusted, other->untrusted, clone);
824 copy_certs(this->trusted, other->trusted, clone);
825 this->lock->unlock(this->lock);
826 }
827
828 static void reset_secrets(private_mem_cred_t *this)
829 {
830 this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
831 this->shared->destroy_function(this->shared, (void*)shared_entry_destroy);
832 this->keys = linked_list_create();
833 this->shared = linked_list_create();
834 }
835
836 METHOD(mem_cred_t, replace_secrets, void,
837 private_mem_cred_t *this, mem_cred_t *other_set, bool clone)
838 {
839 private_mem_cred_t *other = (private_mem_cred_t*)other_set;
840 enumerator_t *enumerator;
841 shared_entry_t *entry, *new_entry;
842 private_key_t *key;
843
844 this->lock->write_lock(this->lock);
845
846 reset_secrets(this);
847
848 if (clone)
849 {
850 enumerator = other->keys->create_enumerator(other->keys);
851 while (enumerator->enumerate(enumerator, &key))
852 {
853 this->keys->insert_last(this->keys, key->get_ref(key));
854 }
855 enumerator->destroy(enumerator);
856 enumerator = other->shared->create_enumerator(other->shared);
857 while (enumerator->enumerate(enumerator, &entry))
858 {
859 INIT(new_entry,
860 .shared = entry->shared->get_ref(entry->shared),
861 .owners = entry->owners->clone_offset(entry->owners,
862 offsetof(identification_t, clone)),
863 );
864 this->shared->insert_last(this->shared, new_entry);
865 }
866 enumerator->destroy(enumerator);
867 }
868 else
869 {
870 while (other->keys->remove_first(other->keys, (void**)&key) == SUCCESS)
871 {
872 this->keys->insert_last(this->keys, key);
873 }
874 while (other->shared->remove_first(other->shared,
875 (void**)&entry) == SUCCESS)
876 {
877 this->shared->insert_last(this->shared, entry);
878 }
879 }
880 this->lock->unlock(this->lock);
881 }
882
883 METHOD(mem_cred_t, clear_secrets, void,
884 private_mem_cred_t *this)
885 {
886 this->lock->write_lock(this->lock);
887 reset_secrets(this);
888 this->lock->unlock(this->lock);
889 }
890
891 METHOD(mem_cred_t, clear_, void,
892 private_mem_cred_t *this)
893 {
894 this->lock->write_lock(this->lock);
895 this->cdps->destroy_function(this->cdps, (void*)cdp_destroy);
896 this->cdps = linked_list_create();
897 reset_certs(this);
898 reset_secrets(this);
899 this->lock->unlock(this->lock);
900 }
901
902 METHOD(mem_cred_t, destroy, void,
903 private_mem_cred_t *this)
904 {
905 clear_(this);
906 this->trusted->destroy(this->trusted);
907 this->untrusted->destroy(this->untrusted);
908 this->keys->destroy(this->keys);
909 this->shared->destroy(this->shared);
910 this->cdps->destroy(this->cdps);
911 this->lock->destroy(this->lock);
912 free(this);
913 }
914
915 /**
916 * See header
917 */
918 mem_cred_t *mem_cred_create()
919 {
920 private_mem_cred_t *this;
921
922 INIT(this,
923 .public = {
924 .set = {
925 .create_shared_enumerator = _create_shared_enumerator,
926 .create_private_enumerator = _create_private_enumerator,
927 .create_cert_enumerator = _create_cert_enumerator,
928 .create_cdp_enumerator = _create_cdp_enumerator,
929 .cache_cert = (void*)nop,
930 },
931 .add_cert = _add_cert,
932 .add_cert_ref = _add_cert_ref,
933 .get_cert_ref = _get_cert_ref,
934 .add_crl = _add_crl,
935 .add_key = _add_key,
936 .remove_key = _remove_key,
937 .add_shared = _add_shared,
938 .add_shared_list = _add_shared_list,
939 .add_shared_unique = _add_shared_unique,
940 .remove_shared_unique = _remove_shared_unique,
941 .create_unique_shared_enumerator = _create_unique_shared_enumerator,
942 .add_cdp = _add_cdp,
943 .replace_certs = _replace_certs,
944 .replace_secrets = _replace_secrets,
945 .clear = _clear_,
946 .clear_secrets = _clear_secrets,
947 .destroy = _destroy,
948 },
949 .trusted = linked_list_create(),
950 .untrusted = linked_list_create(),
951 .keys = linked_list_create(),
952 .shared = linked_list_create(),
953 .cdps = linked_list_create(),
954 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
955 );
956
957 return &this->public;
958 }