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