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, &current))
                    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, &current))
                    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>