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