2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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>.
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
16 #include "credential_manager.h"
20 #include <threading/thread_value.h>
21 #include <threading/mutex.h>
22 #include <threading/rwlock.h>
23 #include <utils/linked_list.h>
24 #include <credentials/sets/cert_cache.h>
25 #include <credentials/sets/auth_cfg_wrapper.h>
26 #include <credentials/certificates/x509.h>
29 * Maximum length of a certificate trust chain
31 #define MAX_TRUST_PATH_LEN 7
33 typedef struct private_credential_manager_t private_credential_manager_t
;
36 * private data of credential_manager
38 struct private_credential_manager_t
{
43 credential_manager_t
public;
46 * list of credential sets
51 * thread local set of credentials, linked_list_t with credential_set_t's
53 thread_value_t
*local_sets
;
56 * trust relationship and certificate cache
61 * certificates queued for persistent caching
63 linked_list_t
*cache_queue
;
66 * list of certificate validators, cert_validator_t
68 linked_list_t
*validators
;
71 * read-write lock to sets list
76 * mutex for cache queue
81 /** data to pass to create_private_enumerator */
83 private_credential_manager_t
*this;
85 identification_t
* keyid
;
88 /** data to pass to create_cert_enumerator */
90 private_credential_manager_t
*this;
91 certificate_type_t cert
;
97 /** data to pass to create_cdp_enumerator */
99 private_credential_manager_t
*this;
100 certificate_type_t type
;
101 identification_t
*id
;
104 /** data to pass to create_shared_enumerator */
106 private_credential_manager_t
*this;
107 shared_key_type_t type
;
108 identification_t
*me
;
109 identification_t
*other
;
112 /** enumerator over local and global sets */
114 /** implements enumerator_t */
116 /** enumerator over global sets */
117 enumerator_t
*global
;
118 /** enumerator over local sets */
123 METHOD(enumerator_t
, sets_enumerate
, bool,
124 sets_enumerator_t
*this, credential_set_t
**set
)
128 if (this->global
->enumerate(this->global
, set
))
132 /* end of global sets, look for local */
133 this->global
->destroy(this->global
);
138 return this->local
->enumerate(this->local
, set
);
143 METHOD(enumerator_t
, sets_destroy
, void,
144 sets_enumerator_t
*this)
146 DESTROY_IF(this->global
);
147 DESTROY_IF(this->local
);
152 * create an enumerator over both, global and local sets
154 static enumerator_t
*create_sets_enumerator(private_credential_manager_t
*this)
156 sets_enumerator_t
*enumerator
;
157 linked_list_t
*local
;
161 .enumerate
= (void*)_sets_enumerate
,
162 .destroy
= _sets_destroy
,
164 .global
= this->sets
->create_enumerator(this->sets
),
166 local
= this->local_sets
->get(this->local_sets
);
169 enumerator
->local
= local
->create_enumerator(local
);
171 return &enumerator
->public;
175 * cleanup function for cert data
177 static void destroy_cert_data(cert_data_t
*data
)
179 data
->this->lock
->unlock(data
->this->lock
);
184 * enumerator constructor for certificates
186 static enumerator_t
*create_cert(credential_set_t
*set
, cert_data_t
*data
)
188 return set
->create_cert_enumerator(set
, data
->cert
, data
->key
,
189 data
->id
, data
->trusted
);
192 METHOD(credential_manager_t
, create_cert_enumerator
, enumerator_t
*,
193 private_credential_manager_t
*this, certificate_type_t certificate
,
194 key_type_t key
, identification_t
*id
, bool trusted
)
196 cert_data_t
*data
= malloc_thing(cert_data_t
);
198 data
->cert
= certificate
;
201 data
->trusted
= trusted
;
203 this->lock
->read_lock(this->lock
);
204 return enumerator_create_nested(create_sets_enumerator(this),
205 (void*)create_cert
, data
,
206 (void*)destroy_cert_data
);
209 METHOD(credential_manager_t
, get_cert
, certificate_t
*,
210 private_credential_manager_t
*this, certificate_type_t cert
, key_type_t key
,
211 identification_t
*id
, bool trusted
)
213 certificate_t
*current
, *found
= NULL
;
214 enumerator_t
*enumerator
;
216 enumerator
= create_cert_enumerator(this, cert
, key
, id
, trusted
);
217 if (enumerator
->enumerate(enumerator
, ¤t
))
219 /* TODO: best match? order by keyid, subject, sualtname */
220 found
= current
->get_ref(current
);
222 enumerator
->destroy(enumerator
);
228 * cleanup function for cdp data
230 static void destroy_cdp_data(cdp_data_t
*data
)
232 data
->this->lock
->unlock(data
->this->lock
);
237 * enumerator constructor for CDPs
239 static enumerator_t
*create_cdp(credential_set_t
*set
, cdp_data_t
*data
)
241 return set
->create_cdp_enumerator(set
, data
->type
, data
->id
);
244 METHOD(credential_manager_t
, create_cdp_enumerator
, enumerator_t
*,
245 private_credential_manager_t
*this, certificate_type_t type
,
246 identification_t
*id
)
255 this->lock
->read_lock(this->lock
);
256 return enumerator_create_nested(create_sets_enumerator(this),
257 (void*)create_cdp
, data
,
258 (void*)destroy_cdp_data
);
262 * cleanup function for private data
264 static void destroy_private_data(private_data_t
*data
)
266 data
->this->lock
->unlock(data
->this->lock
);
271 * enumerator constructor for private keys
273 static enumerator_t
*create_private(credential_set_t
*set
, private_data_t
*data
)
275 return set
->create_private_enumerator(set
, data
->type
, data
->keyid
);
279 * Create an enumerator over private keys
281 static enumerator_t
*create_private_enumerator(
282 private_credential_manager_t
*this, key_type_t key
, identification_t
*keyid
)
284 private_data_t
*data
;
291 this->lock
->read_lock(this->lock
);
292 return enumerator_create_nested(create_sets_enumerator(this),
293 (void*)create_private
, data
,
294 (void*)destroy_private_data
);
298 * Look up a private key by its key identifier
300 static private_key_t
* get_private_by_keyid(private_credential_manager_t
*this,
301 key_type_t key
, identification_t
*keyid
)
303 private_key_t
*found
= NULL
;
304 enumerator_t
*enumerator
;
306 enumerator
= create_private_enumerator(this, key
, keyid
);
307 if (enumerator
->enumerate(enumerator
, &found
))
309 found
->get_ref(found
);
311 enumerator
->destroy(enumerator
);
316 * cleanup function for shared data
318 static void destroy_shared_data(shared_data_t
*data
)
320 data
->this->lock
->unlock(data
->this->lock
);
325 * enumerator constructor for shared keys
327 static enumerator_t
*create_shared(credential_set_t
*set
, shared_data_t
*data
)
329 return set
->create_shared_enumerator(set
, data
->type
, data
->me
, data
->other
);
332 METHOD(credential_manager_t
, create_shared_enumerator
, enumerator_t
*,
333 private_credential_manager_t
*this, shared_key_type_t type
,
334 identification_t
*me
, identification_t
*other
)
344 this->lock
->read_lock(this->lock
);
345 return enumerator_create_nested(create_sets_enumerator(this),
346 (void*)create_shared
, data
,
347 (void*)destroy_shared_data
);
350 METHOD(credential_manager_t
, get_shared
, shared_key_t
*,
351 private_credential_manager_t
*this, shared_key_type_t type
,
352 identification_t
*me
, identification_t
*other
)
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
;
359 enumerator
= create_shared_enumerator(this, type
, me
, other
);
360 while (enumerator
->enumerate(enumerator
, ¤t
, &match_me
, &match_other
))
362 if (match_other
> best_other
||
363 (match_other
== best_other
&& match_me
> best_me
))
366 found
= current
->get_ref(current
);
368 best_other
= match_other
;
371 enumerator
->destroy(enumerator
);
375 METHOD(credential_manager_t
, add_local_set
, void,
376 private_credential_manager_t
*this, credential_set_t
*set
)
380 sets
= this->local_sets
->get(this->local_sets
);
382 { /* first invocation */
383 sets
= linked_list_create();
384 this->local_sets
->set(this->local_sets
, sets
);
386 sets
->insert_last(sets
, set
);
389 METHOD(credential_manager_t
, remove_local_set
, void,
390 private_credential_manager_t
*this, credential_set_t
*set
)
394 sets
= this->local_sets
->get(this->local_sets
);
395 sets
->remove(sets
, set
, NULL
);
398 METHOD(credential_manager_t
, cache_cert
, void,
399 private_credential_manager_t
*this, certificate_t
*cert
)
401 credential_set_t
*set
;
402 enumerator_t
*enumerator
;
404 if (this->lock
->try_write_lock(this->lock
))
406 enumerator
= this->sets
->create_enumerator(this->sets
);
407 while (enumerator
->enumerate(enumerator
, &set
))
409 set
->cache_cert(set
, cert
);
411 enumerator
->destroy(enumerator
);
412 this->lock
->unlock(this->lock
);
415 { /* we can't cache now as other threads are active, queue for later */
416 this->queue_mutex
->lock(this->queue_mutex
);
417 this->cache_queue
->insert_last(this->cache_queue
, cert
->get_ref(cert
));
418 this->queue_mutex
->unlock(this->queue_mutex
);
423 * Try to cache certificates queued for caching
425 static void cache_queue(private_credential_manager_t
*this)
427 credential_set_t
*set
;
429 enumerator_t
*enumerator
;
431 this->queue_mutex
->lock(this->queue_mutex
);
432 if (this->cache_queue
->get_count(this->cache_queue
) > 0 &&
433 this->lock
->try_write_lock(this->lock
))
435 while (this->cache_queue
->remove_last(this->cache_queue
,
436 (void**)&cert
) == SUCCESS
)
438 enumerator
= this->sets
->create_enumerator(this->sets
);
439 while (enumerator
->enumerate(enumerator
, &set
))
441 set
->cache_cert(set
, cert
);
443 enumerator
->destroy(enumerator
);
446 this->lock
->unlock(this->lock
);
448 this->queue_mutex
->unlock(this->queue_mutex
);
452 * check a certificate for its lifetime
454 static bool check_certificate(private_credential_manager_t
*this,
455 certificate_t
*subject
, certificate_t
*issuer
, bool online
,
456 int pathlen
, bool trusted
, auth_cfg_t
*auth
)
458 time_t not_before
, not_after
;
459 cert_validator_t
*validator
;
460 enumerator_t
*enumerator
;
462 if (!subject
->get_validity(subject
, NULL
, ¬_before
, ¬_after
))
464 DBG1(DBG_CFG
, "subject certificate invalid (valid from %T to %T)",
465 ¬_before
, FALSE
, ¬_after
, FALSE
);
468 if (!issuer
->get_validity(issuer
, NULL
, ¬_before
, ¬_after
))
470 DBG1(DBG_CFG
, "issuer certificate invalid (valid from %T to %T)",
471 ¬_before
, FALSE
, ¬_after
, FALSE
);
475 enumerator
= this->validators
->create_enumerator(this->validators
);
476 while (enumerator
->enumerate(enumerator
, &validator
))
478 if (!validator
->validate(validator
, subject
, issuer
,
479 online
, pathlen
, trusted
, auth
))
481 enumerator
->destroy(enumerator
);
485 enumerator
->destroy(enumerator
);
490 * Get a trusted certificate from a credential set
492 static certificate_t
*get_pretrusted_cert(private_credential_manager_t
*this,
493 key_type_t type
, identification_t
*id
)
495 certificate_t
*subject
;
496 public_key_t
*public;
498 subject
= get_cert(this, CERT_ANY
, type
, id
, TRUE
);
503 public = subject
->get_public_key(subject
);
506 subject
->destroy(subject
);
509 public->destroy(public);
514 * Get the issuing certificate of a subject certificate
516 static certificate_t
*get_issuer_cert(private_credential_manager_t
*this,
517 certificate_t
*subject
, bool trusted
)
519 enumerator_t
*enumerator
;
520 certificate_t
*issuer
= NULL
, *candidate
;
522 enumerator
= create_cert_enumerator(this, subject
->get_type(subject
), KEY_ANY
,
523 subject
->get_issuer(subject
), trusted
);
524 while (enumerator
->enumerate(enumerator
, &candidate
))
526 if (this->cache
->issued_by(this->cache
, subject
, candidate
))
528 issuer
= candidate
->get_ref(candidate
);
532 enumerator
->destroy(enumerator
);
537 * Get the strength of certificate, add it to auth
539 static void get_key_strength(certificate_t
*cert
, auth_cfg_t
*auth
)
545 key
= cert
->get_public_key(cert
);
548 type
= key
->get_type(key
);
549 strength
= key
->get_keysize(key
);
550 DBG2(DBG_CFG
, " certificate \"%Y\" key: %d bit %N",
551 cert
->get_subject(cert
), strength
, key_type_names
, type
);
555 auth
->add(auth
, AUTH_RULE_RSA_STRENGTH
, strength
);
558 auth
->add(auth
, AUTH_RULE_ECDSA_STRENGTH
, strength
);
568 * try to verify the trust chain of subject, return TRUE if trusted
570 static bool verify_trust_chain(private_credential_manager_t
*this,
571 certificate_t
*subject
, auth_cfg_t
*result
,
572 bool trusted
, bool online
)
574 certificate_t
*current
, *issuer
;
578 auth
= auth_cfg_create();
579 get_key_strength(subject
, auth
);
580 current
= subject
->get_ref(subject
);
581 auth
->add(auth
, AUTH_RULE_SUBJECT_CERT
, current
->get_ref(current
));
583 for (pathlen
= 0; pathlen
<= MAX_TRUST_PATH_LEN
; pathlen
++)
585 issuer
= get_issuer_cert(this, current
, TRUE
);
588 /* accept only self-signed CAs as trust anchor */
589 if (this->cache
->issued_by(this->cache
, issuer
, issuer
))
591 auth
->add(auth
, AUTH_RULE_CA_CERT
, issuer
->get_ref(issuer
));
592 DBG1(DBG_CFG
, " using trusted ca certificate \"%Y\"",
593 issuer
->get_subject(issuer
));
598 auth
->add(auth
, AUTH_RULE_IM_CERT
, issuer
->get_ref(issuer
));
599 DBG1(DBG_CFG
, " using trusted intermediate ca certificate "
600 "\"%Y\"", issuer
->get_subject(issuer
));
605 issuer
= get_issuer_cert(this, current
, FALSE
);
608 if (current
->equals(current
, issuer
))
610 DBG1(DBG_CFG
, " self-signed certificate \"%Y\" is not trusted",
611 current
->get_subject(current
));
612 issuer
->destroy(issuer
);
615 auth
->add(auth
, AUTH_RULE_IM_CERT
, issuer
->get_ref(issuer
));
616 DBG1(DBG_CFG
, " using untrusted intermediate certificate "
617 "\"%Y\"", issuer
->get_subject(issuer
));
621 DBG1(DBG_CFG
, "no issuer certificate found for \"%Y\"",
622 current
->get_subject(current
));
626 if (!check_certificate(this, current
, issuer
, online
,
627 pathlen
, trusted
, auth
))
630 issuer
->destroy(issuer
);
635 get_key_strength(issuer
, auth
);
637 current
->destroy(current
);
641 DBG1(DBG_CFG
, " reached self-signed root ca with a path length of %d",
646 current
->destroy(current
);
647 if (pathlen
> MAX_TRUST_PATH_LEN
)
649 DBG1(DBG_CFG
, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN
);
653 result
->merge(result
, auth
, FALSE
);
660 * List find match function for certificates
662 static bool cert_equals(certificate_t
*a
, certificate_t
*b
)
664 return a
->equals(a
, b
);
668 * enumerator for trusted certificates
671 /** implements enumerator_t interface */
673 /** enumerator over candidate peer certificates */
674 enumerator_t
*candidates
;
675 /** reference to the credential_manager */
676 private_credential_manager_t
*this;
677 /** type of the requested key */
679 /** identity the requested key belongs to */
680 identification_t
*id
;
681 /** TRUE to do CRL/OCSP checking */
683 /** pretrusted certificate we have served at first invocation */
684 certificate_t
*pretrusted
;
685 /** currently enumerating auth config */
687 /** list of failed candidates */
688 linked_list_t
*failed
;
689 } trusted_enumerator_t
;
691 METHOD(enumerator_t
, trusted_enumerate
, bool,
692 trusted_enumerator_t
*this, certificate_t
**cert
, auth_cfg_t
**auth
)
694 certificate_t
*current
;
696 DESTROY_IF(this->auth
);
697 this->auth
= auth_cfg_create();
699 if (!this->candidates
)
701 /* first invocation, build enumerator for next one */
702 this->candidates
= create_cert_enumerator(this->this, CERT_ANY
,
703 this->type
, this->id
, FALSE
);
704 /* check if we have a trusted certificate for that peer */
705 this->pretrusted
= get_pretrusted_cert(this->this, this->type
, this->id
);
706 if (this->pretrusted
)
708 /* if we find a trusted self signed certificate, we just accept it.
709 * However, in order to fulfill authorization rules, we try to build
710 * the trust chain if it is not self signed */
711 if (this->this->cache
->issued_by(this->this->cache
,
712 this->pretrusted
, this->pretrusted
) ||
713 verify_trust_chain(this->this, this->pretrusted
, this->auth
,
716 DBG1(DBG_CFG
, " using trusted certificate \"%Y\"",
717 this->pretrusted
->get_subject(this->pretrusted
));
718 *cert
= this->pretrusted
;
719 if (!this->auth
->get(this->auth
, AUTH_RULE_SUBJECT_CERT
))
720 { /* add cert to auth info, if not returned by trustchain */
721 this->auth
->add(this->auth
, AUTH_RULE_SUBJECT_CERT
,
722 this->pretrusted
->get_ref(this->pretrusted
));
732 /* try to verify the trust chain for each certificate found */
733 while (this->candidates
->enumerate(this->candidates
, ¤t
))
735 if (this->pretrusted
&&
736 this->pretrusted
->equals(this->pretrusted
, current
))
737 { /* skip pretrusted certificate we already served */
741 if (this->failed
->find_first(this->failed
, (void*)cert_equals
,
742 NULL
, current
) == SUCCESS
)
743 { /* check each candidate only once */
747 DBG1(DBG_CFG
, " using certificate \"%Y\"",
748 current
->get_subject(current
));
749 if (verify_trust_chain(this->this, current
, this->auth
, FALSE
,
759 this->failed
->insert_last(this->failed
, current
->get_ref(current
));
764 METHOD(enumerator_t
, trusted_destroy
, void,
765 trusted_enumerator_t
*this)
767 DESTROY_IF(this->pretrusted
);
768 DESTROY_IF(this->auth
);
769 DESTROY_IF(this->candidates
);
770 this->failed
->destroy_offset(this->failed
, offsetof(certificate_t
, destroy
));
774 METHOD(credential_manager_t
, create_trusted_enumerator
, enumerator_t
*,
775 private_credential_manager_t
*this, key_type_t type
,
776 identification_t
*id
, bool online
)
778 trusted_enumerator_t
*enumerator
;
782 .enumerate
= (void*)_trusted_enumerate
,
783 .destroy
= _trusted_destroy
,
789 .failed
= linked_list_create(),
791 return &enumerator
->public;
795 * enumerator for public keys
798 /** implements enumerator_t interface */
800 /** enumerator over candidate peer certificates */
802 /** reference to the credential_manager */
803 private_credential_manager_t
*this;
804 /** currently enumerating key */
805 public_key_t
*current
;
806 /** credset wrapper around auth config */
807 auth_cfg_wrapper_t
*wrapper
;
808 } public_enumerator_t
;
810 METHOD(enumerator_t
, public_enumerate
, bool,
811 public_enumerator_t
*this, public_key_t
**key
, auth_cfg_t
**auth
)
815 while (this->inner
->enumerate(this->inner
, &cert
, auth
))
817 DESTROY_IF(this->current
);
818 this->current
= cert
->get_public_key(cert
);
821 *key
= this->current
;
828 METHOD(enumerator_t
, public_destroy
, void,
829 public_enumerator_t
*this)
831 DESTROY_IF(this->current
);
832 this->inner
->destroy(this->inner
);
835 remove_local_set(this->this, &this->wrapper
->set
);
836 this->wrapper
->destroy(this->wrapper
);
838 this->this->lock
->unlock(this->this->lock
);
840 /* check for delayed certificate cache queue */
841 cache_queue(this->this);
845 METHOD(credential_manager_t
, create_public_enumerator
, enumerator_t
*,
846 private_credential_manager_t
*this, key_type_t type
, identification_t
*id
,
849 public_enumerator_t
*enumerator
;
853 .enumerate
= (void*)_public_enumerate
,
854 .destroy
= _public_destroy
,
856 .inner
= create_trusted_enumerator(this, type
, id
, TRUE
),
861 enumerator
->wrapper
= auth_cfg_wrapper_create(auth
);
862 add_local_set(this, &enumerator
->wrapper
->set
);
864 this->lock
->read_lock(this->lock
);
865 return &enumerator
->public;
869 * Check if an helper contains a certificate as trust anchor
871 static bool auth_contains_cacert(auth_cfg_t
*auth
, certificate_t
*cert
)
873 enumerator_t
*enumerator
;
874 identification_t
*value
;
878 enumerator
= auth
->create_enumerator(auth
);
879 while (enumerator
->enumerate(enumerator
, &type
, &value
))
881 if (type
== AUTH_RULE_CA_CERT
&&
882 cert
->equals(cert
, (certificate_t
*)value
))
888 enumerator
->destroy(enumerator
);
893 * build a trustchain from subject up to a trust anchor in trusted
895 static auth_cfg_t
*build_trustchain(private_credential_manager_t
*this,
896 certificate_t
*subject
, auth_cfg_t
*auth
)
898 certificate_t
*issuer
, *current
;
899 auth_cfg_t
*trustchain
;
903 trustchain
= auth_cfg_create();
904 has_anchor
= auth
->get(auth
, AUTH_RULE_CA_CERT
) != NULL
;
905 current
= subject
->get_ref(subject
);
908 if (auth_contains_cacert(auth
, current
))
910 trustchain
->add(trustchain
, AUTH_RULE_CA_CERT
, current
);
913 if (subject
== current
)
915 trustchain
->add(trustchain
, AUTH_RULE_SUBJECT_CERT
, current
);
920 this->cache
->issued_by(this->cache
, current
, current
))
921 { /* If no trust anchor specified, accept any CA */
922 trustchain
->add(trustchain
, AUTH_RULE_CA_CERT
, current
);
925 trustchain
->add(trustchain
, AUTH_RULE_IM_CERT
, current
);
927 if (pathlen
++ > MAX_TRUST_PATH_LEN
)
931 issuer
= get_issuer_cert(this, current
, FALSE
);
935 { /* If no trust anchor specified, accept incomplete chains */
940 if (has_anchor
&& issuer
->equals(issuer
, current
))
942 issuer
->destroy(issuer
);
947 trustchain
->destroy(trustchain
);
952 * find a private key of a give certificate
954 static private_key_t
*get_private_by_cert(private_credential_manager_t
*this,
955 certificate_t
*cert
, key_type_t type
)
957 private_key_t
*private = NULL
;
958 identification_t
*keyid
;
960 public_key_t
*public;
962 public = cert
->get_public_key(cert
);
965 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1
, &chunk
))
967 keyid
= identification_create_from_encoding(ID_KEY_ID
, chunk
);
968 private = get_private_by_keyid(this, type
, keyid
);
969 keyid
->destroy(keyid
);
971 public->destroy(public);
976 METHOD(credential_manager_t
, get_private
, private_key_t
*,
977 private_credential_manager_t
*this, key_type_t type
, identification_t
*id
,
980 enumerator_t
*enumerator
;
982 private_key_t
*private = NULL
;
983 auth_cfg_t
*trustchain
;
985 /* check if this is a lookup by key ID, and do it if so */
986 if (id
&& id
->get_type(id
) == ID_KEY_ID
)
988 private = get_private_by_keyid(this, type
, id
);
995 /* if a specific certificate is preferred, check for a matching key */
996 cert
= auth
->get(auth
, AUTH_RULE_SUBJECT_CERT
);
999 private = get_private_by_cert(this, cert
, type
);
1002 trustchain
= build_trustchain(this, cert
, auth
);
1005 auth
->merge(auth
, trustchain
, FALSE
);
1006 trustchain
->destroy(trustchain
);
1012 /* try to build a trust chain for each certificate found */
1013 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1014 while (enumerator
->enumerate(enumerator
, &cert
))
1016 private = get_private_by_cert(this, cert
, type
);
1019 trustchain
= build_trustchain(this, cert
, auth
);
1022 auth
->merge(auth
, trustchain
, FALSE
);
1023 trustchain
->destroy(trustchain
);
1026 private->destroy(private);
1030 enumerator
->destroy(enumerator
);
1032 /* if no valid trustchain was found, fall back to the first usable cert */
1035 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1036 while (enumerator
->enumerate(enumerator
, &cert
))
1038 private = get_private_by_cert(this, cert
, type
);
1041 auth
->add(auth
, AUTH_RULE_SUBJECT_CERT
, cert
->get_ref(cert
));
1045 enumerator
->destroy(enumerator
);
1050 METHOD(credential_manager_t
, flush_cache
, void,
1051 private_credential_manager_t
*this, certificate_type_t type
)
1053 this->cache
->flush(this->cache
, type
);
1056 METHOD(credential_manager_t
, issued_by
, bool,
1057 private_credential_manager_t
*this, certificate_t
*subject
,
1058 certificate_t
*issuer
)
1060 return this->cache
->issued_by(this->cache
, subject
, issuer
);
1063 METHOD(credential_manager_t
, add_set
, void,
1064 private_credential_manager_t
*this, credential_set_t
*set
)
1066 this->lock
->write_lock(this->lock
);
1067 this->sets
->insert_last(this->sets
, set
);
1068 this->lock
->unlock(this->lock
);
1071 METHOD(credential_manager_t
, remove_set
, void,
1072 private_credential_manager_t
*this, credential_set_t
*set
)
1074 this->lock
->write_lock(this->lock
);
1075 this->sets
->remove(this->sets
, set
, NULL
);
1076 this->lock
->unlock(this->lock
);
1079 METHOD(credential_manager_t
, add_validator
, void,
1080 private_credential_manager_t
*this, cert_validator_t
*vdtr
)
1082 this->lock
->write_lock(this->lock
);
1083 this->sets
->insert_last(this->validators
, vdtr
);
1084 this->lock
->unlock(this->lock
);
1087 METHOD(credential_manager_t
, remove_validator
, void,
1088 private_credential_manager_t
*this, cert_validator_t
*vdtr
)
1090 this->lock
->write_lock(this->lock
);
1091 this->validators
->remove(this->validators
, vdtr
, NULL
);
1092 this->lock
->unlock(this->lock
);
1095 METHOD(credential_manager_t
, destroy
, void,
1096 private_credential_manager_t
*this)
1099 this->cache_queue
->destroy(this->cache_queue
);
1100 this->sets
->remove(this->sets
, this->cache
, NULL
);
1101 this->sets
->destroy(this->sets
);
1102 this->local_sets
->destroy(this->local_sets
);
1103 this->cache
->destroy(this->cache
);
1104 this->validators
->destroy(this->validators
);
1105 this->lock
->destroy(this->lock
);
1106 this->queue_mutex
->destroy(this->queue_mutex
);
1113 credential_manager_t
*credential_manager_create()
1115 private_credential_manager_t
*this;
1119 .create_cert_enumerator
= _create_cert_enumerator
,
1120 .create_shared_enumerator
= _create_shared_enumerator
,
1121 .create_cdp_enumerator
= _create_cdp_enumerator
,
1122 .get_cert
= _get_cert
,
1123 .get_shared
= _get_shared
,
1124 .get_private
= _get_private
,
1125 .create_trusted_enumerator
= _create_trusted_enumerator
,
1126 .create_public_enumerator
= _create_public_enumerator
,
1127 .flush_cache
= _flush_cache
,
1128 .cache_cert
= _cache_cert
,
1129 .issued_by
= _issued_by
,
1130 .add_set
= _add_set
,
1131 .remove_set
= _remove_set
,
1132 .add_local_set
= _add_local_set
,
1133 .remove_local_set
= _remove_local_set
,
1134 .add_validator
= _add_validator
,
1135 .remove_validator
= _remove_validator
,
1136 .destroy
= _destroy
,
1138 .sets
= linked_list_create(),
1139 .validators
= linked_list_create(),
1140 .cache
= cert_cache_create(),
1141 .cache_queue
= linked_list_create(),
1142 .lock
= rwlock_create(RWLOCK_TYPE_DEFAULT
),
1143 .queue_mutex
= mutex_create(MUTEX_TYPE_DEFAULT
),
1146 this->local_sets
= thread_value_create((thread_cleanup_t
)this->sets
->destroy
);
1147 this->sets
->insert_first(this->sets
, this->cache
);
1149 return &this->public;