Annotation of embedaddon/strongswan/src/libstrongswan/plugins/revocation/revocation_validator.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>