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