Merge branch 'charon-xpc'
[strongswan.git] / src / libstrongswan / credentials / credential_manager.c
1 /*
2 * Copyright (C) 2007 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "credential_manager.h"
17
18 #include <library.h>
19 #include <utils/debug.h>
20 #include <threading/thread_value.h>
21 #include <threading/mutex.h>
22 #include <threading/rwlock.h>
23 #include <collections/linked_list.h>
24 #include <credentials/sets/cert_cache.h>
25 #include <credentials/sets/auth_cfg_wrapper.h>
26 #include <credentials/certificates/x509.h>
27
28 /**
29 * Maximum length of a certificate trust chain
30 */
31 #define MAX_TRUST_PATH_LEN 7
32
33 typedef struct private_credential_manager_t private_credential_manager_t;
34
35 /**
36 * private data of credential_manager
37 */
38 struct private_credential_manager_t {
39
40 /**
41 * public functions
42 */
43 credential_manager_t public;
44
45 /**
46 * list of credential sets
47 */
48 linked_list_t *sets;
49
50 /**
51 * thread local set of credentials, linked_list_t with credential_set_t's
52 */
53 thread_value_t *local_sets;
54
55 /**
56 * Exclusive local sets, linked_list_t with credential_set_t
57 */
58 thread_value_t *exclusive_local_sets;
59
60 /**
61 * trust relationship and certificate cache
62 */
63 cert_cache_t *cache;
64
65 /**
66 * certificates queued for persistent caching
67 */
68 linked_list_t *cache_queue;
69
70 /**
71 * list of certificate validators, cert_validator_t
72 */
73 linked_list_t *validators;
74
75 /**
76 * read-write lock to sets list
77 */
78 rwlock_t *lock;
79
80 /**
81 * mutex for cache queue
82 */
83 mutex_t *queue_mutex;
84 };
85
86 /** data to pass to create_private_enumerator */
87 typedef struct {
88 private_credential_manager_t *this;
89 key_type_t type;
90 identification_t* keyid;
91 } private_data_t;
92
93 /** data to pass to create_cert_enumerator */
94 typedef struct {
95 private_credential_manager_t *this;
96 certificate_type_t cert;
97 key_type_t key;
98 identification_t *id;
99 bool trusted;
100 } cert_data_t;
101
102 /** data to pass to create_cdp_enumerator */
103 typedef struct {
104 private_credential_manager_t *this;
105 certificate_type_t type;
106 identification_t *id;
107 } cdp_data_t;
108
109 /** data to pass to create_shared_enumerator */
110 typedef struct {
111 private_credential_manager_t *this;
112 shared_key_type_t type;
113 identification_t *me;
114 identification_t *other;
115 } shared_data_t;
116
117 /** enumerator over local and global sets */
118 typedef struct {
119 /** implements enumerator_t */
120 enumerator_t public;
121 /** enumerator over global sets */
122 enumerator_t *global;
123 /** enumerator over local sets */
124 enumerator_t *local;
125 /** enumerator over exclusive local sets */
126 enumerator_t *exclusive;
127 } sets_enumerator_t;
128
129
130 METHOD(enumerator_t, sets_enumerate, bool,
131 sets_enumerator_t *this, credential_set_t **set)
132 {
133 if (this->exclusive)
134 {
135 if (this->exclusive->enumerate(this->exclusive, set))
136 { /* only enumerate last added */
137 this->exclusive->destroy(this->exclusive);
138 this->exclusive = NULL;
139 return TRUE;
140 }
141 }
142 if (this->global)
143 {
144 if (this->global->enumerate(this->global, set))
145 {
146 return TRUE;
147 }
148 /* end of global sets, look for local */
149 this->global->destroy(this->global);
150 this->global = NULL;
151 }
152 if (this->local)
153 {
154 return this->local->enumerate(this->local, set);
155 }
156 return FALSE;
157 }
158
159 METHOD(enumerator_t, sets_destroy, void,
160 sets_enumerator_t *this)
161 {
162 DESTROY_IF(this->global);
163 DESTROY_IF(this->local);
164 DESTROY_IF(this->exclusive);
165 free(this);
166 }
167
168 /**
169 * create an enumerator over both, global and local sets
170 */
171 static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
172 {
173 sets_enumerator_t *enumerator;
174 linked_list_t *list;
175
176 INIT(enumerator,
177 .public = {
178 .enumerate = (void*)_sets_enumerate,
179 .destroy = _sets_destroy,
180 },
181 );
182
183 list = this->exclusive_local_sets->get(this->exclusive_local_sets);
184 if (list && list->get_count(list))
185 {
186 enumerator->exclusive = list->create_enumerator(list);
187 }
188 else
189 {
190 enumerator->global = this->sets->create_enumerator(this->sets);
191 list = this->local_sets->get(this->local_sets);
192 if (list)
193 {
194 enumerator->local = list->create_enumerator(list);
195 }
196 }
197 return &enumerator->public;
198 }
199
200 /**
201 * cleanup function for cert data
202 */
203 static void destroy_cert_data(cert_data_t *data)
204 {
205 data->this->lock->unlock(data->this->lock);
206 free(data);
207 }
208
209 /**
210 * enumerator constructor for certificates
211 */
212 static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
213 {
214 return set->create_cert_enumerator(set, data->cert, data->key,
215 data->id, data->trusted);
216 }
217
218 METHOD(credential_manager_t, create_cert_enumerator, enumerator_t*,
219 private_credential_manager_t *this, certificate_type_t certificate,
220 key_type_t key, identification_t *id, bool trusted)
221 {
222 cert_data_t *data = malloc_thing(cert_data_t);
223 data->this = this;
224 data->cert = certificate;
225 data->key = key;
226 data->id = id;
227 data->trusted = trusted;
228
229 this->lock->read_lock(this->lock);
230 return enumerator_create_nested(create_sets_enumerator(this),
231 (void*)create_cert, data,
232 (void*)destroy_cert_data);
233 }
234
235 METHOD(credential_manager_t, get_cert, certificate_t*,
236 private_credential_manager_t *this, certificate_type_t cert, key_type_t key,
237 identification_t *id, bool trusted)
238 {
239 certificate_t *current, *found = NULL;
240 enumerator_t *enumerator;
241
242 enumerator = create_cert_enumerator(this, cert, key, id, trusted);
243 if (enumerator->enumerate(enumerator, &current))
244 {
245 /* TODO: best match? order by keyid, subject, sualtname */
246 found = current->get_ref(current);
247 }
248 enumerator->destroy(enumerator);
249 return found;
250 }
251
252
253 /**
254 * cleanup function for cdp data
255 */
256 static void destroy_cdp_data(cdp_data_t *data)
257 {
258 data->this->lock->unlock(data->this->lock);
259 free(data);
260 }
261
262 /**
263 * enumerator constructor for CDPs
264 */
265 static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
266 {
267 return set->create_cdp_enumerator(set, data->type, data->id);
268 }
269
270 METHOD(credential_manager_t, create_cdp_enumerator, enumerator_t*,
271 private_credential_manager_t *this, certificate_type_t type,
272 identification_t *id)
273 {
274 cdp_data_t *data;
275
276 INIT(data,
277 .this = this,
278 .type = type,
279 .id = id,
280 );
281 this->lock->read_lock(this->lock);
282 return enumerator_create_nested(create_sets_enumerator(this),
283 (void*)create_cdp, data,
284 (void*)destroy_cdp_data);
285 }
286
287 /**
288 * cleanup function for private data
289 */
290 static void destroy_private_data(private_data_t *data)
291 {
292 data->this->lock->unlock(data->this->lock);
293 free(data);
294 }
295
296 /**
297 * enumerator constructor for private keys
298 */
299 static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
300 {
301 return set->create_private_enumerator(set, data->type, data->keyid);
302 }
303
304 /**
305 * Create an enumerator over private keys
306 */
307 static enumerator_t *create_private_enumerator(
308 private_credential_manager_t *this, key_type_t key, identification_t *keyid)
309 {
310 private_data_t *data;
311
312 INIT(data,
313 .this = this,
314 .type = key,
315 .keyid = keyid,
316 );
317 this->lock->read_lock(this->lock);
318 return enumerator_create_nested(create_sets_enumerator(this),
319 (void*)create_private, data,
320 (void*)destroy_private_data);
321 }
322
323 /**
324 * Look up a private key by its key identifier
325 */
326 static private_key_t* get_private_by_keyid(private_credential_manager_t *this,
327 key_type_t key, identification_t *keyid)
328 {
329 private_key_t *found = NULL;
330 enumerator_t *enumerator;
331
332 enumerator = create_private_enumerator(this, key, keyid);
333 if (enumerator->enumerate(enumerator, &found))
334 {
335 found->get_ref(found);
336 }
337 enumerator->destroy(enumerator);
338 return found;
339 }
340
341 /**
342 * cleanup function for shared data
343 */
344 static void destroy_shared_data(shared_data_t *data)
345 {
346 data->this->lock->unlock(data->this->lock);
347 free(data);
348 }
349
350 /**
351 * enumerator constructor for shared keys
352 */
353 static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
354 {
355 return set->create_shared_enumerator(set, data->type, data->me, data->other);
356 }
357
358 METHOD(credential_manager_t, create_shared_enumerator, enumerator_t*,
359 private_credential_manager_t *this, shared_key_type_t type,
360 identification_t *me, identification_t *other)
361 {
362 shared_data_t *data;
363
364 INIT(data,
365 .this = this,
366 .type = type,
367 .me = me,
368 .other = other,
369 );
370 this->lock->read_lock(this->lock);
371 return enumerator_create_nested(create_sets_enumerator(this),
372 (void*)create_shared, data,
373 (void*)destroy_shared_data);
374 }
375
376 METHOD(credential_manager_t, get_shared, shared_key_t*,
377 private_credential_manager_t *this, shared_key_type_t type,
378 identification_t *me, identification_t *other)
379 {
380 shared_key_t *current, *found = NULL;
381 id_match_t best_me = ID_MATCH_NONE, best_other = ID_MATCH_NONE;
382 id_match_t match_me, match_other;
383 enumerator_t *enumerator;
384
385 enumerator = create_shared_enumerator(this, type, me, other);
386 while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
387 {
388 if (match_other > best_other ||
389 (match_other == best_other && match_me > best_me))
390 {
391 DESTROY_IF(found);
392 found = current->get_ref(current);
393 best_me = match_me;
394 best_other = match_other;
395 }
396 if (best_me == ID_MATCH_PERFECT && best_other == ID_MATCH_PERFECT)
397 {
398 break;
399 }
400 }
401 enumerator->destroy(enumerator);
402 return found;
403 }
404
405 METHOD(credential_manager_t, add_local_set, void,
406 private_credential_manager_t *this, credential_set_t *set, bool exclusive)
407 {
408 linked_list_t *sets;
409 thread_value_t *tv;
410
411 if (exclusive)
412 {
413 tv = this->exclusive_local_sets;
414 }
415 else
416 {
417 tv = this->local_sets;
418 }
419 sets = tv->get(tv);
420 if (!sets)
421 {
422 sets = linked_list_create();
423 tv->set(tv, sets);
424 }
425 if (exclusive)
426 {
427 sets->insert_first(sets, set);
428 }
429 else
430 {
431 sets->insert_last(sets, set);
432 }
433 }
434
435 METHOD(credential_manager_t, remove_local_set, void,
436 private_credential_manager_t *this, credential_set_t *set)
437 {
438 linked_list_t *sets;
439 thread_value_t *tv;
440
441 tv = this->local_sets;
442 sets = tv->get(tv);
443 if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
444 {
445 tv->set(tv, NULL);
446 sets->destroy(sets);
447 }
448 tv = this->exclusive_local_sets;
449 sets = tv->get(tv);
450 if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
451 {
452 tv->set(tv, NULL);
453 sets->destroy(sets);
454 }
455 }
456
457 METHOD(credential_manager_t, issued_by, bool,
458 private_credential_manager_t *this, certificate_t *subject,
459 certificate_t *issuer, signature_scheme_t *scheme)
460 {
461 if (this->cache)
462 {
463 return this->cache->issued_by(this->cache, subject, issuer, scheme);
464 }
465 return subject->issued_by(subject, issuer, scheme);
466 }
467
468 METHOD(credential_manager_t, cache_cert, void,
469 private_credential_manager_t *this, certificate_t *cert)
470 {
471 credential_set_t *set;
472 enumerator_t *enumerator;
473
474 if (this->lock->try_write_lock(this->lock))
475 {
476 enumerator = this->sets->create_enumerator(this->sets);
477 while (enumerator->enumerate(enumerator, &set))
478 {
479 set->cache_cert(set, cert);
480 }
481 enumerator->destroy(enumerator);
482 this->lock->unlock(this->lock);
483 }
484 else
485 { /* we can't cache now as other threads are active, queue for later */
486 this->queue_mutex->lock(this->queue_mutex);
487 this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
488 this->queue_mutex->unlock(this->queue_mutex);
489 }
490 }
491
492 /**
493 * Try to cache certificates queued for caching
494 */
495 static void cache_queue(private_credential_manager_t *this)
496 {
497 credential_set_t *set;
498 certificate_t *cert;
499 enumerator_t *enumerator;
500
501 this->queue_mutex->lock(this->queue_mutex);
502 if (this->cache_queue->get_count(this->cache_queue) > 0 &&
503 this->lock->try_write_lock(this->lock))
504 {
505 while (this->cache_queue->remove_last(this->cache_queue,
506 (void**)&cert) == SUCCESS)
507 {
508 enumerator = this->sets->create_enumerator(this->sets);
509 while (enumerator->enumerate(enumerator, &set))
510 {
511 set->cache_cert(set, cert);
512 }
513 enumerator->destroy(enumerator);
514 cert->destroy(cert);
515 }
516 this->lock->unlock(this->lock);
517 }
518 this->queue_mutex->unlock(this->queue_mutex);
519 }
520
521 /**
522 * Use validators to check the lifetime of certificates
523 */
524 static bool check_lifetime(private_credential_manager_t *this,
525 certificate_t *cert, char *label,
526 int pathlen, bool trusted, auth_cfg_t *auth)
527 {
528 time_t not_before, not_after;
529 cert_validator_t *validator;
530 enumerator_t *enumerator;
531 status_t status = NEED_MORE;
532
533 enumerator = this->validators->create_enumerator(this->validators);
534 while (enumerator->enumerate(enumerator, &validator))
535 {
536 if (!validator->check_lifetime)
537 {
538 continue;
539 }
540 status = validator->check_lifetime(validator, cert,
541 pathlen, trusted, auth);
542 if (status != NEED_MORE)
543 {
544 break;
545 }
546 }
547 enumerator->destroy(enumerator);
548
549 switch (status)
550 {
551 case NEED_MORE:
552 if (!cert->get_validity(cert, NULL, &not_before, &not_after))
553 {
554 DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)",
555 label, &not_before, FALSE, &not_after, FALSE);
556 return FALSE;
557 }
558 return TRUE;
559 case SUCCESS:
560 return TRUE;
561 case FAILED:
562 default:
563 return FALSE;
564 }
565 }
566
567 /**
568 * check a certificate for its lifetime
569 */
570 static bool check_certificate(private_credential_manager_t *this,
571 certificate_t *subject, certificate_t *issuer, bool online,
572 int pathlen, bool trusted, auth_cfg_t *auth)
573 {
574 cert_validator_t *validator;
575 enumerator_t *enumerator;
576
577 if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) ||
578 !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth))
579 {
580 return FALSE;
581 }
582
583 enumerator = this->validators->create_enumerator(this->validators);
584 while (enumerator->enumerate(enumerator, &validator))
585 {
586 if (!validator->validate)
587 {
588 continue;
589 }
590 if (!validator->validate(validator, subject, issuer,
591 online, pathlen, trusted, auth))
592 {
593 enumerator->destroy(enumerator);
594 return FALSE;
595 }
596 }
597 enumerator->destroy(enumerator);
598 return TRUE;
599 }
600
601 /**
602 * Get a trusted certificate from a credential set
603 */
604 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
605 key_type_t type, identification_t *id)
606 {
607 certificate_t *subject;
608 public_key_t *public;
609
610 subject = get_cert(this, CERT_ANY, type, id, TRUE);
611 if (!subject)
612 {
613 return NULL;
614 }
615 public = subject->get_public_key(subject);
616 if (!public)
617 {
618 subject->destroy(subject);
619 return NULL;
620 }
621 public->destroy(public);
622 return subject;
623 }
624
625 /**
626 * Get the issuing certificate of a subject certificate
627 */
628 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
629 certificate_t *subject, bool trusted,
630 signature_scheme_t *scheme)
631 {
632 enumerator_t *enumerator;
633 certificate_t *issuer = NULL, *candidate;
634
635 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
636 subject->get_issuer(subject), trusted);
637 while (enumerator->enumerate(enumerator, &candidate))
638 {
639 if (issued_by(this, subject, candidate, scheme))
640 {
641 issuer = candidate->get_ref(candidate);
642 break;
643 }
644 }
645 enumerator->destroy(enumerator);
646 return issuer;
647 }
648
649 /**
650 * Get the strength of certificate, add it to auth
651 */
652 static void get_key_strength(certificate_t *cert, auth_cfg_t *auth)
653 {
654 uintptr_t strength;
655 public_key_t *key;
656 key_type_t type;
657
658 key = cert->get_public_key(cert);
659 if (key)
660 {
661 type = key->get_type(key);
662 strength = key->get_keysize(key);
663 DBG2(DBG_CFG, " certificate \"%Y\" key: %d bit %N",
664 cert->get_subject(cert), strength, key_type_names, type);
665 switch (type)
666 {
667 case KEY_RSA:
668 auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength);
669 break;
670 case KEY_ECDSA:
671 auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength);
672 break;
673 default:
674 break;
675 }
676 key->destroy(key);
677 }
678 }
679
680 /**
681 * try to verify the trust chain of subject, return TRUE if trusted
682 */
683 static bool verify_trust_chain(private_credential_manager_t *this,
684 certificate_t *subject, auth_cfg_t *result,
685 bool trusted, bool online)
686 {
687 certificate_t *current, *issuer;
688 auth_cfg_t *auth;
689 signature_scheme_t scheme;
690 int pathlen;
691
692 auth = auth_cfg_create();
693 get_key_strength(subject, auth);
694 current = subject->get_ref(subject);
695 auth->add(auth, AUTH_RULE_SUBJECT_CERT, current->get_ref(current));
696
697 for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++)
698 {
699 issuer = get_issuer_cert(this, current, TRUE, &scheme);
700 if (issuer)
701 {
702 /* accept only self-signed CAs as trust anchor */
703 if (issued_by(this, issuer, issuer, NULL))
704 {
705 auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
706 DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
707 issuer->get_subject(issuer));
708 trusted = TRUE;
709 }
710 else
711 {
712 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
713 DBG1(DBG_CFG, " using trusted intermediate ca certificate "
714 "\"%Y\"", issuer->get_subject(issuer));
715 }
716 auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
717 }
718 else
719 {
720 issuer = get_issuer_cert(this, current, FALSE, &scheme);
721 if (issuer)
722 {
723 if (current->equals(current, issuer))
724 {
725 DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
726 current->get_subject(current));
727 issuer->destroy(issuer);
728 break;
729 }
730 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
731 DBG1(DBG_CFG, " using untrusted intermediate certificate "
732 "\"%Y\"", issuer->get_subject(issuer));
733 auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
734 }
735 else
736 {
737 DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
738 current->get_subject(current));
739 break;
740 }
741 }
742 if (!check_certificate(this, current, issuer, online,
743 pathlen, trusted, auth))
744 {
745 trusted = FALSE;
746 issuer->destroy(issuer);
747 break;
748 }
749 if (issuer)
750 {
751 get_key_strength(issuer, auth);
752 }
753 current->destroy(current);
754 current = issuer;
755 if (trusted)
756 {
757 DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d",
758 pathlen);
759 break;
760 }
761 }
762 current->destroy(current);
763 if (pathlen > MAX_TRUST_PATH_LEN)
764 {
765 DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN);
766 }
767 if (trusted)
768 {
769 result->merge(result, auth, FALSE);
770 }
771 auth->destroy(auth);
772 return trusted;
773 }
774
775 /**
776 * List find match function for certificates
777 */
778 static bool cert_equals(certificate_t *a, certificate_t *b)
779 {
780 return a->equals(a, b);
781 }
782
783 /**
784 * enumerator for trusted certificates
785 */
786 typedef struct {
787 /** implements enumerator_t interface */
788 enumerator_t public;
789 /** enumerator over candidate peer certificates */
790 enumerator_t *candidates;
791 /** reference to the credential_manager */
792 private_credential_manager_t *this;
793 /** type of the requested key */
794 key_type_t type;
795 /** identity the requested key belongs to */
796 identification_t *id;
797 /** TRUE to do CRL/OCSP checking */
798 bool online;
799 /** pretrusted certificate we have served at first invocation */
800 certificate_t *pretrusted;
801 /** currently enumerating auth config */
802 auth_cfg_t *auth;
803 /** list of failed candidates */
804 linked_list_t *failed;
805 } trusted_enumerator_t;
806
807 METHOD(enumerator_t, trusted_enumerate, bool,
808 trusted_enumerator_t *this, certificate_t **cert, auth_cfg_t **auth)
809 {
810 certificate_t *current;
811
812 DESTROY_IF(this->auth);
813 this->auth = auth_cfg_create();
814
815 if (!this->candidates)
816 {
817 /* first invocation, build enumerator for next one */
818 this->candidates = create_cert_enumerator(this->this, CERT_ANY,
819 this->type, this->id, FALSE);
820 /* check if we have a trusted certificate for that peer */
821 this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
822 if (this->pretrusted)
823 {
824 /* if we find a trusted self signed certificate, we just accept it.
825 * However, in order to fulfill authorization rules, we try to build
826 * the trust chain if it is not self signed */
827 if (issued_by(this->this, this->pretrusted, this->pretrusted, NULL) ||
828 verify_trust_chain(this->this, this->pretrusted, this->auth,
829 TRUE, this->online))
830 {
831 DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
832 this->pretrusted->get_subject(this->pretrusted));
833 *cert = this->pretrusted;
834 if (!this->auth->get(this->auth, AUTH_RULE_SUBJECT_CERT))
835 { /* add cert to auth info, if not returned by trustchain */
836 this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
837 this->pretrusted->get_ref(this->pretrusted));
838 }
839 if (auth)
840 {
841 *auth = this->auth;
842 }
843 return TRUE;
844 }
845 }
846 }
847 /* try to verify the trust chain for each certificate found */
848 while (this->candidates->enumerate(this->candidates, &current))
849 {
850 if (this->pretrusted &&
851 this->pretrusted->equals(this->pretrusted, current))
852 { /* skip pretrusted certificate we already served */
853 continue;
854 }
855
856 if (this->failed->find_first(this->failed, (void*)cert_equals,
857 NULL, current) == SUCCESS)
858 { /* check each candidate only once */
859 continue;
860 }
861
862 DBG1(DBG_CFG, " using certificate \"%Y\"",
863 current->get_subject(current));
864 if (verify_trust_chain(this->this, current, this->auth, FALSE,
865 this->online))
866 {
867 *cert = current;
868 if (auth)
869 {
870 *auth = this->auth;
871 }
872 return TRUE;
873 }
874 this->failed->insert_last(this->failed, current->get_ref(current));
875 }
876 return FALSE;
877 }
878
879 METHOD(enumerator_t, trusted_destroy, void,
880 trusted_enumerator_t *this)
881 {
882 DESTROY_IF(this->pretrusted);
883 DESTROY_IF(this->auth);
884 DESTROY_IF(this->candidates);
885 this->failed->destroy_offset(this->failed, offsetof(certificate_t, destroy));
886 free(this);
887 }
888
889 METHOD(credential_manager_t, create_trusted_enumerator, enumerator_t*,
890 private_credential_manager_t *this, key_type_t type,
891 identification_t *id, bool online)
892 {
893 trusted_enumerator_t *enumerator;
894
895 INIT(enumerator,
896 .public = {
897 .enumerate = (void*)_trusted_enumerate,
898 .destroy = _trusted_destroy,
899 },
900 .this = this,
901 .type = type,
902 .id = id,
903 .online = online,
904 .failed = linked_list_create(),
905 );
906 return &enumerator->public;
907 }
908
909 /**
910 * enumerator for public keys
911 */
912 typedef struct {
913 /** implements enumerator_t interface */
914 enumerator_t public;
915 /** enumerator over candidate peer certificates */
916 enumerator_t *inner;
917 /** reference to the credential_manager */
918 private_credential_manager_t *this;
919 /** currently enumerating key */
920 public_key_t *current;
921 /** credset wrapper around auth config */
922 auth_cfg_wrapper_t *wrapper;
923 } public_enumerator_t;
924
925 METHOD(enumerator_t, public_enumerate, bool,
926 public_enumerator_t *this, public_key_t **key, auth_cfg_t **auth)
927 {
928 certificate_t *cert;
929
930 while (this->inner->enumerate(this->inner, &cert, auth))
931 {
932 DESTROY_IF(this->current);
933 this->current = cert->get_public_key(cert);
934 if (this->current)
935 {
936 *key = this->current;
937 return TRUE;
938 }
939 }
940 return FALSE;
941 }
942
943 METHOD(enumerator_t, public_destroy, void,
944 public_enumerator_t *this)
945 {
946 DESTROY_IF(this->current);
947 this->inner->destroy(this->inner);
948 if (this->wrapper)
949 {
950 remove_local_set(this->this, &this->wrapper->set);
951 this->wrapper->destroy(this->wrapper);
952 }
953 this->this->lock->unlock(this->this->lock);
954
955 /* check for delayed certificate cache queue */
956 cache_queue(this->this);
957 free(this);
958 }
959
960 METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
961 private_credential_manager_t *this, key_type_t type, identification_t *id,
962 auth_cfg_t *auth)
963 {
964 public_enumerator_t *enumerator;
965
966 INIT(enumerator,
967 .public = {
968 .enumerate = (void*)_public_enumerate,
969 .destroy = _public_destroy,
970 },
971 .inner = create_trusted_enumerator(this, type, id, TRUE),
972 .this = this,
973 );
974 if (auth)
975 {
976 enumerator->wrapper = auth_cfg_wrapper_create(auth);
977 add_local_set(this, &enumerator->wrapper->set, FALSE);
978 }
979 this->lock->read_lock(this->lock);
980 return &enumerator->public;
981 }
982
983 /**
984 * Check if a helper contains a certificate as trust anchor
985 */
986 static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
987 {
988 enumerator_t *enumerator;
989 identification_t *value;
990 auth_rule_t type;
991 bool found = FALSE;
992
993 enumerator = auth->create_enumerator(auth);
994 while (enumerator->enumerate(enumerator, &type, &value))
995 {
996 if (type == AUTH_RULE_CA_CERT &&
997 cert->equals(cert, (certificate_t*)value))
998 {
999 found = TRUE;
1000 break;
1001 }
1002 }
1003 enumerator->destroy(enumerator);
1004 return found;
1005 }
1006
1007 /**
1008 * build a trustchain from subject up to a trust anchor in trusted
1009 */
1010 static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
1011 certificate_t *subject, auth_cfg_t *auth)
1012 {
1013 certificate_t *issuer, *current;
1014 auth_cfg_t *trustchain;
1015 int pathlen = 0;
1016 bool has_anchor;
1017
1018 trustchain = auth_cfg_create();
1019 has_anchor = auth->get(auth, AUTH_RULE_CA_CERT) != NULL;
1020 current = subject->get_ref(subject);
1021 while (TRUE)
1022 {
1023 if (auth_contains_cacert(auth, current))
1024 {
1025 trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
1026 return trustchain;
1027 }
1028 if (subject == current)
1029 {
1030 trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
1031 }
1032 else
1033 {
1034 if (!has_anchor && issued_by(this, current, current, NULL))
1035 { /* If no trust anchor specified, accept any CA */
1036 trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
1037 return trustchain;
1038 }
1039 trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
1040 }
1041 if (pathlen++ > MAX_TRUST_PATH_LEN)
1042 {
1043 break;
1044 }
1045 issuer = get_issuer_cert(this, current, FALSE, NULL);
1046 if (!issuer)
1047 {
1048 if (!has_anchor)
1049 { /* If no trust anchor specified, accept incomplete chains */
1050 return trustchain;
1051 }
1052 break;
1053 }
1054 if (has_anchor && issuer->equals(issuer, current))
1055 {
1056 issuer->destroy(issuer);
1057 break;
1058 }
1059 current = issuer;
1060 }
1061 trustchain->destroy(trustchain);
1062 return NULL;
1063 }
1064
1065 /**
1066 * find a private key of a given certificate
1067 */
1068 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1069 certificate_t *cert, key_type_t type)
1070 {
1071 private_key_t *private = NULL;
1072 identification_t *keyid;
1073 chunk_t chunk;
1074 public_key_t *public;
1075
1076 public = cert->get_public_key(cert);
1077 if (public)
1078 {
1079 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
1080 {
1081 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
1082 private = get_private_by_keyid(this, type, keyid);
1083 keyid->destroy(keyid);
1084 }
1085 public->destroy(public);
1086 }
1087 return private;
1088 }
1089
1090 /**
1091 * Move the actually used certificate to front, so it gets returned with get()
1092 */
1093 static void prefer_cert(auth_cfg_t *auth, certificate_t *cert)
1094 {
1095 enumerator_t *enumerator;
1096 auth_rule_t rule;
1097 certificate_t *current;
1098
1099 enumerator = auth->create_enumerator(auth);
1100 while (enumerator->enumerate(enumerator, &rule, &current))
1101 {
1102 if (rule == AUTH_RULE_SUBJECT_CERT)
1103 {
1104 current->get_ref(current);
1105 auth->replace(auth, enumerator, AUTH_RULE_SUBJECT_CERT, cert);
1106 cert = current;
1107 }
1108 }
1109 enumerator->destroy(enumerator);
1110 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert);
1111 }
1112
1113 METHOD(credential_manager_t, get_private, private_key_t*,
1114 private_credential_manager_t *this, key_type_t type, identification_t *id,
1115 auth_cfg_t *auth)
1116 {
1117 enumerator_t *enumerator;
1118 certificate_t *cert;
1119 private_key_t *private = NULL;
1120 auth_cfg_t *trustchain;
1121 auth_rule_t rule;
1122
1123 /* check if this is a lookup by key ID, and do it if so */
1124 if (id && id->get_type(id) == ID_KEY_ID)
1125 {
1126 private = get_private_by_keyid(this, type, id);
1127 if (private)
1128 {
1129 return private;
1130 }
1131 }
1132
1133 if (auth)
1134 {
1135 /* try to find a trustchain with one of the configured subject certs */
1136 enumerator = auth->create_enumerator(auth);
1137 while (enumerator->enumerate(enumerator, &rule, &cert))
1138 {
1139 if (rule == AUTH_RULE_SUBJECT_CERT)
1140 {
1141 private = get_private_by_cert(this, cert, type);
1142 if (private)
1143 {
1144 trustchain = build_trustchain(this, cert, auth);
1145 if (trustchain)
1146 {
1147 auth->merge(auth, trustchain, FALSE);
1148 prefer_cert(auth, cert->get_ref(cert));
1149 trustchain->destroy(trustchain);
1150 break;
1151 }
1152 private->destroy(private);
1153 private = NULL;
1154 }
1155 }
1156 }
1157 enumerator->destroy(enumerator);
1158 if (private)
1159 {
1160 return private;
1161 }
1162
1163 /* if none yielded a trustchain, enforce the first configured cert */
1164 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
1165 if (cert)
1166 {
1167 private = get_private_by_cert(this, cert, type);
1168 if (private)
1169 {
1170 trustchain = build_trustchain(this, cert, auth);
1171 if (trustchain)
1172 {
1173 auth->merge(auth, trustchain, FALSE);
1174 trustchain->destroy(trustchain);
1175 }
1176 return private;
1177 }
1178 }
1179
1180 /* try to build a trust chain for each certificate found */
1181 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1182 while (enumerator->enumerate(enumerator, &cert))
1183 {
1184 private = get_private_by_cert(this, cert, type);
1185 if (private)
1186 {
1187 trustchain = build_trustchain(this, cert, auth);
1188 if (trustchain)
1189 {
1190 auth->merge(auth, trustchain, FALSE);
1191 trustchain->destroy(trustchain);
1192 break;
1193 }
1194 private->destroy(private);
1195 private = NULL;
1196 }
1197 }
1198 enumerator->destroy(enumerator);
1199 }
1200
1201 /* if no valid trustchain was found, fall back to the first usable cert */
1202 if (!private)
1203 {
1204 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1205 while (enumerator->enumerate(enumerator, &cert))
1206 {
1207 private = get_private_by_cert(this, cert, type);
1208 if (private)
1209 {
1210 if (auth)
1211 {
1212 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
1213 }
1214 break;
1215 }
1216 }
1217 enumerator->destroy(enumerator);
1218 }
1219 return private;
1220 }
1221
1222 METHOD(credential_manager_t, flush_cache, void,
1223 private_credential_manager_t *this, certificate_type_t type)
1224 {
1225 if (this->cache)
1226 {
1227 this->cache->flush(this->cache, type);
1228 }
1229 }
1230
1231 METHOD(credential_manager_t, add_set, void,
1232 private_credential_manager_t *this, credential_set_t *set)
1233 {
1234 this->lock->write_lock(this->lock);
1235 this->sets->insert_last(this->sets, set);
1236 this->lock->unlock(this->lock);
1237 }
1238
1239 METHOD(credential_manager_t, remove_set, void,
1240 private_credential_manager_t *this, credential_set_t *set)
1241 {
1242 this->lock->write_lock(this->lock);
1243 this->sets->remove(this->sets, set, NULL);
1244 this->lock->unlock(this->lock);
1245 }
1246
1247 METHOD(credential_manager_t, add_validator, void,
1248 private_credential_manager_t *this, cert_validator_t *vdtr)
1249 {
1250 this->lock->write_lock(this->lock);
1251 this->sets->insert_last(this->validators, vdtr);
1252 this->lock->unlock(this->lock);
1253 }
1254
1255 METHOD(credential_manager_t, remove_validator, void,
1256 private_credential_manager_t *this, cert_validator_t *vdtr)
1257 {
1258 this->lock->write_lock(this->lock);
1259 this->validators->remove(this->validators, vdtr, NULL);
1260 this->lock->unlock(this->lock);
1261 }
1262
1263 METHOD(credential_manager_t, destroy, void,
1264 private_credential_manager_t *this)
1265 {
1266 cache_queue(this);
1267 this->cache_queue->destroy(this->cache_queue);
1268 if (this->cache)
1269 {
1270 this->sets->remove(this->sets, this->cache, NULL);
1271 this->cache->destroy(this->cache);
1272 }
1273 this->sets->destroy(this->sets);
1274 this->local_sets->destroy(this->local_sets);
1275 this->exclusive_local_sets->destroy(this->exclusive_local_sets);
1276 this->validators->destroy(this->validators);
1277 this->lock->destroy(this->lock);
1278 this->queue_mutex->destroy(this->queue_mutex);
1279 free(this);
1280 }
1281
1282 /*
1283 * see header file
1284 */
1285 credential_manager_t *credential_manager_create()
1286 {
1287 private_credential_manager_t *this;
1288
1289 INIT(this,
1290 .public = {
1291 .create_cert_enumerator = _create_cert_enumerator,
1292 .create_shared_enumerator = _create_shared_enumerator,
1293 .create_cdp_enumerator = _create_cdp_enumerator,
1294 .get_cert = _get_cert,
1295 .get_shared = _get_shared,
1296 .get_private = _get_private,
1297 .create_trusted_enumerator = _create_trusted_enumerator,
1298 .create_public_enumerator = _create_public_enumerator,
1299 .flush_cache = _flush_cache,
1300 .cache_cert = _cache_cert,
1301 .issued_by = _issued_by,
1302 .add_set = _add_set,
1303 .remove_set = _remove_set,
1304 .add_local_set = _add_local_set,
1305 .remove_local_set = _remove_local_set,
1306 .add_validator = _add_validator,
1307 .remove_validator = _remove_validator,
1308 .destroy = _destroy,
1309 },
1310 .sets = linked_list_create(),
1311 .validators = linked_list_create(),
1312 .cache_queue = linked_list_create(),
1313 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1314 .queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
1315 );
1316
1317 this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
1318 this->exclusive_local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
1319 if (lib->settings->get_bool(lib->settings, "libstrongswan.cert_cache", TRUE))
1320 {
1321 this->cache = cert_cache_create();
1322 this->sets->insert_first(this->sets, this->cache);
1323 }
1324
1325 return &this->public;
1326 }