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 */
429 DBG1(DBG_CFG
, " ocsp response contains no status on our certificate");
434 /* select the better of the two responses */
435 if (best
== NULL
|| cand
->is_newer(cand
, best
))
439 if (best
->get_validity(best
, NULL
, NULL
, &valid_until
))
441 DBG1(DBG_CFG
, " ocsp response is valid: until %#T",
442 &valid_until
, FALSE
);
443 *valid
= VALIDATION_GOOD
;
447 DBG1(DBG_CFG
, " ocsp response is stale: since %#T",
448 &valid_until
, FALSE
);
449 *valid
= VALIDATION_STALE
;
454 *valid
= VALIDATION_STALE
;
461 * validate a x509 certificate using OCSP
463 static cert_validation_t
check_ocsp(private_credential_manager_t
*this,
464 x509_t
*subject
, x509_t
*issuer
,
467 enumerator_t
*enumerator
;
468 cert_validation_t valid
= VALIDATION_SKIPPED
;
469 certificate_t
*best
= NULL
, *current
;
470 identification_t
*keyid
= NULL
;
471 public_key_t
*public;
474 /** lookup cache for valid OCSP responses */
475 enumerator
= create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE
,
476 KEY_ANY
, NULL
, FALSE
);
477 while (enumerator
->enumerate(enumerator
, ¤t
))
479 current
->get_ref(current
);
480 best
= get_better_ocsp(this, current
, best
, subject
, issuer
, &valid
);
481 if (best
&& valid
!= VALIDATION_STALE
)
483 DBG1(DBG_CFG
, " using cached ocsp response");
487 enumerator
->destroy(enumerator
);
489 /* derive the authorityKeyIdentifier from the issuer's public key */
490 current
= &issuer
->interface
;
491 public = current
->get_public_key(current
);
494 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
496 /** fetch from configured OCSP responder URLs */
497 if (keyid
&& valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
499 enumerator
= create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE
, keyid
);
500 while (enumerator
->enumerate(enumerator
, &uri
))
502 current
= fetch_ocsp(this, uri
, &subject
->interface
,
506 best
= get_better_ocsp(this, current
, best
, subject
, issuer
, &valid
);
507 if (best
&& valid
!= VALIDATION_STALE
)
513 enumerator
->destroy(enumerator
);
517 /* fallback to URL fetching from subject certificate's URIs */
518 if (valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
520 enumerator
= subject
->create_ocsp_uri_enumerator(subject
);
521 while (enumerator
->enumerate(enumerator
, &uri
))
523 current
= fetch_ocsp(this, uri
, &subject
->interface
,
527 best
= get_better_ocsp(this, current
, best
, subject
, issuer
, &valid
);
528 if (best
&& valid
!= VALIDATION_STALE
)
534 enumerator
->destroy(enumerator
);
536 /* an uri was found, but no result. switch validation state to failed */
537 if (valid
== VALIDATION_SKIPPED
&& uri
)
539 valid
= VALIDATION_FAILED
;
543 auth
->add_item(auth
, AUTHZ_OCSP_VALIDATION
, &valid
);
550 * fetch a CRL from an URL
552 static certificate_t
* fetch_crl(private_credential_manager_t
*this, char *url
)
557 /* TODO: unlock the manager while fetching? */
558 DBG1(DBG_CFG
, " fetching crl from '%s' ...", url
);
559 if (lib
->fetcher
->fetch(lib
->fetcher
, url
, &chunk
, FETCH_END
) != SUCCESS
)
561 DBG1(DBG_CFG
, "crl fetching failed");
564 crl
= lib
->creds
->create(lib
->creds
, CRED_CERTIFICATE
, CERT_X509_CRL
,
565 BUILD_BLOB_ASN1_DER
, chunk
, BUILD_END
);
568 DBG1(DBG_CFG
, "crl fetched successfully but parsing failed");
575 * check the signature of an CRL
577 static bool verify_crl(private_credential_manager_t
*this, certificate_t
*crl
)
579 certificate_t
*issuer
;
580 enumerator_t
*enumerator
;
581 bool verified
= FALSE
;
583 enumerator
= create_trusted_enumerator(this, KEY_ANY
, crl
->get_issuer(crl
),
585 while (enumerator
->enumerate(enumerator
, &issuer
, NULL
))
587 if (this->cache
->issued_by(this->cache
, crl
, issuer
))
589 DBG1(DBG_CFG
, " crl correctly signed by \"%D\"",
590 issuer
->get_subject(issuer
));
595 enumerator
->destroy(enumerator
);
601 * Get the better of two CRLs, and check for usable CRL info
603 static certificate_t
*get_better_crl(private_credential_manager_t
*this,
604 certificate_t
*cand
, certificate_t
*best
,
605 x509_t
*subject
, x509_t
*issuer
,
606 cert_validation_t
*valid
)
608 enumerator_t
*enumerator
;
609 time_t revocation
, valid_until
;
614 /* check CRL signature */
615 if (!verify_crl(this, cand
))
617 DBG1(DBG_CFG
, "crl response verification failed");
623 enumerator
= crl
->create_enumerator(crl
);
624 while (enumerator
->enumerate(enumerator
, &serial
, &revocation
, &reason
))
626 if (chunk_equals(serial
, subject
->get_serial(subject
)))
628 DBG1(DBG_CFG
, "certificate was revoked on %T, reason: %N",
629 &revocation
, crl_reason_names
, reason
);
630 *valid
= VALIDATION_REVOKED
;
631 enumerator
->destroy(enumerator
);
636 enumerator
->destroy(enumerator
);
638 /* select the better of the two CRLs */
639 if (best
== NULL
|| cand
->is_newer(cand
, best
))
643 if (best
->get_validity(best
, NULL
, NULL
, &valid_until
))
645 DBG1(DBG_CFG
, " crl is valid: until %#T", &valid_until
, FALSE
);
646 *valid
= VALIDATION_GOOD
;
650 DBG1(DBG_CFG
, " crl is stale: since %#T", &valid_until
, FALSE
);
651 *valid
= VALIDATION_STALE
;
656 *valid
= VALIDATION_STALE
;
663 * validate a x509 certificate using CRL
665 static cert_validation_t
check_crl(private_credential_manager_t
*this,
666 x509_t
*subject
, x509_t
*issuer
,
669 cert_validation_t valid
= VALIDATION_SKIPPED
;
670 identification_t
*keyid
= NULL
;
671 certificate_t
*best
= NULL
;
672 certificate_t
*current
;
673 public_key_t
*public;
674 enumerator_t
*enumerator
;
677 /* derive the authorityKeyIdentifier from the issuer's public key */
678 current
= &issuer
->interface
;
679 public = current
->get_public_key(current
);
682 keyid
= public->get_id(public, ID_PUBKEY_SHA1
);
685 /* find a cached crl by authorityKeyIdentifier */
688 enumerator
= create_cert_enumerator(this, CERT_X509_CRL
, KEY_ANY
,
690 while (enumerator
->enumerate(enumerator
, ¤t
))
692 current
->get_ref(current
);
693 best
= get_better_crl(this, current
, best
, subject
, issuer
, &valid
);
694 if (best
&& valid
!= VALIDATION_STALE
)
696 DBG1(DBG_CFG
, " using cached crl");
700 enumerator
->destroy(enumerator
);
703 /* fallback to fetching crls from credential sets cdps */
704 if (keyid
&& valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
706 enumerator
= create_cdp_enumerator(this, CERT_X509_CRL
, keyid
);
708 while (enumerator
->enumerate(enumerator
, &uri
))
710 current
= fetch_crl(this, uri
);
713 best
= get_better_crl(this, current
, best
, subject
, issuer
, &valid
);
714 if (best
&& valid
!= VALIDATION_STALE
)
720 enumerator
->destroy(enumerator
);
724 /* fallback to fetching crls from cdps from subject's certificate */
725 if (valid
!= VALIDATION_GOOD
&& valid
!= VALIDATION_REVOKED
)
727 enumerator
= subject
->create_crl_uri_enumerator(subject
);
729 while (enumerator
->enumerate(enumerator
, &uri
))
731 current
= fetch_crl(this, uri
);
734 best
= get_better_crl(this, current
, best
, subject
, issuer
, &valid
);
735 if (best
&& valid
!= VALIDATION_STALE
)
741 enumerator
->destroy(enumerator
);
744 /* an uri was found, but no result. switch validation state to failed */
745 if (valid
== VALIDATION_SKIPPED
&& uri
)
747 valid
= VALIDATION_FAILED
;
751 auth
->add_item(auth
, AUTHZ_CRL_VALIDATION
, &valid
);
758 * check a certificate for its lifetime
760 static bool check_certificate(private_credential_manager_t
*this,
761 certificate_t
*subject
, certificate_t
*issuer
,
762 bool crl
, bool ocsp
, auth_info_t
*auth
)
764 time_t not_before
, not_after
;
766 if (!subject
->get_validity(subject
, NULL
, ¬_before
, ¬_after
))
768 DBG1(DBG_CFG
, "subject certificate invalid (valid from %T to %T)",
769 ¬_before
, ¬_after
);
772 if (!issuer
->get_validity(issuer
, NULL
, ¬_before
, ¬_after
))
774 DBG1(DBG_CFG
, "issuer certificate invalid (valid from %T to %T)",
775 ¬_before
, ¬_after
);
778 if (issuer
->get_type(issuer
) == CERT_X509
&&
779 subject
->get_type(subject
) == CERT_X509
)
783 DBG1(DBG_CFG
, "checking certificate status of \"%D\"",
784 subject
->get_subject(subject
));
788 switch (check_ocsp(this, (x509_t
*)subject
, (x509_t
*)issuer
, auth
))
790 case VALIDATION_GOOD
:
791 DBG1(DBG_CFG
, "certificate status is good");
793 case VALIDATION_REVOKED
:
794 /* has already been logged */
796 case VALIDATION_SKIPPED
:
797 DBG2(DBG_CFG
, "ocsp check skipped, no ocsp found");
799 case VALIDATION_STALE
:
800 DBG1(DBG_CFG
, "ocsp information stale, fallback to crl");
802 case VALIDATION_FAILED
:
803 DBG1(DBG_CFG
, "ocsp check failed, fallback to crl");
809 switch (check_crl(this, (x509_t
*)subject
, (x509_t
*)issuer
, auth
))
811 case VALIDATION_GOOD
:
812 DBG1(DBG_CFG
, "certificate status is good");
814 case VALIDATION_REVOKED
:
815 /* has already been logged */
817 case VALIDATION_FAILED
:
818 case VALIDATION_SKIPPED
:
819 DBG1(DBG_CFG
, "certificate status is not available");
821 case VALIDATION_STALE
:
822 DBG1(DBG_CFG
, "certificate status is unknown, crl is stale");
831 * Get a trusted certificate from a credential set
833 static certificate_t
*get_pretrusted_cert(private_credential_manager_t
*this,
834 key_type_t type
, identification_t
*id
)
836 certificate_t
*subject
;
837 public_key_t
*public;
839 subject
= get_cert(this, CERT_ANY
, type
, id
, TRUE
);
844 public = subject
->get_public_key(subject
);
847 subject
->destroy(subject
);
850 public->destroy(public);
855 * Get the issuing certificate of a subject certificate
857 static certificate_t
*get_issuer_cert(private_credential_manager_t
*this,
858 certificate_t
*subject
, bool trusted
)
860 enumerator_t
*enumerator
;
861 certificate_t
*issuer
= NULL
, *candidate
;
863 enumerator
= create_cert_enumerator(this, subject
->get_type(subject
), KEY_ANY
,
864 subject
->get_issuer(subject
), trusted
);
865 while (enumerator
->enumerate(enumerator
, &candidate
))
867 if (this->cache
->issued_by(this->cache
, subject
, candidate
))
869 issuer
= candidate
->get_ref(candidate
);
873 enumerator
->destroy(enumerator
);
878 * try to verify the trust chain of subject, return TRUE if trusted
880 static bool verify_trust_chain(private_credential_manager_t
*this,
881 certificate_t
*subject
, auth_info_t
*result
,
882 bool trusted
, bool crl
, bool ocsp
)
884 certificate_t
*current
, *issuer
;
888 auth
= auth_info_create();
889 current
= subject
->get_ref(subject
);
890 while (level
++ < MAX_CA_LEVELS
)
892 issuer
= get_issuer_cert(this, current
, TRUE
);
895 /* accept only self-signed CAs as trust anchor */
896 if (this->cache
->issued_by(this->cache
, issuer
, issuer
))
898 auth
->add_item(auth
, AUTHZ_CA_CERT
, issuer
);
899 DBG1(DBG_CFG
, " using trusted ca certificate \"%D\"",
900 issuer
->get_subject(issuer
));
905 auth
->add_item(auth
, AUTHZ_IM_CERT
, issuer
);
906 DBG1(DBG_CFG
, " using trusted intermediate ca certificate "
907 "\"%D\"", issuer
->get_subject(issuer
));
912 issuer
= get_issuer_cert(this, current
, FALSE
);
915 if (current
->equals(current
, issuer
))
917 DBG1(DBG_CFG
, " self-signed certificate \"%D\" is not trusted",
918 current
->get_subject(current
));
919 issuer
->destroy(issuer
);
922 auth
->add_item(auth
, AUTHZ_IM_CERT
, issuer
);
923 DBG1(DBG_CFG
, " using untrusted intermediate certificate "
924 "\"%D\"", issuer
->get_subject(issuer
));
928 DBG1(DBG_CFG
, "no issuer certificate found for \"%D\"",
929 current
->get_subject(current
));
930 issuer
->destroy(issuer
);
934 if (!check_certificate(this, current
, issuer
, crl
, ocsp
,
935 current
== subject ? auth
: NULL
))
938 issuer
->destroy(issuer
);
941 current
->destroy(current
);
948 current
->destroy(current
);
949 if (level
> MAX_CA_LEVELS
)
951 DBG1(DBG_CFG
, "maximum ca path length of %d levels reached", level
);
955 result
->merge(result
, auth
);
962 * enumerator for trusted certificates
965 /** implements enumerator_t interface */
967 /** enumerator over candidate peer certificates */
968 enumerator_t
*candidates
;
969 /** reference to the credential_manager */
970 private_credential_manager_t
*this;
971 /** type of the requested key */
973 /** identity the requested key belongs to */
974 identification_t
*id
;
975 /** TRUE to do CRL checking */
977 /** TRUE to do OCSP checking */
979 /** pretrusted certificate we have served at first invocation */
980 certificate_t
*pretrusted
;
981 /** currently enumerating auth info */
983 } trusted_enumerator_t
;
986 * Implements trusted_enumerator_t.enumerate
988 static bool trusted_enumerate(trusted_enumerator_t
*this,
989 certificate_t
**cert
, auth_info_t
**auth
)
991 certificate_t
*current
;
993 DESTROY_IF(this->auth
);
994 this->auth
= auth_info_create();
996 if (!this->candidates
)
998 /* first invocation, build enumerator for next one */
999 this->candidates
= create_cert_enumerator(this->this, CERT_ANY
,
1000 this->type
, this->id
, FALSE
);
1001 /* check if we have a trusted certificate for that peer */
1002 this->pretrusted
= get_pretrusted_cert(this->this, this->type
, this->id
);
1003 if (this->pretrusted
)
1005 /* if we find a trusted self signed certificate, we just accept it.
1006 * However, in order to fulfill authorization rules, we try to build
1007 * the trust chain if it is not self signed */
1008 if (this->this->cache
->issued_by(this->this->cache
,
1009 this->pretrusted
, this->pretrusted
) ||
1010 verify_trust_chain(this->this, this->pretrusted
, this->auth
,
1011 TRUE
, this->crl
, this->ocsp
))
1013 DBG1(DBG_CFG
, " using trusted certificate \"%D\"",
1014 this->pretrusted
->get_subject(this->pretrusted
));
1015 *cert
= this->pretrusted
;
1024 /* try to verify the trust chain for each certificate found */
1025 while (this->candidates
->enumerate(this->candidates
, ¤t
))
1027 if (this->pretrusted
&&
1028 this->pretrusted
->equals(this->pretrusted
, current
))
1029 { /* skip pretrusted certificate we already served */
1033 DBG1(DBG_CFG
, " using certificate \"%D\"",
1034 current
->get_subject(current
));
1035 if (verify_trust_chain(this->this, current
, this->auth
, FALSE
,
1036 this->crl
, this->ocsp
))
1050 * Implements trusted_enumerator_t.destroy
1052 static void trusted_destroy(trusted_enumerator_t
*this)
1054 DESTROY_IF(this->pretrusted
);
1055 DESTROY_IF(this->auth
);
1056 DESTROY_IF(this->candidates
);
1061 * create an enumerator over trusted certificates and their trustchain
1063 static enumerator_t
*create_trusted_enumerator(private_credential_manager_t
*this,
1064 key_type_t type
, identification_t
*id
, bool crl
, bool ocsp
)
1066 trusted_enumerator_t
*enumerator
= malloc_thing(trusted_enumerator_t
);
1068 enumerator
->public.enumerate
= (void*)trusted_enumerate
;
1069 enumerator
->public.destroy
= (void*)trusted_destroy
;
1071 enumerator
->candidates
= NULL
;
1072 enumerator
->this = this;
1073 enumerator
->type
= type
;
1074 enumerator
->id
= id
;
1075 enumerator
->crl
= crl
;
1076 enumerator
->ocsp
= ocsp
;
1077 enumerator
->pretrusted
= NULL
;
1078 enumerator
->auth
= NULL
;
1080 return &enumerator
->public;
1084 * enumerator for public keys
1087 /** implements enumerator_t interface */
1088 enumerator_t
public;
1089 /** enumerator over candidate peer certificates */
1090 enumerator_t
*inner
;
1091 /** reference to the credential_manager */
1092 private_credential_manager_t
*this;
1093 /** currently enumerating key */
1094 public_key_t
*current
;
1095 /** credset wrapper around auth */
1096 auth_info_wrapper_t
*wrapper
;
1097 } public_enumerator_t
;
1100 * Implements public_enumerator_t.enumerate
1102 static bool public_enumerate(public_enumerator_t
*this,
1103 public_key_t
**key
, auth_info_t
**auth
)
1105 certificate_t
*cert
;
1107 while (this->inner
->enumerate(this->inner
, &cert
, auth
))
1109 DESTROY_IF(this->current
);
1110 this->current
= cert
->get_public_key(cert
);
1113 *key
= this->current
;
1121 * Implements public_enumerator_t.destroy
1123 static void public_destroy(public_enumerator_t
*this)
1125 DESTROY_IF(this->current
);
1126 this->inner
->destroy(this->inner
);
1129 this->this->sets
->remove(this->this->sets
, this->wrapper
, NULL
);
1130 this->wrapper
->destroy(this->wrapper
);
1132 this->this->mutex
->unlock(this->this->mutex
);
1137 * Implementation of credential_manager_t.create_public_enumerator.
1139 static enumerator_t
* create_public_enumerator(private_credential_manager_t
*this,
1140 key_type_t type
, identification_t
*id
, auth_info_t
*auth
)
1142 public_enumerator_t
*enumerator
= malloc_thing(public_enumerator_t
);
1144 enumerator
->public.enumerate
= (void*)public_enumerate
;
1145 enumerator
->public.destroy
= (void*)public_destroy
;
1146 enumerator
->inner
= create_trusted_enumerator(this, type
, id
, TRUE
, TRUE
);
1147 enumerator
->this = this;
1148 enumerator
->current
= NULL
;
1149 enumerator
->wrapper
= NULL
;
1150 this->mutex
->lock(this->mutex
);
1153 enumerator
->wrapper
= auth_info_wrapper_create(auth
);
1154 this->sets
->insert_last(this->sets
, enumerator
->wrapper
);
1156 return &enumerator
->public;
1160 * Check if a certificate's keyid is contained in the auth helper
1162 static bool auth_contains_cacert(auth_info_t
*auth
, certificate_t
*cert
)
1164 enumerator_t
*enumerator
;
1165 identification_t
*value
;
1169 enumerator
= auth
->create_item_enumerator(auth
);
1170 while (enumerator
->enumerate(enumerator
, &type
, &value
))
1172 if (type
== AUTHN_CA_CERT
&& cert
->equals(cert
, (certificate_t
*)value
))
1177 if (type
== AUTHN_CA_CERT_KEYID
)
1179 public_key_t
*public;
1180 identification_t
*certid
, *keyid
;
1182 public = cert
->get_public_key(cert
);
1185 keyid
= (identification_t
*)value
;
1186 certid
= public->get_id(public, keyid
->get_type(keyid
));
1187 if (certid
&& certid
->equals(certid
, keyid
))
1189 public->destroy(public);
1193 public->destroy(public);
1197 enumerator
->destroy(enumerator
);
1202 * build a trustchain from subject up to a trust anchor in trusted
1204 static auth_info_t
*build_trustchain(private_credential_manager_t
*this,
1205 certificate_t
*subject
, auth_info_t
*auth
)
1207 certificate_t
*issuer
, *current
;
1208 auth_info_t
*trustchain
;
1211 trustchain
= auth_info_create();
1213 if (!auth
->get_item(auth
, AUTHN_CA_CERT
, (void**)¤t
))
1215 /* no trust anchor specified, return this cert only */
1216 trustchain
->add_item(trustchain
, AUTHZ_SUBJECT_CERT
, subject
);
1219 current
= subject
->get_ref(subject
);
1222 if (auth_contains_cacert(auth
, current
))
1224 trustchain
->add_item(trustchain
, AUTHZ_CA_CERT
, current
);
1225 current
->destroy(current
);
1228 if (subject
== current
)
1230 trustchain
->add_item(trustchain
, AUTHZ_SUBJECT_CERT
, current
);
1234 trustchain
->add_item(trustchain
, AUTHZ_IM_CERT
, current
);
1236 issuer
= get_issuer_cert(this, current
, FALSE
);
1237 if (!issuer
|| issuer
->equals(issuer
, current
) || level
> MAX_CA_LEVELS
)
1240 current
->destroy(current
);
1243 current
->destroy(current
);
1247 trustchain
->destroy(trustchain
);
1252 * find a private key of a give certificate
1254 static private_key_t
*get_private_by_cert(private_credential_manager_t
*this,
1255 certificate_t
*cert
, key_type_t type
)
1257 private_key_t
*private = NULL
;
1258 identification_t
* keyid
;
1259 public_key_t
*public;
1261 public = cert
->get_public_key(cert
);
1264 keyid
= public->get_id(public, ID_PUBKEY_INFO_SHA1
);
1267 private = get_private_by_keyid(this, type
, keyid
);
1269 public->destroy(public);
1275 * Implementation of credential_manager_t.get_private.
1277 static private_key_t
*get_private(private_credential_manager_t
*this,
1278 key_type_t type
, identification_t
*id
,
1281 enumerator_t
*enumerator
;
1282 certificate_t
*cert
;
1283 private_key_t
*private = NULL
;
1284 auth_info_t
*trustchain
;
1286 /* check if this is a lookup by key ID, and do it if so */
1289 switch (id
->get_type(id
))
1291 case ID_PUBKEY_SHA1
:
1292 case ID_PUBKEY_INFO_SHA1
:
1293 return get_private_by_keyid(this, type
, id
);
1299 this->mutex
->lock(this->mutex
);
1300 /* try to build a trustchain for each certificate found */
1301 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1302 while (enumerator
->enumerate(enumerator
, &cert
))
1304 private = get_private_by_cert(this, cert
, type
);
1307 trustchain
= build_trustchain(this, cert
, auth
);
1310 auth
->merge(auth
, trustchain
);
1311 trustchain
->destroy(trustchain
);
1314 private->destroy(private);
1318 enumerator
->destroy(enumerator
);
1319 /* if no valid trustchain was found, fall back to the first usable cert */
1322 enumerator
= create_cert_enumerator(this, CERT_ANY
, type
, id
, FALSE
);
1323 while (enumerator
->enumerate(enumerator
, &cert
))
1325 private = get_private_by_cert(this, cert
, type
);
1328 auth
->add_item(auth
, AUTHZ_SUBJECT_CERT
, cert
);
1332 enumerator
->destroy(enumerator
);
1334 this->mutex
->unlock(this->mutex
);
1339 * Implementation of credential_manager_t.flush_cache.
1341 static void flush_cache(private_credential_manager_t
*this,
1342 certificate_type_t type
)
1344 this->mutex
->lock(this->mutex
);
1345 this->cache
->flush(this->cache
, type
);
1346 this->mutex
->unlock(this->mutex
);
1350 * Implementation of credential_manager_t.add_set.
1352 static void add_set(private_credential_manager_t
*this,
1353 credential_set_t
*set
)
1355 this->mutex
->lock(this->mutex
);
1356 this->sets
->insert_last(this->sets
, set
);
1357 this->mutex
->unlock(this->mutex
);
1360 * Implementation of credential_manager_t.remove_set.
1362 static void remove_set(private_credential_manager_t
*this, credential_set_t
*set
)
1364 this->mutex
->lock(this->mutex
);
1365 this->sets
->remove(this->sets
, set
, NULL
);
1366 this->mutex
->unlock(this->mutex
);
1370 * Implementation of credential_manager_t.destroy
1372 static void destroy(private_credential_manager_t
*this)
1374 this->sets
->remove(this->sets
, this->cache
, NULL
);
1375 this->sets
->destroy(this->sets
);
1376 this->cache
->destroy(this->cache
);
1377 this->mutex
->destroy(this->mutex
);
1384 credential_manager_t
*credential_manager_create()
1386 private_credential_manager_t
*this = malloc_thing(private_credential_manager_t
);
1388 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
;
1389 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
;
1390 this->public.create_cdp_enumerator
= (enumerator_t
*(*)(credential_manager_t
*, credential_type_t type
, identification_t
*id
))create_cdp_enumerator
;
1391 this->public.get_cert
= (certificate_t
*(*)(credential_manager_t
*this,certificate_type_t cert
, key_type_t key
,identification_t
*, bool))get_cert
;
1392 this->public.get_shared
= (shared_key_t
*(*)(credential_manager_t
*this,shared_key_type_t type
,identification_t
*me
, identification_t
*other
))get_shared
;
1393 this->public.get_private
= (private_key_t
*(*)(credential_manager_t
*, key_type_t type
, identification_t
*, auth_info_t
*))get_private
;
1394 this->public.create_public_enumerator
= (enumerator_t
*(*)(credential_manager_t
*, key_type_t type
, identification_t
*id
, auth_info_t
*aut
))create_public_enumerator
;
1395 this->public.flush_cache
= (void(*)(credential_manager_t
*, certificate_type_t type
))flush_cache
;
1396 this->public.add_set
= (void(*)(credential_manager_t
*, credential_set_t
*set
))add_set
;
1397 this->public.remove_set
= (void(*)(credential_manager_t
*, credential_set_t
*set
))remove_set
;
1398 this->public.destroy
= (void(*)(credential_manager_t
*))destroy
;
1400 this->sets
= linked_list_create();
1401 this->cache
= cert_cache_create();
1402 this->sets
->insert_first(this->sets
, this->cache
);
1403 this->mutex
= mutex_create(MUTEX_RECURSIVE
);
1405 return &this->public;