asn1: Fix a compiler warning with GCC 9.1
[strongswan.git] / src / libstrongswan / plugins / revocation / revocation_validator.c
1 /*
2 * Copyright (C) 2015-2018 Tobias Brunner
3 * Copyright (C) 2010 Martin Willi
4 * Copyright (C) 2010 revosec AG
5 * Copyright (C) 2009 Andreas Steffen
6 * HSR Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include <time.h>
20
21 #include "revocation_validator.h"
22
23 #include <utils/debug.h>
24 #include <credentials/certificates/x509.h>
25 #include <credentials/certificates/crl.h>
26 #include <credentials/certificates/ocsp_request.h>
27 #include <credentials/certificates/ocsp_response.h>
28 #include <credentials/sets/ocsp_response_wrapper.h>
29 #include <selectors/traffic_selector.h>
30 #include <threading/spinlock.h>
31
32 typedef struct private_revocation_validator_t private_revocation_validator_t;
33
34 /**
35 * Private data of an revocation_validator_t object.
36 */
37 struct private_revocation_validator_t {
38
39 /**
40 * Public revocation_validator_t interface.
41 */
42 revocation_validator_t public;
43
44 /**
45 * Enable OCSP validation
46 */
47 bool enable_ocsp;
48
49 /**
50 * Enable CRL validation
51 */
52 bool enable_crl;
53
54 /**
55 * Lock to access flags
56 */
57 spinlock_t *lock;
58 };
59
60 /**
61 * Do an OCSP request
62 */
63 static certificate_t *fetch_ocsp(char *url, certificate_t *subject,
64 certificate_t *issuer)
65 {
66 certificate_t *request, *response;
67 chunk_t send, receive = chunk_empty;
68
69 /* TODO: requestor name, signature */
70 request = lib->creds->create(lib->creds,
71 CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
72 BUILD_CA_CERT, issuer,
73 BUILD_CERT, subject, BUILD_END);
74 if (!request)
75 {
76 DBG1(DBG_CFG, "generating ocsp request failed");
77 return NULL;
78 }
79
80 if (!request->get_encoding(request, CERT_ASN1_DER, &send))
81 {
82 DBG1(DBG_CFG, "encoding ocsp request failed");
83 request->destroy(request);
84 return NULL;
85 }
86 request->destroy(request);
87
88 DBG1(DBG_CFG, " requesting ocsp status from '%s' ...", url);
89 if (lib->fetcher->fetch(lib->fetcher, url, &receive,
90 FETCH_REQUEST_DATA, send,
91 FETCH_REQUEST_TYPE, "application/ocsp-request",
92 FETCH_END) != SUCCESS)
93 {
94 DBG1(DBG_CFG, "ocsp request to %s failed", url);
95 chunk_free(&receive);
96 chunk_free(&send);
97 return NULL;
98 }
99 chunk_free(&send);
100
101 response = lib->creds->create(lib->creds,
102 CRED_CERTIFICATE, CERT_X509_OCSP_RESPONSE,
103 BUILD_BLOB_ASN1_DER, receive, BUILD_END);
104 chunk_free(&receive);
105 if (!response)
106 {
107 DBG1(DBG_CFG, "parsing ocsp response failed");
108 return NULL;
109 }
110 return response;
111 }
112
113 /**
114 * check the signature of an OCSP response
115 */
116 static bool verify_ocsp(ocsp_response_t *response, certificate_t *ca)
117 {
118 certificate_t *issuer, *subject;
119 identification_t *responder;
120 ocsp_response_wrapper_t *wrapper;
121 enumerator_t *enumerator;
122 x509_t *x509;
123 bool verified = FALSE, found = FALSE;
124
125 wrapper = ocsp_response_wrapper_create((ocsp_response_t*)response);
126 lib->credmgr->add_local_set(lib->credmgr, &wrapper->set, FALSE);
127
128 subject = &response->certificate;
129 responder = subject->get_issuer(subject);
130
131 /* check OCSP response using CA or directly delegated OCSP signer */
132 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr, CERT_X509,
133 KEY_ANY, responder, FALSE);
134 while (enumerator->enumerate(enumerator, &issuer))
135 {
136 x509 = (x509_t*)issuer;
137 if (!issuer->get_validity(issuer, NULL, NULL, NULL))
138 { /* OCSP signer currently invalid */
139 continue;
140 }
141 if (!ca->equals(ca, issuer))
142 { /* delegated OCSP signer? */
143 if (!lib->credmgr->issued_by(lib->credmgr, issuer, ca, NULL))
144 { /* OCSP response not signed by CA, nor delegated OCSP signer */
145 continue;
146 }
147 if (!(x509->get_flags(x509) & X509_OCSP_SIGNER))
148 { /* delegated OCSP signer does not have OCSP signer flag */
149 continue;
150 }
151 }
152 found = TRUE;
153 if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL))
154 {
155 DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
156 issuer->get_subject(issuer));
157 verified = TRUE;
158 break;
159 }
160 DBG1(DBG_CFG, "ocsp response verification failed, "
161 "invalid signature");
162 }
163 enumerator->destroy(enumerator);
164
165 if (!verified)
166 {
167 /* as fallback, use any locally installed OCSP signer certificate */
168 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
169 CERT_X509, KEY_ANY, responder, TRUE);
170 while (enumerator->enumerate(enumerator, &issuer))
171 {
172 x509 = (x509_t*)issuer;
173 /* while issued_by() accepts both OCSP signer or CA basic
174 * constraint flags to verify OCSP responses, unrelated but trusted
175 * OCSP signers must explicitly have the OCSP signer flag set. */
176 if ((x509->get_flags(x509) & X509_OCSP_SIGNER) &&
177 issuer->get_validity(issuer, NULL, NULL, NULL))
178 {
179 found = TRUE;
180 if (lib->credmgr->issued_by(lib->credmgr, subject, issuer, NULL))
181 {
182 DBG1(DBG_CFG, " ocsp response correctly signed by \"%Y\"",
183 issuer->get_subject(issuer));
184 verified = TRUE;
185 break;
186 }
187 DBG1(DBG_CFG, "ocsp response verification failed, "
188 "invalid signature");
189 }
190 }
191 enumerator->destroy(enumerator);
192 }
193
194 lib->credmgr->remove_local_set(lib->credmgr, &wrapper->set);
195 wrapper->destroy(wrapper);
196
197 if (!found)
198 {
199 DBG1(DBG_CFG, "ocsp response verification failed, "
200 "no signer certificate '%Y' found", responder);
201 }
202 return verified;
203 }
204
205 /**
206 * Get the better of two OCSP responses, and check for usable OCSP info
207 */
208 static certificate_t *get_better_ocsp(certificate_t *cand, certificate_t *best,
209 x509_t *subject, x509_t *issuer,
210 cert_validation_t *valid, bool cache)
211 {
212 ocsp_response_t *response;
213 time_t revocation, this_update, next_update, valid_until;
214 crl_reason_t reason;
215 bool revoked = FALSE;
216
217 response = (ocsp_response_t*)cand;
218
219 /* check ocsp signature */
220 if (!verify_ocsp(response, &issuer->interface))
221 {
222 cand->destroy(cand);
223 return best;
224 }
225 /* check if response contains our certificate */
226 switch (response->get_status(response, subject, issuer, &revocation, &reason,
227 &this_update, &next_update))
228 {
229 case VALIDATION_REVOKED:
230 /* subject has been revoked by a valid OCSP response */
231 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
232 &revocation, TRUE, crl_reason_names, reason);
233 revoked = TRUE;
234 break;
235 case VALIDATION_GOOD:
236 /* results in either good or stale */
237 break;
238 default:
239 case VALIDATION_FAILED:
240 /* candidate unusable, does not contain our cert */
241 DBG1(DBG_CFG, " ocsp response contains no status on our certificate");
242 cand->destroy(cand);
243 return best;
244 }
245
246 /* select the better of the two responses */
247 if (best == NULL || certificate_is_newer(cand, best))
248 {
249 DESTROY_IF(best);
250 best = cand;
251 if (best->get_validity(best, NULL, NULL, &valid_until))
252 {
253 DBG1(DBG_CFG, " ocsp response is valid: until %T",
254 &valid_until, FALSE);
255 *valid = VALIDATION_GOOD;
256 if (cache)
257 { /* cache non-stale only, stale certs get refetched */
258 lib->credmgr->cache_cert(lib->credmgr, best);
259 }
260 }
261 else
262 {
263 DBG1(DBG_CFG, " ocsp response is stale: since %T",
264 &valid_until, FALSE);
265 *valid = VALIDATION_STALE;
266 }
267 }
268 else
269 {
270 *valid = VALIDATION_STALE;
271 cand->destroy(cand);
272 }
273 if (revoked)
274 { /* revoked always counts, even if stale */
275 *valid = VALIDATION_REVOKED;
276 }
277 return best;
278 }
279
280 /**
281 * validate a x509 certificate using OCSP
282 */
283 static cert_validation_t check_ocsp(x509_t *subject, x509_t *issuer,
284 auth_cfg_t *auth)
285 {
286 enumerator_t *enumerator;
287 cert_validation_t valid = VALIDATION_SKIPPED;
288 certificate_t *best = NULL, *current;
289 identification_t *keyid = NULL;
290 public_key_t *public;
291 chunk_t chunk;
292 char *uri = NULL;
293
294 /** lookup cache for valid OCSP responses */
295 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
296 CERT_X509_OCSP_RESPONSE, KEY_ANY, NULL, FALSE);
297 while (enumerator->enumerate(enumerator, &current))
298 {
299 current->get_ref(current);
300 best = get_better_ocsp(current, best, subject, issuer, &valid, FALSE);
301 if (best && valid != VALIDATION_STALE)
302 {
303 DBG1(DBG_CFG, " using cached ocsp response");
304 break;
305 }
306 }
307 enumerator->destroy(enumerator);
308
309 /* derive the authorityKeyIdentifier from the issuer's public key */
310 current = &issuer->interface;
311 public = current->get_public_key(current);
312 if (public && public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &chunk))
313 {
314 keyid = identification_create_from_encoding(ID_KEY_ID, chunk);
315 }
316 /** fetch from configured OCSP responder URLs */
317 if (keyid && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
318 {
319 enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
320 CERT_X509_OCSP_RESPONSE, keyid);
321 while (enumerator->enumerate(enumerator, &uri))
322 {
323 current = fetch_ocsp(uri, &subject->interface, &issuer->interface);
324 if (current)
325 {
326 best = get_better_ocsp(current, best, subject, issuer,
327 &valid, TRUE);
328 if (best && valid != VALIDATION_STALE)
329 {
330 break;
331 }
332 }
333 }
334 enumerator->destroy(enumerator);
335 }
336 DESTROY_IF(public);
337 DESTROY_IF(keyid);
338
339 /* fallback to URL fetching from subject certificate's URIs */
340 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
341 {
342 enumerator = subject->create_ocsp_uri_enumerator(subject);
343 while (enumerator->enumerate(enumerator, &uri))
344 {
345 current = fetch_ocsp(uri, &subject->interface, &issuer->interface);
346 if (current)
347 {
348 best = get_better_ocsp(current, best, subject, issuer,
349 &valid, TRUE);
350 if (best && valid != VALIDATION_STALE)
351 {
352 break;
353 }
354 }
355 }
356 enumerator->destroy(enumerator);
357 }
358 /* an uri was found, but no result. switch validation state to failed */
359 if (valid == VALIDATION_SKIPPED && uri)
360 {
361 valid = VALIDATION_FAILED;
362 }
363 auth->add(auth, AUTH_RULE_OCSP_VALIDATION, valid);
364 if (valid == VALIDATION_GOOD)
365 { /* successful OCSP check fulfills also CRL constraint */
366 auth->add(auth, AUTH_RULE_CRL_VALIDATION, VALIDATION_GOOD);
367 }
368 DESTROY_IF(best);
369 return valid;
370 }
371
372 /**
373 * fetch a CRL from an URL
374 */
375 static certificate_t* fetch_crl(char *url)
376 {
377 certificate_t *crl;
378 chunk_t chunk = chunk_empty;
379
380 DBG1(DBG_CFG, " fetching crl from '%s' ...", url);
381 if (lib->fetcher->fetch(lib->fetcher, url, &chunk, FETCH_END) != SUCCESS)
382 {
383 DBG1(DBG_CFG, "crl fetching failed");
384 chunk_free(&chunk);
385 return NULL;
386 }
387 crl = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_CRL,
388 BUILD_BLOB_PEM, chunk, BUILD_END);
389 chunk_free(&chunk);
390 if (!crl)
391 {
392 DBG1(DBG_CFG, "crl fetched successfully but parsing failed");
393 return NULL;
394 }
395 return crl;
396 }
397
398 /**
399 * check the signature of an CRL
400 */
401 static bool verify_crl(certificate_t *crl)
402 {
403 certificate_t *issuer;
404 enumerator_t *enumerator;
405 bool verified = FALSE;
406
407 enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
408 KEY_ANY, crl->get_issuer(crl), FALSE);
409 while (enumerator->enumerate(enumerator, &issuer, NULL))
410 {
411 if (lib->credmgr->issued_by(lib->credmgr, crl, issuer, NULL))
412 {
413 DBG1(DBG_CFG, " crl correctly signed by \"%Y\"",
414 issuer->get_subject(issuer));
415 verified = TRUE;
416 break;
417 }
418 }
419 enumerator->destroy(enumerator);
420
421 return verified;
422 }
423
424 /**
425 * Report the given CRL's validity and cache it if valid and requested
426 */
427 static bool is_crl_valid(certificate_t *crl, time_t now, bool cache)
428 {
429 time_t valid_until;
430
431 if (crl->get_validity(crl, &now, NULL, &valid_until))
432 {
433 DBG1(DBG_CFG, " crl is valid: until %T", &valid_until, FALSE);
434 if (cache)
435 {
436 lib->credmgr->cache_cert(lib->credmgr, crl);
437 }
438 return TRUE;
439 }
440 DBG1(DBG_CFG, " crl is stale: since %T", &valid_until, FALSE);
441 return FALSE;
442 }
443
444 /**
445 * Check if the CRL should be used yet
446 */
447 static bool is_crl_not_valid_yet(certificate_t *crl, time_t now)
448 {
449 time_t this_update;
450
451 if (!crl->get_validity(crl, &now, &this_update, NULL))
452 {
453 if (this_update > now)
454 {
455 DBG1(DBG_CFG, " crl is not valid: until %T", &this_update, FALSE);
456 return TRUE;
457 }
458 /* we accept stale CRLs */
459 }
460 return FALSE;
461 }
462
463 /**
464 * Get the better of two CRLs, and check for usable CRL info
465 */
466 static certificate_t *get_better_crl(certificate_t *cand, certificate_t *best,
467 x509_t *subject, cert_validation_t *valid,
468 bool cache, crl_t *base)
469 {
470 enumerator_t *enumerator;
471 time_t now, revocation;
472 crl_reason_t reason;
473 chunk_t subject_serial, serial;
474 crl_t *crl = (crl_t*)cand;
475
476 if (base)
477 {
478 if (!crl->is_delta_crl(crl, &serial) ||
479 !chunk_equals(serial, base->get_serial(base)))
480 {
481 cand->destroy(cand);
482 return best;
483 }
484 }
485 else
486 {
487 if (crl->is_delta_crl(crl, NULL))
488 {
489 cand->destroy(cand);
490 return best;
491 }
492 }
493
494 /* check CRL signature */
495 if (!verify_crl(cand))
496 {
497 DBG1(DBG_CFG, "crl response verification failed");
498 cand->destroy(cand);
499 return best;
500 }
501 now = time(NULL);
502 if (is_crl_not_valid_yet(cand, now))
503 {
504 cand->destroy(cand);
505 return best;
506 }
507
508 subject_serial = chunk_skip_zero(subject->get_serial(subject));
509 enumerator = crl->create_enumerator(crl);
510 while (enumerator->enumerate(enumerator, &serial, &revocation, &reason))
511 {
512 if (chunk_equals(subject_serial, chunk_skip_zero(serial)))
513 {
514 if (reason != CRL_REASON_CERTIFICATE_HOLD)
515 {
516 *valid = VALIDATION_REVOKED;
517 }
518 else
519 {
520 /* if the cert is on hold, a newer CRL might not contain it */
521 *valid = VALIDATION_ON_HOLD;
522 }
523 is_crl_valid(cand, now, cache);
524 DBG1(DBG_CFG, "certificate was revoked on %T, reason: %N",
525 &revocation, TRUE, crl_reason_names, reason);
526 enumerator->destroy(enumerator);
527 DESTROY_IF(best);
528 return cand;
529 }
530 }
531 enumerator->destroy(enumerator);
532
533 /* select the better of the two CRLs */
534 if (best == NULL || crl_is_newer(crl, (crl_t*)best))
535 {
536 DESTROY_IF(best);
537 best = cand;
538 if (is_crl_valid(best, now, cache))
539 {
540 *valid = VALIDATION_GOOD;
541 }
542 else
543 {
544 *valid = VALIDATION_STALE;
545 }
546 }
547 else
548 {
549 *valid = VALIDATION_STALE;
550 cand->destroy(cand);
551 }
552 return best;
553 }
554
555 /**
556 * Find or fetch a certificate for a given crlIssuer
557 */
558 static cert_validation_t find_crl(x509_t *subject, identification_t *issuer,
559 crl_t *base, certificate_t **best,
560 bool *uri_found)
561 {
562 cert_validation_t valid = VALIDATION_SKIPPED;
563 enumerator_t *enumerator;
564 certificate_t *current;
565 char *uri;
566
567 /* find a cached (delta) crl */
568 enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
569 CERT_X509_CRL, KEY_ANY, issuer, FALSE);
570 while (enumerator->enumerate(enumerator, &current))
571 {
572 current->get_ref(current);
573 *best = get_better_crl(current, *best, subject, &valid, FALSE, base);
574 if (*best && valid != VALIDATION_STALE)
575 {
576 DBG1(DBG_CFG, " using cached crl");
577 break;
578 }
579 }
580 enumerator->destroy(enumerator);
581
582 /* fallback to fetching crls from credential sets cdps */
583 if (!base && valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
584 {
585 enumerator = lib->credmgr->create_cdp_enumerator(lib->credmgr,
586 CERT_X509_CRL, issuer);
587 while (enumerator->enumerate(enumerator, &uri))
588 {
589 *uri_found = TRUE;
590 current = fetch_crl(uri);
591 if (current)
592 {
593 if (!current->has_issuer(current, issuer))
594 {
595 DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match CRL "
596 "issuer '%Y'", current->get_issuer(current), issuer);
597 current->destroy(current);
598 continue;
599 }
600 *best = get_better_crl(current, *best, subject,
601 &valid, TRUE, base);
602 if (*best && valid != VALIDATION_STALE)
603 {
604 break;
605 }
606 }
607 }
608 enumerator->destroy(enumerator);
609 }
610 return valid;
611 }
612
613 /**
614 * Check if the issuer of the given CRL matches
615 */
616 static bool check_issuer(certificate_t *crl, x509_t *issuer, x509_cdp_t *cdp)
617 {
618 certificate_t *cissuer = (certificate_t*)issuer;
619 identification_t *id;
620 chunk_t chunk;
621 bool matches = FALSE;
622
623 if (cdp->issuer)
624 {
625 return crl->has_issuer(crl, cdp->issuer);
626 }
627 /* check SKI/AKI first, but fall back to DN matching */
628 chunk = issuer->get_subjectKeyIdentifier(issuer);
629 if (chunk.len)
630 {
631 id = identification_create_from_encoding(ID_KEY_ID, chunk);
632 matches = crl->has_issuer(crl, id);
633 id->destroy(id);
634 }
635 return matches || crl->has_issuer(crl, cissuer->get_subject(cissuer));
636 }
637
638 /**
639 * Look for a delta CRL for a given base CRL
640 */
641 static cert_validation_t check_delta_crl(x509_t *subject, x509_t *issuer,
642 crl_t *base, cert_validation_t base_valid)
643 {
644 cert_validation_t valid = VALIDATION_SKIPPED;
645 certificate_t *best = NULL, *current, *cissuer = (certificate_t*)issuer;
646 enumerator_t *enumerator;
647 identification_t *id;
648 x509_cdp_t *cdp;
649 chunk_t chunk;
650 bool uri;
651
652 /* find cached delta CRL via subjectKeyIdentifier */
653 chunk = issuer->get_subjectKeyIdentifier(issuer);
654 if (chunk.len)
655 {
656 id = identification_create_from_encoding(ID_KEY_ID, chunk);
657 valid = find_crl(subject, id, base, &best, &uri);
658 id->destroy(id);
659 }
660
661 /* find delta CRL by CRLIssuer */
662 enumerator = subject->create_crl_uri_enumerator(subject);
663 while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
664 enumerator->enumerate(enumerator, &cdp))
665 {
666 if (cdp->issuer)
667 {
668 valid = find_crl(subject, cdp->issuer, base, &best, &uri);
669 }
670 }
671 enumerator->destroy(enumerator);
672
673 /* fetch from URIs found in Freshest CRL extension */
674 enumerator = base->create_delta_crl_uri_enumerator(base);
675 while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
676 enumerator->enumerate(enumerator, &cdp))
677 {
678 current = fetch_crl(cdp->uri);
679 if (current)
680 {
681 if (!check_issuer(current, issuer, cdp))
682 {
683 DBG1(DBG_CFG, "issuer of fetched delta CRL '%Y' does not match "
684 "certificate's %sissuer '%Y'",
685 current->get_issuer(current), cdp->issuer ? "CRL " : "",
686 cdp->issuer ?: cissuer->get_subject(cissuer));
687 current->destroy(current);
688 continue;
689 }
690 best = get_better_crl(current, best, subject, &valid, TRUE, base);
691 if (best && valid != VALIDATION_STALE)
692 {
693 break;
694 }
695 }
696 }
697 enumerator->destroy(enumerator);
698
699 if (best)
700 {
701 best->destroy(best);
702 return valid;
703 }
704 return base_valid;
705 }
706
707 /**
708 * validate a x509 certificate using CRL
709 */
710 static cert_validation_t check_crl(x509_t *subject, x509_t *issuer,
711 auth_cfg_t *auth)
712 {
713 cert_validation_t valid = VALIDATION_SKIPPED;
714 certificate_t *best = NULL, *cissuer = (certificate_t*)issuer;
715 identification_t *id;
716 x509_cdp_t *cdp;
717 bool uri_found = FALSE;
718 certificate_t *current;
719 enumerator_t *enumerator;
720 chunk_t chunk;
721
722 /* use issuers subjectKeyIdentifier to find a cached CRL / fetch from CDP */
723 chunk = issuer->get_subjectKeyIdentifier(issuer);
724 if (chunk.len)
725 {
726 id = identification_create_from_encoding(ID_KEY_ID, chunk);
727 valid = find_crl(subject, id, NULL, &best, &uri_found);
728 id->destroy(id);
729 }
730
731 /* find a cached CRL or fetch via configured CDP via CRLIssuer */
732 enumerator = subject->create_crl_uri_enumerator(subject);
733 while (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED &&
734 enumerator->enumerate(enumerator, &cdp))
735 {
736 if (cdp->issuer)
737 {
738 valid = find_crl(subject, cdp->issuer, NULL, &best, &uri_found);
739 }
740 }
741 enumerator->destroy(enumerator);
742
743 /* fallback to fetching CRLs from CDPs found in subjects certificate */
744 if (valid != VALIDATION_GOOD && valid != VALIDATION_REVOKED)
745 {
746 enumerator = subject->create_crl_uri_enumerator(subject);
747 while (enumerator->enumerate(enumerator, &cdp))
748 {
749 uri_found = TRUE;
750 current = fetch_crl(cdp->uri);
751 if (current)
752 {
753 if (!check_issuer(current, issuer, cdp))
754 {
755 DBG1(DBG_CFG, "issuer of fetched CRL '%Y' does not match "
756 "certificate's %sissuer '%Y'",
757 current->get_issuer(current), cdp->issuer ? "CRL " : "",
758 cdp->issuer ?: cissuer->get_subject(cissuer));
759 current->destroy(current);
760 continue;
761 }
762 best = get_better_crl(current, best, subject, &valid,
763 TRUE, NULL);
764 if (best && valid != VALIDATION_STALE)
765 {
766 break;
767 }
768 }
769 }
770 enumerator->destroy(enumerator);
771 }
772
773 /* look for delta CRLs */
774 if (best && (valid == VALIDATION_GOOD || valid == VALIDATION_STALE))
775 {
776 valid = check_delta_crl(subject, issuer, (crl_t*)best, valid);
777 }
778
779 /* an uri was found, but no result. switch validation state to failed */
780 if (valid == VALIDATION_SKIPPED && uri_found)
781 {
782 valid = VALIDATION_FAILED;
783 }
784 if (valid == VALIDATION_SKIPPED)
785 { /* if we skipped CRL validation, we use the result of OCSP for
786 * constraint checking */
787 auth->add(auth, AUTH_RULE_CRL_VALIDATION,
788 auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
789 }
790 else
791 {
792 auth->add(auth, AUTH_RULE_CRL_VALIDATION, valid);
793 }
794 DESTROY_IF(best);
795 return valid;
796 }
797
798 METHOD(cert_validator_t, validate, bool,
799 private_revocation_validator_t *this, certificate_t *subject,
800 certificate_t *issuer, bool online, u_int pathlen, bool anchor,
801 auth_cfg_t *auth)
802 {
803 bool enable_ocsp, enable_crl;
804
805 this->lock->lock(this->lock);
806 enable_ocsp = this->enable_ocsp;
807 enable_crl = this->enable_crl;
808 this->lock->unlock(this->lock);
809
810 if (online && (enable_ocsp || enable_crl) &&
811 subject->get_type(subject) == CERT_X509 &&
812 issuer->get_type(issuer) == CERT_X509)
813 {
814 DBG1(DBG_CFG, "checking certificate status of \"%Y\"",
815 subject->get_subject(subject));
816
817 if (enable_ocsp)
818 {
819 switch (check_ocsp((x509_t*)subject, (x509_t*)issuer, auth))
820 {
821 case VALIDATION_GOOD:
822 DBG1(DBG_CFG, "certificate status is good");
823 return TRUE;
824 case VALIDATION_REVOKED:
825 case VALIDATION_ON_HOLD:
826 /* has already been logged */
827 lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_REVOKED,
828 subject);
829 return FALSE;
830 case VALIDATION_SKIPPED:
831 DBG2(DBG_CFG, "ocsp check skipped, no ocsp found");
832 break;
833 case VALIDATION_STALE:
834 DBG1(DBG_CFG, "ocsp information stale, fallback to crl");
835 break;
836 case VALIDATION_FAILED:
837 DBG1(DBG_CFG, "ocsp check failed, fallback to crl");
838 break;
839 }
840 }
841 else
842 {
843 auth->add(auth, AUTH_RULE_OCSP_VALIDATION, VALIDATION_SKIPPED);
844 }
845
846 if (enable_crl)
847 {
848 switch (check_crl((x509_t*)subject, (x509_t*)issuer, auth))
849 {
850 case VALIDATION_GOOD:
851 DBG1(DBG_CFG, "certificate status is good");
852 return TRUE;
853 case VALIDATION_REVOKED:
854 case VALIDATION_ON_HOLD:
855 /* has already been logged */
856 lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_REVOKED,
857 subject);
858 return FALSE;
859 case VALIDATION_FAILED:
860 case VALIDATION_SKIPPED:
861 DBG1(DBG_CFG, "certificate status is not available");
862 break;
863 case VALIDATION_STALE:
864 DBG1(DBG_CFG, "certificate status is unknown, crl is stale");
865 break;
866 }
867 }
868 else
869 {
870 auth->add(auth, AUTH_RULE_CRL_VALIDATION,
871 auth->get(auth, AUTH_RULE_OCSP_VALIDATION));
872 }
873
874 lib->credmgr->call_hook(lib->credmgr, CRED_HOOK_VALIDATION_FAILED,
875 subject);
876 }
877 return TRUE;
878 }
879
880 METHOD(revocation_validator_t, reload, void,
881 private_revocation_validator_t *this)
882 {
883 bool enable_ocsp, enable_crl;
884
885 enable_ocsp = lib->settings->get_bool(lib->settings,
886 "%s.plugins.revocation.enable_ocsp", TRUE, lib->ns);
887 enable_crl = lib->settings->get_bool(lib->settings,
888 "%s.plugins.revocation.enable_crl", TRUE, lib->ns);
889
890 this->lock->lock(this->lock);
891 this->enable_ocsp = enable_ocsp;
892 this->enable_crl = enable_crl;
893 this->lock->unlock(this->lock);
894
895 if (!enable_ocsp)
896 {
897 DBG1(DBG_LIB, "all OCSP validation disabled");
898 }
899 if (!enable_crl)
900 {
901 DBG1(DBG_LIB, "all CRL validation disabled");
902 }
903 }
904
905 METHOD(revocation_validator_t, destroy, void,
906 private_revocation_validator_t *this)
907 {
908 this->lock->destroy(this->lock);
909 free(this);
910 }
911
912 /**
913 * See header
914 */
915 revocation_validator_t *revocation_validator_create()
916 {
917 private_revocation_validator_t *this;
918
919 INIT(this,
920 .public = {
921 .validator.validate = _validate,
922 .reload = _reload,
923 .destroy = _destroy,
924 },
925 .lock = spinlock_create(),
926 );
927
928 reload(this);
929
930 return &this->public;
931 }