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