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