added a charon.install_virtual_ip option to disable IP installation for testing
[strongswan.git] / src / charon / credentials / credential_manager.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 <pthread.h>
17
18 #include "credential_manager.h"
19
20 #include <daemon.h>
21 #include <utils/mutex.h>
22 #include <utils/linked_list.h>
23 #include <credentials/sets/cert_cache.h>
24 #include <credentials/sets/auth_cfg_wrapper.h>
25 #include <credentials/sets/ocsp_response_wrapper.h>
26 #include <credentials/certificates/x509.h>
27 #include <credentials/certificates/crl.h>
28 #include <credentials/certificates/ocsp_request.h>
29 #include <credentials/certificates/ocsp_response.h>
30
31 #define MAX_CA_LEVELS 6
32
33 typedef struct private_credential_manager_t private_credential_manager_t;
34
35 /**
36 * private data of credential_manager
37 */
38 struct private_credential_manager_t {
39
40 /**
41 * public functions
42 */
43 credential_manager_t public;
44
45 /**
46 * list of credential sets
47 */
48 linked_list_t *sets;
49
50 /**
51 * thread local set of credentials, linked_list_t with credential_set_t's
52 */
53 pthread_key_t local_sets;
54
55 /**
56 * trust relationship and certificate cache
57 */
58 cert_cache_t *cache;
59
60 /**
61 * certificates queued for persistent caching
62 */
63 linked_list_t *cache_queue;
64
65 /**
66 * read-write lock to sets list
67 */
68 rwlock_t *lock;
69 };
70
71 /** data to pass to create_private_enumerator */
72 typedef struct {
73 private_credential_manager_t *this;
74 key_type_t type;
75 identification_t* keyid;
76 } private_data_t;
77
78 /** data to pass to create_cert_enumerator */
79 typedef struct {
80 private_credential_manager_t *this;
81 certificate_type_t cert;
82 key_type_t key;
83 identification_t *id;
84 bool trusted;
85 } cert_data_t;
86
87 /** data to pass to create_cdp_enumerator */
88 typedef struct {
89 private_credential_manager_t *this;
90 certificate_type_t type;
91 identification_t *id;
92 } cdp_data_t;
93
94 /** data to pass to create_shared_enumerator */
95 typedef struct {
96 private_credential_manager_t *this;
97 shared_key_type_t type;
98 identification_t *me;
99 identification_t *other;
100 } shared_data_t;
101
102 /** enumerator over local and global sets */
103 typedef struct {
104 /** implements enumerator_t */
105 enumerator_t public;
106 /** enumerator over global sets */
107 enumerator_t *global;
108 /** enumerator over local sets */
109 enumerator_t *local;
110 } sets_enumerator_t;
111
112 /**
113 * destroy a sets_enumerator_t
114 */
115 static void sets_enumerator_destroy(sets_enumerator_t *this)
116 {
117 DESTROY_IF(this->global);
118 DESTROY_IF(this->local);
119 free(this);
120 }
121
122 /**
123 * sets_enumerator_t.enumerate
124 */
125 static bool sets_enumerator_enumerate(sets_enumerator_t *this,
126 credential_set_t **set)
127 {
128 if (this->global)
129 {
130 if (this->global->enumerate(this->global, set))
131 {
132 return TRUE;
133 }
134 /* end of global sets, look for local */
135 this->global->destroy(this->global);
136 this->global = NULL;
137 }
138 if (this->local)
139 {
140 return this->local->enumerate(this->local, set);
141 }
142 return FALSE;
143 }
144
145 /**
146 * create an enumerator over both, global and local sets
147 */
148 static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
149 {
150 linked_list_t *local;
151 sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t);
152
153 enumerator->public.enumerate = (void*)sets_enumerator_enumerate;
154 enumerator->public.destroy = (void*)sets_enumerator_destroy;
155 enumerator->global = this->sets->create_enumerator(this->sets);
156 enumerator->local = NULL;
157 local = pthread_getspecific(this->local_sets);
158 if (local)
159 {
160 enumerator->local = local->create_enumerator(local);
161 }
162 return &enumerator->public;
163 }
164
165 /**
166 * cleanup function for cert data
167 */
168 static void destroy_cert_data(cert_data_t *data)
169 {
170 data->this->lock->unlock(data->this->lock);
171 free(data);
172 }
173
174 /**
175 * enumerator constructor for certificates
176 */
177 static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
178 {
179 return set->create_cert_enumerator(set, data->cert, data->key,
180 data->id, data->trusted);
181 }
182
183 /**
184 * Implementation of credential_manager_t.create_cert_enumerator.
185 */
186 static enumerator_t *create_cert_enumerator(private_credential_manager_t *this,
187 certificate_type_t certificate, key_type_t key,
188 identification_t *id, bool trusted)
189 {
190 cert_data_t *data = malloc_thing(cert_data_t);
191 data->this = this;
192 data->cert = certificate;
193 data->key = key;
194 data->id = id;
195 data->trusted = trusted;
196
197 this->lock->read_lock(this->lock);
198 return enumerator_create_nested(create_sets_enumerator(this),
199 (void*)create_cert, data,
200 (void*)destroy_cert_data);
201 }
202
203 /**
204 * Implementation of credential_manager_t.get_cert.
205 */
206 static certificate_t *get_cert(private_credential_manager_t *this,
207 certificate_type_t cert, key_type_t key,
208 identification_t *id, bool trusted)
209 {
210 certificate_t *current, *found = NULL;
211 enumerator_t *enumerator;
212
213 enumerator = create_cert_enumerator(this, cert, key, id, trusted);
214 if (enumerator->enumerate(enumerator, &current))
215 {
216 /* TODO: best match? order by keyid, subject, sualtname */
217 found = current->get_ref(current);
218 }
219 enumerator->destroy(enumerator);
220 return found;
221 }
222
223
224 /**
225 * cleanup function for cdp data
226 */
227 static void destroy_cdp_data(cdp_data_t *data)
228 {
229 data->this->lock->unlock(data->this->lock);
230 free(data);
231 }
232
233 /**
234 * enumerator constructor for CDPs
235 */
236 static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
237 {
238 return set->create_cdp_enumerator(set, data->type, data->id);
239 }
240 /**
241 * Implementation of credential_manager_t.create_cdp_enumerator.
242 */
243 static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
244 certificate_type_t type, identification_t *id)
245 {
246 cdp_data_t *data = malloc_thing(cdp_data_t);
247 data->this = this;
248 data->type = type;
249 data->id = id;
250
251 this->lock->read_lock(this->lock);
252 return enumerator_create_nested(create_sets_enumerator(this),
253 (void*)create_cdp, data,
254 (void*)destroy_cdp_data);
255 }
256
257 /**
258 * cleanup function for private data
259 */
260 static void destroy_private_data(private_data_t *data)
261 {
262 data->this->lock->unlock(data->this->lock);
263 free(data);
264 }
265
266 /**
267 * enumerator constructor for private keys
268 */
269 static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
270 {
271 return set->create_private_enumerator(set, data->type, data->keyid);
272 }
273
274 /**
275 * Implementation of credential_manager_t.create_private_enumerator.
276 */
277 static enumerator_t* create_private_enumerator(
278 private_credential_manager_t *this,
279 key_type_t key, identification_t *keyid)
280 {
281 private_data_t *data;
282
283 data = malloc_thing(private_data_t);
284 data->this = this;
285 data->type = key;
286 data->keyid = keyid;
287 this->lock->read_lock(this->lock);
288 return enumerator_create_nested(create_sets_enumerator(this),
289 (void*)create_private, data,
290 (void*)destroy_private_data);
291 }
292
293 /**
294 * Implementation of credential_manager_t.get_private_by_keyid.
295 */
296 static private_key_t *get_private_by_keyid(private_credential_manager_t *this,
297 key_type_t key, identification_t *keyid)
298 {
299 private_key_t *found = NULL;
300 enumerator_t *enumerator;
301
302 enumerator = create_private_enumerator(this, key, keyid);
303 if (enumerator->enumerate(enumerator, &found))
304 {
305 found->get_ref(found);
306 }
307 enumerator->destroy(enumerator);
308 return found;
309 }
310
311 /**
312 * cleanup function for shared data
313 */
314 static void destroy_shared_data(shared_data_t *data)
315 {
316 data->this->lock->unlock(data->this->lock);
317 free(data);
318 }
319
320 /**
321 * enumerator constructor for shared keys
322 */
323 static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
324 {
325 return set->create_shared_enumerator(set, data->type, data->me, data->other);
326 }
327
328 /**
329 * Implementation of credential_manager_t.create_shared_enumerator.
330 */
331 static enumerator_t *create_shared_enumerator(private_credential_manager_t *this,
332 shared_key_type_t type,
333 identification_t *me, identification_t *other)
334 {
335 shared_data_t *data = malloc_thing(shared_data_t);
336 data->this = this;
337 data->type = type;
338 data->me = me;
339 data->other = other;
340
341 this->lock->read_lock(this->lock);
342 return enumerator_create_nested(create_sets_enumerator(this),
343 (void*)create_shared, data,
344 (void*)destroy_shared_data);
345 }
346
347 /**
348 * Implementation of credential_manager_t.get_shared.
349 */
350 static shared_key_t *get_shared(private_credential_manager_t *this,
351 shared_key_type_t type, identification_t *me,
352 identification_t *other)
353 {
354 shared_key_t *current, *found = NULL;
355 id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE;
356 id_match_t *match_me, *match_other;
357 enumerator_t *enumerator;
358
359 enumerator = create_shared_enumerator(this, type, me, other);
360 while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
361 {
362 if (match_other > best_other ||
363 (match_other == best_other && match_me > best_me))
364 {
365 DESTROY_IF(found);
366 found = current->get_ref(current);
367 best_me = match_me;
368 best_other = match_other;
369 }
370 }
371 enumerator->destroy(enumerator);
372 return found;
373 }
374
375 /**
376 * add a credential set to the thread local list
377 */
378 static void add_local_set(private_credential_manager_t *this,
379 credential_set_t *set)
380 {
381 linked_list_t *sets;
382
383 sets = pthread_getspecific(this->local_sets);
384 if (!sets)
385 { /* first invocation */
386 sets = linked_list_create();
387 pthread_setspecific(this->local_sets, sets);
388 }
389 sets->insert_last(sets, set);
390 }
391
392 /**
393 * remove a credential set from the thread local list
394 */
395 static void remove_local_set(private_credential_manager_t *this,
396 credential_set_t *set)
397 {
398 linked_list_t *sets;
399
400 sets = pthread_getspecific(this->local_sets);
401 sets->remove(sets, set, NULL);
402 }
403
404 /**
405 * Implementation of credential_manager_t.cache_cert.
406 */
407 static void cache_cert(private_credential_manager_t *this, certificate_t *cert)
408 {
409 credential_set_t *set;
410 enumerator_t *enumerator;
411
412 if (this->lock->try_write_lock(this->lock))
413 {
414 enumerator = this->sets->create_enumerator(this->sets);
415 while (enumerator->enumerate(enumerator, &set))
416 {
417 set->cache_cert(set, cert);
418 }
419 enumerator->destroy(enumerator);
420 }
421 else
422 { /* we can't cache now as other threads are active, queue for later */
423 this->lock->read_lock(this->lock);
424 this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
425 }
426 this->lock->unlock(this->lock);
427 }
428
429 /**
430 * Try to cache certificates queued for caching
431 */
432 static void cache_queue(private_credential_manager_t *this)
433 {
434 credential_set_t *set;
435 certificate_t *cert;
436 enumerator_t *enumerator;
437
438 if (this->cache_queue->get_count(this->cache_queue) > 0 &&
439 this->lock->try_write_lock(this->lock))
440 {
441 while (this->cache_queue->remove_last(this->cache_queue,
442 (void**)&cert) == SUCCESS)
443 {
444 enumerator = this->sets->create_enumerator(this->sets);
445 while (enumerator->enumerate(enumerator, &set))
446 {
447 set->cache_cert(set, cert);
448 }
449 enumerator->destroy(enumerator);
450 cert->destroy(cert);
451 }
452 this->lock->unlock(this->lock);
453 }
454 }
455
456 /**
457 * forward declaration
458 */
459 static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
460 key_type_t type, identification_t *id, bool crl, bool ocsp);
461
462 /**
463 * Do an OCSP request
464 */
465 static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
466 certificate_t *subject, certificate_t *issuer)
467 {
468 certificate_t *request, *response;
469 chunk_t send, receive;
470
471 /* TODO: requestor name, signature */
472 request = lib->creds->create(lib->creds,
473 CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
474 BUILD_CA_CERT, issuer,
475 BUILD_CERT, subject, BUILD_END);
476 if (!request)
477 {
478 DBG1(DBG_CFG, "generating ocsp request failed");
479 return NULL;
480 }
481
482 send = request->get_encoding(request);
483 request->destroy(request);
484
485 DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
486 if (lib->fetcher->fetch(lib->fetcher, url, &receive,
487 FETCH_REQUEST_DATA, send,
488 FETCH_REQUEST_TYPE, "application/ocsp-request",
489 FETCH_END) != SUCCESS)
490 {
491 DBG1(DBG_CFG, "ocsp request to %s failed", url);
492 chunk_free(&send);
493 return NULL;
494 }
495 chunk_free(&send);
496
497 response = lib->creds->create(lib->creds,
498 CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
499 BUILD_BLOB_ASN1_DER, receive, BUILD_END);
500 chunk_free(&receive);
501 if (!response)
502 {
503 DBG1(DBG_CFG, "parsing ocsp response failed");
504 return NULL;
505 }
506 return response;
507 }
508
509 /**
510 * check the signature of an OCSP response
511 */
512 static bool verify_ocsp(private_credential_manager_t *this,
513 ocsp_response_t *response)
514 {
515 certificate_t *issuer, *subject;
516 identification_t *responder;
517 ocsp_response_wrapper_t *wrapper;
518 enumerator_t *enumerator;
519 bool verified = FALSE;
520
521 wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
522 add_local_set(this, &wrapper->set);
523
524 subject = &response->certificate;
525 responder = subject->get_issuer(subject);
526 enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE, FALSE);
527 while (enumerator->enumerate(enumerator, &issuer, NULL))
528 {
529 if (this->cache->issued_by(this->cache, subject, issuer))
530 {
531 DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
532 issuer->get_subject(issuer));
533 verified = TRUE;
534 break;
535 }
536 }
537 enumerator->destroy(enumerator);
538
539 remove_local_set(this, &wrapper->set);
540 wrapper->destroy(wrapper);
541 return verified;
542 }
543
544 /**
545 * Get the better of two OCSP responses, and check for usable OCSP info
546 */
547 static certificate_t *get_better_ocsp(private_credential_manager_t *this,
548 certificate_t *cand, certificate_t *best,
549 x509_t *subject, x509_t *issuer,
550 cert_validation_t *valid, bool cache)
551 {
552 ocsp_response_t *response;
553 time_t revocation, this_update, next_update, valid_until;
554 crl_reason_t reason;
555 bool revoked = FALSE;
556
557 response = (ocsp_response_t*)cand;
558
559 /* check ocsp signature */
560 if (!verify_ocsp(this, response))
561 {
562 DBG1(DBG_CFG, "ocsp response verification failed");
563 cand->destroy(cand);
564 return best;
565 }
566 /* check if response contains our certificate */
567 switch (response->get_status(response, subject, issuer, &revocation, &reason,
568 &this_update, &next_update))
569 {
570 case VALIDATION_REVOKED:
571 /* subject has been revoked by a valid OCSP response */
572 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
573 &revocation, TRUE, crl_reason_names, reason);
574 revoked = TRUE;
575 break;
576 case VALIDATION_GOOD:
577 /* results in either good or stale */
578 break;
579 default:
580 case VALIDATION_FAILED:
581 /* candidate unusable, does not contain our cert */
582 DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
583 cand->destroy(cand);
584 return best;
585 }
586
587 /* select the better of the two responses */
588 if (best == NULL || cand->is_newer(cand, best))
589 {
590 DESTROY_IF(best);
591 best = cand;
592 if (best->get_validity(best, NULL, NULL, &valid_until))
593 {
594 DBG1(DBG_CFG, " ocsp response is valid: until %T",
595 &valid_until, FALSE);
596 *valid = VALIDATION_GOOD;
597 if (cache)
598 { /* cache non-stale only, stale certs get refetched */
599 cache_cert(this, best);
600 }
601 }
602 else
603 {
604 DBG1(DBG_CFG, " ocsp response is stale: since %T",
605 &valid_until, FALSE);
606 *valid = VALIDATION_STALE;
607 }
608 }
609 else
610 {
611 *valid = VALIDATION_STALE;
612 cand->destroy(cand);
613 }
614 if (revoked)
615 { /* revoked always counts, even if stale */
616 *valid = VALIDATION_REVOKED;
617 }
618 return best;
619 }
620
621 /**
622 * validate a x509 certificate using OCSP
623 */
624 static cert_validation_t check_ocsp(private_credential_manager_t *this,
625 x509_t *subject, x509_t *issuer,
626 auth_cfg_t *auth)
627 {
628 enumerator_t *enumerator;
629 cert_validation_t valid = VALIDATION_SKIPPED;
630 certificate_t *best = NULL, *current;
631 identification_t *keyid = NULL;
632 public_key_t *public;
633 char *uri = NULL;
634
635 /** lookup cache for valid OCSP responses */
636 enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
637 KEY_ANY, NULL, FALSE);
638 while (enumerator->enumerate(enumerator, &current))
639 {
640 current->get_ref(current);
641 best = get_better_ocsp(this, current, best, subject, issuer,
642 &valid, FALSE);
643 if (best && valid != VALIDATION_STALE)
644 {
645 DBG1(DBG_CFG, " using cached ocsp response");
646 break;
647 }
648 }
649 enumerator->destroy(enumerator);
650
651 /* derive the authorityKeyIdentifier from the issuer's public key */
652 current = &issuer->interface;
653 public = current->get_public_key(current);
654 if (public)
655 {
656 keyid = public->get_id(public, ID_PUBKEY_SHA1);
657 }
658 /** fetch from configured OCSP responder URLs */
659 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
660 {
661 enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
662 while (enumerator->enumerate(enumerator, &uri))
663 {
664 current = fetch_ocsp(this, uri, &subject->interface,
665 &issuer->interface);
666 if (current)
667 {
668 best = get_better_ocsp(this, current, best, subject, issuer,
669 &valid, TRUE);
670 if (best && valid != VALIDATION_STALE)
671 {
672 break;
673 }
674 }
675 }
676 enumerator->destroy(enumerator);
677 }
678 DESTROY_IF(public);
679
680 /* fallback to URL fetching from subject certificate's URIs */
681 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
682 {
683 enumerator = subject->create_ocsp_uri_enumerator(subject);
684 while (enumerator->enumerate(enumerator, &uri))
685 {
686 current = fetch_ocsp(this, uri, &subject->interface,
687 &issuer->interface);
688 if (current)
689 {
690 best = get_better_ocsp(this, current, best, subject, issuer,
691 &valid, TRUE);
692 if (best && valid != VALIDATION_STALE)
693 {
694 break;
695 }
696 }
697 }
698 enumerator->destroy(enumerator);
699 }
700 /* an uri was found, but no result. switch validation state to failed */
701 if (valid == VALIDATION_SKIPPED && uri)
702 {
703 valid = VALIDATION_FAILED;
704 }
705 if (auth)
706 {
707 auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
708 if (valid == VALIDATION_GOOD)
709 { /* successful OCSP check fulfills also CRL constraint */
710 auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
711 }
712 }
713 DESTROY_IF(best);
714 return valid;
715 }
716
717 /**
718 * fetch a CRL from an URL
719 */
720 static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
721 {
722 certificate_t *crl;
723 chunk_t chunk;
724
725 DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
726 if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
727 {
728 DBG1(DBG_CFG, "crl fetching failed");
729 return NULL;
730 }
731 crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
732 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
733 chunk_free(&chunk);
734 if (!crl)
735 {
736 DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
737 return NULL;
738 }
739 return crl;
740 }
741
742 /**
743 * check the signature of an CRL
744 */
745 static bool verify_crl(private_credential_manager_t *this, certificate_t *crl)
746 {
747 certificate_t *issuer;
748 enumerator_t *enumerator;
749 bool verified = FALSE;
750
751 enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl),
752 FALSE, FALSE);
753 while (enumerator->enumerate(enumerator, &issuer, NULL))
754 {
755 if (this->cache->issued_by(this->cache, crl, issuer))
756 {
757 DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
758 issuer->get_subject(issuer));
759 verified = TRUE;
760 break;
761 }
762 }
763 enumerator->destroy(enumerator);
764
765 return verified;
766 }
767
768 /**
769 * Get the better of two CRLs, and check for usable CRL info
770 */
771 static certificate_t *get_better_crl(private_credential_manager_t *this,
772 certificate_t *cand, certificate_t *best,
773 x509_t *subject, x509_t *issuer,
774 cert_validation_t *valid, bool cache)
775 {
776 enumerator_t *enumerator;
777 time_t revocation, valid_until;
778 crl_reason_t reason;
779 chunk_t serial;
780 crl_t *crl;
781
782 /* check CRL signature */
783 if (!verify_crl(this, cand))
784 {
785 DBG1(DBG_CFG, "crl response verification failed");
786 cand->destroy(cand);
787 return best;
788 }
789
790 crl = (crl_t*)cand;
791 enumerator = crl->create_enumerator(crl);
792 while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
793 {
794 if (chunk_equals(serial, subject->get_serial(subject)))
795 {
796 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
797 &revocation, TRUE, crl_reason_names, reason);
798 *valid = VALIDATION_REVOKED;
799 enumerator->destroy(enumerator);
800 DESTROY_IF(best);
801 return cand;
802 }
803 }
804 enumerator->destroy(enumerator);
805
806 /* select the better of the two CRLs */
807 if (best == NULL || cand->is_newer(cand, best))
808 {
809 DESTROY_IF(best);
810 best = cand;
811 if (best->get_validity(best, NULL, NULL, &valid_until))
812 {
813 DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
814 *valid = VALIDATION_GOOD;
815 if (cache)
816 { /* we cache non-stale crls only, as a stale crls are refetched */
817 cache_cert(this, best);
818 }
819 }
820 else
821 {
822 DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
823 *valid = VALIDATION_STALE;
824 }
825 }
826 else
827 {
828 *valid = VALIDATION_STALE;
829 cand->destroy(cand);
830 }
831 return best;
832 }
833
834 /**
835 * validate a x509 certificate using CRL
836 */
837 static cert_validation_t check_crl(private_credential_manager_t *this,
838 x509_t *subject, x509_t *issuer,
839 auth_cfg_t *auth)
840 {
841 cert_validation_t valid = VALIDATION_SKIPPED;
842 identification_t *keyid = NULL;
843 certificate_t *best = NULL;
844 certificate_t *current;
845 public_key_t *public;
846 enumerator_t *enumerator;
847 char *uri = NULL;
848
849 /* derive the authorityKeyIdentifier from the issuer's public key */
850 current = &issuer->interface;
851 public = current->get_public_key(current);
852 if (public)
853 {
854 keyid = public->get_id(public, ID_PUBKEY_SHA1);
855 }
856
857 /* find a cached crl by authorityKeyIdentifier */
858 if (keyid)
859 {
860 enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY,
861 keyid, FALSE);
862 while (enumerator->enumerate(enumerator, &current))
863 {
864 current->get_ref(current);
865 best = get_better_crl(this, current, best, subject, issuer,
866 &valid, FALSE);
867 if (best && valid != VALIDATION_STALE)
868 {
869 DBG1(DBG_CFG, " using cached crl");
870 break;
871 }
872 }
873 enumerator->destroy(enumerator);
874 }
875
876 /* fallback to fetching crls from credential sets cdps */
877 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
878 {
879 enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid);
880
881 while (enumerator->enumerate(enumerator, &uri))
882 {
883 current = fetch_crl(this, uri);
884 if (current)
885 {
886 best = get_better_crl(this, current, best, subject, issuer,
887 &valid, TRUE);
888 if (best && valid != VALIDATION_STALE)
889 {
890 break;
891 }
892 }
893 }
894 enumerator->destroy(enumerator);
895 }
896 DESTROY_IF(public);
897
898 /* fallback to fetching crls from cdps from subject's certificate */
899 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
900 {
901 enumerator = subject->create_crl_uri_enumerator(subject);
902
903 while (enumerator->enumerate(enumerator, &uri))
904 {
905 current = fetch_crl(this, uri);
906 if (current)
907 {
908 best = get_better_crl(this, current, best, subject, issuer,
909 &valid, TRUE);
910 if (best && valid != VALIDATION_STALE)
911 {
912 break;
913 }
914 }
915 }
916 enumerator->destroy(enumerator);
917 }
918
919 /* an uri was found, but no result. switch validation state to failed */
920 if (valid == VALIDATION_SKIPPED && uri)
921 {
922 valid = VALIDATION_FAILED;
923 }
924 if (auth)
925 {
926 if (valid == VALIDATION_SKIPPED)
927 { /* if we skipped CRL validation, we use the result of OCSP for
928 * constraint checking */
929 auth->add(auth, AUTH_RULE_CRL_VALIDATION,
930 auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
931 }
932 else
933 {
934 auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
935 }
936 }
937 DESTROY_IF(best);
938 return valid;
939 }
940
941 /**
942 * check a certificate for its lifetime
943 */
944 static bool check_certificate(private_credential_manager_t *this,
945 certificate_t *subject, certificate_t *issuer,
946 bool crl, bool ocsp, auth_cfg_t *auth)
947 {
948 time_t not_before, not_after;
949
950 if (!subject->get_validity(subject, NULL, &not_before, &not_after))
951 {
952 DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
953 &not_before, TRUE, &not_after, TRUE);
954 return FALSE;
955 }
956 if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
957 {
958 DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
959 &not_before, TRUE, &not_after, TRUE);
960 return FALSE;
961 }
962 if (issuer->get_type(issuer) == CERT_X509 &&
963 subject->get_type(subject) == CERT_X509)
964 {
965 if (ocsp || crl)
966 {
967 DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
968 subject->get_subject(subject));
969 }
970 if (ocsp)
971 {
972 switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
973 {
974 case VALIDATION_GOOD:
975 DBG1(DBG_CFG, "certificate status is good");
976 return TRUE;
977 case VALIDATION_REVOKED:
978 /* has already been logged */
979 return FALSE;
980 case VALIDATION_SKIPPED:
981 DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
982 break;
983 case VALIDATION_STALE:
984 DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
985 break;
986 case VALIDATION_FAILED:
987 DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
988 break;
989 }
990 }
991 if (crl)
992 {
993 switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
994 {
995 case VALIDATION_GOOD:
996 DBG1(DBG_CFG, "certificate status is good");
997 return TRUE;
998 case VALIDATION_REVOKED:
999 /* has already been logged */
1000 return FALSE;
1001 case VALIDATION_FAILED:
1002 case VALIDATION_SKIPPED:
1003 DBG1(DBG_CFG, "certificate status is not available");
1004 break;
1005 case VALIDATION_STALE:
1006 DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
1007 break;
1008 }
1009 }
1010 }
1011 return TRUE;
1012 }
1013
1014 /**
1015 * Get a trusted certificate from a credential set
1016 */
1017 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
1018 key_type_t type, identification_t *id)
1019 {
1020 certificate_t *subject;
1021 public_key_t *public;
1022
1023 subject = get_cert(this, CERT_ANY, type, id, TRUE);
1024 if (!subject)
1025 {
1026 return NULL;
1027 }
1028 public = subject->get_public_key(subject);
1029 if (!public)
1030 {
1031 subject->destroy(subject);
1032 return NULL;
1033 }
1034 public->destroy(public);
1035 return subject;
1036 }
1037
1038 /**
1039 * Get the issuing certificate of a subject certificate
1040 */
1041 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
1042 certificate_t *subject, bool trusted)
1043 {
1044 enumerator_t *enumerator;
1045 certificate_t *issuer = NULL, *candidate;
1046
1047 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
1048 subject->get_issuer(subject), trusted);
1049 while (enumerator->enumerate(enumerator, &candidate))
1050 {
1051 if (this->cache->issued_by(this->cache, subject, candidate))
1052 {
1053 issuer = candidate->get_ref(candidate);
1054 break;
1055 }
1056 }
1057 enumerator->destroy(enumerator);
1058 return issuer;
1059 }
1060
1061 /**
1062 * try to verify the trust chain of subject, return TRUE if trusted
1063 */
1064 static bool verify_trust_chain(private_credential_manager_t *this,
1065 certificate_t *subject, auth_cfg_t *result,
1066 bool trusted, bool crl, bool ocsp)
1067 {
1068 certificate_t *current, *issuer;
1069 auth_cfg_t *auth;
1070 u_int level = 0;
1071
1072 auth = auth_cfg_create();
1073 current = subject->get_ref(subject);
1074 while (level++ < MAX_CA_LEVELS)
1075 {
1076 issuer = get_issuer_cert(this, current, TRUE);
1077 if (issuer)
1078 {
1079 /* accept only self-signed CAs as trust anchor */
1080 if (this->cache->issued_by(this->cache, issuer, issuer))
1081 {
1082 auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
1083 DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
1084 issuer->get_subject(issuer));
1085 trusted = TRUE;
1086 }
1087 else
1088 {
1089 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
1090 DBG1(DBG_CFG, " using trusted intermediate ca certificate "
1091 "\"%Y\"", issuer->get_subject(issuer));
1092 }
1093 }
1094 else
1095 {
1096 issuer = get_issuer_cert(this, current, FALSE);
1097 if (issuer)
1098 {
1099 if (current->equals(current, issuer))
1100 {
1101 DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
1102 current->get_subject(current));
1103 issuer->destroy(issuer);
1104 break;
1105 }
1106 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
1107 DBG1(DBG_CFG, " using untrusted intermediate certificate "
1108 "\"%Y\"", issuer->get_subject(issuer));
1109 }
1110 else
1111 {
1112 DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
1113 current->get_subject(current));
1114 break;
1115 }
1116 }
1117 if (!check_certificate(this, current, issuer, crl, ocsp,
1118 current == subject ? auth : NULL))
1119 {
1120 trusted = FALSE;
1121 issuer->destroy(issuer);
1122 break;
1123 }
1124 current->destroy(current);
1125 current = issuer;
1126 if (trusted)
1127 {
1128 break;
1129 }
1130 }
1131 current->destroy(current);
1132 if (level > MAX_CA_LEVELS)
1133 {
1134 DBG1(DBG_CFG, "maximum ca path length of %d levels reached", level);
1135 }
1136 if (trusted)
1137 {
1138 result->merge(result, auth, FALSE);
1139 }
1140 auth->destroy(auth);
1141 return trusted;
1142 }
1143
1144 /**
1145 * enumerator for trusted certificates
1146 */
1147 typedef struct {
1148 /** implements enumerator_t interface */
1149 enumerator_t public;
1150 /** enumerator over candidate peer certificates */
1151 enumerator_t *candidates;
1152 /** reference to the credential_manager */
1153 private_credential_manager_t *this;
1154 /** type of the requested key */
1155 key_type_t type;
1156 /** identity the requested key belongs to */
1157 identification_t *id;
1158 /** TRUE to do CRL checking */
1159 bool crl;
1160 /** TRUE to do OCSP checking */
1161 bool ocsp;
1162 /** pretrusted certificate we have served at first invocation */
1163 certificate_t *pretrusted;
1164 /** currently enumerating auth config */
1165 auth_cfg_t *auth;
1166 } trusted_enumerator_t;
1167
1168 /**
1169 * Implements trusted_enumerator_t.enumerate
1170 */
1171 static bool trusted_enumerate(trusted_enumerator_t *this,
1172 certificate_t **cert, auth_cfg_t **auth)
1173 {
1174 certificate_t *current;
1175
1176 DESTROY_IF(this->auth);
1177 this->auth = auth_cfg_create();
1178
1179 if (!this->candidates)
1180 {
1181 /* first invocation, build enumerator for next one */
1182 this->candidates = create_cert_enumerator(this->this, CERT_ANY,
1183 this->type, this->id, FALSE);
1184 /* check if we have a trusted certificate for that peer */
1185 this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
1186 if (this->pretrusted)
1187 {
1188 /* if we find a trusted self signed certificate, we just accept it.
1189 * However, in order to fulfill authorization rules, we try to build
1190 * the trust chain if it is not self signed */
1191 if (this->this->cache->issued_by(this->this->cache,
1192 this->pretrusted, this->pretrusted) ||
1193 verify_trust_chain(this->this, this->pretrusted, this->auth,
1194 TRUE, this->crl, this->ocsp))
1195 {
1196 this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
1197 this->pretrusted->get_ref(this->pretrusted));
1198 DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
1199 this->pretrusted->get_subject(this->pretrusted));
1200 *cert = this->pretrusted;
1201 if (auth)
1202 {
1203 *auth = this->auth;
1204 }
1205 return TRUE;
1206 }
1207 }
1208 }
1209 /* try to verify the trust chain for each certificate found */
1210 while (this->candidates->enumerate(this->candidates, &current))
1211 {
1212 if (this->pretrusted &&
1213 this->pretrusted->equals(this->pretrusted, current))
1214 { /* skip pretrusted certificate we already served */
1215 continue;
1216 }
1217
1218 DBG1(DBG_CFG, " using certificate \"%Y\"",
1219 current->get_subject(current));
1220 if (verify_trust_chain(this->this, current, this->auth, FALSE,
1221 this->crl, this->ocsp))
1222 {
1223 *cert = current;
1224 if (auth)
1225 {
1226 *auth = this->auth;
1227 }
1228 return TRUE;
1229 }
1230 }
1231 return FALSE;
1232 }
1233
1234 /**
1235 * Implements trusted_enumerator_t.destroy
1236 */
1237 static void trusted_destroy(trusted_enumerator_t *this)
1238 {
1239 DESTROY_IF(this->pretrusted);
1240 DESTROY_IF(this->auth);
1241 DESTROY_IF(this->candidates);
1242 free(this);
1243 }
1244
1245 /**
1246 * create an enumerator over trusted certificates and their trustchain
1247 */
1248 static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
1249 key_type_t type, identification_t *id, bool crl, bool ocsp)
1250 {
1251 trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t);
1252
1253 enumerator->public.enumerate = (void*)trusted_enumerate;
1254 enumerator->public.destroy = (void*)trusted_destroy;
1255
1256 enumerator->candidates = NULL;
1257 enumerator->this = this;
1258 enumerator->type = type;
1259 enumerator->id = id;
1260 enumerator->crl = crl;
1261 enumerator->ocsp = ocsp;
1262 enumerator->pretrusted = NULL;
1263 enumerator->auth = NULL;
1264
1265 return &enumerator->public;
1266 }
1267
1268 /**
1269 * enumerator for public keys
1270 */
1271 typedef struct {
1272 /** implements enumerator_t interface */
1273 enumerator_t public;
1274 /** enumerator over candidate peer certificates */
1275 enumerator_t *inner;
1276 /** reference to the credential_manager */
1277 private_credential_manager_t *this;
1278 /** currently enumerating key */
1279 public_key_t *current;
1280 /** credset wrapper around auth config */
1281 auth_cfg_wrapper_t *wrapper;
1282 } public_enumerator_t;
1283
1284 /**
1285 * Implements public_enumerator_t.enumerate
1286 */
1287 static bool public_enumerate(public_enumerator_t *this,
1288 public_key_t **key, auth_cfg_t **auth)
1289 {
1290 certificate_t *cert;
1291
1292 while (this->inner->enumerate(this->inner, &cert, auth))
1293 {
1294 DESTROY_IF(this->current);
1295 this->current = cert->get_public_key(cert);
1296 if (this->current)
1297 {
1298 *key = this->current;
1299 return TRUE;
1300 }
1301 }
1302 return FALSE;
1303 }
1304
1305 /**
1306 * Implements public_enumerator_t.destroy
1307 */
1308 static void public_destroy(public_enumerator_t *this)
1309 {
1310 DESTROY_IF(this->current);
1311 this->inner->destroy(this->inner);
1312 if (this->wrapper)
1313 {
1314 remove_local_set(this->this, &this->wrapper->set);
1315 this->wrapper->destroy(this->wrapper);
1316 }
1317 this->this->lock->unlock(this->this->lock);
1318
1319 /* check for delayed certificate cache queue */
1320 cache_queue(this->this);
1321 free(this);
1322 }
1323
1324 /**
1325 * Implementation of credential_manager_t.create_public_enumerator.
1326 */
1327 static enumerator_t* create_public_enumerator(private_credential_manager_t *this,
1328 key_type_t type, identification_t *id, auth_cfg_t *auth)
1329 {
1330 public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
1331
1332 enumerator->public.enumerate = (void*)public_enumerate;
1333 enumerator->public.destroy = (void*)public_destroy;
1334 enumerator->inner = create_trusted_enumerator(this, type, id, TRUE, TRUE);
1335 enumerator->this = this;
1336 enumerator->current = NULL;
1337 enumerator->wrapper = NULL;
1338 if (auth)
1339 {
1340 enumerator->wrapper = auth_cfg_wrapper_create(auth);
1341 add_local_set(this, &enumerator->wrapper->set);
1342 }
1343 this->lock->read_lock(this->lock);
1344 return &enumerator->public;
1345 }
1346
1347 /**
1348 * Check if a certificate's keyid is contained in the auth helper
1349 */
1350 static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
1351 {
1352 enumerator_t *enumerator;
1353 identification_t *value;
1354 auth_rule_t type;
1355 bool found = FALSE;
1356
1357 enumerator = auth->create_enumerator(auth);
1358 while (enumerator->enumerate(enumerator, &type, &value))
1359 {
1360 if (type == AUTH_RULE_CA_CERT &&
1361 cert->equals(cert, (certificate_t*)value))
1362 {
1363 found = TRUE;
1364 break;
1365 }
1366 }
1367 enumerator->destroy(enumerator);
1368 return found;
1369 }
1370
1371 /**
1372 * build a trustchain from subject up to a trust anchor in trusted
1373 */
1374 static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
1375 certificate_t *subject, auth_cfg_t *auth)
1376 {
1377 certificate_t *issuer, *current;
1378 auth_cfg_t *trustchain;
1379 u_int level = 0;
1380
1381 trustchain = auth_cfg_create();
1382
1383 current = auth->get(auth, AUTH_RULE_CA_CERT);
1384 if (!current)
1385 {
1386 /* no trust anchor specified, return this cert only */
1387 trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
1388 subject->get_ref(subject));
1389 return trustchain;
1390 }
1391 current = subject->get_ref(subject);
1392 while (TRUE)
1393 {
1394 if (auth_contains_cacert(auth, current))
1395 {
1396 trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
1397 return trustchain;
1398 }
1399 if (subject == current)
1400 {
1401 trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
1402 }
1403 else
1404 {
1405 trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
1406 }
1407 issuer = get_issuer_cert(this, current, FALSE);
1408 if (!issuer || issuer->equals(issuer, current) || level > MAX_CA_LEVELS)
1409 {
1410 DESTROY_IF(issuer);
1411 break;
1412 }
1413 current = issuer;
1414 level++;
1415 }
1416 trustchain->destroy(trustchain);
1417 return NULL;
1418 }
1419
1420 /**
1421 * find a private key of a give certificate
1422 */
1423 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1424 certificate_t *cert, key_type_t type)
1425 {
1426 private_key_t *private = NULL;
1427 identification_t* keyid;
1428 public_key_t *public;
1429
1430 public = cert->get_public_key(cert);
1431 if (public)
1432 {
1433 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
1434 if (keyid)
1435 {
1436 private = get_private_by_keyid(this, type, keyid);
1437 }
1438 public->destroy(public);
1439 }
1440 return private;
1441 }
1442
1443 /**
1444 * Implementation of credential_manager_t.get_private.
1445 */
1446 static private_key_t *get_private(private_credential_manager_t *this,
1447 key_type_t type, identification_t *id,
1448 auth_cfg_t *auth)
1449 {
1450 enumerator_t *enumerator;
1451 certificate_t *cert;
1452 private_key_t *private = NULL;
1453 auth_cfg_t *trustchain;
1454
1455 /* check if this is a lookup by key ID, and do it if so */
1456 if (id)
1457 {
1458 switch (id->get_type(id))
1459 {
1460 case ID_PUBKEY_SHA1:
1461 case ID_PUBKEY_INFO_SHA1:
1462 case ID_KEY_ID:
1463 return get_private_by_keyid(this, type, id);
1464 default:
1465 break;
1466 }
1467 }
1468
1469 /* if a specific certificate is preferred, check for a matching key */
1470 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
1471 if (cert)
1472 {
1473 private = get_private_by_cert(this, cert, type);
1474 if (private)
1475 {
1476 trustchain = build_trustchain(this, cert, auth);
1477 if (trustchain)
1478 {
1479 auth->merge(auth, trustchain, FALSE);
1480 trustchain->destroy(trustchain);
1481 }
1482 return private;
1483 }
1484 }
1485
1486 /* try to build a trust chain for each certificate found */
1487 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1488 while (enumerator->enumerate(enumerator, &cert))
1489 {
1490 private = get_private_by_cert(this, cert, type);
1491 if (private)
1492 {
1493 trustchain = build_trustchain(this, cert, auth);
1494 if (trustchain)
1495 {
1496 auth->merge(auth, trustchain, FALSE);
1497 trustchain->destroy(trustchain);
1498 break;
1499 }
1500 private->destroy(private);
1501 private = NULL;
1502 }
1503 }
1504 enumerator->destroy(enumerator);
1505
1506 /* if no valid trustchain was found, fall back to the first usable cert */
1507 if (!private)
1508 {
1509 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1510 while (enumerator->enumerate(enumerator, &cert))
1511 {
1512 private = get_private_by_cert(this, cert, type);
1513 if (private)
1514 {
1515 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
1516 break;
1517 }
1518 }
1519 enumerator->destroy(enumerator);
1520 }
1521 return private;
1522 }
1523
1524 /**
1525 * Implementation of credential_manager_t.flush_cache.
1526 */
1527 static void flush_cache(private_credential_manager_t *this,
1528 certificate_type_t type)
1529 {
1530 this->cache->flush(this->cache, type);
1531 }
1532
1533 /**
1534 * Implementation of credential_manager_t.add_set.
1535 */
1536 static void add_set(private_credential_manager_t *this,
1537 credential_set_t *set)
1538 {
1539 this->lock->write_lock(this->lock);
1540 this->sets->insert_last(this->sets, set);
1541 this->lock->unlock(this->lock);
1542 }
1543
1544 /**
1545 * Implementation of credential_manager_t.remove_set.
1546 */
1547 static void remove_set(private_credential_manager_t *this, credential_set_t *set)
1548 {
1549 this->lock->write_lock(this->lock);
1550 this->sets->remove(this->sets, set, NULL);
1551 this->lock->unlock(this->lock);
1552 }
1553
1554 /**
1555 * Implementation of credential_manager_t.destroy
1556 */
1557 static void destroy(private_credential_manager_t *this)
1558 {
1559 cache_queue(this);
1560 this->cache_queue->destroy(this->cache_queue);
1561 this->sets->remove(this->sets, this->cache, NULL);
1562 this->sets->destroy(this->sets);
1563 pthread_key_delete(this->local_sets);
1564 this->cache->destroy(this->cache);
1565 this->lock->destroy(this->lock);
1566 free(this);
1567 }
1568
1569 /*
1570 * see header file
1571 */
1572 credential_manager_t *credential_manager_create()
1573 {
1574 private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
1575
1576 this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator;
1577 this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator;
1578 this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator;
1579 this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
1580 this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
1581 this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private;
1582 this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_t *aut))create_public_enumerator;
1583 this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache;
1584 this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert;
1585 this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
1586 this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
1587 this->public.destroy = (void(*)(credential_manager_t*))destroy;
1588
1589 this->sets = linked_list_create();
1590 pthread_key_create(&this->local_sets, (void*)this->sets->destroy);
1591 this->cache = cert_cache_create();
1592 this->cache_queue = linked_list_create();
1593 this->sets->insert_first(this->sets, this->cache);
1594 this->lock = rwlock_create(RWLOCK_DEFAULT);
1595
1596 return &this->public;
1597 }
1598