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