bee7fce4bf7144a2ae76b882137e52a8991abba0
[strongswan.git] / src / charon / config / credentials / local_credential_store.c
1 /**
2 * @file local_credential_store.c
3 *
4 * @brief Implementation of local_credential_store_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23 #include <sys/stat.h>
24 #include <dirent.h>
25 #include <string.h>
26 #include <pthread.h>
27
28 #include <library.h>
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>
38
39 #include "local_credential_store.h"
40
41 #define PATH_BUF 256
42 #define MAX_CA_PATH_LEN 7
43
44 typedef struct shared_key_t shared_key_t;
45
46 /**
47 * Private date of a shared_key_t object
48 */
49 struct shared_key_t {
50
51 /**
52 * shared secret
53 */
54 chunk_t secret;
55
56 /**
57 * list of peer IDs
58 */
59 linked_list_t *peers;
60 };
61
62
63 /**
64 * Implementation of shared_key_t.destroy.
65 */
66 static void shared_key_destroy(shared_key_t *this)
67 {
68 this->peers->destroy_offset(this->peers, offsetof(identification_t, destroy));
69 chunk_free(&this->secret);
70 free(this);
71 }
72
73 /**
74 * @brief Creates a shared_key_t object.
75 *
76 * @param shared_key shared key value
77 * @return shared_key_t object
78 *
79 * @ingroup config
80 */
81 static shared_key_t *shared_key_create(chunk_t secret)
82 {
83 shared_key_t *this = malloc_thing(shared_key_t);
84
85 /* private data */
86 this->secret = chunk_clone(secret);
87 this->peers = linked_list_create();
88
89 return (this);
90 }
91
92 /* ------------------------------------------------------------------------ *
93 * the ca_info_t object as a central control element
94
95 +--------------------------------------------------------+
96 | local_credential_store_t |
97 +--------------------------------------------------------+
98 | |
99 +---------------------------+ +-------------------------+
100 | linked_list_t *auth_certs | | linked_list_t *ca_infos |
101 +---------------------------+ +-------------------------+
102 | |
103 | +------------------------- +
104 | | ca_info_t |
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 | +--------------------------+
129 | |
130
131 * ------------------------------------------------------------------------ */
132
133 typedef struct private_local_credential_store_t private_local_credential_store_t;
134
135 /**
136 * Private data of an local_credential_store_t object
137 */
138 struct private_local_credential_store_t {
139
140 /**
141 * Public part
142 */
143 local_credential_store_t public;
144
145 /**
146 * list of shared keys
147 */
148 linked_list_t *shared_keys;
149
150 /**
151 * list of EAP keys
152 */
153 linked_list_t *eap_keys;
154
155 /**
156 * list of key_entry_t's with private keys
157 */
158 linked_list_t *private_keys;
159
160 /**
161 * list of X.509 certificates with public keys
162 */
163 linked_list_t *certs;
164
165 /**
166 * list of X.509 authority certificates with public keys
167 */
168 linked_list_t *auth_certs;
169
170 /**
171 * list of X.509 CA information records
172 */
173 linked_list_t *ca_infos;
174
175 /**
176 * enforce strict crl policy
177 */
178 bool strict;
179 };
180
181
182 /**
183 * Get a key from a list with shared_key_t's
184 */
185 static status_t get_key(linked_list_t *keys,
186 identification_t *my_id,
187 identification_t *other_id, chunk_t *secret)
188 {
189 typedef enum {
190 PRIO_UNDEFINED= 0x00,
191 PRIO_ANY_MATCH= 0x01,
192 PRIO_MY_MATCH= 0x02,
193 PRIO_OTHER_MATCH= 0x04,
194 } prio_t;
195
196 prio_t best_prio = PRIO_UNDEFINED;
197 chunk_t found = chunk_empty;
198 shared_key_t *shared_key;
199
200 iterator_t *iterator = keys->create_iterator(keys, TRUE);
201
202 while (iterator->iterate(iterator, (void**)&shared_key))
203 {
204 iterator_t *peer_iterator;
205 identification_t *peer_id;
206 prio_t prio = PRIO_UNDEFINED;
207
208 peer_iterator = shared_key->peers->create_iterator(shared_key->peers, TRUE);
209
210 if (peer_iterator->get_count(peer_iterator) == 0)
211 {
212 /* this is a wildcard shared key */
213 prio = PRIO_ANY_MATCH;
214 }
215 else
216 {
217 while (peer_iterator->iterate(peer_iterator, (void**)&peer_id))
218 {
219 if (my_id->equals(my_id, peer_id))
220 {
221 prio |= PRIO_MY_MATCH;
222 }
223 if (other_id->equals(other_id, peer_id))
224 {
225 prio |= PRIO_OTHER_MATCH;
226 }
227 }
228 }
229 peer_iterator->destroy(peer_iterator);
230
231 if (prio > best_prio)
232 {
233 best_prio = prio;
234 found = shared_key->secret;
235 }
236 }
237 iterator->destroy(iterator);
238
239 if (best_prio == PRIO_UNDEFINED)
240 {
241 return NOT_FOUND;
242 }
243 else
244 {
245 *secret = chunk_clone(found);
246 return SUCCESS;
247 }
248 }
249
250
251 /**
252 * Implementation of local_credential_store_t.get_shared_key.
253 */
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)
257 {
258 return get_key(this->shared_keys, my_id, other_id, secret);
259 }
260
261 /**
262 * Implementation of local_credential_store_t.get_eap_key.
263 */
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)
267 {
268 return get_key(this->eap_keys, my_id, other_id, secret);
269 }
270
271 /**
272 * Implementation of credential_store_t.get_certificate.
273 */
274 static x509_t* get_certificate(private_local_credential_store_t *this,
275 identification_t *id)
276 {
277 x509_t *found = NULL;
278 x509_t *current_cert;
279
280 iterator_t *iterator = this->certs->create_iterator(this->certs, TRUE);
281
282 while (iterator->iterate(iterator, (void**)&current_cert))
283 {
284 if (id->equals(id, current_cert->get_subject(current_cert)) ||
285 current_cert->equals_subjectAltName(current_cert, id))
286 {
287 found = current_cert;
288 break;
289 }
290 }
291 iterator->destroy(iterator);
292 return found;
293 }
294
295 /**
296 * Implementation of local_credential_store_t.get_rsa_public_key.
297 */
298 static rsa_public_key_t *get_rsa_public_key(private_local_credential_store_t *this,
299 identification_t *id)
300 {
301 x509_t *cert = get_certificate(this, id);
302
303 return (cert == NULL)? NULL:cert->get_public_key(cert);
304 }
305
306 /**
307 * Implementation of local_credential_store_t.get_trusted_public_key.
308 */
309 static rsa_public_key_t *get_trusted_public_key(private_local_credential_store_t *this,
310 identification_t *id)
311 {
312 cert_status_t status;
313 err_t ugh;
314
315 x509_t *cert = get_certificate(this, id);
316
317 if (cert == NULL)
318 return NULL;
319
320 ugh = cert->is_valid(cert, NULL);
321 if (ugh != NULL)
322 {
323 DBG1(DBG_CFG, "certificate %s", ugh);
324 return NULL;
325 }
326
327 status = cert->get_status(cert);
328 if (status == CERT_REVOKED || status == CERT_UNTRUSTED || (this->strict && status != CERT_GOOD))
329 {
330 DBG1(DBG_CFG, "certificate status: %N", cert_status_names, status);
331 return NULL;
332 }
333 if (status == CERT_GOOD && cert->get_until(cert) < time(NULL))
334 {
335 DBG1(DBG_CFG, "certificate is good but crl is stale");
336 return NULL;
337 }
338
339 return cert->get_public_key(cert);
340 }
341
342 /**
343 * Implementation of local_credential_store_t.get_rsa_private_key.
344 */
345 static rsa_private_key_t *get_rsa_private_key(private_local_credential_store_t *this,
346 rsa_public_key_t *pubkey)
347 {
348 rsa_private_key_t *found = NULL, *current;
349
350 iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
351
352 while (iterator->iterate(iterator, (void**)&current))
353 {
354 if (current->belongs_to(current, pubkey))
355 {
356 found = current->clone(current);
357 break;
358 }
359 }
360 iterator->destroy(iterator);
361 return found;
362 }
363
364 /**
365 * Implementation of local_credential_store_t.has_rsa_private_key.
366 */
367 static bool has_rsa_private_key(private_local_credential_store_t *this, rsa_public_key_t *pubkey)
368 {
369 bool found = FALSE;
370 rsa_private_key_t *current;
371
372 iterator_t *iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
373
374 while (iterator->iterate(iterator, (void**)&current))
375 {
376 if (current->belongs_to(current, pubkey))
377 {
378 found = TRUE;
379 break;
380 }
381 }
382 iterator->destroy(iterator);
383 return found;
384 }
385
386 /**
387 * Implementation of credential_store_t.get_auth_certificate.
388 */
389 static x509_t* get_auth_certificate(private_local_credential_store_t *this,
390 u_int auth_flags,
391 identification_t *id)
392 {
393 x509_t *found = NULL;
394 x509_t *current_cert;
395
396 iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE);
397
398 while (iterator->iterate(iterator, (void**)&current_cert))
399 {
400 if (current_cert->has_authority_flag(current_cert, auth_flags)
401 && id->equals(id, current_cert->get_subject(current_cert)))
402 {
403 found = current_cert;
404 break;
405 }
406 }
407 iterator->destroy(iterator);
408
409 return found;
410 }
411
412 /**
413 * Implementation of credential_store_t.get_ca_certificate_by_keyid.
414 */
415 static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *this,
416 chunk_t keyid)
417 {
418 x509_t *found = NULL;
419 x509_t *current_cert;
420
421 iterator_t *iterator = this->auth_certs->create_iterator(this->auth_certs, TRUE);
422
423 while (iterator->iterate(iterator, (void**)&current_cert))
424 {
425 rsa_public_key_t *pubkey = current_cert->get_public_key(current_cert);
426
427 if (current_cert->has_authority_flag(current_cert, AUTH_CA)
428 && chunk_equals(keyid, pubkey->get_keyid(pubkey)))
429 {
430 found = current_cert;
431 break;
432 }
433 }
434 iterator->destroy(iterator);
435
436 return found;
437 }
438
439 /**
440 * Implementation of credential_store_t.get_issuer.
441 */
442 static ca_info_t* get_issuer(private_local_credential_store_t *this, const x509_t *cert)
443 {
444 ca_info_t *found = NULL;
445 ca_info_t *ca_info;
446
447 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
448
449 while (iterator->iterate(iterator, (void**)&ca_info))
450 {
451 if (ca_info->is_cert_issuer(ca_info, cert))
452 {
453 found = ca_info;
454 break;
455 }
456 }
457 iterator->destroy(iterator);
458
459 return found;
460 }
461
462 /**
463 * Find an exact copy of a certificate in a linked list
464 */
465 static x509_t* find_certificate(linked_list_t *certs, x509_t *cert)
466 {
467 x509_t *found_cert = NULL, *current_cert;
468
469 iterator_t *iterator = certs->create_iterator(certs, TRUE);
470
471 while (iterator->iterate(iterator, (void**)&current_cert))
472 {
473 if (cert->equals(cert, current_cert))
474 {
475 found_cert = current_cert;
476 break;
477 }
478 }
479 iterator->destroy(iterator);
480
481 return found_cert;
482 }
483
484 /**
485 * Adds crl and ocsp uris to the corresponding issuer info record
486 */
487 static void add_uris(ca_info_t *issuer, x509_t *cert)
488 {
489 iterator_t *iterator;
490 identification_t *uri;
491
492 /* add any crl distribution points to the issuer ca info record */
493 iterator = cert->create_crluri_iterator(cert);
494
495 while (iterator->iterate(iterator, (void**)&uri))
496 {
497 issuer->add_crluri(issuer, uri->get_encoding(uri));
498 }
499 iterator->destroy(iterator);
500
501 /* add any ocsp access points to the issuer ca info record */
502 iterator = cert->create_ocspuri_iterator(cert);
503
504 while (iterator->iterate(iterator, (void**)&uri))
505 {
506 issuer->add_ocspuri(issuer, uri->get_encoding(uri));
507 }
508 iterator->destroy(iterator);
509 }
510
511 /**
512 * Implementation of credential_store_t.is_trusted
513 */
514 static bool is_trusted(private_local_credential_store_t *this, x509_t *cert)
515 {
516 int pathlen;
517 time_t until = UNDEFINED_TIME;
518 x509_t *cert_to_be_trusted = cert;
519
520 DBG2(DBG_CFG, "establishing trust in certificate:");
521
522 for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
523 {
524 err_t ugh = NULL;
525 ca_info_t *issuer;
526 x509_t *issuer_cert;
527 rsa_public_key_t *issuer_public_key;
528 bool valid_signature;
529
530 DBG2(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
531 DBG2(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert));
532
533 ugh = cert->is_valid(cert, &until);
534 if (ugh != NULL)
535 {
536 DBG1(DBG_CFG, "certificate %s", ugh);
537 return FALSE;
538 }
539 DBG2(DBG_CFG, "certificate is valid");
540
541 issuer = get_issuer(this, cert);
542 if (issuer == NULL)
543 {
544 DBG1(DBG_CFG, "issuer not found");
545 return FALSE;
546 }
547 DBG2(DBG_CFG, "issuer found");
548
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);
552
553 if (!valid_signature)
554 {
555 DBG1(DBG_CFG, "certificate signature is invalid");
556 return FALSE;
557 }
558 DBG2(DBG_CFG, "certificate signature is valid");
559
560 /* check if cert is a self-signed root ca */
561 if (pathlen > 0 && cert->is_self_signed(cert))
562 {
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);
566 return TRUE;
567 }
568 else
569 {
570 /* go up one step in the trust chain */
571 cert = issuer_cert;
572 }
573 }
574 DBG1(DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
575 return FALSE;
576 }
577
578 /**
579 * Implementation of credential_store_t.verify.
580 */
581 static bool verify(private_local_credential_store_t *this, x509_t *cert, bool *found)
582 {
583 int pathlen;
584 time_t until = UNDEFINED_TIME;
585
586 x509_t *end_cert = cert;
587 x509_t *cert_copy = find_certificate(this->certs, end_cert);
588
589 DBG2(DBG_CFG, "verifying end entity certificate:");
590
591 *found = (cert_copy != NULL);
592 if (*found)
593 {
594 DBG2(DBG_CFG,
595 "end entitity certificate is already in credential store");
596 }
597
598 for (pathlen = 0; pathlen < MAX_CA_PATH_LEN; pathlen++)
599 {
600 err_t ugh = NULL;
601 ca_info_t *issuer;
602 x509_t *issuer_cert;
603 rsa_public_key_t *issuer_public_key;
604 bool valid_signature;
605
606 DBG1(DBG_CFG, "subject: '%D'", cert->get_subject(cert));
607 DBG1(DBG_CFG, "issuer: '%D'", cert->get_issuer(cert));
608
609 ugh = cert->is_valid(cert, &until);
610 if (ugh != NULL)
611 {
612 DBG1(DBG_CFG, "certificate %s", ugh);
613 return FALSE;
614 }
615 DBG2(DBG_CFG, "certificate is valid");
616
617 issuer = get_issuer(this, cert);
618 if (issuer == NULL)
619 {
620 DBG1(DBG_CFG, "issuer not found");
621 return FALSE;
622 }
623 DBG2(DBG_CFG, "issuer found");
624
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);
628
629 if (!valid_signature)
630 {
631 DBG1(DBG_CFG, "certificate signature is invalid");
632 return FALSE;
633 }
634 DBG2(DBG_CFG, "certificate signature is valid");
635
636 /* check if cert is a self-signed root ca */
637 if (pathlen > 0 && cert->is_self_signed(cert))
638 {
639 DBG1(DBG_CFG, "reached self-signed root ca");
640
641 /* set the definite status and trust interval of the end entity certificate */
642 end_cert->set_until(end_cert, until);
643 if (cert_copy)
644 {
645 cert_copy->set_status(cert_copy, end_cert->get_status(end_cert));
646 cert_copy->set_until(cert_copy, until);
647 }
648 return TRUE;
649 }
650 else
651 {
652 time_t nextUpdate;
653 cert_status_t status;
654 certinfo_t *certinfo = certinfo_create(cert->get_serialNumber(cert));
655
656 certinfo->set_nextUpdate(certinfo, until);
657
658 if (pathlen == 0)
659 {
660 /* add any crl and ocsp uris contained in the certificate under test */
661 add_uris(issuer, cert);
662 }
663
664 /* first check certificate revocation using ocsp */
665 status = issuer->verify_by_ocsp(issuer, certinfo, &this->public.credential_store);
666
667 /* if ocsp service is not available then fall back to crl */
668 if ((status == CERT_UNDEFINED) || (status == CERT_UNKNOWN && this->strict))
669 {
670 status = issuer->verify_by_crl(issuer, certinfo, CRL_DIR);
671 }
672
673 nextUpdate = certinfo->get_nextUpdate(certinfo);
674 cert->set_status(cert, status);
675
676 switch (status)
677 {
678 case CERT_GOOD:
679 /* set nextUpdate */
680 cert->set_until(cert, nextUpdate);
681
682 /* if status information is stale */
683 if (this->strict && nextUpdate < time(NULL))
684 {
685 DBG2(DBG_CFG, "certificate is good but status is stale");
686 certinfo->destroy(certinfo);
687 return FALSE;
688 }
689 DBG1(DBG_CFG, "certificate is good");
690
691 /* with strict crl policy the public key must have the same
692 * lifetime as the validity of the ocsp status or crl lifetime
693 */
694 if (this->strict && nextUpdate < until)
695 until = nextUpdate;
696 break;
697 case CERT_REVOKED:
698 {
699 time_t revocationTime = certinfo->get_revocationTime(certinfo);
700 DBG1(DBG_CFG,
701 "certificate was revoked on %T, reason: %N",
702 &revocationTime, crl_reason_names,
703 certinfo->get_revocationReason(certinfo));
704
705 /* set revocationTime */
706 cert->set_until(cert, revocationTime);
707
708 /* update status of end certificate in the credential store */
709 if (cert_copy)
710 {
711 if (pathlen > 0)
712 {
713 cert_copy->set_status(cert_copy, CERT_UNTRUSTED);
714 }
715 else
716 {
717 cert_copy->set_status(cert_copy, CERT_REVOKED);
718 cert_copy->set_until(cert_copy,
719 certinfo->get_revocationTime(certinfo));
720 }
721 }
722 certinfo->destroy(certinfo);
723 return FALSE;
724 }
725 case CERT_UNKNOWN:
726 case CERT_UNDEFINED:
727 default:
728 DBG1(DBG_CFG, "certificate status unknown");
729 if (this->strict)
730 {
731 /* update status of end certificate in the credential store */
732 if (cert_copy)
733 {
734 cert_copy->set_status(cert_copy, CERT_UNTRUSTED);
735 }
736 certinfo->destroy(certinfo);
737 return FALSE;
738 }
739 break;
740 }
741 certinfo->destroy(certinfo);
742 }
743 /* go up one step in the trust chain */
744 cert = issuer_cert;
745 }
746 DBG1(DBG_CFG, "maximum ca path length of %d levels exceeded", MAX_CA_PATH_LEN);
747 return FALSE;
748 }
749
750 /**
751 * Add a unique certificate to a linked list
752 */
753 static x509_t* add_certificate(linked_list_t *certs, x509_t *cert)
754 {
755 x509_t *found_cert = find_certificate(certs, cert);
756
757 if (found_cert)
758 {
759 /* add the authority flags */
760 found_cert->add_authority_flags(found_cert, cert->get_authority_flags(cert));
761
762 cert->destroy(cert);
763 return found_cert;
764 }
765 else
766 {
767 certs->insert_last(certs, (void*)cert);
768 return cert;
769 }
770 }
771
772 /**
773 * Add a unique ca info record to a linked list
774 */
775 static void add_ca_info(private_local_credential_store_t *this, ca_info_t *ca_info)
776 {
777 ca_info_t *current_ca_info;
778 ca_info_t *found_ca_info = NULL;
779
780 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
781
782 while (iterator->iterate(iterator, (void**)&current_ca_info))
783 {
784 if (current_ca_info->equals(current_ca_info, ca_info))
785 {
786 found_ca_info = current_ca_info;
787 break;
788 }
789 }
790 iterator->destroy(iterator);
791
792 if (found_ca_info)
793 {
794 current_ca_info->add_info(current_ca_info, ca_info);
795 ca_info->destroy(ca_info);
796 }
797 else
798 {
799 this->ca_infos->insert_last(this->ca_infos, (void*)ca_info);
800 }
801 }
802
803 /**
804 * Release ca info record of a given name
805 */
806 static status_t release_ca_info(private_local_credential_store_t *this, const char *name)
807 {
808 status_t status = NOT_FOUND;
809 ca_info_t *ca_info;
810
811 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
812
813 while (iterator->iterate(iterator, (void**)&ca_info))
814 {
815 if (ca_info->equals_name_release_info(ca_info, name))
816 {
817 status = SUCCESS;
818 break;
819 }
820 }
821 iterator->destroy(iterator);
822
823 return status;
824 }
825
826 /**
827 * Implements local_credential_store_t.add_end_certificate
828 */
829 static x509_t* add_end_certificate(private_local_credential_store_t *this, x509_t *cert)
830 {
831 x509_t *ret_cert = add_certificate(this->certs, cert);
832
833 /* add crl and ocsp uris the first time the certificate is added */
834 if (ret_cert == cert)
835 {
836 ca_info_t *issuer = get_issuer(this, cert);
837
838 if (issuer)
839 {
840 add_uris(issuer, cert);
841 }
842 }
843 return ret_cert;
844 }
845
846 /**
847 * Implements local_credential_store_t.add_auth_certificate
848 */
849 static x509_t* add_auth_certificate(private_local_credential_store_t *this, x509_t *cert, u_int auth_flags)
850 {
851 cert->add_authority_flags(cert, auth_flags);
852 return add_certificate(this->auth_certs, cert);
853 }
854
855 /**
856 * Implements local_credential_store_t.create_cert_iterator
857 */
858 static iterator_t* create_cert_iterator(private_local_credential_store_t *this)
859 {
860 return this->certs->create_iterator(this->certs, TRUE);
861 }
862
863 /**
864 * Implements local_credential_store_t.create_cacert_iterator
865 */
866 static iterator_t* create_auth_cert_iterator(private_local_credential_store_t *this)
867 {
868 return this->auth_certs->create_iterator(this->auth_certs, TRUE);
869 }
870
871 /**
872 * Implements local_credential_store_t.create_cainfo_iterator
873 */
874 static iterator_t* create_cainfo_iterator(private_local_credential_store_t *this)
875 {
876 return this->ca_infos->create_iterator(this->ca_infos, TRUE);
877 }
878
879 /**
880 * Implements local_credential_store_t.load_auth_certificates
881 */
882 static void load_auth_certificates(private_local_credential_store_t *this,
883 u_int auth_flag,
884 const char* label,
885 const char* path)
886 {
887 struct dirent* entry;
888 struct stat stb;
889 DIR* dir;
890
891 DBG1(DBG_CFG, "loading %s certificates from '%s'", label, path);
892
893 dir = opendir(path);
894 if (dir == NULL)
895 {
896 DBG1(DBG_CFG, "error opening %s certs directory '%s'", label, path);
897 return;
898 }
899
900 while ((entry = readdir(dir)) != NULL)
901 {
902 char file[PATH_BUF];
903
904 snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
905
906 if (stat(file, &stb) == -1)
907 {
908 continue;
909 }
910 /* try to parse all regular files */
911 if (stb.st_mode & S_IFREG)
912 {
913 x509_t *cert = x509_create_from_file(file, label);
914
915 if (cert)
916 {
917 err_t ugh = cert->is_valid(cert, NULL);
918
919 if (ugh != NULL)
920 {
921 DBG1(DBG_CFG, "warning: %s certificate %s", label, ugh);
922 }
923
924 if (auth_flag == AUTH_CA && !cert->is_ca(cert))
925 {
926 DBG1(DBG_CFG, " CA basic constraints flag not set, cert discarded");
927 cert->destroy(cert);
928 }
929 else
930 {
931 x509_t *ret_cert;
932
933 cert->add_authority_flags(cert, auth_flag);
934
935 ret_cert = add_certificate(this->auth_certs, cert);
936
937 if (auth_flag == AUTH_CA && ret_cert == cert)
938 {
939 ca_info_t *ca_info = ca_info_create(NULL, cert);
940
941 add_ca_info(this, ca_info);
942 }
943 }
944 }
945 }
946 }
947 closedir(dir);
948 }
949
950 /**
951 * Implements local_credential_store_t.load_ca_certificates
952 */
953 static void load_ca_certificates(private_local_credential_store_t *this)
954 {
955 load_auth_certificates(this, AUTH_CA, "ca", CA_CERTIFICATE_DIR);
956
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.
960 */
961 {
962 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
963 ca_info_t *ca_info;
964
965 while (iterator->iterate(iterator, (void **)&ca_info))
966 {
967 x509_t *cacert = ca_info->get_certificate(ca_info);
968 ca_info_t *issuer = get_issuer(this, cacert);
969
970 if (issuer)
971 {
972 add_uris(issuer, cacert);
973 }
974 }
975 iterator->destroy(iterator);
976 }
977 }
978
979 /**
980 * Implements local_credential_store_t.load_aa_certificates
981 */
982 static void load_aa_certificates(private_local_credential_store_t *this)
983 {
984 load_auth_certificates(this, AUTH_AA, "aa", AA_CERTIFICATE_DIR);
985 }
986
987 /**
988 * Add a unique attribute certificate to a linked list
989 */
990 static void add_attr_certificate(private_local_credential_store_t *this, x509ac_t *cert)
991 {
992 /* TODO add a new attribute certificate to the linked list */
993 }
994
995 /**
996 * Implements local_credential_store_t.load_attr_certificates
997 */
998 static void load_attr_certificates(private_local_credential_store_t *this)
999 {
1000 struct dirent* entry;
1001 struct stat stb;
1002 DIR* dir;
1003
1004 const char *path = ATTR_CERTIFICATE_DIR;
1005
1006 DBG1(DBG_CFG, "loading attribute certificates from '%s'", path);
1007
1008 dir = opendir(ATTR_CERTIFICATE_DIR);
1009 if (dir == NULL)
1010 {
1011 DBG1(DBG_CFG, "error opening attribute certs directory '%s'", path);
1012 return;
1013 }
1014
1015 while ((entry = readdir(dir)) != NULL)
1016 {
1017 char file[PATH_BUF];
1018
1019 snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
1020
1021 if (stat(file, &stb) == -1)
1022 {
1023 continue;
1024 }
1025 /* try to parse all regular files */
1026 if (stb.st_mode & S_IFREG)
1027 {
1028 x509ac_t *cert = x509ac_create_from_file(file);
1029
1030 if (cert)
1031 {
1032 err_t ugh = cert->is_valid(cert, NULL);
1033
1034 if (ugh != NULL)
1035 {
1036 DBG1(DBG_CFG, "warning: attribute certificate %s", ugh);
1037 }
1038 add_attr_certificate(this, cert);
1039 }
1040 }
1041 }
1042 closedir(dir);
1043
1044
1045 }
1046
1047 /**
1048 * Implements local_credential_store_t.load_ocsp_certificates
1049 */
1050 static void load_ocsp_certificates(private_local_credential_store_t *this)
1051 {
1052 load_auth_certificates(this, AUTH_OCSP, "ocsp", OCSP_CERTIFICATE_DIR);
1053 }
1054
1055 /**
1056 * Add the latest crl to the issuing ca
1057 */
1058 static void add_crl(private_local_credential_store_t *this, crl_t *crl, const char *path)
1059 {
1060 iterator_t *iterator = this->ca_infos->create_iterator(this->ca_infos, TRUE);
1061 ca_info_t *ca_info;
1062 bool found = FALSE;
1063
1064 while (iterator->iterate(iterator, (void**)&ca_info))
1065 {
1066 if (ca_info->is_crl_issuer(ca_info, crl))
1067 {
1068 char buffer[BUF_LEN];
1069 chunk_t uri = { buffer, 7 + strlen(path) };
1070
1071 ca_info->add_crl(ca_info, crl);
1072 if (uri.len < BUF_LEN)
1073 {
1074 snprintf(buffer, BUF_LEN, "file://%s", path);
1075 ca_info->add_crluri(ca_info, uri);
1076 }
1077 found = TRUE;
1078 break;
1079 }
1080 }
1081 iterator->destroy(iterator);
1082
1083 if (!found)
1084 {
1085 crl->destroy(crl);
1086 DBG2(DBG_CFG, " no issuing ca found for this crl - discarded");
1087 }
1088 }
1089
1090 /**
1091 * Implements local_credential_store_t.load_crls
1092 */
1093 static void load_crls(private_local_credential_store_t *this)
1094 {
1095 struct dirent* entry;
1096 struct stat stb;
1097 DIR* dir;
1098 crl_t *crl;
1099
1100 DBG1(DBG_CFG, "loading crls from '%s'", CRL_DIR);
1101
1102 dir = opendir(CRL_DIR);
1103 if (dir == NULL)
1104 {
1105 DBG1(DBG_CFG, "error opening crl directory '%s'", CRL_DIR);
1106 return;
1107 }
1108
1109 while ((entry = readdir(dir)) != NULL)
1110 {
1111 char file[PATH_BUF];
1112
1113 snprintf(file, sizeof(file), "%s/%s", CRL_DIR, entry->d_name);
1114
1115 if (stat(file, &stb) == -1)
1116 {
1117 continue;
1118 }
1119 /* try to parse all regular files */
1120 if (stb.st_mode & S_IFREG)
1121 {
1122 crl = crl_create_from_file(file);
1123 if (crl)
1124 {
1125 DBG1(DBG_CFG, " crl is %s", crl->is_valid(crl)? "valid":"stale");
1126 add_crl(this, crl, file);
1127 }
1128 }
1129 }
1130 closedir(dir);
1131 }
1132
1133 /**
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
1137 */
1138 static err_t extract_secret(chunk_t *secret, chunk_t *line)
1139 {
1140 chunk_t raw_secret;
1141 char delimiter = ' ';
1142 bool quotes = FALSE;
1143
1144 if (!eat_whitespace(line))
1145 {
1146 return "missing secret";
1147 }
1148
1149 if (*line->ptr == '\'' || *line->ptr == '"')
1150 {
1151 quotes = TRUE;
1152 delimiter = *line->ptr;
1153 line->ptr++; line->len--;
1154 }
1155
1156 if (!extract_token(&raw_secret, delimiter, line))
1157 {
1158 if (delimiter == ' ')
1159 {
1160 raw_secret = *line;
1161 }
1162 else
1163 {
1164 return "missing second delimiter";
1165 }
1166 }
1167
1168 if (quotes)
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;
1174 }
1175 else
1176 { /* convert from HEX or Base64 to binary */
1177 size_t len;
1178 err_t ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len);
1179
1180 if (ugh != NULL)
1181 return ugh;
1182 if (len > secret->len)
1183 return "secret larger than buffer";
1184 secret->len = len;
1185 }
1186 return NULL;
1187 }
1188
1189 /**
1190 * Implements local_credential_store_t.load_secrets
1191 */
1192 static void load_secrets(private_local_credential_store_t *this)
1193 {
1194 FILE *fd = fopen(SECRETS_FILE, "r");
1195
1196 if (fd)
1197 {
1198 int bytes;
1199 int line_nr = 0;
1200 chunk_t chunk, src, line;
1201
1202 DBG1(DBG_CFG, "loading secrets from \"%s\"", SECRETS_FILE);
1203
1204 fseek(fd, 0, SEEK_END);
1205 chunk.len = ftell(fd);
1206 rewind(fd);
1207 chunk.ptr = malloc(chunk.len);
1208 bytes = fread(chunk.ptr, 1, chunk.len, fd);
1209 fclose(fd);
1210
1211 src = chunk;
1212
1213 while (fetchline(&src, &line))
1214 {
1215 chunk_t ids, token;
1216 bool is_eap = FALSE;
1217
1218 line_nr++;
1219
1220 if (!eat_whitespace(&line))
1221 {
1222 continue;
1223 }
1224 if (!extract_token(&ids, ':', &line))
1225 {
1226 DBG1(DBG_CFG, "line %d: missing ':' separator", line_nr);
1227 goto error;
1228 }
1229 /* NULL terminate the ids string by replacing the : separator */
1230 *(ids.ptr + ids.len) = '\0';
1231
1232 if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line))
1233 {
1234 DBG1(DBG_CFG, "line %d: missing token", line_nr);
1235 goto error;
1236 }
1237 if (match("RSA", &token))
1238 {
1239 char path[PATH_BUF];
1240 chunk_t filename;
1241
1242 char buf[BUF_LEN];
1243 chunk_t secret = { buf, BUF_LEN };
1244 chunk_t *passphrase = NULL;
1245
1246 rsa_private_key_t *key;
1247
1248 err_t ugh = extract_value(&filename, &line);
1249
1250 if (ugh != NULL)
1251 {
1252 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
1253 goto error;
1254 }
1255 if (filename.len == 0)
1256 {
1257 DBG1(DBG_CFG, "line %d: empty filename", line_nr);
1258 goto error;
1259 }
1260 if (*filename.ptr == '/')
1261 {
1262 /* absolute path name */
1263 snprintf(path, sizeof(path), "%.*s", filename.len, filename.ptr);
1264 }
1265 else
1266 {
1267 /* relative path name */
1268 snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR,
1269 filename.len, filename.ptr);
1270 }
1271
1272 /* check for optional passphrase */
1273 if (eat_whitespace(&line))
1274 {
1275 ugh = extract_secret(&secret, &line);
1276 if (ugh != NULL)
1277 {
1278 DBG1(DBG_CFG, "line %d: malformed passphrase: %s", line_nr, ugh);
1279 goto error;
1280 }
1281 if (secret.len > 0)
1282 passphrase = &secret;
1283 }
1284 key = rsa_private_key_create_from_file(path, passphrase);
1285 if (key)
1286 {
1287 this->private_keys->insert_last(this->private_keys, (void*)key);
1288 }
1289 }
1290 else if ( match("PSK", &token) ||
1291 ((match("EAP", &token) || match("XAUTH", &token)) && (is_eap = TRUE)))
1292 {
1293 shared_key_t *shared_key;
1294
1295 char buf[BUF_LEN];
1296 chunk_t secret = { buf, BUF_LEN };
1297
1298 err_t ugh = extract_secret(&secret, &line);
1299 if (ugh != NULL)
1300 {
1301 DBG1(DBG_CFG, "line %d: malformed secret: %s", line_nr, ugh);
1302 goto error;
1303 }
1304
1305 DBG1(DBG_CFG, " loading %s key for %s",
1306 is_eap ? "EAP" : "shared",
1307 ids.len > 0 ? (char*)ids.ptr : "%any");
1308
1309 DBG4(DBG_CFG, " secret:", secret);
1310
1311 shared_key = shared_key_create(secret);
1312 if (shared_key)
1313 {
1314 if (is_eap)
1315 {
1316 this->eap_keys->insert_last(this->eap_keys, (void*)shared_key);
1317 }
1318 else
1319 {
1320 this->shared_keys->insert_last(this->shared_keys, (void*)shared_key);
1321 }
1322 }
1323 while (ids.len > 0)
1324 {
1325 chunk_t id;
1326 identification_t *peer_id;
1327
1328 ugh = extract_value(&id, &ids);
1329 if (ugh != NULL)
1330 {
1331 DBG1(DBG_CFG, "line %d: %s", line_nr, ugh);
1332 goto error;
1333 }
1334 if (id.len == 0)
1335 {
1336 continue;
1337 }
1338
1339 /* NULL terminate the ID string */
1340 *(id.ptr + id.len) = '\0';
1341
1342 peer_id = identification_create_from_string(id.ptr);
1343 if (peer_id == NULL)
1344 {
1345 DBG1(DBG_CFG, "line %d: malformed ID: %s", line_nr, id.ptr);
1346 goto error;
1347 }
1348
1349 if (peer_id->get_type(peer_id) == ID_ANY)
1350 {
1351 peer_id->destroy(peer_id);
1352 continue;
1353 }
1354 shared_key->peers->insert_last(shared_key->peers, (void*)peer_id);
1355 }
1356 }
1357 else if (match("PIN", &token))
1358 {
1359
1360 }
1361 else
1362 {
1363 DBG1(DBG_CFG, "line %d: token must be either "
1364 "RSA, PSK, EAP, or PIN", line_nr, token.len);
1365 goto error;
1366 }
1367 }
1368 error:
1369 free(chunk.ptr);
1370 }
1371 else
1372 {
1373 DBG1(DBG_CFG, "could not open file '%s'", SECRETS_FILE);
1374 }
1375 }
1376
1377 /**
1378 * Implementation of local_credential_store_t.destroy.
1379 */
1380 static void destroy(private_local_credential_store_t *this)
1381 {
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);
1388 free(this);
1389 }
1390
1391 /**
1392 * Described in header.
1393 */
1394 local_credential_store_t * local_credential_store_create(bool strict)
1395 {
1396 private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
1397
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;
1424
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;
1433
1434 return (&this->public);
1435 }