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 /** pretrusted certificate we have served at first invocation */
974 certificate_t
*pretrusted
;
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 certificate_t
*current
;
987 DESTROY_IF(this->auth
);
988 this->auth
= auth_info_create();
990 if (!this->candidates
)
992 /* first invocation, build enumerator for next one */
993 this->candidates
= create_cert_enumerator(this->this, CERT_ANY
,
994 this->type
, this->id
, FALSE
);
995 /* check if we have a trusted certificate for that peer */
996 this->pretrusted
= get_pretrusted_cert(this->this, this->type
, this->id
);
997 if (this->pretrusted
)
999 /* if we find a trusted self signed certificate, we just accept it.
1000 * However, in order to fulfill authorization rules, we try to build
1001 * the trust chain if it is not self signed */
1002 if (this->this->cache
->issued_by(this->this->cache
,
1003 this->pretrusted
, this->pretrusted
) ||
1004 verify_trust_chain(this->this, this->pretrusted
, this->auth
,
1005 TRUE
, this->crl
, this->ocsp
))
1007 DBG1(DBG_CFG
, " using trusted certificate \"%D\"",
1008 this->pretrusted
->get_subject(this->pretrusted
));
1009 *cert
= this->pretrusted
;
1018 /* try to verify the trust chain for each certificate found */
1019 while (this->candidates
->enumerate(this->candidates
, ¤t
))
1021 if (this->pretrusted
&&
1022 this->pretrusted
->equals(this->pretrusted
, current
))
1023 { /* skip pretrusted certificate we already served */
1027 DBG1(DBG_CFG
, " using certificate \"%D\"",
1028 current
->get_subject(current
));
1029 if (verify_trust_chain(this->this, current
, this->auth
, FALSE
,
1030 this->crl
, this->ocsp
))
1044 * Implements trusted_enumerator_t.destroy
1046 static void trusted_destroy(trusted_enumerator_t
*this)
1048 DESTROY_IF(this->pretrusted
);
1049 DESTROY_IF(this->auth
);
1050 DESTROY_IF(this->candidates
);
1055 * create an enumerator over trusted certificates and their trustchain
1057 static enumerator_t
*create_trusted_enumerator(private_credential_manager_t
*this,
1058 key_type_t type
, identification_t
*id
, bool crl
, bool ocsp
)
1060 trusted_enumerator_t
*enumerator
= malloc_thing(trusted_enumerator_t
);
1062 enumerator
->public.enumerate
= (void*)trusted_enumerate
;
1063 enumerator
->public.destroy
= (void*)trusted_destroy
;
1065 enumerator
->candidates
= NULL
;
1066 enumerator
->this = this;
1067 enumerator
->type
= type
;
1068 enumerator
->id
= id
;
1069 enumerator
->crl
= crl
;
1070 enumerator
->ocsp
= ocsp
;
1071 enumerator
->pretrusted
= NULL
;
1072 enumerator
->auth
= NULL
;
1074 return &enumerator
->public;
1078 * enumerator for public keys
1081 /** implements enumerator_t interface */
1082 enumerator_t
public;
1083 /** enumerator over candidate peer certificates */
1084 enumerator_t
*inner
;
1085 /** reference to the credential_manager */
1086 private_credential_manager_t
*this;
1087 /** currently enumerating key */
1088 public_key_t
*current
;
1089 /** credset wrapper around auth */
1090 auth_info_wrapper_t
*wrapper
;
1091 } public_enumerator_t
;
1094 * Implements public_enumerator_t.enumerate
1096 static bool public_enumerate(public_enumerator_t
*this,
1097 public_key_t
**key
, auth_info_t
**auth
)
1099 certificate_t
*cert
;
1101 while (this->inner
->enumerate(this->inner
, &cert
, auth
))
1103 DESTROY_IF(this->current
);
1104 this->current
= cert
->get_public_key(cert
);
1107 *key
= this->current
;
1115 * Implements public_enumerator_t.destroy
1117 static void public_destroy(public_enumerator_t
*this)
1119 DESTROY_IF(this->current
);
1120 this->inner
->destroy(this->inner
);
1123 this->this->sets
->remove(this->this->sets
, this->wrapper
, NULL
);
1124 this->wrapper
->destroy(this->wrapper
);
1126 this->this->mutex
->unlock(this->this->mutex
);
1131 * Implementation of credential_manager_t.create_public_enumerator.
1133 static enumerator_t
* create_public_enumerator(private_credential_manager_t
*this,
1134 key_type_t type
, identification_t
*id
, auth_info_t
*auth
)
1136 public_enumerator_t
*enumerator
= malloc_thing(public_enumerator_t
);
1138 enumerator
->public.enumerate
= (void*)public_enumerate
;
1139 enumerator
->public.destroy
= (void*)public_destroy
;
1140 enumerator
->inner
= create_trusted_enumerator(this, type
, id
, TRUE
, TRUE
);
1141 enumerator
->this = this;
1142 enumerator
->current
= NULL
;
1143 enumerator
->wrapper
= NULL
;
1144 this->mutex
->lock(this->mutex
);
1147 enumerator
->wrapper
= auth_info_wrapper_create(auth
);
1148 this->sets
->insert_last(this->sets
, enumerator
->wrapper
);
1150 return &enumerator
->public;
1154 * Check if a certificate's keyid is contained in the auth helper
1156 static bool auth_contains_cacert(auth_info_t
*auth
, certificate_t
*cert
)
1158 enumerator_t
*enumerator
;
1159 identification_t
*value
;
1163 enumerator
= auth
->create_item_enumerator(auth
);
1164 while (enumerator
->enumerate(enumerator
, &type
, &value
))
1166 if (type
== AUTHN_CA_CERT
&& cert
->equals(cert
, (certificate_t
*)value
))
1171 if (type
== AUTHN_CA_CERT_KEYID
)
1173 public_key_t
*public;
1174 identification_t
*certid
, *keyid
;
1176 public = cert
->get_public_key(cert
);
1179 keyid
= (identification_t
*)value
;
1180 certid
= public->get_id(public, keyid
->get_type(keyid
));
1181 if (certid
&& certid
->equals(certid
, keyid
))
1183 public->destroy(public);
1187 public->destroy(public);
1191 enumerator
->destroy(enumerator
);
1196 * build a trustchain from subject up to a trust anchor in trusted
1198 static auth_info_t
*build_trustchain(private_credential_manager_t
*this,
1199 certificate_t
*subject
, auth_info_t
*auth
)
1201 certificate_t
*issuer
, *current
;
1202 auth_info_t
*trustchain
;
1205 trustchain
= auth_info_create();
1207 if (!auth
->get_item(auth
, AUTHN_CA_CERT
, (void**)¤t
))
1209 /* no trust anchor specified, return this cert only */
1210 trustchain
->add_item(trustchain
, AUTHZ_SUBJECT_CERT
, subject
);
1213 current
= subject
->get_ref(subject
);
1216 if (auth_contains_cacert(auth
, current
))
1218 trustchain
->add_item(trustchain
, AUTHZ_CA_CERT
, current
);
1219 current
->destroy(current
);
1222 if (subject
== current
)
1224 trustchain
->add_item(trustchain
, AUTHZ_SUBJECT_CERT
, current
);
1228 trustchain
->add_item(trustchain
, AUTHZ_IM_CERT
, current
);
1230 issuer
= get_issuer_cert(this, current
, FALSE
);
1231 if (!issuer
|| issuer
->equals(issuer
, current
) || level
> MAX_CA_LEVELS
)
1234 current
->destroy(current
);
1237 current
->destroy(current
);
1241 trustchain
->destroy(trustchain
);
1246 * find a private key of a give certificate
1248 static private_key_t
*get_private_by_cert(private_credential_manager_t
*this,
1249 certificate_t
*cert
, key_type_t type
)
1251 private_key_t
*private = NULL
;
1252 identification_t
* keyid
;
1253 public_key_t
*public;
1255 public = cert
->get_public_key(cert
);
1258 keyid
= public->get_id(public, ID_PUBKEY_INFO_SHA1
);
1261 private = get_private_by_keyid(this, type
, keyid
);
1263 public->destroy(public);
1269 * Implementation of credential_manager_t.get_private.
1271 static private_key_t
*get_private(private_credential_manager_t
*this,
1272 key_type_t type
, identification_t
*id
,
1275 enumerator_t
*enumerator
;
1276 certificate_t
*cert
;
1277 private_key_t
*private = NULL
;
1278 auth_info_t
*trustchain
;
1280 /* check if this is a lookup by key ID, and do it if so */
1283 switch (id
->get_type(id
))
1285 case ID_PUBKEY_SHA1
:
1286 case ID_PUBKEY_INFO_SHA1
:
1287 return get_private_by_keyid(this, type
, id
);
1293 this->mutex
->lock(this->mutex
);
1294 /* try to build a trustchain for each certificate found */
1295 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1296 while (enumerator
->enumerate(enumerator
, &cert
))
1298 private = get_private_by_cert(this, cert
, type
);
1301 trustchain
= build_trustchain(this, cert
, auth
);
1304 auth
->merge(auth
, trustchain
);
1305 trustchain
->destroy(trustchain
);
1308 private->destroy(private);
1312 enumerator
->destroy(enumerator
);
1313 /* if no valid trustchain was found, fall back to the first usable cert */
1316 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1317 while (enumerator
->enumerate(enumerator
, &cert
))
1319 private = get_private_by_cert(this, cert
, type
);
1322 auth
->add_item(auth
, AUTHZ_SUBJECT_CERT
, cert
);
1326 enumerator
->destroy(enumerator
);
1328 this->mutex
->unlock(this->mutex
);
1333 * Implementation of credential_manager_t.flush_cache.
1335 static void flush_cache(private_credential_manager_t
*this,
1336 certificate_type_t type
)
1338 this->mutex
->lock(this->mutex
);
1339 this->cache
->flush(this->cache
, type
);
1340 this->mutex
->unlock(this->mutex
);
1344 * Implementation of credential_manager_t.add_set.
1346 static void add_set(private_credential_manager_t
*this,
1347 credential_set_t
*set
)
1349 this->mutex
->lock(this->mutex
);
1350 this->sets
->insert_last(this->sets
, set
);
1351 this->mutex
->unlock(this->mutex
);
1354 * Implementation of credential_manager_t.remove_set.
1356 static void remove_set(private_credential_manager_t
*this, credential_set_t
*set
)
1358 this->mutex
->lock(this->mutex
);
1359 this->sets
->remove(this->sets
, set
, NULL
);
1360 this->mutex
->unlock(this->mutex
);
1364 * Implementation of credential_manager_t.destroy
1366 static void destroy(private_credential_manager_t
*this)
1368 this->sets
->remove(this->sets
, this->cache
, NULL
);
1369 this->sets
->destroy(this->sets
);
1370 this->cache
->destroy(this->cache
);
1371 this->mutex
->destroy(this->mutex
);
1378 credential_manager_t
*credential_manager_create()
1380 private_credential_manager_t
*this = malloc_thing(private_credential_manager_t
);
1382 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
;
1383 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
;
1384 this->public.create_cdp_enumerator
= (enumerator_t
*(*)(credential_manager_t
*, credential_type_t type
, identification_t
*id
))create_cdp_enumerator
;
1385 this->public.get_cert
= (certificate_t
*(*)(credential_manager_t
*this,certificate_type_t cert
, key_type_t key
,identification_t
*, bool))get_cert
;
1386 this->public.get_shared
= (shared_key_t
*(*)(credential_manager_t
*this,shared_key_type_t type
,identification_t
*me
, identification_t
*other
))get_shared
;
1387 this->public.get_private
= (private_key_t
*(*)(credential_manager_t
*, key_type_t type
, identification_t
*, auth_info_t
*))get_private
;
1388 this->public.create_public_enumerator
= (enumerator_t
*(*)(credential_manager_t
*, key_type_t type
, identification_t
*id
, auth_info_t
*aut
))create_public_enumerator
;
1389 this->public.flush_cache
= (void(*)(credential_manager_t
*, certificate_type_t type
))flush_cache
;
1390 this->public.add_set
= (void(*)(credential_manager_t
*, credential_set_t
*set
))add_set
;
1391 this->public.remove_set
= (void(*)(credential_manager_t
*, credential_set_t
*set
))remove_set
;
1392 this->public.destroy
= (void(*)(credential_manager_t
*))destroy
;
1394 this->sets
= linked_list_create();
1395 this->cache
= cert_cache_create();
1396 this->sets
->insert_first(this->sets
, this->cache
);
1397 this->mutex
= mutex_create(MUTEX_RECURSIVE
);
1399 return &this->public;