2 * @file local_credential_store.c
4 * @brief Implementation of local_credential_store_t.
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30 #include <utils/lexparser.h>
31 #include <utils/linked_list.h>
32 #include <crypto/rsa/rsa_public_key.h>
33 #include <crypto/certinfo.h>
34 #include <crypto/x509.h>
35 #include <crypto/ca.h>
36 #include <crypto/ac.h>
37 #include <crypto/crl.h>
38 #include <asn1/ttodata.h>
40 #include "local_credential_store.h"
44 typedef struct shared_key_t shared_key_t
;
47 * Private date of a shared_key_t object
64 * Implementation of shared_key_t.destroy.
66 static void shared_key_destroy(shared_key_t
*this)
68 this->peers
->destroy_offset(this->peers
, offsetof(identification_t
, destroy
));
69 chunk_free(&this->secret
);
74 * @brief Creates a shared_key_t object.
76 * @param shared_key shared key value
77 * @return shared_key_t object
81 static shared_key_t
*shared_key_create(chunk_t secret
)
83 shared_key_t
*this = malloc_thing(shared_key_t
);
86 this->secret
= chunk_clone(secret
);
87 this->peers
= linked_list_create();
92 /* ------------------------------------------------------------------------ *
93 * the ca_info_t object as a central control element
95 +--------------------------------------------------------+
96 | local_credential_store_t |
97 +--------------------------------------------------------+
99 +---------------------------+ +-------------------------+
100 | linked_list_t *auth_certs | | linked_list_t *ca_infos |
101 +---------------------------+ +-------------------------+
103 | +------------------------- +
105 | +--------------------------+
106 +---------------+ | char *name |
107 | x509_t |<--| x509_t *cacert |
108 +---------------+ | linked_list_t *attrcerts | +----------------------+
109 | chunk_t keyid | | linked_list_t *certinfos |-->| certinfo_t |
110 +---------------+ | linked_list_t *ocspuris | +----------------------+
111 | | crl_t *crl | | chunk_t serialNumber |
112 | | linked_list_t *crluris | | cert_status_t status |
113 +---------------+ | pthread_mutex_t mutex | | time_t thisUpdate |
114 | x509_t | +--------------------------+ | time_t nextUpdate |
115 +---------------+ | | bool once |
116 | chunk_t keyid | | +----------------------+
117 +---------------+ +------------------------- + |
118 | | ca_info_t | +----------------------+
119 | +--------------------------+ | certinfo_t |
120 +---------------+ | char *name | +----------------------+
121 | x509_t |<--| x509_t *cacert | | chunk_t serialNumber |
122 +---------------+ | linked_list_t *attrcerts | | cert_status_t status |
123 | chunk_t keyid | | linked_list_t *certinfos | | time_t thisUpdate |
124 +---------------+ | linked_list_t *ocspuris | | time_t nextUpdate |
125 | | crl_t *crl | | bool once |
126 | | linked_list_t *crluris | +----------------------+
127 | | pthread_mutex_t mutex; | |
128 | +--------------------------+
131 * ------------------------------------------------------------------------ */
133 typedef struct private_local_credential_store_t private_local_credential_store_t
;
136 * Private data of an local_credential_store_t object
138 struct private_local_credential_store_t
{
143 local_credential_store_t
public;
146 * list of shared keys
148 linked_list_t
*shared_keys
;
153 linked_list_t
*eap_keys
;
156 * list of key_entry_t's with private keys
158 linked_list_t
*private_keys
;
161 * list of X.509 certificates with public keys
163 linked_list_t
*certs
;
166 * list of X.509 authority certificates with public keys
168 linked_list_t
*auth_certs
;
171 * list of X.509 CA information records
173 linked_list_t
*ca_infos
;
178 * Get a key from a list with shared_key_t's
180 static status_t
get_key(linked_list_t
*keys
,
181 identification_t
*my_id
,
182 identification_t
*other_id
, chunk_t
*secret
)
185 PRIO_UNDEFINED
= 0x00,
186 PRIO_ANY_MATCH
= 0x01,
188 PRIO_OTHER_MATCH
= 0x04,
191 prio_t best_prio
= PRIO_UNDEFINED
;
192 chunk_t found
= chunk_empty
;
193 shared_key_t
*shared_key
;
195 iterator_t
*iterator
= keys
->create_iterator(keys
, TRUE
);
197 while (iterator
->iterate(iterator
, (void**)&shared_key
))
199 iterator_t
*peer_iterator
;
200 identification_t
*peer_id
;
201 prio_t prio
= PRIO_UNDEFINED
;
203 peer_iterator
= shared_key
->peers
->create_iterator(shared_key
->peers
, TRUE
);
205 if (peer_iterator
->get_count(peer_iterator
) == 0)
207 /* this is a wildcard shared key */
208 prio
= PRIO_ANY_MATCH
;
212 while (peer_iterator
->iterate(peer_iterator
, (void**)&peer_id
))
214 if (my_id
->equals(my_id
, peer_id
))
216 prio
|= PRIO_MY_MATCH
;
218 if (other_id
->equals(other_id
, peer_id
))
220 prio
|= PRIO_OTHER_MATCH
;
224 peer_iterator
->destroy(peer_iterator
);
226 if (prio
> best_prio
)
229 found
= shared_key
->secret
;
232 iterator
->destroy(iterator
);
234 if (best_prio
== PRIO_UNDEFINED
)
240 *secret
= chunk_clone(found
);
247 * Implementation of local_credential_store_t.get_shared_key.
249 static status_t
get_shared_key(private_local_credential_store_t
*this,
250 identification_t
*my_id
,
251 identification_t
*other_id
, chunk_t
*secret
)
253 return get_key(this->shared_keys
, my_id
, other_id
, secret
);
257 * Implementation of local_credential_store_t.get_eap_key.
259 static status_t
get_eap_key(private_local_credential_store_t
*this,
260 identification_t
*my_id
,
261 identification_t
*other_id
, chunk_t
*secret
)
263 return get_key(this->eap_keys
, my_id
, other_id
, secret
);
267 * Implementation of credential_store_t.get_certificate.
269 static x509_t
* get_certificate(private_local_credential_store_t
*this,
270 identification_t
*id
)
272 x509_t
*found
= NULL
;
273 x509_t
*current_cert
;
275 iterator_t
*iterator
= this->certs
->create_iterator(this->certs
, TRUE
);
277 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
279 if (id
->equals(id
, current_cert
->get_subject(current_cert
)) ||
280 current_cert
->equals_subjectAltName(current_cert
, id
))
282 found
= current_cert
;
286 iterator
->destroy(iterator
);
291 * Implementation of local_credential_store_t.get_rsa_public_key.
293 static rsa_public_key_t
*get_rsa_public_key(private_local_credential_store_t
*this,
294 identification_t
*id
)
296 x509_t
*cert
= get_certificate(this, id
);
298 return (cert
== NULL
)? NULL
:cert
->get_public_key(cert
);
302 * Implementation of credential_store_t.get_issuer.
304 static ca_info_t
* get_issuer(private_local_credential_store_t
*this, const x509_t
*cert
)
306 ca_info_t
*found
= cert
->get_ca_info(cert
);
310 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
313 while (iterator
->iterate(iterator
, (void**)&ca_info
))
315 if (ca_info
->is_cert_issuer(ca_info
, cert
))
318 cert
->set_ca_info(cert
, found
);
322 iterator
->destroy(iterator
);
328 * Implementation of local_credential_store_t.get_rsa_private_key.
330 static rsa_private_key_t
*get_rsa_private_key(private_local_credential_store_t
*this,
331 rsa_public_key_t
*pubkey
)
333 rsa_private_key_t
*found
= NULL
, *current
;
335 iterator_t
*iterator
= this->private_keys
->create_iterator(this->private_keys
, TRUE
);
337 while (iterator
->iterate(iterator
, (void**)¤t
))
339 if (current
->belongs_to(current
, pubkey
))
341 found
= current
->clone(current
);
345 iterator
->destroy(iterator
);
350 * Implementation of local_credential_store_t.has_rsa_private_key.
352 static bool has_rsa_private_key(private_local_credential_store_t
*this, rsa_public_key_t
*pubkey
)
355 rsa_private_key_t
*current
;
357 iterator_t
*iterator
= this->private_keys
->create_iterator(this->private_keys
, TRUE
);
359 while (iterator
->iterate(iterator
, (void**)¤t
))
361 if (current
->belongs_to(current
, pubkey
))
367 iterator
->destroy(iterator
);
372 * Implementation of credential_store_t.get_auth_certificate.
374 static x509_t
* get_auth_certificate(private_local_credential_store_t
*this,
376 identification_t
*id
)
378 x509_t
*found
= NULL
;
379 x509_t
*current_cert
;
381 iterator_t
*iterator
= this->auth_certs
->create_iterator(this->auth_certs
, TRUE
);
383 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
385 if (current_cert
->has_authority_flag(current_cert
, auth_flags
)
386 && id
->equals(id
, current_cert
->get_subject(current_cert
)))
388 found
= current_cert
;
392 iterator
->destroy(iterator
);
398 * Implementation of credential_store_t.get_ca_certificate_by_keyid.
400 static x509_t
* get_ca_certificate_by_keyid(private_local_credential_store_t
*this,
403 x509_t
*found
= NULL
;
404 x509_t
*current_cert
;
406 iterator_t
*iterator
= this->auth_certs
->create_iterator(this->auth_certs
, TRUE
);
408 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
410 rsa_public_key_t
*pubkey
= current_cert
->get_public_key(current_cert
);
412 if (current_cert
->has_authority_flag(current_cert
, AUTH_CA
)
413 && chunk_equals(keyid
, pubkey
->get_keyid(pubkey
)))
415 found
= current_cert
;
419 iterator
->destroy(iterator
);
425 * Find an exact copy of a certificate in a linked list
427 static x509_t
* find_certificate(linked_list_t
*certs
, x509_t
*cert
)
429 x509_t
*found_cert
= NULL
, *current_cert
;
431 iterator_t
*iterator
= certs
->create_iterator(certs
, TRUE
);
433 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
435 if (cert
->equals(cert
, current_cert
))
437 found_cert
= current_cert
;
441 iterator
->destroy(iterator
);
447 * Adds crl and ocsp uris to the corresponding issuer info record
449 static void add_uris(ca_info_t
*issuer
, x509_t
*cert
)
451 iterator_t
*iterator
;
452 identification_t
*uri
;
454 /* add any crl distribution points to the issuer ca info record */
455 iterator
= cert
->create_crluri_iterator(cert
);
457 while (iterator
->iterate(iterator
, (void**)&uri
))
459 issuer
->add_crluri(issuer
, uri
->get_encoding(uri
));
461 iterator
->destroy(iterator
);
463 /* add any ocsp access points to the issuer ca info record */
464 iterator
= cert
->create_ocspuri_iterator(cert
);
466 while (iterator
->iterate(iterator
, (void**)&uri
))
468 issuer
->add_ocspuri(issuer
, uri
->get_encoding(uri
));
470 iterator
->destroy(iterator
);
474 * Implementation of credential_store_t.is_trusted
476 static bool is_trusted(private_local_credential_store_t
*this, x509_t
*cert
)
479 time_t until
= UNDEFINED_TIME
;
480 x509_t
*cert_to_be_trusted
= cert
;
482 DBG2(DBG_CFG
, "establishing trust in certificate:");
484 for (pathlen
= 0; pathlen
< MAX_CA_PATH_LEN
; pathlen
++)
489 rsa_public_key_t
*issuer_public_key
;
490 bool valid_signature
;
492 DBG2(DBG_CFG
, "subject: '%D'", cert
->get_subject(cert
));
493 DBG2(DBG_CFG
, "issuer: '%D'", cert
->get_issuer(cert
));
495 ugh
= cert
->is_valid(cert
, &until
);
498 DBG1(DBG_CFG
, "certificate %s", ugh
);
501 DBG2(DBG_CFG
, "certificate is valid");
503 issuer
= get_issuer(this, cert
);
506 DBG1(DBG_CFG
, "issuer not found");
509 DBG2(DBG_CFG
, "issuer found");
511 issuer_cert
= issuer
->get_certificate(issuer
);
512 issuer_public_key
= issuer_cert
->get_public_key(issuer_cert
);
513 valid_signature
= cert
->verify(cert
, issuer_public_key
);
515 if (!valid_signature
)
517 DBG1(DBG_CFG
, "certificate signature is invalid");
520 DBG2(DBG_CFG
, "certificate signature is valid");
522 /* check if cert is a self-signed root ca */
523 if (pathlen
> 0 && cert
->is_self_signed(cert
))
525 DBG2(DBG_CFG
, "reached self-signed root ca");
526 cert_to_be_trusted
->set_until(cert_to_be_trusted
, until
);
527 cert_to_be_trusted
->set_status(cert_to_be_trusted
, CERT_GOOD
);
532 /* go up one step in the trust chain */
536 DBG1(DBG_CFG
, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN
);
541 * Implementation of credential_store_t.verify.
543 static bool verify(private_local_credential_store_t
*this, x509_t
*cert
, bool *found
)
546 time_t until
= UNDEFINED_TIME
;
548 x509_t
*end_cert
= cert
;
549 x509_t
*cert_copy
= find_certificate(this->certs
, end_cert
);
551 DBG2(DBG_CFG
, "verifying end entity certificate:");
553 *found
= (cert_copy
!= NULL
);
557 "end entitity certificate is already in credential store");
560 for (pathlen
= 0; pathlen
< MAX_CA_PATH_LEN
; pathlen
++)
562 bool valid_signature
;
566 rsa_public_key_t
*issuer_public_key
;
567 chunk_t keyid
= cert
->get_keyid(cert
);
569 DBG1(DBG_CFG
, "subject: '%D'", cert
->get_subject(cert
));
570 DBG1(DBG_CFG
, "issuer: '%D'", cert
->get_issuer(cert
));
571 DBG1(DBG_CFG
, "keyid: %#B", &keyid
);
573 ugh
= cert
->is_valid(cert
, &until
);
576 DBG1(DBG_CFG
, "certificate %s", ugh
);
579 DBG2(DBG_CFG
, "certificate is valid");
581 issuer
= get_issuer(this, cert
);
584 DBG1(DBG_CFG
, "issuer not found");
587 DBG2(DBG_CFG
, "issuer found");
589 issuer_cert
= issuer
->get_certificate(issuer
);
590 issuer_public_key
= issuer_cert
->get_public_key(issuer_cert
);
591 valid_signature
= cert
->verify(cert
, issuer_public_key
);
593 if (!valid_signature
)
595 DBG1(DBG_CFG
, "certificate signature is invalid");
598 DBG2(DBG_CFG
, "certificate signature is valid");
600 /* check if cert is a self-signed root ca */
601 if (pathlen
> 0 && cert
->is_self_signed(cert
))
603 DBG1(DBG_CFG
, "reached self-signed root ca");
605 /* set the definite status and trust interval of the end entity certificate */
606 end_cert
->set_until(end_cert
, until
);
609 cert_copy
->set_status(cert_copy
, end_cert
->get_status(end_cert
));
610 cert_copy
->set_until(cert_copy
, until
);
618 cert_status_t status
;
619 certinfo_t
*certinfo
= certinfo_create(cert
->get_serialNumber(cert
));
623 /* add any crl and ocsp uris contained in the certificate under test */
624 add_uris(issuer
, cert
);
627 strict
= issuer
->is_strict(issuer
);
628 DBG1(DBG_CFG
, "issuer %s a strict crl policy",
629 strict ?
"enforces":"does not enforce");
631 /* first check certificate revocation using ocsp */
632 status
= issuer
->verify_by_ocsp(issuer
, certinfo
, &this->public.credential_store
);
634 /* if ocsp service is not available then fall back to crl */
635 if ((status
== CERT_UNDEFINED
) || (status
== CERT_UNKNOWN
&& strict
))
637 status
= issuer
->verify_by_crl(issuer
, certinfo
, CRL_DIR
);
640 nextUpdate
= certinfo
->get_nextUpdate(certinfo
);
641 cert
->set_status(cert
, status
);
646 /* with strict crl policy the public key must have the same
647 * lifetime as the validity of the ocsp status or crl lifetime
651 cert
->set_until(cert
, nextUpdate
);
652 until
= (nextUpdate
< until
)? nextUpdate
: until
;
655 /* if status information is stale */
656 if (strict
&& nextUpdate
< time(NULL
))
658 DBG2(DBG_CFG
, "certificate is good but status is stale");
659 certinfo
->destroy(certinfo
);
662 DBG1(DBG_CFG
, "certificate is good");
666 time_t revocationTime
= certinfo
->get_revocationTime(certinfo
);
668 "certificate was revoked on %T, reason: %N",
669 &revocationTime
, crl_reason_names
,
670 certinfo
->get_revocationReason(certinfo
));
672 /* set revocationTime */
673 cert
->set_until(cert
, revocationTime
);
675 /* update status of end certificate in the credential store */
680 cert_copy
->set_status(cert_copy
, CERT_UNTRUSTED
);
684 cert_copy
->set_status(cert_copy
, CERT_REVOKED
);
685 cert_copy
->set_until(cert_copy
,
686 certinfo
->get_revocationTime(certinfo
));
689 certinfo
->destroy(certinfo
);
695 DBG1(DBG_CFG
, "certificate status unknown");
698 /* update status of end certificate in the credential store */
701 cert_copy
->set_status(cert_copy
, CERT_UNTRUSTED
);
703 certinfo
->destroy(certinfo
);
708 certinfo
->destroy(certinfo
);
710 /* go up one step in the trust chain */
713 DBG1(DBG_CFG
, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN
);
718 * Implementation of local_credential_store_t.verify_signature.
720 static status_t
verify_signature(private_local_credential_store_t
*this,
721 chunk_t hash
, chunk_t sig
,
722 identification_t
*id
, ca_info_t
**issuer_p
)
724 iterator_t
*iterator
= this->certs
->create_iterator(this->certs
, TRUE
);
728 /* default return values in case of failure */
729 sig_status
= NOT_FOUND
;
732 while (iterator
->iterate(iterator
, (void**)&cert
))
734 if (id
->equals(id
, cert
->get_subject(cert
))
735 || cert
->equals_subjectAltName(cert
, id
))
737 rsa_public_key_t
*public_key
= cert
->get_public_key(cert
);
738 cert_status_t cert_status
= cert
->get_status(cert
);
740 DBG2(DBG_CFG
, "found candidate peer certificate");
742 if (cert_status
== CERT_UNDEFINED
|| cert
->get_until(cert
) < time(NULL
))
746 if (!verify(this, cert
, &found
))
748 sig_status
= VERIFY_ERROR
;
749 DBG1(DBG_CFG
, "candidate peer certificate was not successfully verified");
752 *issuer_p
= get_issuer(this, cert
);
756 ca_info_t
*issuer
= get_issuer(this, cert
);
757 chunk_t keyid
= public_key
->get_keyid(public_key
);
759 DBG2(DBG_CFG
, "subject: '%D'", cert
->get_subject(cert
));
760 DBG2(DBG_CFG
, "issuer: '%D'", cert
->get_issuer(cert
));
761 DBG2(DBG_CFG
, "keyid: %#B", &keyid
);
765 DBG1(DBG_CFG
, "candidate peer certificate has no retrievable issuer");
766 sig_status
= NOT_FOUND
;
769 if (cert_status
== CERT_REVOKED
|| cert_status
== CERT_UNTRUSTED
770 || ((issuer
)->is_strict(issuer
) && cert_status
!= CERT_GOOD
))
772 DBG1(DBG_CFG
, "candidate peer certificate has an inacceptable status: %N", cert_status_names
, cert_status
);
773 sig_status
= VERIFY_ERROR
;
778 sig_status
= public_key
->verify_emsa_pkcs1_signature(public_key
, hash
, sig
);
779 if (sig_status
== SUCCESS
)
781 DBG2(DBG_CFG
, "candidate peer certificate has a matching RSA public key");
786 DBG1(DBG_CFG
, "candidate peer certificate has a non-matching RSA public key");
791 iterator
->destroy(iterator
);
792 if (sig_status
== NOT_FOUND
)
794 DBG1(DBG_CFG
, "no candidate peer certificate found");
800 * Add a unique certificate to a linked list
802 static x509_t
* add_certificate(linked_list_t
*certs
, x509_t
*cert
)
804 x509_t
*found_cert
= find_certificate(certs
, cert
);
808 /* add the authority flags */
809 found_cert
->add_authority_flags(found_cert
, cert
->get_authority_flags(cert
));
816 certs
->insert_last(certs
, (void*)cert
);
822 * Add a unique ca info record to a linked list
824 static ca_info_t
* add_ca_info(private_local_credential_store_t
*this, ca_info_t
*ca_info
)
826 ca_info_t
*current_ca_info
;
827 ca_info_t
*found_ca_info
= NULL
;
829 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
831 while (iterator
->iterate(iterator
, (void**)¤t_ca_info
))
833 if (current_ca_info
->equals(current_ca_info
, ca_info
))
835 found_ca_info
= current_ca_info
;
839 iterator
->destroy(iterator
);
843 current_ca_info
->add_info(current_ca_info
, ca_info
);
844 ca_info
->destroy(ca_info
);
845 ca_info
= found_ca_info
;
849 this->ca_infos
->insert_last(this->ca_infos
, (void*)ca_info
);
855 * Release ca info record of a given name
857 static status_t
release_ca_info(private_local_credential_store_t
*this, const char *name
)
859 status_t status
= NOT_FOUND
;
862 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
864 while (iterator
->iterate(iterator
, (void**)&ca_info
))
866 if (ca_info
->equals_name_release_info(ca_info
, name
))
872 iterator
->destroy(iterator
);
878 * Implements local_credential_store_t.add_end_certificate
880 static x509_t
* add_end_certificate(private_local_credential_store_t
*this, x509_t
*cert
)
882 x509_t
*ret_cert
= add_certificate(this->certs
, cert
);
884 /* add crl and ocsp uris the first time the certificate is added */
885 if (ret_cert
== cert
)
887 ca_info_t
*issuer
= get_issuer(this, cert
);
891 add_uris(issuer
, cert
);
898 * Implements local_credential_store_t.add_auth_certificate
900 static x509_t
* add_auth_certificate(private_local_credential_store_t
*this, x509_t
*cert
, u_int auth_flags
)
902 cert
->add_authority_flags(cert
, auth_flags
);
903 return add_certificate(this->auth_certs
, cert
);
907 * Implements local_credential_store_t.create_cert_iterator
909 static iterator_t
* create_cert_iterator(private_local_credential_store_t
*this)
911 return this->certs
->create_iterator(this->certs
, TRUE
);
915 * Implements local_credential_store_t.create_cacert_iterator
917 static iterator_t
* create_auth_cert_iterator(private_local_credential_store_t
*this)
919 return this->auth_certs
->create_iterator(this->auth_certs
, TRUE
);
923 * Implements local_credential_store_t.create_cainfo_iterator
925 static iterator_t
* create_cainfo_iterator(private_local_credential_store_t
*this)
927 return this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
931 * Implements local_credential_store_t.load_auth_certificates
933 static void load_auth_certificates(private_local_credential_store_t
*this,
938 struct dirent
* entry
;
942 DBG1(DBG_CFG
, "loading %s certificates from '%s'", label
, path
);
947 DBG1(DBG_CFG
, "error opening %s certs directory '%s'", label
, path
);
951 while ((entry
= readdir(dir
)) != NULL
)
955 snprintf(file
, sizeof(file
), "%s/%s", path
, entry
->d_name
);
957 if (stat(file
, &stb
) == -1)
961 /* try to parse all regular files */
962 if (stb
.st_mode
& S_IFREG
)
964 x509_t
*cert
= x509_create_from_file(file
, label
);
968 err_t ugh
= cert
->is_valid(cert
, NULL
);
972 DBG1(DBG_CFG
, "warning: %s certificate %s", label
, ugh
);
975 if (auth_flag
== AUTH_CA
&& !cert
->is_ca(cert
))
977 DBG1(DBG_CFG
, " CA basic constraints flag not set, cert discarded");
984 cert
->add_authority_flags(cert
, auth_flag
);
986 ret_cert
= add_certificate(this->auth_certs
, cert
);
988 if (auth_flag
== AUTH_CA
&& ret_cert
== cert
)
990 ca_info_t
*ca_info
= ca_info_create(NULL
, cert
);
992 add_ca_info(this, ca_info
);
1002 * Implements local_credential_store_t.load_ca_certificates
1004 static void load_ca_certificates(private_local_credential_store_t
*this)
1006 load_auth_certificates(this, AUTH_CA
, "ca", CA_CERTIFICATE_DIR
);
1008 /* add any crl and ocsp uris found in the ca certificates to the
1009 * corresponding issuer info record. We can do this only after all
1010 * ca certificates have been loaded and the ca hierarchy is known.
1013 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
1016 while (iterator
->iterate(iterator
, (void **)&ca_info
))
1018 if (ca_info
->is_ca(ca_info
))
1020 x509_t
*cacert
= ca_info
->get_certificate(ca_info
);
1021 ca_info_t
*issuer
= get_issuer(this, cacert
);
1025 add_uris(issuer
, cacert
);
1029 iterator
->destroy(iterator
);
1034 * Implements local_credential_store_t.load_aa_certificates
1036 static void load_aa_certificates(private_local_credential_store_t
*this)
1038 load_auth_certificates(this, AUTH_AA
, "aa", AA_CERTIFICATE_DIR
);
1042 * Add a unique attribute certificate to a linked list
1044 static void add_attr_certificate(private_local_credential_store_t
*this, x509ac_t
*cert
)
1046 /* TODO add a new attribute certificate to the linked list */
1050 * Implements local_credential_store_t.load_attr_certificates
1052 static void load_attr_certificates(private_local_credential_store_t
*this)
1054 struct dirent
* entry
;
1058 const char *path
= ATTR_CERTIFICATE_DIR
;
1060 DBG1(DBG_CFG
, "loading attribute certificates from '%s'", path
);
1062 dir
= opendir(ATTR_CERTIFICATE_DIR
);
1065 DBG1(DBG_CFG
, "error opening attribute certs directory '%s'", path
);
1069 while ((entry
= readdir(dir
)) != NULL
)
1071 char file
[PATH_BUF
];
1073 snprintf(file
, sizeof(file
), "%s/%s", path
, entry
->d_name
);
1075 if (stat(file
, &stb
) == -1)
1079 /* try to parse all regular files */
1080 if (stb
.st_mode
& S_IFREG
)
1082 x509ac_t
*cert
= x509ac_create_from_file(file
);
1086 err_t ugh
= cert
->is_valid(cert
, NULL
);
1090 DBG1(DBG_CFG
, "warning: attribute certificate %s", ugh
);
1092 add_attr_certificate(this, cert
);
1102 * Implements local_credential_store_t.load_ocsp_certificates
1104 static void load_ocsp_certificates(private_local_credential_store_t
*this)
1106 load_auth_certificates(this, AUTH_OCSP
, "ocsp", OCSP_CERTIFICATE_DIR
);
1110 * Add the latest crl to the issuing ca
1112 static void add_crl(private_local_credential_store_t
*this, crl_t
*crl
, const char *path
)
1114 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
1118 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1120 if (ca_info
->is_ca(ca_info
) && ca_info
->is_crl_issuer(ca_info
, crl
))
1122 char buffer
[BUF_LEN
];
1123 chunk_t uri
= { buffer
, 7 + strlen(path
) };
1125 ca_info
->add_crl(ca_info
, crl
);
1126 if (uri
.len
< BUF_LEN
)
1128 snprintf(buffer
, BUF_LEN
, "file://%s", path
);
1129 ca_info
->add_crluri(ca_info
, uri
);
1135 iterator
->destroy(iterator
);
1140 DBG2(DBG_CFG
, " no issuing ca found for this crl - discarded");
1145 * Implements local_credential_store_t.load_crls
1147 static void load_crls(private_local_credential_store_t
*this)
1149 struct dirent
* entry
;
1154 DBG1(DBG_CFG
, "loading crls from '%s'", CRL_DIR
);
1156 dir
= opendir(CRL_DIR
);
1159 DBG1(DBG_CFG
, "error opening crl directory '%s'", CRL_DIR
);
1163 while ((entry
= readdir(dir
)) != NULL
)
1165 char file
[PATH_BUF
];
1167 snprintf(file
, sizeof(file
), "%s/%s", CRL_DIR
, entry
->d_name
);
1169 if (stat(file
, &stb
) == -1)
1173 /* try to parse all regular files */
1174 if (stb
.st_mode
& S_IFREG
)
1176 crl
= crl_create_from_file(file
);
1179 DBG1(DBG_CFG
, " crl is %s", crl
->is_valid(crl
)?
"valid":"stale");
1180 add_crl(this, crl
, file
);
1188 * Convert a string of characters into a binary secret
1189 * A string between single or double quotes is treated as ASCII characters
1190 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
1192 static err_t
extract_secret(chunk_t
*secret
, chunk_t
*line
)
1195 char delimiter
= ' ';
1196 bool quotes
= FALSE
;
1198 if (!eat_whitespace(line
))
1200 return "missing secret";
1203 if (*line
->ptr
== '\'' || *line
->ptr
== '"')
1206 delimiter
= *line
->ptr
;
1207 line
->ptr
++; line
->len
--;
1210 if (!extract_token(&raw_secret
, delimiter
, line
))
1212 if (delimiter
== ' ')
1218 return "missing second delimiter";
1223 { /* treat as an ASCII string */
1224 if (raw_secret
.len
> secret
->len
)
1225 return "secret larger than buffer";
1226 memcpy(secret
->ptr
, raw_secret
.ptr
, raw_secret
.len
);
1227 secret
->len
= raw_secret
.len
;
1230 { /* convert from HEX or Base64 to binary */
1232 err_t ugh
= ttodata(raw_secret
.ptr
, raw_secret
.len
, 0, secret
->ptr
, secret
->len
, &len
);
1236 if (len
> secret
->len
)
1237 return "secret larger than buffer";
1244 * Implements local_credential_store_t.load_secrets
1246 static void load_secrets(private_local_credential_store_t
*this)
1248 FILE *fd
= fopen(SECRETS_FILE
, "r");
1254 chunk_t chunk
, src
, line
;
1256 DBG1(DBG_CFG
, "loading secrets from \"%s\"", SECRETS_FILE
);
1258 fseek(fd
, 0, SEEK_END
);
1259 chunk
.len
= ftell(fd
);
1261 chunk
.ptr
= malloc(chunk
.len
);
1262 bytes
= fread(chunk
.ptr
, 1, chunk
.len
, fd
);
1267 while (fetchline(&src
, &line
))
1270 bool is_eap
= FALSE
;
1274 if (!eat_whitespace(&line
))
1278 if (!extract_token(&ids
, ':', &line
))
1280 DBG1(DBG_CFG
, "line %d: missing ':' separator", line_nr
);
1283 /* NULL terminate the ids string by replacing the : separator */
1284 *(ids
.ptr
+ ids
.len
) = '\0';
1286 if (!eat_whitespace(&line
) || !extract_token(&token
, ' ', &line
))
1288 DBG1(DBG_CFG
, "line %d: missing token", line_nr
);
1291 if (match("RSA", &token
))
1293 char path
[PATH_BUF
];
1297 chunk_t secret
= { buf
, BUF_LEN
};
1298 chunk_t
*passphrase
= NULL
;
1300 rsa_private_key_t
*key
;
1302 err_t ugh
= extract_value(&filename
, &line
);
1306 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
1309 if (filename
.len
== 0)
1311 DBG1(DBG_CFG
, "line %d: empty filename", line_nr
);
1314 if (*filename
.ptr
== '/')
1316 /* absolute path name */
1317 snprintf(path
, sizeof(path
), "%.*s", filename
.len
, filename
.ptr
);
1321 /* relative path name */
1322 snprintf(path
, sizeof(path
), "%s/%.*s", PRIVATE_KEY_DIR
,
1323 filename
.len
, filename
.ptr
);
1326 /* check for optional passphrase */
1327 if (eat_whitespace(&line
))
1329 ugh
= extract_secret(&secret
, &line
);
1332 DBG1(DBG_CFG
, "line %d: malformed passphrase: %s", line_nr
, ugh
);
1336 passphrase
= &secret
;
1338 key
= rsa_private_key_create_from_file(path
, passphrase
);
1341 this->private_keys
->insert_last(this->private_keys
, (void*)key
);
1344 else if ( match("PSK", &token
) ||
1345 ((match("EAP", &token
) || match("XAUTH", &token
)) && (is_eap
= TRUE
)))
1347 shared_key_t
*shared_key
;
1350 chunk_t secret
= { buf
, BUF_LEN
};
1352 err_t ugh
= extract_secret(&secret
, &line
);
1355 DBG1(DBG_CFG
, "line %d: malformed secret: %s", line_nr
, ugh
);
1359 DBG1(DBG_CFG
, " loading %s key for %s",
1360 is_eap ?
"EAP" : "shared",
1361 ids
.len
> 0 ?
(char*)ids
.ptr
: "%any");
1363 DBG4(DBG_CFG
, " secret:", secret
);
1365 shared_key
= shared_key_create(secret
);
1370 this->eap_keys
->insert_last(this->eap_keys
, (void*)shared_key
);
1374 this->shared_keys
->insert_last(this->shared_keys
, (void*)shared_key
);
1380 identification_t
*peer_id
;
1382 ugh
= extract_value(&id
, &ids
);
1385 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
1393 /* NULL terminate the ID string */
1394 *(id
.ptr
+ id
.len
) = '\0';
1396 peer_id
= identification_create_from_string(id
.ptr
);
1397 if (peer_id
== NULL
)
1399 DBG1(DBG_CFG
, "line %d: malformed ID: %s", line_nr
, id
.ptr
);
1403 if (peer_id
->get_type(peer_id
) == ID_ANY
)
1405 peer_id
->destroy(peer_id
);
1408 shared_key
->peers
->insert_last(shared_key
->peers
, (void*)peer_id
);
1411 else if (match("PIN", &token
))
1417 DBG1(DBG_CFG
, "line %d: token must be either "
1418 "RSA, PSK, EAP, or PIN", line_nr
, token
.len
);
1427 DBG1(DBG_CFG
, "could not open file '%s': %s", SECRETS_FILE
,
1433 * Implementation of local_credential_store_t.destroy.
1435 static void destroy(private_local_credential_store_t
*this)
1437 this->certs
->destroy_offset(this->certs
, offsetof(x509_t
, destroy
));
1438 this->auth_certs
->destroy_offset(this->auth_certs
, offsetof(x509_t
, destroy
));
1439 this->ca_infos
->destroy_offset(this->ca_infos
, offsetof(ca_info_t
, destroy
));
1440 this->private_keys
->destroy_offset(this->private_keys
, offsetof(rsa_private_key_t
, destroy
));
1441 this->shared_keys
->destroy_function(this->shared_keys
, (void*)shared_key_destroy
);
1442 this->eap_keys
->destroy_function(this->eap_keys
, (void*)shared_key_destroy
);
1447 * Described in header.
1449 local_credential_store_t
* local_credential_store_create(void)
1451 private_local_credential_store_t
*this = malloc_thing(private_local_credential_store_t
);
1453 this->public.credential_store
.get_shared_key
= (status_t (*) (credential_store_t
*,identification_t
*,identification_t
*,chunk_t
*))get_shared_key
;
1454 this->public.credential_store
.get_eap_key
= (status_t (*) (credential_store_t
*,identification_t
*,identification_t
*,chunk_t
*))get_eap_key
;
1455 this->public.credential_store
.get_rsa_public_key
= (rsa_public_key_t
*(*)(credential_store_t
*,identification_t
*))get_rsa_public_key
;
1456 this->public.credential_store
.get_rsa_private_key
= (rsa_private_key_t
* (*) (credential_store_t
*,rsa_public_key_t
*))get_rsa_private_key
;
1457 this->public.credential_store
.has_rsa_private_key
= (bool (*) (credential_store_t
*,rsa_public_key_t
*))has_rsa_private_key
;
1458 this->public.credential_store
.get_certificate
= (x509_t
* (*) (credential_store_t
*,identification_t
*))get_certificate
;
1459 this->public.credential_store
.get_auth_certificate
= (x509_t
* (*) (credential_store_t
*,u_int
,identification_t
*))get_auth_certificate
;
1460 this->public.credential_store
.get_ca_certificate_by_keyid
= (x509_t
* (*) (credential_store_t
*,chunk_t
))get_ca_certificate_by_keyid
;
1461 this->public.credential_store
.get_issuer
= (ca_info_t
* (*) (credential_store_t
*,const x509_t
*))get_issuer
;
1462 this->public.credential_store
.is_trusted
= (bool (*) (credential_store_t
*,x509_t
*))is_trusted
;
1463 this->public.credential_store
.verify_signature
= (status_t (*) (credential_store_t
*,chunk_t
,chunk_t
,identification_t
*,ca_info_t
**))verify_signature
;
1464 this->public.credential_store
.verify
= (bool (*) (credential_store_t
*,x509_t
*,bool*))verify
;
1465 this->public.credential_store
.add_end_certificate
= (x509_t
* (*) (credential_store_t
*,x509_t
*))add_end_certificate
;
1466 this->public.credential_store
.add_auth_certificate
= (x509_t
* (*) (credential_store_t
*,x509_t
*,u_int
))add_auth_certificate
;
1467 this->public.credential_store
.add_ca_info
= (ca_info_t
* (*) (credential_store_t
*,ca_info_t
*))add_ca_info
;
1468 this->public.credential_store
.release_ca_info
= (status_t (*) (credential_store_t
*,const char*))release_ca_info
;
1469 this->public.credential_store
.create_cert_iterator
= (iterator_t
* (*) (credential_store_t
*))create_cert_iterator
;
1470 this->public.credential_store
.create_auth_cert_iterator
= (iterator_t
* (*) (credential_store_t
*))create_auth_cert_iterator
;
1471 this->public.credential_store
.create_cainfo_iterator
= (iterator_t
* (*) (credential_store_t
*))create_cainfo_iterator
;
1472 this->public.credential_store
.load_ca_certificates
= (void (*) (credential_store_t
*))load_ca_certificates
;
1473 this->public.credential_store
.load_aa_certificates
= (void (*) (credential_store_t
*))load_aa_certificates
;
1474 this->public.credential_store
.load_attr_certificates
= (void (*) (credential_store_t
*))load_attr_certificates
;
1475 this->public.credential_store
.load_ocsp_certificates
= (void (*) (credential_store_t
*))load_ocsp_certificates
;
1476 this->public.credential_store
.load_crls
= (void (*) (credential_store_t
*))load_crls
;
1477 this->public.credential_store
.load_secrets
= (void (*) (credential_store_t
*))load_secrets
;
1478 this->public.credential_store
.destroy
= (void (*) (credential_store_t
*))destroy
;
1480 /* private variables */
1481 this->shared_keys
= linked_list_create();
1482 this->eap_keys
= linked_list_create();
1483 this->private_keys
= linked_list_create();
1484 this->certs
= linked_list_create();
1485 this->auth_certs
= linked_list_create();
1486 this->ca_infos
= linked_list_create();
1488 return (&this->public);