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
18 #include "credential_manager.h"
21 #include <utils/linked_list.h>
22 #include <utils/mutex.h>
23 #include <credentials/sets/cert_cache.h>
24 #include <credentials/sets/auth_info_wrapper.h>
25 #include <credentials/sets/ocsp_response_wrapper.h>
26 #include <credentials/certificates/x509.h>
27 #include <credentials/certificates/crl.h>
28 #include <credentials/certificates/ocsp_request.h>
29 #include <credentials/certificates/ocsp_response.h>
31 #define MAX_CA_LEVELS 6
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 * trust relationship and certificate cache
56 * mutex to gain exclusive access
61 /** data to pass to create_private_enumerator */
63 private_credential_manager_t
*this;
65 identification_t
* keyid
;
68 /** data to pass to create_cert_enumerator */
70 private_credential_manager_t
*this;
71 certificate_type_t cert
;
77 /** data to pass to create_cdp_enumerator */
79 private_credential_manager_t
*this;
80 certificate_type_t type
;
84 /** data to pass to create_shared_enumerator */
86 private_credential_manager_t
*this;
87 shared_key_type_t type
;
89 identification_t
*other
;
93 * cleanup function for cert data
95 static void destroy_cert_data(cert_data_t
*data
)
97 data
->this->mutex
->unlock(data
->this->mutex
);
102 * enumerator constructor for certificates
104 static enumerator_t
*create_cert(credential_set_t
*set
, cert_data_t
*data
)
106 return set
->create_cert_enumerator(set
, data
->cert
, data
->key
,
107 data
->id
, data
->trusted
);
111 * Implementation of credential_manager_t.create_cert_enumerator.
113 static enumerator_t
*create_cert_enumerator(private_credential_manager_t
*this,
114 certificate_type_t certificate
, key_type_t key
,
115 identification_t
*id
, bool trusted
)
117 cert_data_t
*data
= malloc_thing(cert_data_t
);
119 data
->cert
= certificate
;
122 data
->trusted
= trusted
;
124 this->mutex
->lock(this->mutex
);
125 return enumerator_create_nested(this->sets
->create_enumerator(this->sets
),
126 (void*)create_cert
, data
,
127 (void*)destroy_cert_data
);
131 * Implementation of credential_manager_t.get_cert.
133 static certificate_t
*get_cert(private_credential_manager_t
*this,
134 certificate_type_t cert
, key_type_t key
,
135 identification_t
*id
, bool trusted
)
137 certificate_t
*current
, *found
= NULL
;
138 enumerator_t
*enumerator
;
140 this->mutex
->lock(this->mutex
);
141 enumerator
= create_cert_enumerator(this, cert
, key
, id
, trusted
);
142 if (enumerator
->enumerate(enumerator
, ¤t
))
144 /* TODO: best match? order by keyid, subject, sualtname */
145 found
= current
->get_ref(current
);
147 enumerator
->destroy(enumerator
);
148 this->mutex
->unlock(this->mutex
);
154 * cleanup function for cdp data
156 static void destroy_cdp_data(cdp_data_t
*data
)
158 data
->this->mutex
->unlock(data
->this->mutex
);
163 * enumerator constructor for CDPs
165 static enumerator_t
*create_cdp(credential_set_t
*set
, cdp_data_t
*data
)
167 return set
->create_cdp_enumerator(set
, data
->type
, data
->id
);
170 * Implementation of credential_manager_t.create_cdp_enumerator.
172 static enumerator_t
* create_cdp_enumerator(private_credential_manager_t
*this,
173 credential_type_t type
, identification_t
*id
)
175 cdp_data_t
*data
= malloc_thing(cdp_data_t
);
180 this->mutex
->lock(this->mutex
);
181 return enumerator_create_nested(this->sets
->create_enumerator(this->sets
),
182 (void*)create_cdp
, data
,
183 (void*)destroy_cdp_data
);
187 * cleanup function for private data
189 static void destroy_private_data(private_data_t
*data
)
191 data
->this->mutex
->unlock(data
->this->mutex
);
196 * enumerator constructor for private keys
198 static enumerator_t
*create_private(credential_set_t
*set
, private_data_t
*data
)
200 return set
->create_private_enumerator(set
, data
->type
, data
->keyid
);
204 * Implementation of credential_manager_t.get_private_by_keyid.
206 static enumerator_t
* create_private_enumerator(
207 private_credential_manager_t
*this,
208 key_type_t key
, identification_t
*keyid
)
210 private_data_t
*data
;
212 data
= malloc_thing(private_data_t
);
216 this->mutex
->lock(this->mutex
);
217 return enumerator_create_nested(this->sets
->create_enumerator(this->sets
),
218 (void*)create_private
, data
, (void*)destroy_private_data
);
222 * Implementation of credential_manager_t.get_private_by_keyid.
224 static private_key_t
*get_private_by_keyid(private_credential_manager_t
*this,
225 key_type_t key
, identification_t
*keyid
)
227 private_key_t
*found
= NULL
;
228 enumerator_t
*enumerator
;
230 enumerator
= create_private_enumerator(this, key
, keyid
);
231 if (enumerator
->enumerate(enumerator
, &found
))
233 found
->get_ref(found
);
235 enumerator
->destroy(enumerator
);
240 * cleanup function for shared data
242 static void destroy_shared_data(shared_data_t
*data
)
244 data
->this->mutex
->unlock(data
->this->mutex
);
249 * enumerator constructor for shared keys
251 static enumerator_t
*create_shared(credential_set_t
*set
, shared_data_t
*data
)
253 return set
->create_shared_enumerator(set
, data
->type
, data
->me
, data
->other
);
257 * Implementation of credential_manager_t.create_shared_enumerator.
259 static enumerator_t
*create_shared_enumerator(private_credential_manager_t
*this,
260 shared_key_type_t type
,
261 identification_t
*me
, identification_t
*other
)
263 shared_data_t
*data
= malloc_thing(shared_data_t
);
269 this->mutex
->lock(this->mutex
);
270 return enumerator_create_nested(this->sets
->create_enumerator(this->sets
),
271 (void*)create_shared
, data
,
272 (void*)destroy_shared_data
);
276 * Implementation of credential_manager_t.get_shared.
278 static shared_key_t
*get_shared(private_credential_manager_t
*this,
279 shared_key_type_t type
, identification_t
*me
,
280 identification_t
*other
)
282 shared_key_t
*current
, *found
= NULL
;
283 id_match_t
*best_me
= ID_MATCH_NONE
, *best_other
= ID_MATCH_NONE
;
284 id_match_t
*match_me
, *match_other
;
285 enumerator_t
*enumerator
;
287 enumerator
= create_shared_enumerator(this, type
, me
, other
);
288 while (enumerator
->enumerate(enumerator
, ¤t
, &match_me
, &match_other
))
290 if (match_other
> best_other
||
291 (match_other
== best_other
&& match_me
> best_me
))
294 found
= current
->get_ref(current
);
296 best_other
= match_other
;
299 enumerator
->destroy(enumerator
);
304 * forward declaration
307 static enumerator_t
*create_trusted_enumerator(private_credential_manager_t
*this,
308 key_type_t type
, identification_t
*id
, bool crl
, bool ocsp
);
312 static certificate_t
*fetch_ocsp(private_credential_manager_t
*this, char *url
,
313 certificate_t
*subject
, certificate_t
*issuer
)
315 certificate_t
*request
, *response
;
316 chunk_t send
, receive
;
318 /* TODO: requestor name, signature */
319 request
= lib
->creds
->create(lib
->creds
,
320 CRED_CERTIFICATE
, CERT_X509_OCSP_REQUEST
,
321 BUILD_CA_CERT
, issuer
->get_ref(issuer
),
322 BUILD_CERT
, subject
->get_ref(subject
), BUILD_END
);
325 DBG1(DBG_CFG
, "generating ocsp request failed");
329 send
= request
->get_encoding(request
);
330 request
->destroy(request
);
332 DBG1(DBG_CFG
, "requesting ocsp status from '%s' ...", url
);
333 /* TODO: unlock manager while fetching? */
334 if (lib
->fetcher
->fetch(lib
->fetcher
, url
, &receive
,
335 FETCH_REQUEST_DATA
, send
,
336 FETCH_REQUEST_TYPE
, "application/ocsp-request",
337 FETCH_END
) != SUCCESS
)
339 DBG1(DBG_CFG
, "ocsp request to %s failed", url
);
345 response
= lib
->creds
->create(lib
->creds
,
346 CRED_CERTIFICATE
, CERT_X509_OCSP_RESPONSE
,
347 BUILD_BLOB_ASN1_DER
, receive
, BUILD_END
);
350 DBG1(DBG_CFG
, "parsing ocsp response failed");
357 * check the signature of an OCSP response
359 static bool verify_ocsp(private_credential_manager_t
*this,
360 ocsp_response_t
*response
)
362 certificate_t
*issuer
, *subject
;
363 identification_t
*responder
;
364 ocsp_response_wrapper_t
*wrapper
;
365 enumerator_t
*enumerator
;
366 bool verified
= FALSE
;
368 wrapper
= ocsp_response_wrapper_create((ocsp_response_t
*)response
);
369 this->sets
->insert_last(this->sets
, wrapper
);
371 subject
= &response
->certificate
;
372 responder
= subject
->get_issuer(subject
);
373 enumerator
= create_trusted_enumerator(this, KEY_ANY
, responder
, FALSE
, FALSE
);
374 while (enumerator
->enumerate(enumerator
, &issuer
, NULL
))
376 if (this->cache
->issued_by(this->cache
, subject
, issuer
))
378 DBG1(DBG_CFG
, " ocsp response correctly signed by \"%D\"",
379 issuer
->get_subject(issuer
));
384 enumerator
->destroy(enumerator
);
386 this->sets
->remove(this->sets
, wrapper
, NULL
);
387 wrapper
->destroy(wrapper
);
392 * Get the better of two OCSP responses, and check for usable OCSP info
394 static certificate_t
*get_better_ocsp(private_credential_manager_t
*this,
395 certificate_t
*cand
, certificate_t
*best
,
396 x509_t
*subject
, x509_t
*issuer
,
397 cert_validation_t
*valid
)
399 ocsp_response_t
*response
;
400 time_t revocation
, this_update
, next_update
, valid_until
;
403 response
= (ocsp_response_t
*)cand
;
405 /* check ocsp signature */
406 if (!verify_ocsp(this, response
))
408 DBG1(DBG_CFG
, "ocsp response verification failed");
412 /* check if response contains our certificate */
413 switch (response
->get_status(response
, subject
, issuer
, &revocation
, &reason
,
414 &this_update
, &next_update
))
416 case VALIDATION_REVOKED
:
417 /* subject has been revoked by a valid OCSP response */
418 DBG1(DBG_CFG
, "certificate was revoked on %T, reason: %N",
419 &revocation
, crl_reason_names
, reason
);
421 *valid
= VALIDATION_REVOKED
;
423 case VALIDATION_GOOD
:
424 /* results in either good or stale */
427 case VALIDATION_FAILED
:
428 /* candidate unusable, does not contain our cert */
433 /* select the better of the two responses */
434 if (best
== NULL
|| cand
->is_newer(cand
, best
))
438 if (best
->get_validity(best
, NULL
, NULL
, &valid_until
))
440 DBG1(DBG_CFG
, " ocsp response is valid: until %#T",
441 &valid_until
, FALSE
);
442 *valid
= VALIDATION_GOOD
;
446 DBG1(DBG_CFG
, " ocsp response is stale: since %#T",
447 &valid_until
, FALSE
);
448 *valid
= VALIDATION_STALE
;
453 *valid
= VALIDATION_STALE
;
460 * validate a x509 certificate using OCSP
462 static cert_validation_t
check_ocsp(private_credential_manager_t
*this,
463 x509_t
*subject
, x509_t
*issuer
,
466 enumerator_t
*enumerator
;
467 cert_validation_t valid
= VALIDATION_SKIPPED
;
468 certificate_t
*best
= NULL
, *current
;
469 identification_t
*keyid
= NULL
;
470 public_key_t
*public;
473 /** lookup cache for valid OCSP responses */
474 enumerator
= create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE
,
475 KEY_ANY
, NULL
, FALSE
);
476 while (enumerator
->enumerate(enumerator
, ¤t
))
478 current
->get_ref(current
);
479 best
= get_better_ocsp(this, current
, best
, subject
, issuer
, &valid
);
480 if (best
&& valid
!= VALIDATION_STALE
)
482 DBG1(DBG_CFG
, "found cached ocsp response");
486 enumerator
->destroy(enumerator
);
488 /* derive the authorityKeyIdentifier from the issuer's public key */
489 current
= &issuer
->interface
;
490 public = current
->get_public_key(current
);
493 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
495 /** fetch from configured OCSP responder URLs */
496 if (keyid
&& valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
498 enumerator
= create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE
, keyid
);
499 while (enumerator
->enumerate(enumerator
, &uri
))
501 current
= fetch_ocsp(this, uri
, &subject
->interface
,
505 best
= get_better_ocsp(this, current
, best
, subject
, issuer
, &valid
);
506 if (best
&& valid
!= VALIDATION_STALE
)
512 enumerator
->destroy(enumerator
);
516 /* fallback to URL fetching from subject certificate's URIs */
517 if (valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
519 enumerator
= subject
->create_ocsp_uri_enumerator(subject
);
520 while (enumerator
->enumerate(enumerator
, &uri
))
522 current
= fetch_ocsp(this, uri
, &subject
->interface
,
526 best
= get_better_ocsp(this, current
, best
, subject
, issuer
, &valid
);
527 if (best
&& valid
!= VALIDATION_STALE
)
533 enumerator
->destroy(enumerator
);
535 /* an uri was found, but no result. switch validation state to failed */
536 if (valid
== VALIDATION_SKIPPED
&& uri
)
538 valid
= VALIDATION_FAILED
;
542 auth
->add_item(auth
, AUTHZ_OCSP_VALIDATION
, &valid
);
549 * fetch a CRL from an URL
551 static certificate_t
* fetch_crl(private_credential_manager_t
*this, char *url
)
556 /* TODO: unlock the manager while fetching? */
557 DBG1(DBG_CFG
, "fetching crl from '%s' ...", url
);
558 if (lib
->fetcher
->fetch(lib
->fetcher
, url
, &chunk
, FETCH_END
) != SUCCESS
)
560 DBG1(DBG_CFG
, "crl fetching failed");
563 crl
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509_CRL
,
564 BUILD_BLOB_ASN1_DER
, chunk
, BUILD_END
);
567 DBG1(DBG_CFG
, "crl fetched successfully but parsing failed");
574 * check the signature of an CRL
576 static bool verify_crl(private_credential_manager_t
*this, certificate_t
*crl
)
578 certificate_t
*issuer
;
579 enumerator_t
*enumerator
;
580 bool verified
= FALSE
;
582 enumerator
= create_trusted_enumerator(this, KEY_ANY
, crl
->get_issuer(crl
),
584 while (enumerator
->enumerate(enumerator
, &issuer
, NULL
))
586 if (this->cache
->issued_by(this->cache
, crl
, issuer
))
588 DBG1(DBG_CFG
, " crl correctly signed by \"%D\"",
589 issuer
->get_subject(issuer
));
594 enumerator
->destroy(enumerator
);
600 * Get the better of two CRLs, and check for usable CRL info
602 static certificate_t
*get_better_crl(private_credential_manager_t
*this,
603 certificate_t
*cand
, certificate_t
*best
,
604 x509_t
*subject
, x509_t
*issuer
,
605 cert_validation_t
*valid
)
607 enumerator_t
*enumerator
;
608 time_t revocation
, valid_until
;
613 /* check CRL signature */
614 if (!verify_crl(this, cand
))
616 DBG1(DBG_CFG
, "crl response verification failed");
622 enumerator
= crl
->create_enumerator(crl
);
623 while (enumerator
->enumerate(enumerator
, &serial
, &revocation
, &reason
))
625 if (chunk_equals(serial
, subject
->get_serial(subject
)))
627 DBG1(DBG_CFG
, "certificate was revoked on %T, reason: %N",
628 &revocation
, crl_reason_names
, reason
);
629 *valid
= VALIDATION_REVOKED
;
630 enumerator
->destroy(enumerator
);
635 enumerator
->destroy(enumerator
);
637 /* select the better of the two CRLs */
638 if (best
== NULL
|| cand
->is_newer(cand
, best
))
642 if (best
->get_validity(best
, NULL
, NULL
, &valid_until
))
644 DBG1(DBG_CFG
, " crl is valid: until %#T", &valid_until
, FALSE
);
645 *valid
= VALIDATION_GOOD
;
649 DBG1(DBG_CFG
, " crl is stale: since %#T", &valid_until
, FALSE
);
650 *valid
= VALIDATION_STALE
;
655 *valid
= VALIDATION_STALE
;
662 * validate a x509 certificate using CRL
664 static cert_validation_t
check_crl(private_credential_manager_t
*this,
665 x509_t
*subject
, x509_t
*issuer
,
668 cert_validation_t valid
= VALIDATION_SKIPPED
;
669 identification_t
*keyid
= NULL
;
670 certificate_t
*best
= NULL
;
671 certificate_t
*current
;
672 public_key_t
*public;
673 enumerator_t
*enumerator
;
676 /* derive the authorityKeyIdentifier from the issuer's public key */
677 current
= &issuer
->interface
;
678 public = current
->get_public_key(current
);
681 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
684 /* find a cached crl by authorityKeyIdentifier */
687 enumerator
= create_cert_enumerator(this, CERT_X509_CRL
, KEY_ANY
,
689 while (enumerator
->enumerate(enumerator
, ¤t
))
691 current
->get_ref(current
);
692 best
= get_better_crl(this, current
, best
, subject
, issuer
, &valid
);
693 if (best
&& valid
!= VALIDATION_STALE
)
695 DBG1(DBG_CFG
, "found cached crl");
699 enumerator
->destroy(enumerator
);
702 /* fallback to fetching crls from credential sets cdps */
703 if (keyid
&& valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
705 enumerator
= create_cdp_enumerator(this, CERT_X509_CRL
, keyid
);
707 while (enumerator
->enumerate(enumerator
, &uri
))
709 current
= fetch_crl(this, uri
);
712 best
= get_better_crl(this, current
, best
, subject
, issuer
, &valid
);
713 if (best
&& valid
!= VALIDATION_STALE
)
719 enumerator
->destroy(enumerator
);
723 /* fallback to fetching crls from cdps from subject's certificate */
724 if (valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
726 enumerator
= subject
->create_crl_uri_enumerator(subject
);
728 while (enumerator
->enumerate(enumerator
, &uri
))
730 current
= fetch_crl(this, uri
);
733 best
= get_better_crl(this, current
, best
, subject
, issuer
, &valid
);
734 if (best
&& valid
!= VALIDATION_STALE
)
740 enumerator
->destroy(enumerator
);
743 /* an uri was found, but no result. switch validation state to failed */
744 if (valid
== VALIDATION_SKIPPED
&& uri
)
746 valid
= VALIDATION_FAILED
;
750 auth
->add_item(auth
, AUTHZ_CRL_VALIDATION
, &valid
);
757 * check a certificate for its lifetime
759 static bool check_certificate(private_credential_manager_t
*this,
760 certificate_t
*subject
, certificate_t
*issuer
,
761 bool crl
, bool ocsp
, auth_info_t
*auth
)
763 time_t not_before
, not_after
;
765 if (!subject
->get_validity(subject
, NULL
, ¬_before
, ¬_after
))
767 DBG1(DBG_CFG
, "subject certificate invalid (valid from %T to %T)",
768 ¬_before
, ¬_after
);
771 if (!issuer
->get_validity(issuer
, NULL
, ¬_before
, ¬_after
))
773 DBG1(DBG_CFG
, "issuer certificate invalid (valid from %T to %T)",
774 ¬_before
, ¬_after
);
777 if (issuer
->get_type(issuer
) == CERT_X509
&&
778 subject
->get_type(subject
) == CERT_X509
)
782 switch (check_ocsp(this, (x509_t
*)subject
, (x509_t
*)issuer
, auth
))
784 case VALIDATION_GOOD
:
785 DBG1(DBG_CFG
, "certificate status is good");
787 case VALIDATION_REVOKED
:
788 /* has already been logged */
790 case VALIDATION_SKIPPED
:
791 DBG2(DBG_CFG
, "ocsp check skipped, no ocsp found");
793 case VALIDATION_STALE
:
794 DBG1(DBG_CFG
, "ocsp information stale, fallback to crl");
796 case VALIDATION_FAILED
:
797 DBG1(DBG_CFG
, "ocsp check failed, fallback to crl");
803 switch (check_crl(this, (x509_t
*)subject
, (x509_t
*)issuer
, auth
))
805 case VALIDATION_GOOD
:
806 DBG1(DBG_CFG
, "certificate status is good");
808 case VALIDATION_REVOKED
:
809 /* has already been logged */
811 case VALIDATION_FAILED
:
812 case VALIDATION_SKIPPED
:
813 DBG1(DBG_CFG
, "certificate status is not available");
815 case VALIDATION_STALE
:
816 DBG1(DBG_CFG
, "certificate status is unknown, crl is stale");
825 * Get a trusted certificate from a credential set
827 static certificate_t
*get_pretrusted_cert(private_credential_manager_t
*this,
828 key_type_t type
, identification_t
*id
)
830 certificate_t
*subject
;
831 public_key_t
*public;
833 subject
= get_cert(this, CERT_ANY
, type
, id
, TRUE
);
838 public = subject
->get_public_key(subject
);
841 subject
->destroy(subject
);
844 public->destroy(public);
849 * Get the issuing certificate of a subject certificate
851 static certificate_t
*get_issuer_cert(private_credential_manager_t
*this,
852 certificate_t
*subject
, bool trusted
)
854 enumerator_t
*enumerator
;
855 certificate_t
*issuer
= NULL
, *candidate
;
857 enumerator
= create_cert_enumerator(this, subject
->get_type(subject
), KEY_ANY
,
858 subject
->get_issuer(subject
), trusted
);
859 while (enumerator
->enumerate(enumerator
, &candidate
))
861 if (this->cache
->issued_by(this->cache
, subject
, candidate
))
863 issuer
= candidate
->get_ref(candidate
);
867 enumerator
->destroy(enumerator
);
872 * try to verify the trust chain of subject, return TRUE if trusted
874 static bool verify_trust_chain(private_credential_manager_t
*this,
875 certificate_t
*subject
, auth_info_t
*result
,
876 bool trusted
, bool crl
, bool ocsp
)
878 certificate_t
*current
, *issuer
;
882 auth
= auth_info_create();
883 current
= subject
->get_ref(subject
);
884 while (level
++ < MAX_CA_LEVELS
)
886 issuer
= get_issuer_cert(this, current
, TRUE
);
889 /* accept only self-signed CAs as trust anchor */
890 if (this->cache
->issued_by(this->cache
, issuer
, issuer
))
892 auth
->add_item(auth
, AUTHZ_CA_CERT
, issuer
);
893 DBG1(DBG_CFG
, " using trusted ca certificate \"%D\"",
894 issuer
->get_subject(issuer
));
899 auth
->add_item(auth
, AUTHZ_IM_CERT
, issuer
);
900 DBG1(DBG_CFG
, " using trusted intermediate ca certificate "
901 "\"%D\"", issuer
->get_subject(issuer
));
906 issuer
= get_issuer_cert(this, current
, FALSE
);
909 if (current
->equals(current
, issuer
))
911 DBG1(DBG_CFG
, " self-signed certificate \"%D\" is not trusted",
912 current
->get_subject(current
));
913 issuer
->destroy(issuer
);
916 auth
->add_item(auth
, AUTHZ_IM_CERT
, issuer
);
917 DBG1(DBG_CFG
, " using untrusted intermediate certificate "
918 "\"%D\"", issuer
->get_subject(issuer
));
922 DBG1(DBG_CFG
, "no issuer certificate found for \"%D\"",
923 current
->get_subject(current
));
924 issuer
->destroy(issuer
);
928 if (!check_certificate(this, current
, issuer
, crl
, ocsp
,
929 current
== subject ? auth
: NULL
))
932 issuer
->destroy(issuer
);
935 current
->destroy(current
);
942 current
->destroy(current
);
943 if (level
> MAX_CA_LEVELS
)
945 DBG1(DBG_CFG
, "maximum ca path length of %d levels reached", level
);
949 result
->merge(result
, auth
);
956 * enumerator for trusted certificates
959 /** implements enumerator_t interface */
961 /** enumerator over candidate peer certificates */
962 enumerator_t
*candidates
;
963 /** reference to the credential_manager */
964 private_credential_manager_t
*this;
965 /** type of the requested key */
967 /** identity the requested key belongs to */
968 identification_t
*id
;
969 /** TRUE to do CRL checking */
971 /** TRUE to do OCSP checking */
973 /** currently enumerating certificate */
974 certificate_t
*current
;
975 /** currently enumerating auth info */
977 } trusted_enumerator_t
;
980 * Implements trusted_enumerator_t.enumerate
982 static bool trusted_enumerate(trusted_enumerator_t
*this,
983 certificate_t
**cert
, auth_info_t
**auth
)
985 DESTROY_IF(this->current
);
986 DESTROY_IF(this->auth
);
987 this->auth
= auth_info_create();
989 if (!this->candidates
)
991 /* first invocation, build enumerator for next one */
992 this->candidates
= create_cert_enumerator(this->this, CERT_ANY
,
993 this->type
, this->id
, FALSE
);
994 /* check if we have a trusted certificate for that peer */
995 this->current
= get_pretrusted_cert(this->this, this->type
, this->id
);
998 /* if we find a trusted self signed certificate, we just accept it.
999 * However, in order to fulfill authorization rules, we try to build
1000 * the trust chain if it is not self signed */
1001 if (this->this->cache
->issued_by(this->this->cache
,
1002 this->current
, this->current
) ||
1003 verify_trust_chain(this->this, this->current
, this->auth
,
1004 TRUE
, this->crl
, this->ocsp
))
1006 DBG1(DBG_CFG
, " using trusted certificate \"%D\"",
1007 this->current
->get_subject(this->current
));
1008 *cert
= this->current
;
1015 this->current
->destroy(this->current
);
1016 this->current
= NULL
;
1019 /* try to verify the trust chain for each certificate found */
1020 while (this->candidates
->enumerate(this->candidates
, &this->current
))
1022 DBG1(DBG_CFG
, " using certificate \"%D\"",
1023 this->current
->get_subject(this->current
));
1024 if (verify_trust_chain(this->this, this->current
, this->auth
, FALSE
,
1025 this->crl
, this->ocsp
))
1027 *cert
= this->current
->get_ref(this->current
);
1034 this->current
= NULL
;
1040 * Implements trusted_enumerator_t.destroy
1042 static void trusted_destroy(trusted_enumerator_t
*this)
1044 DESTROY_IF(this->current
);
1045 DESTROY_IF(this->auth
);
1046 DESTROY_IF(this->candidates
);
1051 * create an enumerator over trusted certificates and their trustchain
1053 static enumerator_t
*create_trusted_enumerator(private_credential_manager_t
*this,
1054 key_type_t type
, identification_t
*id
, bool crl
, bool ocsp
)
1056 trusted_enumerator_t
*enumerator
= malloc_thing(trusted_enumerator_t
);
1058 enumerator
->public.enumerate
= (void*)trusted_enumerate
;
1059 enumerator
->public.destroy
= (void*)trusted_destroy
;
1061 enumerator
->candidates
= NULL
;
1062 enumerator
->this = this;
1063 enumerator
->type
= type
;
1064 enumerator
->id
= id
;
1065 enumerator
->crl
= crl
;
1066 enumerator
->ocsp
= ocsp
;
1067 enumerator
->current
= NULL
;
1068 enumerator
->auth
= NULL
;
1070 return &enumerator
->public;
1074 * enumerator for public keys
1077 /** implements enumerator_t interface */
1078 enumerator_t
public;
1079 /** enumerator over candidate peer certificates */
1080 enumerator_t
*inner
;
1081 /** reference to the credential_manager */
1082 private_credential_manager_t
*this;
1083 /** currently enumerating key */
1084 public_key_t
*current
;
1085 /** credset wrapper around auth */
1086 auth_info_wrapper_t
*wrapper
;
1087 } public_enumerator_t
;
1090 * Implements public_enumerator_t.enumerate
1092 static bool public_enumerate(public_enumerator_t
*this,
1093 public_key_t
**key
, auth_info_t
**auth
)
1095 certificate_t
*cert
;
1097 while (this->inner
->enumerate(this->inner
, &cert
, auth
))
1099 DESTROY_IF(this->current
);
1100 this->current
= cert
->get_public_key(cert
);
1103 *key
= this->current
;
1111 * Implements public_enumerator_t.destroy
1113 static void public_destroy(public_enumerator_t
*this)
1115 DESTROY_IF(this->current
);
1116 this->inner
->destroy(this->inner
);
1119 this->this->sets
->remove(this->this->sets
, this->wrapper
, NULL
);
1120 this->wrapper
->destroy(this->wrapper
);
1122 this->this->mutex
->unlock(this->this->mutex
);
1127 * Implementation of credential_manager_t.create_public_enumerator.
1129 static enumerator_t
* create_public_enumerator(private_credential_manager_t
*this,
1130 key_type_t type
, identification_t
*id
, auth_info_t
*auth
)
1132 public_enumerator_t
*enumerator
= malloc_thing(public_enumerator_t
);
1134 enumerator
->public.enumerate
= (void*)public_enumerate
;
1135 enumerator
->public.destroy
= (void*)public_destroy
;
1136 enumerator
->inner
= create_trusted_enumerator(this, type
, id
, TRUE
, TRUE
);
1137 enumerator
->this = this;
1138 enumerator
->current
= NULL
;
1139 enumerator
->wrapper
= NULL
;
1140 this->mutex
->lock(this->mutex
);
1143 enumerator
->wrapper
= auth_info_wrapper_create(auth
);
1144 this->sets
->insert_last(this->sets
, enumerator
->wrapper
);
1146 return &enumerator
->public;
1150 * Check if a certificate's keyid is contained in the auth helper
1152 static bool auth_contains_cacert(auth_info_t
*auth
, certificate_t
*cert
)
1154 enumerator_t
*enumerator
;
1155 identification_t
*value
;
1159 enumerator
= auth
->create_item_enumerator(auth
);
1160 while (enumerator
->enumerate(enumerator
, &type
, &value
))
1162 if (type
== AUTHN_CA_CERT
&& cert
->equals(cert
, (certificate_t
*)value
))
1167 if (type
== AUTHN_CA_CERT_KEYID
)
1169 public_key_t
*public;
1170 identification_t
*certid
, *keyid
;
1172 public = cert
->get_public_key(cert
);
1175 keyid
= (identification_t
*)value
;
1176 certid
= public->get_id(public, keyid
->get_type(keyid
));
1177 if (certid
&& certid
->equals(certid
, keyid
))
1179 public->destroy(public);
1183 public->destroy(public);
1187 enumerator
->destroy(enumerator
);
1192 * build a trustchain from subject up to a trust anchor in trusted
1194 static auth_info_t
*build_trustchain(private_credential_manager_t
*this,
1195 certificate_t
*subject
, auth_info_t
*auth
)
1197 certificate_t
*issuer
, *current
;
1198 auth_info_t
*trustchain
;
1201 trustchain
= auth_info_create();
1203 if (!auth
->get_item(auth
, AUTHN_CA_CERT
, (void**)¤t
))
1205 /* no trust anchor specified, return this cert only */
1206 trustchain
->add_item(trustchain
, AUTHZ_SUBJECT_CERT
, subject
);
1209 current
= subject
->get_ref(subject
);
1212 if (auth_contains_cacert(auth
, current
))
1214 trustchain
->add_item(trustchain
, AUTHZ_CA_CERT
, current
);
1215 current
->destroy(current
);
1218 if (subject
== current
)
1220 trustchain
->add_item(trustchain
, AUTHZ_SUBJECT_CERT
, current
);
1224 trustchain
->add_item(trustchain
, AUTHZ_IM_CERT
, current
);
1226 issuer
= get_issuer_cert(this, current
, FALSE
);
1227 if (!issuer
|| issuer
->equals(issuer
, current
) || level
> MAX_CA_LEVELS
)
1230 current
->destroy(current
);
1233 current
->destroy(current
);
1237 trustchain
->destroy(trustchain
);
1242 * find a private key of a give certificate
1244 static private_key_t
*get_private_by_cert(private_credential_manager_t
*this,
1245 certificate_t
*cert
, key_type_t type
)
1247 private_key_t
*private = NULL
;
1248 identification_t
* keyid
;
1249 public_key_t
*public;
1251 public = cert
->get_public_key(cert
);
1254 keyid
= public->get_id(public, ID_PUBKEY_INFO_SHA1
);
1257 private = get_private_by_keyid(this, type
, keyid
);
1259 public->destroy(public);
1265 * Implementation of credential_manager_t.get_private.
1267 static private_key_t
*get_private(private_credential_manager_t
*this,
1268 key_type_t type
, identification_t
*id
,
1271 enumerator_t
*enumerator
;
1272 certificate_t
*cert
;
1273 private_key_t
*private = NULL
;
1274 auth_info_t
*trustchain
;
1276 /* check if this is a lookup by key ID, and do it if so */
1279 switch (id
->get_type(id
))
1281 case ID_PUBKEY_SHA1
:
1282 case ID_PUBKEY_INFO_SHA1
:
1283 return get_private_by_keyid(this, type
, id
);
1289 this->mutex
->lock(this->mutex
);
1290 /* try to build a trustchain for each certificate found */
1291 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1292 while (enumerator
->enumerate(enumerator
, &cert
))
1294 private = get_private_by_cert(this, cert
, type
);
1297 trustchain
= build_trustchain(this, cert
, auth
);
1300 auth
->merge(auth
, trustchain
);
1301 trustchain
->destroy(trustchain
);
1304 private->destroy(private);
1308 enumerator
->destroy(enumerator
);
1309 /* if no valid trustchain was found, fall back to the first usable cert */
1312 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1313 while (enumerator
->enumerate(enumerator
, &cert
))
1315 private = get_private_by_cert(this, cert
, type
);
1318 auth
->add_item(auth
, AUTHZ_SUBJECT_CERT
, cert
);
1322 enumerator
->destroy(enumerator
);
1324 this->mutex
->unlock(this->mutex
);
1329 * Implementation of credential_manager_t.flush_cache.
1331 static void flush_cache(private_credential_manager_t
*this,
1332 certificate_type_t type
)
1334 this->mutex
->lock(this->mutex
);
1335 this->cache
->flush(this->cache
, type
);
1336 this->mutex
->unlock(this->mutex
);
1340 * Implementation of credential_manager_t.add_set.
1342 static void add_set(private_credential_manager_t
*this,
1343 credential_set_t
*set
)
1345 this->mutex
->lock(this->mutex
);
1346 this->sets
->insert_last(this->sets
, set
);
1347 this->mutex
->unlock(this->mutex
);
1350 * Implementation of credential_manager_t.remove_set.
1352 static void remove_set(private_credential_manager_t
*this, credential_set_t
*set
)
1354 this->mutex
->lock(this->mutex
);
1355 this->sets
->remove(this->sets
, set
, NULL
);
1356 this->mutex
->unlock(this->mutex
);
1360 * Implementation of credential_manager_t.destroy
1362 static void destroy(private_credential_manager_t
*this)
1364 this->sets
->remove(this->sets
, this->cache
, NULL
);
1365 this->sets
->destroy(this->sets
);
1366 this->cache
->destroy(this->cache
);
1367 this->mutex
->destroy(this->mutex
);
1374 credential_manager_t
*credential_manager_create()
1376 private_credential_manager_t
*this = malloc_thing(private_credential_manager_t
);
1378 this->public.create_cert_enumerator
= (enumerator_t
*(*)(credential_manager_t
*this,certificate_type_t cert
, key_type_t key
,identification_t
*id
,bool))create_cert_enumerator
;
1379 this->public.create_shared_enumerator
= (enumerator_t
*(*)(credential_manager_t
*this, shared_key_type_t type
,identification_t
*me
, identification_t
*other
))create_shared_enumerator
;
1380 this->public.create_cdp_enumerator
= (enumerator_t
*(*)(credential_manager_t
*, credential_type_t type
, identification_t
*id
))create_cdp_enumerator
;
1381 this->public.get_cert
= (certificate_t
*(*)(credential_manager_t
*this,certificate_type_t cert
, key_type_t key
,identification_t
*, bool))get_cert
;
1382 this->public.get_shared
= (shared_key_t
*(*)(credential_manager_t
*this,shared_key_type_t type
,identification_t
*me
, identification_t
*other
))get_shared
;
1383 this->public.get_private
= (private_key_t
*(*)(credential_manager_t
*, key_type_t type
, identification_t
*, auth_info_t
*))get_private
;
1384 this->public.create_public_enumerator
= (enumerator_t
*(*)(credential_manager_t
*, key_type_t type
, identification_t
*id
, auth_info_t
*aut
))create_public_enumerator
;
1385 this->public.flush_cache
= (void(*)(credential_manager_t
*, certificate_type_t type
))flush_cache
;
1386 this->public.add_set
= (void(*)(credential_manager_t
*, credential_set_t
*set
))add_set
;
1387 this->public.remove_set
= (void(*)(credential_manager_t
*, credential_set_t
*set
))remove_set
;
1388 this->public.destroy
= (void(*)(credential_manager_t
*))destroy
;
1390 this->sets
= linked_list_create();
1391 this->cache
= cert_cache_create();
1392 this->sets
->insert_first(this->sets
, this->cache
);
1393 this->mutex
= mutex_create(MUTEX_RECURSIVE
);
1395 return &this->public;