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