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