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