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