Make cert_validator_t.validate optional to implement
[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 }
397 enumerator->destroy(enumerator);
398 return found;
399 }
400
401 METHOD(credential_manager_t, add_local_set, void,
402 private_credential_manager_t *this, credential_set_t *set, bool exclusive)
403 {
404 linked_list_t *sets;
405 thread_value_t *tv;
406
407 if (exclusive)
408 {
409 tv = this->exclusive_local_sets;
410 }
411 else
412 {
413 tv = this->local_sets;
414 }
415 sets = tv->get(tv);
416 if (!sets)
417 {
418 sets = linked_list_create();
419 tv->set(tv, sets);
420 }
421 if (exclusive)
422 {
423 sets->insert_first(sets, set);
424 }
425 else
426 {
427 sets->insert_last(sets, set);
428 }
429 }
430
431 METHOD(credential_manager_t, remove_local_set, void,
432 private_credential_manager_t *this, credential_set_t *set)
433 {
434 linked_list_t *sets;
435 thread_value_t *tv;
436
437 tv = this->local_sets;
438 sets = tv->get(tv);
439 if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
440 {
441 tv->set(tv, NULL);
442 sets->destroy(sets);
443 }
444 tv = this->exclusive_local_sets;
445 sets = tv->get(tv);
446 if (sets && sets->remove(sets, set, NULL) && sets->get_count(sets) == 0)
447 {
448 tv->set(tv, NULL);
449 sets->destroy(sets);
450 }
451 }
452
453 METHOD(credential_manager_t, issued_by, bool,
454 private_credential_manager_t *this, certificate_t *subject,
455 certificate_t *issuer, signature_scheme_t *scheme)
456 {
457 if (this->cache)
458 {
459 return this->cache->issued_by(this->cache, subject, issuer, scheme);
460 }
461 return subject->issued_by(subject, issuer, scheme);
462 }
463
464 METHOD(credential_manager_t, cache_cert, void,
465 private_credential_manager_t *this, certificate_t *cert)
466 {
467 credential_set_t *set;
468 enumerator_t *enumerator;
469
470 if (this->lock->try_write_lock(this->lock))
471 {
472 enumerator = this->sets->create_enumerator(this->sets);
473 while (enumerator->enumerate(enumerator, &set))
474 {
475 set->cache_cert(set, cert);
476 }
477 enumerator->destroy(enumerator);
478 this->lock->unlock(this->lock);
479 }
480 else
481 { /* we can't cache now as other threads are active, queue for later */
482 this->queue_mutex->lock(this->queue_mutex);
483 this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
484 this->queue_mutex->unlock(this->queue_mutex);
485 }
486 }
487
488 /**
489 * Try to cache certificates queued for caching
490 */
491 static void cache_queue(private_credential_manager_t *this)
492 {
493 credential_set_t *set;
494 certificate_t *cert;
495 enumerator_t *enumerator;
496
497 this->queue_mutex->lock(this->queue_mutex);
498 if (this->cache_queue->get_count(this->cache_queue) > 0 &&
499 this->lock->try_write_lock(this->lock))
500 {
501 while (this->cache_queue->remove_last(this->cache_queue,
502 (void**)&cert) == SUCCESS)
503 {
504 enumerator = this->sets->create_enumerator(this->sets);
505 while (enumerator->enumerate(enumerator, &set))
506 {
507 set->cache_cert(set, cert);
508 }
509 enumerator->destroy(enumerator);
510 cert->destroy(cert);
511 }
512 this->lock->unlock(this->lock);
513 }
514 this->queue_mutex->unlock(this->queue_mutex);
515 }
516
517 /**
518 * check a certificate for its lifetime
519 */
520 static bool check_certificate(private_credential_manager_t *this,
521 certificate_t *subject, certificate_t *issuer, bool online,
522 int pathlen, bool trusted, auth_cfg_t *auth)
523 {
524 time_t not_before, not_after;
525 cert_validator_t *validator;
526 enumerator_t *enumerator;
527
528 if (!subject->get_validity(subject, NULL, &not_before, &not_after))
529 {
530 DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
531 &not_before, FALSE, &not_after, FALSE);
532 return FALSE;
533 }
534 if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
535 {
536 DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
537 &not_before, FALSE, &not_after, FALSE);
538 return FALSE;
539 }
540
541 enumerator = this->validators->create_enumerator(this->validators);
542 while (enumerator->enumerate(enumerator, &validator))
543 {
544 if (!validator->validate)
545 {
546 continue;
547 }
548 if (!validator->validate(validator, subject, issuer,
549 online, pathlen, trusted, auth))
550 {
551 enumerator->destroy(enumerator);
552 return FALSE;
553 }
554 }
555 enumerator->destroy(enumerator);
556 return TRUE;
557 }
558
559 /**
560 * Get a trusted certificate from a credential set
561 */
562 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
563 key_type_t type, identification_t *id)
564 {
565 certificate_t *subject;
566 public_key_t *public;
567
568 subject = get_cert(this, CERT_ANY, type, id, TRUE);
569 if (!subject)
570 {
571 return NULL;
572 }
573 public = subject->get_public_key(subject);
574 if (!public)
575 {
576 subject->destroy(subject);
577 return NULL;
578 }
579 public->destroy(public);
580 return subject;
581 }
582
583 /**
584 * Get the issuing certificate of a subject certificate
585 */
586 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
587 certificate_t *subject, bool trusted,
588 signature_scheme_t *scheme)
589 {
590 enumerator_t *enumerator;
591 certificate_t *issuer = NULL, *candidate;
592
593 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
594 subject->get_issuer(subject), trusted);
595 while (enumerator->enumerate(enumerator, &candidate))
596 {
597 if (issued_by(this, subject, candidate, scheme))
598 {
599 issuer = candidate->get_ref(candidate);
600 break;
601 }
602 }
603 enumerator->destroy(enumerator);
604 return issuer;
605 }
606
607 /**
608 * Get the strength of certificate, add it to auth
609 */
610 static void get_key_strength(certificate_t *cert, auth_cfg_t *auth)
611 {
612 uintptr_t strength;
613 public_key_t *key;
614 key_type_t type;
615
616 key = cert->get_public_key(cert);
617 if (key)
618 {
619 type = key->get_type(key);
620 strength = key->get_keysize(key);
621 DBG2(DBG_CFG, " certificate \"%Y\" key: %d bit %N",
622 cert->get_subject(cert), strength, key_type_names, type);
623 switch (type)
624 {
625 case KEY_RSA:
626 auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength);
627 break;
628 case KEY_ECDSA:
629 auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength);
630 break;
631 default:
632 break;
633 }
634 key->destroy(key);
635 }
636 }
637
638 /**
639 * try to verify the trust chain of subject, return TRUE if trusted
640 */
641 static bool verify_trust_chain(private_credential_manager_t *this,
642 certificate_t *subject, auth_cfg_t *result,
643 bool trusted, bool online)
644 {
645 certificate_t *current, *issuer;
646 auth_cfg_t *auth;
647 signature_scheme_t scheme;
648 int pathlen;
649
650 auth = auth_cfg_create();
651 get_key_strength(subject, auth);
652 current = subject->get_ref(subject);
653 auth->add(auth, AUTH_RULE_SUBJECT_CERT, current->get_ref(current));
654
655 for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++)
656 {
657 issuer = get_issuer_cert(this, current, TRUE, &scheme);
658 if (issuer)
659 {
660 /* accept only self-signed CAs as trust anchor */
661 if (issued_by(this, issuer, issuer, NULL))
662 {
663 auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
664 DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
665 issuer->get_subject(issuer));
666 trusted = TRUE;
667 }
668 else
669 {
670 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
671 DBG1(DBG_CFG, " using trusted intermediate ca certificate "
672 "\"%Y\"", issuer->get_subject(issuer));
673 }
674 auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
675 }
676 else
677 {
678 issuer = get_issuer_cert(this, current, FALSE, &scheme);
679 if (issuer)
680 {
681 if (current->equals(current, issuer))
682 {
683 DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
684 current->get_subject(current));
685 issuer->destroy(issuer);
686 break;
687 }
688 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
689 DBG1(DBG_CFG, " using untrusted intermediate certificate "
690 "\"%Y\"", issuer->get_subject(issuer));
691 auth->add(auth, AUTH_RULE_SIGNATURE_SCHEME, scheme);
692 }
693 else
694 {
695 DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
696 current->get_subject(current));
697 break;
698 }
699 }
700 if (!check_certificate(this, current, issuer, online,
701 pathlen, trusted, auth))
702 {
703 trusted = FALSE;
704 issuer->destroy(issuer);
705 break;
706 }
707 if (issuer)
708 {
709 get_key_strength(issuer, auth);
710 }
711 current->destroy(current);
712 current = issuer;
713 if (trusted)
714 {
715 DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d",
716 pathlen);
717 break;
718 }
719 }
720 current->destroy(current);
721 if (pathlen > MAX_TRUST_PATH_LEN)
722 {
723 DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN);
724 }
725 if (trusted)
726 {
727 result->merge(result, auth, FALSE);
728 }
729 auth->destroy(auth);
730 return trusted;
731 }
732
733 /**
734 * List find match function for certificates
735 */
736 static bool cert_equals(certificate_t *a, certificate_t *b)
737 {
738 return a->equals(a, b);
739 }
740
741 /**
742 * enumerator for trusted certificates
743 */
744 typedef struct {
745 /** implements enumerator_t interface */
746 enumerator_t public;
747 /** enumerator over candidate peer certificates */
748 enumerator_t *candidates;
749 /** reference to the credential_manager */
750 private_credential_manager_t *this;
751 /** type of the requested key */
752 key_type_t type;
753 /** identity the requested key belongs to */
754 identification_t *id;
755 /** TRUE to do CRL/OCSP checking */
756 bool online;
757 /** pretrusted certificate we have served at first invocation */
758 certificate_t *pretrusted;
759 /** currently enumerating auth config */
760 auth_cfg_t *auth;
761 /** list of failed candidates */
762 linked_list_t *failed;
763 } trusted_enumerator_t;
764
765 METHOD(enumerator_t, trusted_enumerate, bool,
766 trusted_enumerator_t *this, certificate_t **cert, auth_cfg_t **auth)
767 {
768 certificate_t *current;
769
770 DESTROY_IF(this->auth);
771 this->auth = auth_cfg_create();
772
773 if (!this->candidates)
774 {
775 /* first invocation, build enumerator for next one */
776 this->candidates = create_cert_enumerator(this->this, CERT_ANY,
777 this->type, this->id, FALSE);
778 /* check if we have a trusted certificate for that peer */
779 this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
780 if (this->pretrusted)
781 {
782 /* if we find a trusted self signed certificate, we just accept it.
783 * However, in order to fulfill authorization rules, we try to build
784 * the trust chain if it is not self signed */
785 if (issued_by(this->this, this->pretrusted, this->pretrusted, NULL) ||
786 verify_trust_chain(this->this, this->pretrusted, this->auth,
787 TRUE, this->online))
788 {
789 DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
790 this->pretrusted->get_subject(this->pretrusted));
791 *cert = this->pretrusted;
792 if (!this->auth->get(this->auth, AUTH_RULE_SUBJECT_CERT))
793 { /* add cert to auth info, if not returned by trustchain */
794 this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
795 this->pretrusted->get_ref(this->pretrusted));
796 }
797 if (auth)
798 {
799 *auth = this->auth;
800 }
801 return TRUE;
802 }
803 }
804 }
805 /* try to verify the trust chain for each certificate found */
806 while (this->candidates->enumerate(this->candidates, &current))
807 {
808 if (this->pretrusted &&
809 this->pretrusted->equals(this->pretrusted, current))
810 { /* skip pretrusted certificate we already served */
811 continue;
812 }
813
814 if (this->failed->find_first(this->failed, (void*)cert_equals,
815 NULL, current) == SUCCESS)
816 { /* check each candidate only once */
817 continue;
818 }
819
820 DBG1(DBG_CFG, " using certificate \"%Y\"",
821 current->get_subject(current));
822 if (verify_trust_chain(this->this, current, this->auth, FALSE,
823 this->online))
824 {
825 *cert = current;
826 if (auth)
827 {
828 *auth = this->auth;
829 }
830 return TRUE;
831 }
832 this->failed->insert_last(this->failed, current->get_ref(current));
833 }
834 return FALSE;
835 }
836
837 METHOD(enumerator_t, trusted_destroy, void,
838 trusted_enumerator_t *this)
839 {
840 DESTROY_IF(this->pretrusted);
841 DESTROY_IF(this->auth);
842 DESTROY_IF(this->candidates);
843 this->failed->destroy_offset(this->failed, offsetof(certificate_t, destroy));
844 free(this);
845 }
846
847 METHOD(credential_manager_t, create_trusted_enumerator, enumerator_t*,
848 private_credential_manager_t *this, key_type_t type,
849 identification_t *id, bool online)
850 {
851 trusted_enumerator_t *enumerator;
852
853 INIT(enumerator,
854 .public = {
855 .enumerate = (void*)_trusted_enumerate,
856 .destroy = _trusted_destroy,
857 },
858 .this = this,
859 .type = type,
860 .id = id,
861 .online = online,
862 .failed = linked_list_create(),
863 );
864 return &enumerator->public;
865 }
866
867 /**
868 * enumerator for public keys
869 */
870 typedef struct {
871 /** implements enumerator_t interface */
872 enumerator_t public;
873 /** enumerator over candidate peer certificates */
874 enumerator_t *inner;
875 /** reference to the credential_manager */
876 private_credential_manager_t *this;
877 /** currently enumerating key */
878 public_key_t *current;
879 /** credset wrapper around auth config */
880 auth_cfg_wrapper_t *wrapper;
881 } public_enumerator_t;
882
883 METHOD(enumerator_t, public_enumerate, bool,
884 public_enumerator_t *this, public_key_t **key, auth_cfg_t **auth)
885 {
886 certificate_t *cert;
887
888 while (this->inner->enumerate(this->inner, &cert, auth))
889 {
890 DESTROY_IF(this->current);
891 this->current = cert->get_public_key(cert);
892 if (this->current)
893 {
894 *key = this->current;
895 return TRUE;
896 }
897 }
898 return FALSE;
899 }
900
901 METHOD(enumerator_t, public_destroy, void,
902 public_enumerator_t *this)
903 {
904 DESTROY_IF(this->current);
905 this->inner->destroy(this->inner);
906 if (this->wrapper)
907 {
908 remove_local_set(this->this, &this->wrapper->set);
909 this->wrapper->destroy(this->wrapper);
910 }
911 this->this->lock->unlock(this->this->lock);
912
913 /* check for delayed certificate cache queue */
914 cache_queue(this->this);
915 free(this);
916 }
917
918 METHOD(credential_manager_t, create_public_enumerator, enumerator_t*,
919 private_credential_manager_t *this, key_type_t type, identification_t *id,
920 auth_cfg_t *auth)
921 {
922 public_enumerator_t *enumerator;
923
924 INIT(enumerator,
925 .public = {
926 .enumerate = (void*)_public_enumerate,
927 .destroy = _public_destroy,
928 },
929 .inner = create_trusted_enumerator(this, type, id, TRUE),
930 .this = this,
931 );
932 if (auth)
933 {
934 enumerator->wrapper = auth_cfg_wrapper_create(auth);
935 add_local_set(this, &enumerator->wrapper->set, FALSE);
936 }
937 this->lock->read_lock(this->lock);
938 return &enumerator->public;
939 }
940
941 /**
942 * Check if a helper contains a certificate as trust anchor
943 */
944 static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
945 {
946 enumerator_t *enumerator;
947 identification_t *value;
948 auth_rule_t type;
949 bool found = FALSE;
950
951 enumerator = auth->create_enumerator(auth);
952 while (enumerator->enumerate(enumerator, &type, &value))
953 {
954 if (type == AUTH_RULE_CA_CERT &&
955 cert->equals(cert, (certificate_t*)value))
956 {
957 found = TRUE;
958 break;
959 }
960 }
961 enumerator->destroy(enumerator);
962 return found;
963 }
964
965 /**
966 * build a trustchain from subject up to a trust anchor in trusted
967 */
968 static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
969 certificate_t *subject, auth_cfg_t *auth)
970 {
971 certificate_t *issuer, *current;
972 auth_cfg_t *trustchain;
973 int pathlen = 0;
974 bool has_anchor;
975
976 trustchain = auth_cfg_create();
977 has_anchor = auth->get(auth, AUTH_RULE_CA_CERT) != NULL;
978 current = subject->get_ref(subject);
979 while (TRUE)
980 {
981 if (auth_contains_cacert(auth, current))
982 {
983 trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
984 return trustchain;
985 }
986 if (subject == current)
987 {
988 trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
989 }
990 else
991 {
992 if (!has_anchor && issued_by(this, current, current, NULL))
993 { /* If no trust anchor specified, accept any CA */
994 trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
995 return trustchain;
996 }
997 trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
998 }
999 if (pathlen++ > MAX_TRUST_PATH_LEN)
1000 {
1001 break;
1002 }
1003 issuer = get_issuer_cert(this, current, FALSE, NULL);
1004 if (!issuer)
1005 {
1006 if (!has_anchor)
1007 { /* If no trust anchor specified, accept incomplete chains */
1008 return trustchain;
1009 }
1010 break;
1011 }
1012 if (has_anchor && issuer->equals(issuer, current))
1013 {
1014 issuer->destroy(issuer);
1015 break;
1016 }
1017 current = issuer;
1018 }
1019 trustchain->destroy(trustchain);
1020 return NULL;
1021 }
1022
1023 /**
1024 * find a private key of a given certificate
1025 */
1026 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1027 certificate_t *cert, key_type_t type)
1028 {
1029 private_key_t *private = NULL;
1030 identification_t *keyid;
1031 chunk_t chunk;
1032 public_key_t *public;
1033
1034 public = cert->get_public_key(cert);
1035 if (public)
1036 {
1037 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
1038 {
1039 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
1040 private = get_private_by_keyid(this, type, keyid);
1041 keyid->destroy(keyid);
1042 }
1043 public->destroy(public);
1044 }
1045 return private;
1046 }
1047
1048 METHOD(credential_manager_t, get_private, private_key_t*,
1049 private_credential_manager_t *this, key_type_t type, identification_t *id,
1050 auth_cfg_t *auth)
1051 {
1052 enumerator_t *enumerator;
1053 certificate_t *cert;
1054 private_key_t *private = NULL;
1055 auth_cfg_t *trustchain;
1056
1057 /* check if this is a lookup by key ID, and do it if so */
1058 if (id && id->get_type(id) == ID_KEY_ID)
1059 {
1060 private = get_private_by_keyid(this, type, id);
1061 if (private)
1062 {
1063 return private;
1064 }
1065 }
1066
1067 if (auth)
1068 {
1069 /* if a specific certificate is preferred, check for a matching key */
1070 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
1071 if (cert)
1072 {
1073 private = get_private_by_cert(this, cert, type);
1074 if (private)
1075 {
1076 trustchain = build_trustchain(this, cert, auth);
1077 if (trustchain)
1078 {
1079 auth->merge(auth, trustchain, FALSE);
1080 trustchain->destroy(trustchain);
1081 }
1082 return private;
1083 }
1084 }
1085
1086 /* try to build a trust chain for each certificate found */
1087 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1088 while (enumerator->enumerate(enumerator, &cert))
1089 {
1090 private = get_private_by_cert(this, cert, type);
1091 if (private)
1092 {
1093 trustchain = build_trustchain(this, cert, auth);
1094 if (trustchain)
1095 {
1096 auth->merge(auth, trustchain, FALSE);
1097 trustchain->destroy(trustchain);
1098 break;
1099 }
1100 private->destroy(private);
1101 private = NULL;
1102 }
1103 }
1104 enumerator->destroy(enumerator);
1105 }
1106
1107 /* if no valid trustchain was found, fall back to the first usable cert */
1108 if (!private)
1109 {
1110 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1111 while (enumerator->enumerate(enumerator, &cert))
1112 {
1113 private = get_private_by_cert(this, cert, type);
1114 if (private)
1115 {
1116 if (auth)
1117 {
1118 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
1119 }
1120 break;
1121 }
1122 }
1123 enumerator->destroy(enumerator);
1124 }
1125 return private;
1126 }
1127
1128 METHOD(credential_manager_t, flush_cache, void,
1129 private_credential_manager_t *this, certificate_type_t type)
1130 {
1131 if (this->cache)
1132 {
1133 this->cache->flush(this->cache, type);
1134 }
1135 }
1136
1137 METHOD(credential_manager_t, add_set, void,
1138 private_credential_manager_t *this, credential_set_t *set)
1139 {
1140 this->lock->write_lock(this->lock);
1141 this->sets->insert_last(this->sets, set);
1142 this->lock->unlock(this->lock);
1143 }
1144
1145 METHOD(credential_manager_t, remove_set, void,
1146 private_credential_manager_t *this, credential_set_t *set)
1147 {
1148 this->lock->write_lock(this->lock);
1149 this->sets->remove(this->sets, set, NULL);
1150 this->lock->unlock(this->lock);
1151 }
1152
1153 METHOD(credential_manager_t, add_validator, void,
1154 private_credential_manager_t *this, cert_validator_t *vdtr)
1155 {
1156 this->lock->write_lock(this->lock);
1157 this->sets->insert_last(this->validators, vdtr);
1158 this->lock->unlock(this->lock);
1159 }
1160
1161 METHOD(credential_manager_t, remove_validator, void,
1162 private_credential_manager_t *this, cert_validator_t *vdtr)
1163 {
1164 this->lock->write_lock(this->lock);
1165 this->validators->remove(this->validators, vdtr, NULL);
1166 this->lock->unlock(this->lock);
1167 }
1168
1169 METHOD(credential_manager_t, destroy, void,
1170 private_credential_manager_t *this)
1171 {
1172 cache_queue(this);
1173 this->cache_queue->destroy(this->cache_queue);
1174 if (this->cache)
1175 {
1176 this->sets->remove(this->sets, this->cache, NULL);
1177 this->cache->destroy(this->cache);
1178 }
1179 this->sets->destroy(this->sets);
1180 this->local_sets->destroy(this->local_sets);
1181 this->exclusive_local_sets->destroy(this->exclusive_local_sets);
1182 this->validators->destroy(this->validators);
1183 this->lock->destroy(this->lock);
1184 this->queue_mutex->destroy(this->queue_mutex);
1185 free(this);
1186 }
1187
1188 /*
1189 * see header file
1190 */
1191 credential_manager_t *credential_manager_create()
1192 {
1193 private_credential_manager_t *this;
1194
1195 INIT(this,
1196 .public = {
1197 .create_cert_enumerator = _create_cert_enumerator,
1198 .create_shared_enumerator = _create_shared_enumerator,
1199 .create_cdp_enumerator = _create_cdp_enumerator,
1200 .get_cert = _get_cert,
1201 .get_shared = _get_shared,
1202 .get_private = _get_private,
1203 .create_trusted_enumerator = _create_trusted_enumerator,
1204 .create_public_enumerator = _create_public_enumerator,
1205 .flush_cache = _flush_cache,
1206 .cache_cert = _cache_cert,
1207 .issued_by = _issued_by,
1208 .add_set = _add_set,
1209 .remove_set = _remove_set,
1210 .add_local_set = _add_local_set,
1211 .remove_local_set = _remove_local_set,
1212 .add_validator = _add_validator,
1213 .remove_validator = _remove_validator,
1214 .destroy = _destroy,
1215 },
1216 .sets = linked_list_create(),
1217 .validators = linked_list_create(),
1218 .cache_queue = linked_list_create(),
1219 .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
1220 .queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT),
1221 );
1222
1223 this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
1224 this->exclusive_local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
1225 if (lib->settings->get_bool(lib->settings, "libstrongswan.cert_cache", TRUE))
1226 {
1227 this->cache = cert_cache_create();
1228 this->sets->insert_first(this->sets, this->cache);
1229 }
1230
1231 return &this->public;
1232 }