Moved credential manager to libstrongswan
[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 <debug.h>
20 #include <threading/thread_value.h>
21 #include <threading/mutex.h>
22 #include <threading/rwlock.h>
23 #include <selectors/traffic_selector.h>
24 #include <utils/linked_list.h>
25 #include <credentials/sets/cert_cache.h>
26 #include <credentials/sets/auth_cfg_wrapper.h>
27 #include <credentials/sets/ocsp_response_wrapper.h>
28 #include <credentials/certificates/x509.h>
29 #include <credentials/certificates/crl.h>
30 #include <credentials/certificates/ocsp_request.h>
31 #include <credentials/certificates/ocsp_response.h>
32
33 /**
34 * Maximum length of a certificate trust chain
35 */
36 #define MAX_TRUST_PATH_LEN 7
37
38 typedef struct private_credential_manager_t private_credential_manager_t;
39
40 /**
41 * private data of credential_manager
42 */
43 struct private_credential_manager_t {
44
45 /**
46 * public functions
47 */
48 credential_manager_t public;
49
50 /**
51 * list of credential sets
52 */
53 linked_list_t *sets;
54
55 /**
56 * thread local set of credentials, linked_list_t with credential_set_t's
57 */
58 thread_value_t *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 * read-write lock to sets list
72 */
73 rwlock_t *lock;
74
75 /**
76 * mutex for cache queue
77 */
78 mutex_t *queue_mutex;
79 };
80
81 /** data to pass to create_private_enumerator */
82 typedef struct {
83 private_credential_manager_t *this;
84 key_type_t type;
85 identification_t* keyid;
86 } private_data_t;
87
88 /** data to pass to create_cert_enumerator */
89 typedef struct {
90 private_credential_manager_t *this;
91 certificate_type_t cert;
92 key_type_t key;
93 identification_t *id;
94 bool trusted;
95 } cert_data_t;
96
97 /** data to pass to create_cdp_enumerator */
98 typedef struct {
99 private_credential_manager_t *this;
100 certificate_type_t type;
101 identification_t *id;
102 } cdp_data_t;
103
104 /** data to pass to create_shared_enumerator */
105 typedef struct {
106 private_credential_manager_t *this;
107 shared_key_type_t type;
108 identification_t *me;
109 identification_t *other;
110 } shared_data_t;
111
112 /** enumerator over local and global sets */
113 typedef struct {
114 /** implements enumerator_t */
115 enumerator_t public;
116 /** enumerator over global sets */
117 enumerator_t *global;
118 /** enumerator over local sets */
119 enumerator_t *local;
120 } sets_enumerator_t;
121
122 /**
123 * destroy a sets_enumerator_t
124 */
125 static void sets_enumerator_destroy(sets_enumerator_t *this)
126 {
127 DESTROY_IF(this->global);
128 DESTROY_IF(this->local);
129 free(this);
130 }
131
132 /**
133 * sets_enumerator_t.enumerate
134 */
135 static bool sets_enumerator_enumerate(sets_enumerator_t *this,
136 credential_set_t **set)
137 {
138 if (this->global)
139 {
140 if (this->global->enumerate(this->global, set))
141 {
142 return TRUE;
143 }
144 /* end of global sets, look for local */
145 this->global->destroy(this->global);
146 this->global = NULL;
147 }
148 if (this->local)
149 {
150 return this->local->enumerate(this->local, set);
151 }
152 return FALSE;
153 }
154
155 /**
156 * create an enumerator over both, global and local sets
157 */
158 static enumerator_t *create_sets_enumerator(private_credential_manager_t *this)
159 {
160 linked_list_t *local;
161 sets_enumerator_t *enumerator = malloc_thing(sets_enumerator_t);
162
163 enumerator->public.enumerate = (void*)sets_enumerator_enumerate;
164 enumerator->public.destroy = (void*)sets_enumerator_destroy;
165 enumerator->global = this->sets->create_enumerator(this->sets);
166 enumerator->local = NULL;
167 local = this->local_sets->get(this->local_sets);
168 if (local)
169 {
170 enumerator->local = local->create_enumerator(local);
171 }
172 return &enumerator->public;
173 }
174
175 /**
176 * cleanup function for cert data
177 */
178 static void destroy_cert_data(cert_data_t *data)
179 {
180 data->this->lock->unlock(data->this->lock);
181 free(data);
182 }
183
184 /**
185 * enumerator constructor for certificates
186 */
187 static enumerator_t *create_cert(credential_set_t *set, cert_data_t *data)
188 {
189 return set->create_cert_enumerator(set, data->cert, data->key,
190 data->id, data->trusted);
191 }
192
193 /**
194 * Implementation of credential_manager_t.create_cert_enumerator.
195 */
196 static enumerator_t *create_cert_enumerator(private_credential_manager_t *this,
197 certificate_type_t certificate, key_type_t key,
198 identification_t *id, bool trusted)
199 {
200 cert_data_t *data = malloc_thing(cert_data_t);
201 data->this = this;
202 data->cert = certificate;
203 data->key = key;
204 data->id = id;
205 data->trusted = trusted;
206
207 this->lock->read_lock(this->lock);
208 return enumerator_create_nested(create_sets_enumerator(this),
209 (void*)create_cert, data,
210 (void*)destroy_cert_data);
211 }
212
213 /**
214 * Implementation of credential_manager_t.get_cert.
215 */
216 static certificate_t *get_cert(private_credential_manager_t *this,
217 certificate_type_t cert, key_type_t key,
218 identification_t *id, bool trusted)
219 {
220 certificate_t *current, *found = NULL;
221 enumerator_t *enumerator;
222
223 enumerator = create_cert_enumerator(this, cert, key, id, trusted);
224 if (enumerator->enumerate(enumerator, &current))
225 {
226 /* TODO: best match? order by keyid, subject, sualtname */
227 found = current->get_ref(current);
228 }
229 enumerator->destroy(enumerator);
230 return found;
231 }
232
233
234 /**
235 * cleanup function for cdp data
236 */
237 static void destroy_cdp_data(cdp_data_t *data)
238 {
239 data->this->lock->unlock(data->this->lock);
240 free(data);
241 }
242
243 /**
244 * enumerator constructor for CDPs
245 */
246 static enumerator_t *create_cdp(credential_set_t *set, cdp_data_t *data)
247 {
248 return set->create_cdp_enumerator(set, data->type, data->id);
249 }
250 /**
251 * Implementation of credential_manager_t.create_cdp_enumerator.
252 */
253 static enumerator_t * create_cdp_enumerator(private_credential_manager_t *this,
254 certificate_type_t type, identification_t *id)
255 {
256 cdp_data_t *data = malloc_thing(cdp_data_t);
257 data->this = this;
258 data->type = type;
259 data->id = id;
260
261 this->lock->read_lock(this->lock);
262 return enumerator_create_nested(create_sets_enumerator(this),
263 (void*)create_cdp, data,
264 (void*)destroy_cdp_data);
265 }
266
267 /**
268 * cleanup function for private data
269 */
270 static void destroy_private_data(private_data_t *data)
271 {
272 data->this->lock->unlock(data->this->lock);
273 free(data);
274 }
275
276 /**
277 * enumerator constructor for private keys
278 */
279 static enumerator_t *create_private(credential_set_t *set, private_data_t *data)
280 {
281 return set->create_private_enumerator(set, data->type, data->keyid);
282 }
283
284 /**
285 * Implementation of credential_manager_t.create_private_enumerator.
286 */
287 static enumerator_t* create_private_enumerator(
288 private_credential_manager_t *this,
289 key_type_t key, identification_t *keyid)
290 {
291 private_data_t *data;
292
293 data = malloc_thing(private_data_t);
294 data->this = this;
295 data->type = key;
296 data->keyid = keyid;
297 this->lock->read_lock(this->lock);
298 return enumerator_create_nested(create_sets_enumerator(this),
299 (void*)create_private, data,
300 (void*)destroy_private_data);
301 }
302
303 /**
304 * Implementation of credential_manager_t.get_private_by_keyid.
305 */
306 static private_key_t *get_private_by_keyid(private_credential_manager_t *this,
307 key_type_t key, identification_t *keyid)
308 {
309 private_key_t *found = NULL;
310 enumerator_t *enumerator;
311
312 enumerator = create_private_enumerator(this, key, keyid);
313 if (enumerator->enumerate(enumerator, &found))
314 {
315 found->get_ref(found);
316 }
317 enumerator->destroy(enumerator);
318 return found;
319 }
320
321 /**
322 * cleanup function for shared data
323 */
324 static void destroy_shared_data(shared_data_t *data)
325 {
326 data->this->lock->unlock(data->this->lock);
327 free(data);
328 }
329
330 /**
331 * enumerator constructor for shared keys
332 */
333 static enumerator_t *create_shared(credential_set_t *set, shared_data_t *data)
334 {
335 return set->create_shared_enumerator(set, data->type, data->me, data->other);
336 }
337
338 /**
339 * Implementation of credential_manager_t.create_shared_enumerator.
340 */
341 static enumerator_t *create_shared_enumerator(private_credential_manager_t *this,
342 shared_key_type_t type,
343 identification_t *me, identification_t *other)
344 {
345 shared_data_t *data = malloc_thing(shared_data_t);
346 data->this = this;
347 data->type = type;
348 data->me = me;
349 data->other = other;
350
351 this->lock->read_lock(this->lock);
352 return enumerator_create_nested(create_sets_enumerator(this),
353 (void*)create_shared, data,
354 (void*)destroy_shared_data);
355 }
356
357 /**
358 * Implementation of credential_manager_t.get_shared.
359 */
360 static shared_key_t *get_shared(private_credential_manager_t *this,
361 shared_key_type_t type, identification_t *me,
362 identification_t *other)
363 {
364 shared_key_t *current, *found = NULL;
365 id_match_t *best_me = ID_MATCH_NONE, *best_other = ID_MATCH_NONE;
366 id_match_t *match_me, *match_other;
367 enumerator_t *enumerator;
368
369 enumerator = create_shared_enumerator(this, type, me, other);
370 while (enumerator->enumerate(enumerator, &current, &match_me, &match_other))
371 {
372 if (match_other > best_other ||
373 (match_other == best_other && match_me > best_me))
374 {
375 DESTROY_IF(found);
376 found = current->get_ref(current);
377 best_me = match_me;
378 best_other = match_other;
379 }
380 }
381 enumerator->destroy(enumerator);
382 return found;
383 }
384
385 /**
386 * add a credential set to the thread local list
387 */
388 static void add_local_set(private_credential_manager_t *this,
389 credential_set_t *set)
390 {
391 linked_list_t *sets;
392
393 sets = this->local_sets->get(this->local_sets);
394 if (!sets)
395 { /* first invocation */
396 sets = linked_list_create();
397 this->local_sets->set(this->local_sets, sets);
398 }
399 sets->insert_last(sets, set);
400 }
401
402 /**
403 * remove a credential set from the thread local list
404 */
405 static void remove_local_set(private_credential_manager_t *this,
406 credential_set_t *set)
407 {
408 linked_list_t *sets;
409
410 sets = this->local_sets->get(this->local_sets);
411 sets->remove(sets, set, NULL);
412 }
413
414 /**
415 * Implementation of credential_manager_t.cache_cert.
416 */
417 static void cache_cert(private_credential_manager_t *this, certificate_t *cert)
418 {
419 credential_set_t *set;
420 enumerator_t *enumerator;
421
422 if (this->lock->try_write_lock(this->lock))
423 {
424 enumerator = this->sets->create_enumerator(this->sets);
425 while (enumerator->enumerate(enumerator, &set))
426 {
427 set->cache_cert(set, cert);
428 }
429 enumerator->destroy(enumerator);
430 this->lock->unlock(this->lock);
431 }
432 else
433 { /* we can't cache now as other threads are active, queue for later */
434 this->queue_mutex->lock(this->queue_mutex);
435 this->cache_queue->insert_last(this->cache_queue, cert->get_ref(cert));
436 this->queue_mutex->unlock(this->queue_mutex);
437 }
438 }
439
440 /**
441 * Try to cache certificates queued for caching
442 */
443 static void cache_queue(private_credential_manager_t *this)
444 {
445 credential_set_t *set;
446 certificate_t *cert;
447 enumerator_t *enumerator;
448
449 this->queue_mutex->lock(this->queue_mutex);
450 if (this->cache_queue->get_count(this->cache_queue) > 0 &&
451 this->lock->try_write_lock(this->lock))
452 {
453 while (this->cache_queue->remove_last(this->cache_queue,
454 (void**)&cert) == SUCCESS)
455 {
456 enumerator = this->sets->create_enumerator(this->sets);
457 while (enumerator->enumerate(enumerator, &set))
458 {
459 set->cache_cert(set, cert);
460 }
461 enumerator->destroy(enumerator);
462 cert->destroy(cert);
463 }
464 this->lock->unlock(this->lock);
465 }
466 this->queue_mutex->unlock(this->queue_mutex);
467 }
468
469 /**
470 * forward declaration
471 */
472 static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
473 key_type_t type, identification_t *id, bool online);
474
475 /**
476 * Do an OCSP request
477 */
478 static certificate_t *fetch_ocsp(private_credential_manager_t *this, char *url,
479 certificate_t *subject, certificate_t *issuer)
480 {
481 certificate_t *request, *response;
482 chunk_t send, receive;
483
484 /* TODO: requestor name, signature */
485 request = lib->creds->create(lib->creds,
486 CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
487 BUILD_CA_CERT, issuer,
488 BUILD_CERT, subject, BUILD_END);
489 if (!request)
490 {
491 DBG1(DBG_CFG, "generating ocsp request failed");
492 return NULL;
493 }
494
495 send = request->get_encoding(request);
496 request->destroy(request);
497
498 DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
499 if (lib->fetcher->fetch(lib->fetcher, url, &receive,
500 FETCH_REQUEST_DATA, send,
501 FETCH_REQUEST_TYPE, "application/ocsp-request",
502 FETCH_END) != SUCCESS)
503 {
504 DBG1(DBG_CFG, "ocsp request to %s failed", url);
505 chunk_free(&send);
506 return NULL;
507 }
508 chunk_free(&send);
509
510 response = lib->creds->create(lib->creds,
511 CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
512 BUILD_BLOB_ASN1_DER, receive, BUILD_END);
513 chunk_free(&receive);
514 if (!response)
515 {
516 DBG1(DBG_CFG, "parsing ocsp response failed");
517 return NULL;
518 }
519 return response;
520 }
521
522 /**
523 * check the signature of an OCSP response
524 */
525 static bool verify_ocsp(private_credential_manager_t *this,
526 ocsp_response_t *response)
527 {
528 certificate_t *issuer, *subject;
529 identification_t *responder;
530 ocsp_response_wrapper_t *wrapper;
531 enumerator_t *enumerator;
532 bool verified = FALSE;
533
534 wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
535 add_local_set(this, &wrapper->set);
536
537 subject = &response->certificate;
538 responder = subject->get_issuer(subject);
539 enumerator = create_trusted_enumerator(this, KEY_ANY, responder, FALSE);
540 while (enumerator->enumerate(enumerator, &issuer, NULL))
541 {
542 if (this->cache->issued_by(this->cache, subject, issuer))
543 {
544 DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
545 issuer->get_subject(issuer));
546 verified = TRUE;
547 break;
548 }
549 }
550 enumerator->destroy(enumerator);
551
552 remove_local_set(this, &wrapper->set);
553 wrapper->destroy(wrapper);
554 return verified;
555 }
556
557 /**
558 * Get the better of two OCSP responses, and check for usable OCSP info
559 */
560 static certificate_t *get_better_ocsp(private_credential_manager_t *this,
561 certificate_t *cand, certificate_t *best,
562 x509_t *subject, x509_t *issuer,
563 cert_validation_t *valid, bool cache)
564 {
565 ocsp_response_t *response;
566 time_t revocation, this_update, next_update, valid_until;
567 crl_reason_t reason;
568 bool revoked = FALSE;
569
570 response = (ocsp_response_t*)cand;
571
572 /* check ocsp signature */
573 if (!verify_ocsp(this, response))
574 {
575 DBG1(DBG_CFG, "ocsp response verification failed");
576 cand->destroy(cand);
577 return best;
578 }
579 /* check if response contains our certificate */
580 switch (response->get_status(response, subject, issuer, &revocation, &reason,
581 &this_update, &next_update))
582 {
583 case VALIDATION_REVOKED:
584 /* subject has been revoked by a valid OCSP response */
585 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
586 &revocation, TRUE, crl_reason_names, reason);
587 revoked = TRUE;
588 break;
589 case VALIDATION_GOOD:
590 /* results in either good or stale */
591 break;
592 default:
593 case VALIDATION_FAILED:
594 /* candidate unusable, does not contain our cert */
595 DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
596 cand->destroy(cand);
597 return best;
598 }
599
600 /* select the better of the two responses */
601 if (best == NULL || certificate_is_newer(cand, best))
602 {
603 DESTROY_IF(best);
604 best = cand;
605 if (best->get_validity(best, NULL, NULL, &valid_until))
606 {
607 DBG1(DBG_CFG, " ocsp response is valid: until %T",
608 &valid_until, FALSE);
609 *valid = VALIDATION_GOOD;
610 if (cache)
611 { /* cache non-stale only, stale certs get refetched */
612 cache_cert(this, best);
613 }
614 }
615 else
616 {
617 DBG1(DBG_CFG, " ocsp response is stale: since %T",
618 &valid_until, FALSE);
619 *valid = VALIDATION_STALE;
620 }
621 }
622 else
623 {
624 *valid = VALIDATION_STALE;
625 cand->destroy(cand);
626 }
627 if (revoked)
628 { /* revoked always counts, even if stale */
629 *valid = VALIDATION_REVOKED;
630 }
631 return best;
632 }
633
634 /**
635 * validate a x509 certificate using OCSP
636 */
637 static cert_validation_t check_ocsp(private_credential_manager_t *this,
638 x509_t *subject, x509_t *issuer,
639 auth_cfg_t *auth)
640 {
641 enumerator_t *enumerator;
642 cert_validation_t valid = VALIDATION_SKIPPED;
643 certificate_t *best = NULL, *current;
644 identification_t *keyid = NULL;
645 public_key_t *public;
646 chunk_t chunk;
647 char *uri = NULL;
648
649 /** lookup cache for valid OCSP responses */
650 enumerator = create_cert_enumerator(this, CERT_X509_OCSP_RESPONSE,
651 KEY_ANY, NULL, FALSE);
652 while (enumerator->enumerate(enumerator, &current))
653 {
654 current->get_ref(current);
655 best = get_better_ocsp(this, current, best, subject, issuer,
656 &valid, FALSE);
657 if (best && valid != VALIDATION_STALE)
658 {
659 DBG1(DBG_CFG, " using cached ocsp response");
660 break;
661 }
662 }
663 enumerator->destroy(enumerator);
664
665 /* derive the authorityKeyIdentifier from the issuer's public key */
666 current = &issuer->interface;
667 public = current->get_public_key(current);
668 if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
669 {
670 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
671 }
672 /** fetch from configured OCSP responder URLs */
673 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
674 {
675 enumerator = create_cdp_enumerator(this, CERT_X509_OCSP_RESPONSE, keyid);
676 while (enumerator->enumerate(enumerator, &uri))
677 {
678 current = fetch_ocsp(this, uri, &subject->interface,
679 &issuer->interface);
680 if (current)
681 {
682 best = get_better_ocsp(this, current, best, subject, issuer,
683 &valid, TRUE);
684 if (best && valid != VALIDATION_STALE)
685 {
686 break;
687 }
688 }
689 }
690 enumerator->destroy(enumerator);
691 }
692 DESTROY_IF(public);
693 DESTROY_IF(keyid);
694
695 /* fallback to URL fetching from subject certificate's URIs */
696 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
697 {
698 enumerator = subject->create_ocsp_uri_enumerator(subject);
699 while (enumerator->enumerate(enumerator, &uri))
700 {
701 current = fetch_ocsp(this, uri, &subject->interface,
702 &issuer->interface);
703 if (current)
704 {
705 best = get_better_ocsp(this, current, best, subject, issuer,
706 &valid, TRUE);
707 if (best && valid != VALIDATION_STALE)
708 {
709 break;
710 }
711 }
712 }
713 enumerator->destroy(enumerator);
714 }
715 /* an uri was found, but no result. switch validation state to failed */
716 if (valid == VALIDATION_SKIPPED && uri)
717 {
718 valid = VALIDATION_FAILED;
719 }
720 if (auth)
721 {
722 auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
723 if (valid == VALIDATION_GOOD)
724 { /* successful OCSP check fulfills also CRL constraint */
725 auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
726 }
727 }
728 DESTROY_IF(best);
729 return valid;
730 }
731
732 /**
733 * fetch a CRL from an URL
734 */
735 static certificate_t* fetch_crl(private_credential_manager_t *this, char *url)
736 {
737 certificate_t *crl;
738 chunk_t chunk;
739
740 DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
741 if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
742 {
743 DBG1(DBG_CFG, "crl fetching failed");
744 return NULL;
745 }
746 crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
747 BUILD_BLOB_ASN1_DER, chunk, BUILD_END);
748 chunk_free(&chunk);
749 if (!crl)
750 {
751 DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
752 return NULL;
753 }
754 return crl;
755 }
756
757 /**
758 * check the signature of an CRL
759 */
760 static bool verify_crl(private_credential_manager_t *this, certificate_t *crl)
761 {
762 certificate_t *issuer;
763 enumerator_t *enumerator;
764 bool verified = FALSE;
765
766 enumerator = create_trusted_enumerator(this, KEY_ANY, crl->get_issuer(crl),
767 FALSE);
768 while (enumerator->enumerate(enumerator, &issuer, NULL))
769 {
770 if (this->cache->issued_by(this->cache, crl, issuer))
771 {
772 DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
773 issuer->get_subject(issuer));
774 verified = TRUE;
775 break;
776 }
777 }
778 enumerator->destroy(enumerator);
779
780 return verified;
781 }
782
783 /**
784 * Get the better of two CRLs, and check for usable CRL info
785 */
786 static certificate_t *get_better_crl(private_credential_manager_t *this,
787 certificate_t *cand, certificate_t *best,
788 x509_t *subject, x509_t *issuer,
789 cert_validation_t *valid, bool cache)
790 {
791 enumerator_t *enumerator;
792 time_t revocation, valid_until;
793 crl_reason_t reason;
794 chunk_t serial;
795 crl_t *crl;
796
797 /* check CRL signature */
798 if (!verify_crl(this, cand))
799 {
800 DBG1(DBG_CFG, "crl response verification failed");
801 cand->destroy(cand);
802 return best;
803 }
804
805 crl = (crl_t*)cand;
806 enumerator = crl->create_enumerator(crl);
807 while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
808 {
809 if (chunk_equals(serial, subject->get_serial(subject)))
810 {
811 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
812 &revocation, TRUE, crl_reason_names, reason);
813 *valid = VALIDATION_REVOKED;
814 enumerator->destroy(enumerator);
815 DESTROY_IF(best);
816 return cand;
817 }
818 }
819 enumerator->destroy(enumerator);
820
821 /* select the better of the two CRLs */
822 if (best == NULL || crl_is_newer(crl, (crl_t*)best))
823 {
824 DESTROY_IF(best);
825 best = cand;
826 if (best->get_validity(best, NULL, NULL, &valid_until))
827 {
828 DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
829 *valid = VALIDATION_GOOD;
830 if (cache)
831 { /* we cache non-stale crls only, as a stale crls are refetched */
832 cache_cert(this, best);
833 }
834 }
835 else
836 {
837 DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
838 *valid = VALIDATION_STALE;
839 }
840 }
841 else
842 {
843 *valid = VALIDATION_STALE;
844 cand->destroy(cand);
845 }
846 return best;
847 }
848
849 /**
850 * validate a x509 certificate using CRL
851 */
852 static cert_validation_t check_crl(private_credential_manager_t *this,
853 x509_t *subject, x509_t *issuer,
854 auth_cfg_t *auth)
855 {
856 cert_validation_t valid = VALIDATION_SKIPPED;
857 identification_t *keyid = NULL;
858 certificate_t *best = NULL;
859 certificate_t *current;
860 public_key_t *public;
861 enumerator_t *enumerator;
862 chunk_t chunk;
863 char *uri = NULL;
864
865 /* derive the authorityKeyIdentifier from the issuer's public key */
866 current = &issuer->interface;
867 public = current->get_public_key(current);
868 if (public && public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
869 {
870 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
871
872 /* find a cached crl by authorityKeyIdentifier */
873 enumerator = create_cert_enumerator(this, CERT_X509_CRL, KEY_ANY,
874 keyid, FALSE);
875 while (enumerator->enumerate(enumerator, &current))
876 {
877 current->get_ref(current);
878 best = get_better_crl(this, current, best, subject, issuer,
879 &valid, FALSE);
880 if (best && valid != VALIDATION_STALE)
881 {
882 DBG1(DBG_CFG, " using cached crl");
883 break;
884 }
885 }
886 enumerator->destroy(enumerator);
887
888 /* fallback to fetching crls from credential sets cdps */
889 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
890 {
891 enumerator = create_cdp_enumerator(this, CERT_X509_CRL, keyid);
892
893 while (enumerator->enumerate(enumerator, &uri))
894 {
895 current = fetch_crl(this, uri);
896 if (current)
897 {
898 best = get_better_crl(this, current, best, subject, issuer,
899 &valid, TRUE);
900 if (best && valid != VALIDATION_STALE)
901 {
902 break;
903 }
904 }
905 }
906 enumerator->destroy(enumerator);
907 }
908 keyid->destroy(keyid);
909 }
910 DESTROY_IF(public);
911
912 /* fallback to fetching crls from cdps from subject's certificate */
913 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
914 {
915 enumerator = subject->create_crl_uri_enumerator(subject);
916
917 while (enumerator->enumerate(enumerator, &uri))
918 {
919 current = fetch_crl(this, uri);
920 if (current)
921 {
922 best = get_better_crl(this, current, best, subject, issuer,
923 &valid, TRUE);
924 if (best && valid != VALIDATION_STALE)
925 {
926 break;
927 }
928 }
929 }
930 enumerator->destroy(enumerator);
931 }
932
933 /* an uri was found, but no result. switch validation state to failed */
934 if (valid == VALIDATION_SKIPPED && uri)
935 {
936 valid = VALIDATION_FAILED;
937 }
938 if (auth)
939 {
940 if (valid == VALIDATION_SKIPPED)
941 { /* if we skipped CRL validation, we use the result of OCSP for
942 * constraint checking */
943 auth->add(auth, AUTH_RULE_CRL_VALIDATION,
944 auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
945 }
946 else
947 {
948 auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
949 }
950 }
951 DESTROY_IF(best);
952 return valid;
953 }
954
955 /**
956 * check a certificate for optional IP address block constraints
957 */
958 static bool check_ip_addr_block_constraints(x509_t *subject, x509_t *issuer)
959 {
960 bool subject_constraint = subject->get_flags(subject) & X509_IP_ADDR_BLOCKS;
961 bool issuer_constraint = issuer->get_flags(issuer) & X509_IP_ADDR_BLOCKS;
962 bool contained = TRUE;
963
964 enumerator_t *subject_enumerator, *issuer_enumerator;
965 traffic_selector_t *subject_ts, *issuer_ts;
966
967 if (!subject_constraint && !issuer_constraint)
968 {
969 return TRUE;
970 }
971 if (!subject_constraint)
972 {
973 DBG1(DBG_CFG, "subject certficate lacks ipAddrBlocks extension");
974 return FALSE;
975 }
976 if (!issuer_constraint)
977 {
978 DBG1(DBG_CFG, "issuer certficate lacks ipAddrBlocks extension");
979 return FALSE;
980 }
981 subject_enumerator = subject->create_ipAddrBlock_enumerator(subject);
982 while (subject_enumerator->enumerate(subject_enumerator, &subject_ts))
983 {
984 contained = FALSE;
985
986 issuer_enumerator = issuer->create_ipAddrBlock_enumerator(issuer);
987 while (issuer_enumerator->enumerate(issuer_enumerator, &issuer_ts))
988 {
989 if (subject_ts->is_contained_in(subject_ts, issuer_ts))
990 {
991 DBG2(DBG_CFG, " subject address block %R is contained in "
992 "issuer address block %R", subject_ts, issuer_ts);
993 contained = TRUE;
994 break;
995 }
996 }
997 issuer_enumerator->destroy(issuer_enumerator);
998 if (!contained)
999 {
1000 DBG1(DBG_CFG, "subject address block %R is not contained in any "
1001 "issuer address block", subject_ts);
1002 break;
1003 }
1004 }
1005 subject_enumerator->destroy(subject_enumerator);
1006 return contained;
1007 }
1008
1009 /**
1010 * check a certificate for its lifetime
1011 */
1012 static bool check_certificate(private_credential_manager_t *this,
1013 certificate_t *subject, certificate_t *issuer,
1014 bool online, int pathlen, auth_cfg_t *auth)
1015 {
1016 time_t not_before, not_after;
1017
1018 if (!subject->get_validity(subject, NULL, &not_before, &not_after))
1019 {
1020 DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)",
1021 &not_before, FALSE, &not_after, FALSE);
1022 return FALSE;
1023 }
1024 if (!issuer->get_validity(issuer, NULL, &not_before, &not_after))
1025 {
1026 DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)",
1027 &not_before, FALSE, &not_after, FALSE);
1028 return FALSE;
1029 }
1030 if (issuer->get_type(issuer) == CERT_X509 &&
1031 subject->get_type(subject) == CERT_X509)
1032 {
1033 int pathlen_constraint;
1034 x509_t *x509;
1035
1036 if (!check_ip_addr_block_constraints((x509_t*)subject, (x509_t*)issuer))
1037 {
1038 return FALSE;
1039 }
1040
1041 /* check path length constraint */
1042 x509 = (x509_t*)issuer;
1043 pathlen_constraint = x509->get_pathLenConstraint(x509);
1044 if (pathlen_constraint != X509_NO_PATH_LEN_CONSTRAINT &&
1045 pathlen > pathlen_constraint)
1046 {
1047 DBG1(DBG_CFG, "path length of %d violates constraint of %d",
1048 pathlen, pathlen_constraint);
1049 return FALSE;
1050 }
1051
1052 if (online)
1053 {
1054 DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
1055 subject->get_subject(subject));
1056 switch (check_ocsp(this, (x509_t*)subject, (x509_t*)issuer, auth))
1057 {
1058 case VALIDATION_GOOD:
1059 DBG1(DBG_CFG, "certificate status is good");
1060 return TRUE;
1061 case VALIDATION_REVOKED:
1062 /* has already been logged */
1063 return FALSE;
1064 case VALIDATION_SKIPPED:
1065 DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
1066 break;
1067 case VALIDATION_STALE:
1068 DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
1069 break;
1070 case VALIDATION_FAILED:
1071 DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
1072 break;
1073 }
1074 switch (check_crl(this, (x509_t*)subject, (x509_t*)issuer, auth))
1075 {
1076 case VALIDATION_GOOD:
1077 DBG1(DBG_CFG, "certificate status is good");
1078 return TRUE;
1079 case VALIDATION_REVOKED:
1080 /* has already been logged */
1081 return FALSE;
1082 case VALIDATION_FAILED:
1083 case VALIDATION_SKIPPED:
1084 DBG1(DBG_CFG, "certificate status is not available");
1085 break;
1086 case VALIDATION_STALE:
1087 DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
1088 break;
1089 }
1090 }
1091 }
1092 return TRUE;
1093 }
1094
1095 /**
1096 * Get a trusted certificate from a credential set
1097 */
1098 static certificate_t *get_pretrusted_cert(private_credential_manager_t *this,
1099 key_type_t type, identification_t *id)
1100 {
1101 certificate_t *subject;
1102 public_key_t *public;
1103
1104 subject = get_cert(this, CERT_ANY, type, id, TRUE);
1105 if (!subject)
1106 {
1107 return NULL;
1108 }
1109 public = subject->get_public_key(subject);
1110 if (!public)
1111 {
1112 subject->destroy(subject);
1113 return NULL;
1114 }
1115 public->destroy(public);
1116 return subject;
1117 }
1118
1119 /**
1120 * Get the issuing certificate of a subject certificate
1121 */
1122 static certificate_t *get_issuer_cert(private_credential_manager_t *this,
1123 certificate_t *subject, bool trusted)
1124 {
1125 enumerator_t *enumerator;
1126 certificate_t *issuer = NULL, *candidate;
1127
1128 enumerator = create_cert_enumerator(this, subject->get_type(subject), KEY_ANY,
1129 subject->get_issuer(subject), trusted);
1130 while (enumerator->enumerate(enumerator, &candidate))
1131 {
1132 if (this->cache->issued_by(this->cache, subject, candidate))
1133 {
1134 issuer = candidate->get_ref(candidate);
1135 break;
1136 }
1137 }
1138 enumerator->destroy(enumerator);
1139 return issuer;
1140 }
1141
1142 /**
1143 * try to verify the trust chain of subject, return TRUE if trusted
1144 */
1145 static bool verify_trust_chain(private_credential_manager_t *this,
1146 certificate_t *subject, auth_cfg_t *result,
1147 bool trusted, bool online)
1148 {
1149 certificate_t *current, *issuer;
1150 auth_cfg_t *auth;
1151 int pathlen;
1152
1153 auth = auth_cfg_create();
1154 current = subject->get_ref(subject);
1155
1156 for (pathlen = 0; pathlen <= MAX_TRUST_PATH_LEN; pathlen++)
1157 {
1158 issuer = get_issuer_cert(this, current, TRUE);
1159 if (issuer)
1160 {
1161 /* accept only self-signed CAs as trust anchor */
1162 if (this->cache->issued_by(this->cache, issuer, issuer))
1163 {
1164 auth->add(auth, AUTH_RULE_CA_CERT, issuer->get_ref(issuer));
1165 DBG1(DBG_CFG, " using trusted ca certificate \"%Y\"",
1166 issuer->get_subject(issuer));
1167 trusted = TRUE;
1168 }
1169 else
1170 {
1171 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
1172 DBG1(DBG_CFG, " using trusted intermediate ca certificate "
1173 "\"%Y\"", issuer->get_subject(issuer));
1174 }
1175 }
1176 else
1177 {
1178 issuer = get_issuer_cert(this, current, FALSE);
1179 if (issuer)
1180 {
1181 if (current->equals(current, issuer))
1182 {
1183 DBG1(DBG_CFG, " self-signed certificate \"%Y\" is not trusted",
1184 current->get_subject(current));
1185 issuer->destroy(issuer);
1186 break;
1187 }
1188 auth->add(auth, AUTH_RULE_IM_CERT, issuer->get_ref(issuer));
1189 DBG1(DBG_CFG, " using untrusted intermediate certificate "
1190 "\"%Y\"", issuer->get_subject(issuer));
1191 }
1192 else
1193 {
1194 DBG1(DBG_CFG, "no issuer certificate found for \"%Y\"",
1195 current->get_subject(current));
1196 break;
1197 }
1198 }
1199 if (!check_certificate(this, current, issuer, online, pathlen,
1200 current == subject ? auth : NULL))
1201 {
1202 trusted = FALSE;
1203 issuer->destroy(issuer);
1204 break;
1205 }
1206 current->destroy(current);
1207 current = issuer;
1208 if (trusted)
1209 {
1210 DBG1(DBG_CFG, " reached self-signed root ca with a path length of %d",
1211 pathlen);
1212 break;
1213 }
1214 }
1215 current->destroy(current);
1216 if (pathlen > MAX_TRUST_PATH_LEN)
1217 {
1218 DBG1(DBG_CFG, "maximum path length of %d exceeded", MAX_TRUST_PATH_LEN);
1219 }
1220 if (trusted)
1221 {
1222 result->merge(result, auth, FALSE);
1223 }
1224 auth->destroy(auth);
1225 return trusted;
1226 }
1227
1228 /**
1229 * enumerator for trusted certificates
1230 */
1231 typedef struct {
1232 /** implements enumerator_t interface */
1233 enumerator_t public;
1234 /** enumerator over candidate peer certificates */
1235 enumerator_t *candidates;
1236 /** reference to the credential_manager */
1237 private_credential_manager_t *this;
1238 /** type of the requested key */
1239 key_type_t type;
1240 /** identity the requested key belongs to */
1241 identification_t *id;
1242 /** TRUE to do CRL/OCSP checking */
1243 bool online;
1244 /** pretrusted certificate we have served at first invocation */
1245 certificate_t *pretrusted;
1246 /** currently enumerating auth config */
1247 auth_cfg_t *auth;
1248 } trusted_enumerator_t;
1249
1250 /**
1251 * Implements trusted_enumerator_t.enumerate
1252 */
1253 static bool trusted_enumerate(trusted_enumerator_t *this,
1254 certificate_t **cert, auth_cfg_t **auth)
1255 {
1256 certificate_t *current;
1257
1258 DESTROY_IF(this->auth);
1259 this->auth = auth_cfg_create();
1260
1261 if (!this->candidates)
1262 {
1263 /* first invocation, build enumerator for next one */
1264 this->candidates = create_cert_enumerator(this->this, CERT_ANY,
1265 this->type, this->id, FALSE);
1266 /* check if we have a trusted certificate for that peer */
1267 this->pretrusted = get_pretrusted_cert(this->this, this->type, this->id);
1268 if (this->pretrusted)
1269 {
1270 /* if we find a trusted self signed certificate, we just accept it.
1271 * However, in order to fulfill authorization rules, we try to build
1272 * the trust chain if it is not self signed */
1273 if (this->this->cache->issued_by(this->this->cache,
1274 this->pretrusted, this->pretrusted) ||
1275 verify_trust_chain(this->this, this->pretrusted, this->auth,
1276 TRUE, this->online))
1277 {
1278 this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
1279 this->pretrusted->get_ref(this->pretrusted));
1280 DBG1(DBG_CFG, " using trusted certificate \"%Y\"",
1281 this->pretrusted->get_subject(this->pretrusted));
1282 *cert = this->pretrusted;
1283 if (auth)
1284 {
1285 *auth = this->auth;
1286 }
1287 return TRUE;
1288 }
1289 }
1290 }
1291 /* try to verify the trust chain for each certificate found */
1292 while (this->candidates->enumerate(this->candidates, &current))
1293 {
1294 if (this->pretrusted &&
1295 this->pretrusted->equals(this->pretrusted, current))
1296 { /* skip pretrusted certificate we already served */
1297 continue;
1298 }
1299
1300 DBG1(DBG_CFG, " using certificate \"%Y\"",
1301 current->get_subject(current));
1302 if (verify_trust_chain(this->this, current, this->auth, FALSE,
1303 this->online))
1304 {
1305 *cert = current;
1306 if (auth)
1307 {
1308 *auth = this->auth;
1309 }
1310 return TRUE;
1311 }
1312 }
1313 return FALSE;
1314 }
1315
1316 /**
1317 * Implements trusted_enumerator_t.destroy
1318 */
1319 static void trusted_destroy(trusted_enumerator_t *this)
1320 {
1321 DESTROY_IF(this->pretrusted);
1322 DESTROY_IF(this->auth);
1323 DESTROY_IF(this->candidates);
1324 free(this);
1325 }
1326
1327 /**
1328 * create an enumerator over trusted certificates and their trustchain
1329 */
1330 static enumerator_t *create_trusted_enumerator(private_credential_manager_t *this,
1331 key_type_t type, identification_t *id, bool online)
1332 {
1333 trusted_enumerator_t *enumerator = malloc_thing(trusted_enumerator_t);
1334
1335 enumerator->public.enumerate = (void*)trusted_enumerate;
1336 enumerator->public.destroy = (void*)trusted_destroy;
1337
1338 enumerator->candidates = NULL;
1339 enumerator->this = this;
1340 enumerator->type = type;
1341 enumerator->id = id;
1342 enumerator->online = online;
1343 enumerator->pretrusted = NULL;
1344 enumerator->auth = NULL;
1345
1346 return &enumerator->public;
1347 }
1348
1349 /**
1350 * enumerator for public keys
1351 */
1352 typedef struct {
1353 /** implements enumerator_t interface */
1354 enumerator_t public;
1355 /** enumerator over candidate peer certificates */
1356 enumerator_t *inner;
1357 /** reference to the credential_manager */
1358 private_credential_manager_t *this;
1359 /** currently enumerating key */
1360 public_key_t *current;
1361 /** credset wrapper around auth config */
1362 auth_cfg_wrapper_t *wrapper;
1363 } public_enumerator_t;
1364
1365 /**
1366 * Implements public_enumerator_t.enumerate
1367 */
1368 static bool public_enumerate(public_enumerator_t *this,
1369 public_key_t **key, auth_cfg_t **auth)
1370 {
1371 certificate_t *cert;
1372
1373 while (this->inner->enumerate(this->inner, &cert, auth))
1374 {
1375 DESTROY_IF(this->current);
1376 this->current = cert->get_public_key(cert);
1377 if (this->current)
1378 {
1379 *key = this->current;
1380 return TRUE;
1381 }
1382 }
1383 return FALSE;
1384 }
1385
1386 /**
1387 * Implements public_enumerator_t.destroy
1388 */
1389 static void public_destroy(public_enumerator_t *this)
1390 {
1391 DESTROY_IF(this->current);
1392 this->inner->destroy(this->inner);
1393 if (this->wrapper)
1394 {
1395 remove_local_set(this->this, &this->wrapper->set);
1396 this->wrapper->destroy(this->wrapper);
1397 }
1398 this->this->lock->unlock(this->this->lock);
1399
1400 /* check for delayed certificate cache queue */
1401 cache_queue(this->this);
1402 free(this);
1403 }
1404
1405 /**
1406 * Implementation of credential_manager_t.create_public_enumerator.
1407 */
1408 static enumerator_t* create_public_enumerator(private_credential_manager_t *this,
1409 key_type_t type, identification_t *id, auth_cfg_t *auth)
1410 {
1411 public_enumerator_t *enumerator = malloc_thing(public_enumerator_t);
1412
1413 enumerator->public.enumerate = (void*)public_enumerate;
1414 enumerator->public.destroy = (void*)public_destroy;
1415 enumerator->inner = create_trusted_enumerator(this, type, id, TRUE);
1416 enumerator->this = this;
1417 enumerator->current = NULL;
1418 enumerator->wrapper = NULL;
1419 if (auth)
1420 {
1421 enumerator->wrapper = auth_cfg_wrapper_create(auth);
1422 add_local_set(this, &enumerator->wrapper->set);
1423 }
1424 this->lock->read_lock(this->lock);
1425 return &enumerator->public;
1426 }
1427
1428 /**
1429 * Check if a certificate's keyid is contained in the auth helper
1430 */
1431 static bool auth_contains_cacert(auth_cfg_t *auth, certificate_t *cert)
1432 {
1433 enumerator_t *enumerator;
1434 identification_t *value;
1435 auth_rule_t type;
1436 bool found = FALSE;
1437
1438 enumerator = auth->create_enumerator(auth);
1439 while (enumerator->enumerate(enumerator, &type, &value))
1440 {
1441 if (type == AUTH_RULE_CA_CERT &&
1442 cert->equals(cert, (certificate_t*)value))
1443 {
1444 found = TRUE;
1445 break;
1446 }
1447 }
1448 enumerator->destroy(enumerator);
1449 return found;
1450 }
1451
1452 /**
1453 * build a trustchain from subject up to a trust anchor in trusted
1454 */
1455 static auth_cfg_t *build_trustchain(private_credential_manager_t *this,
1456 certificate_t *subject, auth_cfg_t *auth)
1457 {
1458 certificate_t *issuer, *current;
1459 auth_cfg_t *trustchain;
1460 int pathlen = 0;
1461
1462 trustchain = auth_cfg_create();
1463
1464 current = auth->get(auth, AUTH_RULE_CA_CERT);
1465 if (!current)
1466 {
1467 /* no trust anchor specified, return this cert only */
1468 trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT,
1469 subject->get_ref(subject));
1470 return trustchain;
1471 }
1472 current = subject->get_ref(subject);
1473 while (TRUE)
1474 {
1475 if (auth_contains_cacert(auth, current))
1476 {
1477 trustchain->add(trustchain, AUTH_RULE_CA_CERT, current);
1478 return trustchain;
1479 }
1480 if (subject == current)
1481 {
1482 trustchain->add(trustchain, AUTH_RULE_SUBJECT_CERT, current);
1483 }
1484 else
1485 {
1486 trustchain->add(trustchain, AUTH_RULE_IM_CERT, current);
1487 }
1488 issuer = get_issuer_cert(this, current, FALSE);
1489 if (!issuer || issuer->equals(issuer, current) ||
1490 pathlen > MAX_TRUST_PATH_LEN)
1491 {
1492 DESTROY_IF(issuer);
1493 break;
1494 }
1495 current = issuer;
1496 pathlen++;
1497 }
1498 trustchain->destroy(trustchain);
1499 return NULL;
1500 }
1501
1502 /**
1503 * find a private key of a give certificate
1504 */
1505 static private_key_t *get_private_by_cert(private_credential_manager_t *this,
1506 certificate_t *cert, key_type_t type)
1507 {
1508 private_key_t *private = NULL;
1509 identification_t *keyid;
1510 chunk_t chunk;
1511 public_key_t *public;
1512
1513 public = cert->get_public_key(cert);
1514 if (public)
1515 {
1516 if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &chunk))
1517 {
1518 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
1519 private = get_private_by_keyid(this, type, keyid);
1520 keyid->destroy(keyid);
1521 }
1522 public->destroy(public);
1523 }
1524 return private;
1525 }
1526
1527 /**
1528 * Implementation of credential_manager_t.get_private.
1529 */
1530 static private_key_t *get_private(private_credential_manager_t *this,
1531 key_type_t type, identification_t *id,
1532 auth_cfg_t *auth)
1533 {
1534 enumerator_t *enumerator;
1535 certificate_t *cert;
1536 private_key_t *private = NULL;
1537 auth_cfg_t *trustchain;
1538
1539 /* check if this is a lookup by key ID, and do it if so */
1540 if (id && id->get_type(id) == ID_KEY_ID)
1541 {
1542 private = get_private_by_keyid(this, type, id);
1543 if (private)
1544 {
1545 return private;
1546 }
1547 }
1548
1549 /* if a specific certificate is preferred, check for a matching key */
1550 cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT);
1551 if (cert)
1552 {
1553 private = get_private_by_cert(this, cert, type);
1554 if (private)
1555 {
1556 trustchain = build_trustchain(this, cert, auth);
1557 if (trustchain)
1558 {
1559 auth->merge(auth, trustchain, FALSE);
1560 trustchain->destroy(trustchain);
1561 }
1562 return private;
1563 }
1564 }
1565
1566 /* try to build a trust chain for each certificate found */
1567 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1568 while (enumerator->enumerate(enumerator, &cert))
1569 {
1570 private = get_private_by_cert(this, cert, type);
1571 if (private)
1572 {
1573 trustchain = build_trustchain(this, cert, auth);
1574 if (trustchain)
1575 {
1576 auth->merge(auth, trustchain, FALSE);
1577 trustchain->destroy(trustchain);
1578 break;
1579 }
1580 private->destroy(private);
1581 private = NULL;
1582 }
1583 }
1584 enumerator->destroy(enumerator);
1585
1586 /* if no valid trustchain was found, fall back to the first usable cert */
1587 if (!private)
1588 {
1589 enumerator = create_cert_enumerator(this, CERT_ANY, type, id, FALSE);
1590 while (enumerator->enumerate(enumerator, &cert))
1591 {
1592 private = get_private_by_cert(this, cert, type);
1593 if (private)
1594 {
1595 auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
1596 break;
1597 }
1598 }
1599 enumerator->destroy(enumerator);
1600 }
1601 return private;
1602 }
1603
1604 /**
1605 * Implementation of credential_manager_t.flush_cache.
1606 */
1607 static void flush_cache(private_credential_manager_t *this,
1608 certificate_type_t type)
1609 {
1610 this->cache->flush(this->cache, type);
1611 }
1612
1613 /**
1614 * Implementation of credential_manager_t.add_set.
1615 */
1616 static void add_set(private_credential_manager_t *this,
1617 credential_set_t *set)
1618 {
1619 this->lock->write_lock(this->lock);
1620 this->sets->insert_last(this->sets, set);
1621 this->lock->unlock(this->lock);
1622 }
1623
1624 /**
1625 * Implementation of credential_manager_t.remove_set.
1626 */
1627 static void remove_set(private_credential_manager_t *this, credential_set_t *set)
1628 {
1629 this->lock->write_lock(this->lock);
1630 this->sets->remove(this->sets, set, NULL);
1631 this->lock->unlock(this->lock);
1632 }
1633
1634 /**
1635 * Implementation of credential_manager_t.destroy
1636 */
1637 static void destroy(private_credential_manager_t *this)
1638 {
1639 cache_queue(this);
1640 this->cache_queue->destroy(this->cache_queue);
1641 this->sets->remove(this->sets, this->cache, NULL);
1642 this->sets->destroy(this->sets);
1643 this->local_sets->destroy(this->local_sets);
1644 this->cache->destroy(this->cache);
1645 this->lock->destroy(this->lock);
1646 this->queue_mutex->destroy(this->queue_mutex);
1647 free(this);
1648 }
1649
1650 /*
1651 * see header file
1652 */
1653 credential_manager_t *credential_manager_create()
1654 {
1655 private_credential_manager_t *this = malloc_thing(private_credential_manager_t);
1656
1657 this->public.create_cert_enumerator = (enumerator_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *id,bool))create_cert_enumerator;
1658 this->public.create_shared_enumerator = (enumerator_t *(*)(credential_manager_t *this, shared_key_type_t type,identification_t *me, identification_t *other))create_shared_enumerator;
1659 this->public.create_cdp_enumerator = (enumerator_t *(*)(credential_manager_t*, certificate_type_t type, identification_t *id))create_cdp_enumerator;
1660 this->public.get_cert = (certificate_t *(*)(credential_manager_t *this,certificate_type_t cert, key_type_t key,identification_t *, bool))get_cert;
1661 this->public.get_shared = (shared_key_t *(*)(credential_manager_t *this,shared_key_type_t type,identification_t *me, identification_t *other))get_shared;
1662 this->public.get_private = (private_key_t*(*)(credential_manager_t*, key_type_t type, identification_t *, auth_cfg_t*))get_private;
1663 this->public.create_public_enumerator = (enumerator_t*(*)(credential_manager_t*, key_type_t type, identification_t *id, auth_cfg_t *aut))create_public_enumerator;
1664 this->public.flush_cache = (void(*)(credential_manager_t*, certificate_type_t type))flush_cache;
1665 this->public.cache_cert = (void(*)(credential_manager_t*, certificate_t *cert))cache_cert;
1666 this->public.add_set = (void(*)(credential_manager_t*, credential_set_t *set))add_set;
1667 this->public.remove_set = (void(*)(credential_manager_t*, credential_set_t *set))remove_set;
1668 this->public.destroy = (void(*)(credential_manager_t*))destroy;
1669
1670 this->sets = linked_list_create();
1671 this->local_sets = thread_value_create((thread_cleanup_t)this->sets->destroy);
1672 this->cache = cert_cache_create();
1673 this->cache_queue = linked_list_create();
1674 this->sets->insert_first(this->sets, this->cache);
1675 this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
1676 this->queue_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
1677
1678 return &this->public;
1679 }