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