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
29 #include <utils/lexparser.h>
30 #include <utils/linked_list.h>
31 #include <crypto/rsa/rsa_public_key.h>
32 #include <crypto/certinfo.h>
33 #include <crypto/x509.h>
34 #include <crypto/ca.h>
35 #include <crypto/ac.h>
36 #include <crypto/crl.h>
37 #include <asn1/ttodata.h>
39 #include "local_credential_store.h"
42 #define MAX_CA_PATH_LEN 7
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
;
176 * enforce strict crl policy
183 * Get a key from a list with shared_key_t's
185 static status_t
get_key(linked_list_t
*keys
,
186 identification_t
*my_id
,
187 identification_t
*other_id
, chunk_t
*secret
)
190 PRIO_UNDEFINED
= 0x00,
191 PRIO_ANY_MATCH
= 0x01,
193 PRIO_OTHER_MATCH
= 0x04,
196 prio_t best_prio
= PRIO_UNDEFINED
;
197 chunk_t found
= chunk_empty
;
198 shared_key_t
*shared_key
;
200 iterator_t
*iterator
= keys
->create_iterator(keys
, TRUE
);
202 while (iterator
->iterate(iterator
, (void**)&shared_key
))
204 iterator_t
*peer_iterator
;
205 identification_t
*peer_id
;
206 prio_t prio
= PRIO_UNDEFINED
;
208 peer_iterator
= shared_key
->peers
->create_iterator(shared_key
->peers
, TRUE
);
210 if (peer_iterator
->get_count(peer_iterator
) == 0)
212 /* this is a wildcard shared key */
213 prio
= PRIO_ANY_MATCH
;
217 while (peer_iterator
->iterate(peer_iterator
, (void**)&peer_id
))
219 if (my_id
->equals(my_id
, peer_id
))
221 prio
|= PRIO_MY_MATCH
;
223 if (other_id
->equals(other_id
, peer_id
))
225 prio
|= PRIO_OTHER_MATCH
;
229 peer_iterator
->destroy(peer_iterator
);
231 if (prio
> best_prio
)
234 found
= shared_key
->secret
;
237 iterator
->destroy(iterator
);
239 if (best_prio
== PRIO_UNDEFINED
)
245 *secret
= chunk_clone(found
);
252 * Implementation of local_credential_store_t.get_shared_key.
254 static status_t
get_shared_key(private_local_credential_store_t
*this,
255 identification_t
*my_id
,
256 identification_t
*other_id
, chunk_t
*secret
)
258 return get_key(this->shared_keys
, my_id
, other_id
, secret
);
262 * Implementation of local_credential_store_t.get_eap_key.
264 static status_t
get_eap_key(private_local_credential_store_t
*this,
265 identification_t
*my_id
,
266 identification_t
*other_id
, chunk_t
*secret
)
268 return get_key(this->eap_keys
, my_id
, other_id
, secret
);
272 * Implementation of credential_store_t.get_certificate.
274 static x509_t
* get_certificate(private_local_credential_store_t
*this,
275 identification_t
*id
)
277 x509_t
*found
= NULL
;
278 x509_t
*current_cert
;
280 iterator_t
*iterator
= this->certs
->create_iterator(this->certs
, TRUE
);
282 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
284 if (id
->equals(id
, current_cert
->get_subject(current_cert
)) ||
285 current_cert
->equals_subjectAltName(current_cert
, id
))
287 found
= current_cert
;
291 iterator
->destroy(iterator
);
296 * Implementation of local_credential_store_t.get_rsa_public_key.
298 static rsa_public_key_t
*get_rsa_public_key(private_local_credential_store_t
*this,
299 identification_t
*id
)
301 x509_t
*cert
= get_certificate(this, id
);
303 return (cert
== NULL
)? NULL
:cert
->get_public_key(cert
);
307 * Implementation of local_credential_store_t.get_trusted_public_key.
309 static rsa_public_key_t
*get_trusted_public_key(private_local_credential_store_t
*this,
310 identification_t
*id
)
312 cert_status_t status
;
315 x509_t
*cert
= get_certificate(this, id
);
320 ugh
= cert
->is_valid(cert
, NULL
);
323 DBG1(DBG_CFG
, "certificate %s", ugh
);
327 status
= cert
->get_status(cert
);
328 if (status
== CERT_REVOKED
|| status
== CERT_UNTRUSTED
|| (this->strict
&& status
!= CERT_GOOD
))
330 DBG1(DBG_CFG
, "certificate status: %N", cert_status_names
, status
);
333 if (status
== CERT_GOOD
&& cert
->get_until(cert
) < time(NULL
))
335 DBG1(DBG_CFG
, "certificate is good but crl is stale");
339 return cert
->get_public_key(cert
);
343 * Implementation of local_credential_store_t.get_rsa_private_key.
345 static rsa_private_key_t
*get_rsa_private_key(private_local_credential_store_t
*this,
346 rsa_public_key_t
*pubkey
)
348 rsa_private_key_t
*found
= NULL
, *current
;
350 iterator_t
*iterator
= this->private_keys
->create_iterator(this->private_keys
, TRUE
);
352 while (iterator
->iterate(iterator
, (void**)¤t
))
354 if (current
->belongs_to(current
, pubkey
))
356 found
= current
->clone(current
);
360 iterator
->destroy(iterator
);
365 * Implementation of local_credential_store_t.has_rsa_private_key.
367 static bool has_rsa_private_key(private_local_credential_store_t
*this, rsa_public_key_t
*pubkey
)
370 rsa_private_key_t
*current
;
372 iterator_t
*iterator
= this->private_keys
->create_iterator(this->private_keys
, TRUE
);
374 while (iterator
->iterate(iterator
, (void**)¤t
))
376 if (current
->belongs_to(current
, pubkey
))
382 iterator
->destroy(iterator
);
387 * Implementation of credential_store_t.get_auth_certificate.
389 static x509_t
* get_auth_certificate(private_local_credential_store_t
*this,
391 identification_t
*id
)
393 x509_t
*found
= NULL
;
394 x509_t
*current_cert
;
396 iterator_t
*iterator
= this->auth_certs
->create_iterator(this->auth_certs
, TRUE
);
398 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
400 if (current_cert
->has_authority_flag(current_cert
, auth_flags
)
401 && id
->equals(id
, current_cert
->get_subject(current_cert
)))
403 found
= current_cert
;
407 iterator
->destroy(iterator
);
413 * Implementation of credential_store_t.get_ca_certificate_by_keyid.
415 static x509_t
* get_ca_certificate_by_keyid(private_local_credential_store_t
*this,
418 x509_t
*found
= NULL
;
419 x509_t
*current_cert
;
421 iterator_t
*iterator
= this->auth_certs
->create_iterator(this->auth_certs
, TRUE
);
423 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
425 rsa_public_key_t
*pubkey
= current_cert
->get_public_key(current_cert
);
427 if (current_cert
->has_authority_flag(current_cert
, AUTH_CA
)
428 && chunk_equals(keyid
, pubkey
->get_keyid(pubkey
)))
430 found
= current_cert
;
434 iterator
->destroy(iterator
);
440 * Implementation of credential_store_t.get_issuer.
442 static ca_info_t
* get_issuer(private_local_credential_store_t
*this, const x509_t
*cert
)
444 ca_info_t
*found
= NULL
;
447 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
449 while (iterator
->iterate(iterator
, (void**)&ca_info
))
451 if (ca_info
->is_cert_issuer(ca_info
, cert
))
457 iterator
->destroy(iterator
);
463 * Find an exact copy of a certificate in a linked list
465 static x509_t
* find_certificate(linked_list_t
*certs
, x509_t
*cert
)
467 x509_t
*found_cert
= NULL
, *current_cert
;
469 iterator_t
*iterator
= certs
->create_iterator(certs
, TRUE
);
471 while (iterator
->iterate(iterator
, (void**)¤t_cert
))
473 if (cert
->equals(cert
, current_cert
))
475 found_cert
= current_cert
;
479 iterator
->destroy(iterator
);
485 * Adds crl and ocsp uris to the corresponding issuer info record
487 static void add_uris(ca_info_t
*issuer
, x509_t
*cert
)
489 iterator_t
*iterator
;
490 identification_t
*uri
;
492 /* add any crl distribution points to the issuer ca info record */
493 iterator
= cert
->create_crluri_iterator(cert
);
495 while (iterator
->iterate(iterator
, (void**)&uri
))
497 issuer
->add_crluri(issuer
, uri
->get_encoding(uri
));
499 iterator
->destroy(iterator
);
501 /* add any ocsp access points to the issuer ca info record */
502 iterator
= cert
->create_ocspuri_iterator(cert
);
504 while (iterator
->iterate(iterator
, (void**)&uri
))
506 issuer
->add_ocspuri(issuer
, uri
->get_encoding(uri
));
508 iterator
->destroy(iterator
);
512 * Implementation of credential_store_t.is_trusted
514 static bool is_trusted(private_local_credential_store_t
*this, x509_t
*cert
)
517 time_t until
= UNDEFINED_TIME
;
518 x509_t
*cert_to_be_trusted
= cert
;
520 DBG2(DBG_CFG
, "establishing trust in certificate:");
522 for (pathlen
= 0; pathlen
< MAX_CA_PATH_LEN
; pathlen
++)
527 rsa_public_key_t
*issuer_public_key
;
528 bool valid_signature
;
530 DBG2(DBG_CFG
, "subject: '%D'", cert
->get_subject(cert
));
531 DBG2(DBG_CFG
, "issuer: '%D'", cert
->get_issuer(cert
));
533 ugh
= cert
->is_valid(cert
, &until
);
536 DBG1(DBG_CFG
, "certificate %s", ugh
);
539 DBG2(DBG_CFG
, "certificate is valid");
541 issuer
= get_issuer(this, cert
);
544 DBG1(DBG_CFG
, "issuer not found");
547 DBG2(DBG_CFG
, "issuer found");
549 issuer_cert
= issuer
->get_certificate(issuer
);
550 issuer_public_key
= issuer_cert
->get_public_key(issuer_cert
);
551 valid_signature
= cert
->verify(cert
, issuer_public_key
);
553 if (!valid_signature
)
555 DBG1(DBG_CFG
, "certificate signature is invalid");
558 DBG2(DBG_CFG
, "certificate signature is valid");
560 /* check if cert is a self-signed root ca */
561 if (pathlen
> 0 && cert
->is_self_signed(cert
))
563 DBG2(DBG_CFG
, "reached self-signed root ca");
564 cert_to_be_trusted
->set_until(cert_to_be_trusted
, until
);
565 cert_to_be_trusted
->set_status(cert_to_be_trusted
, CERT_GOOD
);
570 /* go up one step in the trust chain */
574 DBG1(DBG_CFG
, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN
);
579 * Implementation of credential_store_t.verify.
581 static bool verify(private_local_credential_store_t
*this, x509_t
*cert
, bool *found
)
584 time_t until
= UNDEFINED_TIME
;
586 x509_t
*end_cert
= cert
;
587 x509_t
*cert_copy
= find_certificate(this->certs
, end_cert
);
589 DBG2(DBG_CFG
, "verifying end entity certificate:");
591 *found
= (cert_copy
!= NULL
);
595 "end entitity certificate is already in credential store");
598 for (pathlen
= 0; pathlen
< MAX_CA_PATH_LEN
; pathlen
++)
603 rsa_public_key_t
*issuer_public_key
;
604 bool valid_signature
;
606 DBG1(DBG_CFG
, "subject: '%D'", cert
->get_subject(cert
));
607 DBG1(DBG_CFG
, "issuer: '%D'", cert
->get_issuer(cert
));
609 ugh
= cert
->is_valid(cert
, &until
);
612 DBG1(DBG_CFG
, "certificate %s", ugh
);
615 DBG2(DBG_CFG
, "certificate is valid");
617 issuer
= get_issuer(this, cert
);
620 DBG1(DBG_CFG
, "issuer not found");
623 DBG2(DBG_CFG
, "issuer found");
625 issuer_cert
= issuer
->get_certificate(issuer
);
626 issuer_public_key
= issuer_cert
->get_public_key(issuer_cert
);
627 valid_signature
= cert
->verify(cert
, issuer_public_key
);
629 if (!valid_signature
)
631 DBG1(DBG_CFG
, "certificate signature is invalid");
634 DBG2(DBG_CFG
, "certificate signature is valid");
636 /* check if cert is a self-signed root ca */
637 if (pathlen
> 0 && cert
->is_self_signed(cert
))
639 DBG1(DBG_CFG
, "reached self-signed root ca");
641 /* set the definite status and trust interval of the end entity certificate */
642 end_cert
->set_until(end_cert
, until
);
645 cert_copy
->set_status(cert_copy
, end_cert
->get_status(end_cert
));
646 cert_copy
->set_until(cert_copy
, until
);
653 cert_status_t status
;
654 certinfo_t
*certinfo
= certinfo_create(cert
->get_serialNumber(cert
));
656 certinfo
->set_nextUpdate(certinfo
, until
);
660 /* add any crl and ocsp uris contained in the certificate under test */
661 add_uris(issuer
, cert
);
664 /* first check certificate revocation using ocsp */
665 status
= issuer
->verify_by_ocsp(issuer
, certinfo
, &this->public.credential_store
);
667 /* if ocsp service is not available then fall back to crl */
668 if ((status
== CERT_UNDEFINED
) || (status
== CERT_UNKNOWN
&& this->strict
))
670 status
= issuer
->verify_by_crl(issuer
, certinfo
, CRL_DIR
);
673 nextUpdate
= certinfo
->get_nextUpdate(certinfo
);
674 cert
->set_status(cert
, status
);
680 cert
->set_until(cert
, nextUpdate
);
682 /* if status information is stale */
683 if (this->strict
&& nextUpdate
< time(NULL
))
685 DBG2(DBG_CFG
, "certificate is good but status is stale");
686 certinfo
->destroy(certinfo
);
689 DBG1(DBG_CFG
, "certificate is good");
691 /* with strict crl policy the public key must have the same
692 * lifetime as the validity of the ocsp status or crl lifetime
694 if (this->strict
&& nextUpdate
< until
)
699 time_t revocationTime
= certinfo
->get_revocationTime(certinfo
);
701 "certificate was revoked on %T, reason: %N",
702 &revocationTime
, crl_reason_names
,
703 certinfo
->get_revocationReason(certinfo
));
705 /* set revocationTime */
706 cert
->set_until(cert
, revocationTime
);
708 /* update status of end certificate in the credential store */
713 cert_copy
->set_status(cert_copy
, CERT_UNTRUSTED
);
717 cert_copy
->set_status(cert_copy
, CERT_REVOKED
);
718 cert_copy
->set_until(cert_copy
,
719 certinfo
->get_revocationTime(certinfo
));
722 certinfo
->destroy(certinfo
);
728 DBG1(DBG_CFG
, "certificate status unknown");
731 /* update status of end certificate in the credential store */
734 cert_copy
->set_status(cert_copy
, CERT_UNTRUSTED
);
736 certinfo
->destroy(certinfo
);
741 certinfo
->destroy(certinfo
);
743 /* go up one step in the trust chain */
746 DBG1(DBG_CFG
, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN
);
751 * Add a unique certificate to a linked list
753 static x509_t
* add_certificate(linked_list_t
*certs
, x509_t
*cert
)
755 x509_t
*found_cert
= find_certificate(certs
, cert
);
759 /* add the authority flags */
760 found_cert
->add_authority_flags(found_cert
, cert
->get_authority_flags(cert
));
767 certs
->insert_last(certs
, (void*)cert
);
773 * Add a unique ca info record to a linked list
775 static void add_ca_info(private_local_credential_store_t
*this, ca_info_t
*ca_info
)
777 ca_info_t
*current_ca_info
;
778 ca_info_t
*found_ca_info
= NULL
;
780 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
782 while (iterator
->iterate(iterator
, (void**)¤t_ca_info
))
784 if (current_ca_info
->equals(current_ca_info
, ca_info
))
786 found_ca_info
= current_ca_info
;
790 iterator
->destroy(iterator
);
794 current_ca_info
->add_info(current_ca_info
, ca_info
);
795 ca_info
->destroy(ca_info
);
799 this->ca_infos
->insert_last(this->ca_infos
, (void*)ca_info
);
804 * Release ca info record of a given name
806 static status_t
release_ca_info(private_local_credential_store_t
*this, const char *name
)
808 status_t status
= NOT_FOUND
;
811 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
813 while (iterator
->iterate(iterator
, (void**)&ca_info
))
815 if (ca_info
->equals_name_release_info(ca_info
, name
))
821 iterator
->destroy(iterator
);
827 * Implements local_credential_store_t.add_end_certificate
829 static x509_t
* add_end_certificate(private_local_credential_store_t
*this, x509_t
*cert
)
831 x509_t
*ret_cert
= add_certificate(this->certs
, cert
);
833 /* add crl and ocsp uris the first time the certificate is added */
834 if (ret_cert
== cert
)
836 ca_info_t
*issuer
= get_issuer(this, cert
);
840 add_uris(issuer
, cert
);
847 * Implements local_credential_store_t.add_auth_certificate
849 static x509_t
* add_auth_certificate(private_local_credential_store_t
*this, x509_t
*cert
, u_int auth_flags
)
851 cert
->add_authority_flags(cert
, auth_flags
);
852 return add_certificate(this->auth_certs
, cert
);
856 * Implements local_credential_store_t.create_cert_iterator
858 static iterator_t
* create_cert_iterator(private_local_credential_store_t
*this)
860 return this->certs
->create_iterator(this->certs
, TRUE
);
864 * Implements local_credential_store_t.create_cacert_iterator
866 static iterator_t
* create_auth_cert_iterator(private_local_credential_store_t
*this)
868 return this->auth_certs
->create_iterator(this->auth_certs
, TRUE
);
872 * Implements local_credential_store_t.create_cainfo_iterator
874 static iterator_t
* create_cainfo_iterator(private_local_credential_store_t
*this)
876 return this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
880 * Implements local_credential_store_t.load_auth_certificates
882 static void load_auth_certificates(private_local_credential_store_t
*this,
887 struct dirent
* entry
;
891 DBG1(DBG_CFG
, "loading %s certificates from '%s'", label
, path
);
896 DBG1(DBG_CFG
, "error opening %s certs directory '%s'", label
, path
);
900 while ((entry
= readdir(dir
)) != NULL
)
904 snprintf(file
, sizeof(file
), "%s/%s", path
, entry
->d_name
);
906 if (stat(file
, &stb
) == -1)
910 /* try to parse all regular files */
911 if (stb
.st_mode
& S_IFREG
)
913 x509_t
*cert
= x509_create_from_file(file
, label
);
917 err_t ugh
= cert
->is_valid(cert
, NULL
);
921 DBG1(DBG_CFG
, "warning: %s certificate %s", label
, ugh
);
924 if (auth_flag
== AUTH_CA
&& !cert
->is_ca(cert
))
926 DBG1(DBG_CFG
, " CA basic constraints flag not set, cert discarded");
933 cert
->add_authority_flags(cert
, auth_flag
);
935 ret_cert
= add_certificate(this->auth_certs
, cert
);
937 if (auth_flag
== AUTH_CA
&& ret_cert
== cert
)
939 ca_info_t
*ca_info
= ca_info_create(NULL
, cert
);
941 add_ca_info(this, ca_info
);
951 * Implements local_credential_store_t.load_ca_certificates
953 static void load_ca_certificates(private_local_credential_store_t
*this)
955 load_auth_certificates(this, AUTH_CA
, "ca", CA_CERTIFICATE_DIR
);
957 /* add any crl and ocsp uris found in the ca certificates to the
958 * corresponding issuer info record. We can do this only after all
959 * ca certificates have been loaded and the ca hierarchy is known.
962 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
965 while (iterator
->iterate(iterator
, (void **)&ca_info
))
967 x509_t
*cacert
= ca_info
->get_certificate(ca_info
);
968 ca_info_t
*issuer
= get_issuer(this, cacert
);
972 add_uris(issuer
, cacert
);
975 iterator
->destroy(iterator
);
980 * Implements local_credential_store_t.load_aa_certificates
982 static void load_aa_certificates(private_local_credential_store_t
*this)
984 load_auth_certificates(this, AUTH_AA
, "aa", AA_CERTIFICATE_DIR
);
988 * Add a unique attribute certificate to a linked list
990 static void add_attr_certificate(private_local_credential_store_t
*this, x509ac_t
*cert
)
992 /* TODO add a new attribute certificate to the linked list */
996 * Implements local_credential_store_t.load_attr_certificates
998 static void load_attr_certificates(private_local_credential_store_t
*this)
1000 struct dirent
* entry
;
1004 const char *path
= ATTR_CERTIFICATE_DIR
;
1006 DBG1(DBG_CFG
, "loading attribute certificates from '%s'", path
);
1008 dir
= opendir(ATTR_CERTIFICATE_DIR
);
1011 DBG1(DBG_CFG
, "error opening attribute certs directory '%s'", path
);
1015 while ((entry
= readdir(dir
)) != NULL
)
1017 char file
[PATH_BUF
];
1019 snprintf(file
, sizeof(file
), "%s/%s", path
, entry
->d_name
);
1021 if (stat(file
, &stb
) == -1)
1025 /* try to parse all regular files */
1026 if (stb
.st_mode
& S_IFREG
)
1028 x509ac_t
*cert
= x509ac_create_from_file(file
);
1032 err_t ugh
= cert
->is_valid(cert
, NULL
);
1036 DBG1(DBG_CFG
, "warning: attribute certificate %s", ugh
);
1038 add_attr_certificate(this, cert
);
1048 * Implements local_credential_store_t.load_ocsp_certificates
1050 static void load_ocsp_certificates(private_local_credential_store_t
*this)
1052 load_auth_certificates(this, AUTH_OCSP
, "ocsp", OCSP_CERTIFICATE_DIR
);
1056 * Add the latest crl to the issuing ca
1058 static void add_crl(private_local_credential_store_t
*this, crl_t
*crl
, const char *path
)
1060 iterator_t
*iterator
= this->ca_infos
->create_iterator(this->ca_infos
, TRUE
);
1064 while (iterator
->iterate(iterator
, (void**)&ca_info
))
1066 if (ca_info
->is_crl_issuer(ca_info
, crl
))
1068 char buffer
[BUF_LEN
];
1069 chunk_t uri
= { buffer
, 7 + strlen(path
) };
1071 ca_info
->add_crl(ca_info
, crl
);
1072 if (uri
.len
< BUF_LEN
)
1074 snprintf(buffer
, BUF_LEN
, "file://%s", path
);
1075 ca_info
->add_crluri(ca_info
, uri
);
1081 iterator
->destroy(iterator
);
1086 DBG2(DBG_CFG
, " no issuing ca found for this crl - discarded");
1091 * Implements local_credential_store_t.load_crls
1093 static void load_crls(private_local_credential_store_t
*this)
1095 struct dirent
* entry
;
1100 DBG1(DBG_CFG
, "loading crls from '%s'", CRL_DIR
);
1102 dir
= opendir(CRL_DIR
);
1105 DBG1(DBG_CFG
, "error opening crl directory '%s'", CRL_DIR
);
1109 while ((entry
= readdir(dir
)) != NULL
)
1111 char file
[PATH_BUF
];
1113 snprintf(file
, sizeof(file
), "%s/%s", CRL_DIR
, entry
->d_name
);
1115 if (stat(file
, &stb
) == -1)
1119 /* try to parse all regular files */
1120 if (stb
.st_mode
& S_IFREG
)
1122 crl
= crl_create_from_file(file
);
1125 DBG1(DBG_CFG
, " crl is %s", crl
->is_valid(crl
)?
"valid":"stale");
1126 add_crl(this, crl
, file
);
1134 * Convert a string of characters into a binary secret
1135 * A string between single or double quotes is treated as ASCII characters
1136 * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
1138 static err_t
extract_secret(chunk_t
*secret
, chunk_t
*line
)
1141 char delimiter
= ' ';
1142 bool quotes
= FALSE
;
1144 if (!eat_whitespace(line
))
1146 return "missing secret";
1149 if (*line
->ptr
== '\'' || *line
->ptr
== '"')
1152 delimiter
= *line
->ptr
;
1153 line
->ptr
++; line
->len
--;
1156 if (!extract_token(&raw_secret
, delimiter
, line
))
1158 if (delimiter
== ' ')
1164 return "missing second delimiter";
1169 { /* treat as an ASCII string */
1170 if (raw_secret
.len
> secret
->len
)
1171 return "secret larger than buffer";
1172 memcpy(secret
->ptr
, raw_secret
.ptr
, raw_secret
.len
);
1173 secret
->len
= raw_secret
.len
;
1176 { /* convert from HEX or Base64 to binary */
1178 err_t ugh
= ttodata(raw_secret
.ptr
, raw_secret
.len
, 0, secret
->ptr
, secret
->len
, &len
);
1182 if (len
> secret
->len
)
1183 return "secret larger than buffer";
1190 * Implements local_credential_store_t.load_secrets
1192 static void load_secrets(private_local_credential_store_t
*this)
1194 FILE *fd
= fopen(SECRETS_FILE
, "r");
1200 chunk_t chunk
, src
, line
;
1202 DBG1(DBG_CFG
, "loading secrets from \"%s\"", SECRETS_FILE
);
1204 fseek(fd
, 0, SEEK_END
);
1205 chunk
.len
= ftell(fd
);
1207 chunk
.ptr
= malloc(chunk
.len
);
1208 bytes
= fread(chunk
.ptr
, 1, chunk
.len
, fd
);
1213 while (fetchline(&src
, &line
))
1216 bool is_eap
= FALSE
;
1220 if (!eat_whitespace(&line
))
1224 if (!extract_token(&ids
, ':', &line
))
1226 DBG1(DBG_CFG
, "line %d: missing ':' separator", line_nr
);
1229 /* NULL terminate the ids string by replacing the : separator */
1230 *(ids
.ptr
+ ids
.len
) = '\0';
1232 if (!eat_whitespace(&line
) || !extract_token(&token
, ' ', &line
))
1234 DBG1(DBG_CFG
, "line %d: missing token", line_nr
);
1237 if (match("RSA", &token
))
1239 char path
[PATH_BUF
];
1243 chunk_t secret
= { buf
, BUF_LEN
};
1244 chunk_t
*passphrase
= NULL
;
1246 rsa_private_key_t
*key
;
1248 err_t ugh
= extract_value(&filename
, &line
);
1252 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
1255 if (filename
.len
== 0)
1257 DBG1(DBG_CFG
, "line %d: empty filename", line_nr
);
1260 if (*filename
.ptr
== '/')
1262 /* absolute path name */
1263 snprintf(path
, sizeof(path
), "%.*s", filename
.len
, filename
.ptr
);
1267 /* relative path name */
1268 snprintf(path
, sizeof(path
), "%s/%.*s", PRIVATE_KEY_DIR
,
1269 filename
.len
, filename
.ptr
);
1272 /* check for optional passphrase */
1273 if (eat_whitespace(&line
))
1275 ugh
= extract_secret(&secret
, &line
);
1278 DBG1(DBG_CFG
, "line %d: malformed passphrase: %s", line_nr
, ugh
);
1282 passphrase
= &secret
;
1284 key
= rsa_private_key_create_from_file(path
, passphrase
);
1287 this->private_keys
->insert_last(this->private_keys
, (void*)key
);
1290 else if ( match("PSK", &token
) ||
1291 ((match("EAP", &token
) || match("XAUTH", &token
)) && (is_eap
= TRUE
)))
1293 shared_key_t
*shared_key
;
1296 chunk_t secret
= { buf
, BUF_LEN
};
1298 err_t ugh
= extract_secret(&secret
, &line
);
1301 DBG1(DBG_CFG
, "line %d: malformed secret: %s", line_nr
, ugh
);
1305 DBG1(DBG_CFG
, " loading %s key for %s",
1306 is_eap ?
"EAP" : "shared",
1307 ids
.len
> 0 ?
(char*)ids
.ptr
: "%any");
1309 DBG4(DBG_CFG
, " secret:", secret
);
1311 shared_key
= shared_key_create(secret
);
1316 this->eap_keys
->insert_last(this->eap_keys
, (void*)shared_key
);
1320 this->shared_keys
->insert_last(this->shared_keys
, (void*)shared_key
);
1326 identification_t
*peer_id
;
1328 ugh
= extract_value(&id
, &ids
);
1331 DBG1(DBG_CFG
, "line %d: %s", line_nr
, ugh
);
1339 /* NULL terminate the ID string */
1340 *(id
.ptr
+ id
.len
) = '\0';
1342 peer_id
= identification_create_from_string(id
.ptr
);
1343 if (peer_id
== NULL
)
1345 DBG1(DBG_CFG
, "line %d: malformed ID: %s", line_nr
, id
.ptr
);
1349 if (peer_id
->get_type(peer_id
) == ID_ANY
)
1351 peer_id
->destroy(peer_id
);
1354 shared_key
->peers
->insert_last(shared_key
->peers
, (void*)peer_id
);
1357 else if (match("PIN", &token
))
1363 DBG1(DBG_CFG
, "line %d: token must be either "
1364 "RSA, PSK, EAP, or PIN", line_nr
, token
.len
);
1373 DBG1(DBG_CFG
, "could not open file '%s'", SECRETS_FILE
);
1378 * Implementation of local_credential_store_t.destroy.
1380 static void destroy(private_local_credential_store_t
*this)
1382 this->certs
->destroy_offset(this->certs
, offsetof(x509_t
, destroy
));
1383 this->auth_certs
->destroy_offset(this->auth_certs
, offsetof(x509_t
, destroy
));
1384 this->ca_infos
->destroy_offset(this->ca_infos
, offsetof(ca_info_t
, destroy
));
1385 this->private_keys
->destroy_offset(this->private_keys
, offsetof(rsa_private_key_t
, destroy
));
1386 this->shared_keys
->destroy_function(this->shared_keys
, (void*)shared_key_destroy
);
1387 this->eap_keys
->destroy_function(this->eap_keys
, (void*)shared_key_destroy
);
1392 * Described in header.
1394 local_credential_store_t
* local_credential_store_create(bool strict
)
1396 private_local_credential_store_t
*this = malloc_thing(private_local_credential_store_t
);
1398 this->public.credential_store
.get_shared_key
= (status_t (*) (credential_store_t
*,identification_t
*,identification_t
*,chunk_t
*))get_shared_key
;
1399 this->public.credential_store
.get_eap_key
= (status_t (*) (credential_store_t
*,identification_t
*,identification_t
*,chunk_t
*))get_eap_key
;
1400 this->public.credential_store
.get_rsa_public_key
= (rsa_public_key_t
*(*)(credential_store_t
*,identification_t
*))get_rsa_public_key
;
1401 this->public.credential_store
.get_rsa_private_key
= (rsa_private_key_t
* (*) (credential_store_t
*,rsa_public_key_t
*))get_rsa_private_key
;
1402 this->public.credential_store
.has_rsa_private_key
= (bool (*) (credential_store_t
*,rsa_public_key_t
*))has_rsa_private_key
;
1403 this->public.credential_store
.get_trusted_public_key
= (rsa_public_key_t
*(*)(credential_store_t
*,identification_t
*))get_trusted_public_key
;
1404 this->public.credential_store
.get_certificate
= (x509_t
* (*) (credential_store_t
*,identification_t
*))get_certificate
;
1405 this->public.credential_store
.get_auth_certificate
= (x509_t
* (*) (credential_store_t
*,u_int
,identification_t
*))get_auth_certificate
;
1406 this->public.credential_store
.get_ca_certificate_by_keyid
= (x509_t
* (*) (credential_store_t
*,chunk_t
))get_ca_certificate_by_keyid
;
1407 this->public.credential_store
.get_issuer
= (ca_info_t
* (*) (credential_store_t
*,const x509_t
*))get_issuer
;
1408 this->public.credential_store
.is_trusted
= (bool (*) (credential_store_t
*,x509_t
*))is_trusted
;
1409 this->public.credential_store
.verify
= (bool (*) (credential_store_t
*,x509_t
*,bool*))verify
;
1410 this->public.credential_store
.add_end_certificate
= (x509_t
* (*) (credential_store_t
*,x509_t
*))add_end_certificate
;
1411 this->public.credential_store
.add_auth_certificate
= (x509_t
* (*) (credential_store_t
*,x509_t
*,u_int
))add_auth_certificate
;
1412 this->public.credential_store
.add_ca_info
= (void (*) (credential_store_t
*,ca_info_t
*))add_ca_info
;
1413 this->public.credential_store
.release_ca_info
= (status_t (*) (credential_store_t
*,const char*))release_ca_info
;
1414 this->public.credential_store
.create_cert_iterator
= (iterator_t
* (*) (credential_store_t
*))create_cert_iterator
;
1415 this->public.credential_store
.create_auth_cert_iterator
= (iterator_t
* (*) (credential_store_t
*))create_auth_cert_iterator
;
1416 this->public.credential_store
.create_cainfo_iterator
= (iterator_t
* (*) (credential_store_t
*))create_cainfo_iterator
;
1417 this->public.credential_store
.load_ca_certificates
= (void (*) (credential_store_t
*))load_ca_certificates
;
1418 this->public.credential_store
.load_aa_certificates
= (void (*) (credential_store_t
*))load_aa_certificates
;
1419 this->public.credential_store
.load_attr_certificates
= (void (*) (credential_store_t
*))load_attr_certificates
;
1420 this->public.credential_store
.load_ocsp_certificates
= (void (*) (credential_store_t
*))load_ocsp_certificates
;
1421 this->public.credential_store
.load_crls
= (void (*) (credential_store_t
*))load_crls
;
1422 this->public.credential_store
.load_secrets
= (void (*) (credential_store_t
*))load_secrets
;
1423 this->public.credential_store
.destroy
= (void (*) (credential_store_t
*))destroy
;
1425 /* private variables */
1426 this->shared_keys
= linked_list_create();
1427 this->eap_keys
= linked_list_create();
1428 this->private_keys
= linked_list_create();
1429 this->certs
= linked_list_create();
1430 this->auth_certs
= linked_list_create();
1431 this->ca_infos
= linked_list_create();
1432 this->strict
= strict
;
1434 return (&this->public);