Пример #1
0
/*
 * The OCSPChecker is created in an idle state, and remains in this state until
 * either (a) the default Responder has been set and enabled, and a Check
 * request is received with no responder specified, or (b) a Check request is
 * received with a specified responder. A request message is constructed and
 * given to the HttpClient. If non-blocking I/O is used the client may return
 * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
 * condition to its caller in turn. On a subsequent call the I/O is resumed.
 * When a response is received it is decoded and the results provided to the
 * caller.
 *
 */
PKIX_Error *
pkix_OcspChecker_CheckLocal(
        PKIX_PL_Cert *cert,
        PKIX_PL_Cert *issuer,
        PKIX_PL_Date *date,
        pkix_RevocationMethod *checkerObject,
        PKIX_ProcessingParams *procParams,
        PKIX_UInt32 methodFlags,
        PKIX_Boolean chainVerificationState,
        PKIX_RevocationStatus *pRevStatus,
        CERTCRLEntryReasonCode *pReasonCode,
        void *plContext)
{
        PKIX_PL_OcspCertID    *cid = NULL;
        PKIX_Boolean           hasFreshStatus = PKIX_FALSE;
        PKIX_Boolean           statusIsGood = PKIX_FALSE;
        SECErrorCodes          resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
        PKIX_RevocationStatus  revStatus = PKIX_RevStatus_NoInfo;

        PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_CheckLocal");

        PKIX_CHECK(
            PKIX_PL_OcspCertID_Create(cert, NULL, &cid,
                                      plContext),
            PKIX_OCSPCERTIDCREATEFAILED);
        if (!cid) {
            goto cleanup;
        }

        PKIX_CHECK(
            PKIX_PL_OcspCertID_GetFreshCacheStatus(cid, date,
                                                   &hasFreshStatus,
                                                   &statusIsGood,
                                                   &resultCode,
                                                   plContext),
            PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);
        if (hasFreshStatus) {
            if (statusIsGood) {
                revStatus = PKIX_RevStatus_Success;
                resultCode = 0;
            } else {
                revStatus = pkix_OcspChecker_MapResultCodeToRevStatus(resultCode);
            }
        }

cleanup:
        *pRevStatus = revStatus;

        /* ocsp carries only tree statuses: good, bad, and unknown.
         * revStatus is used to pass them. reasonCode is always set
         * to be unknown. */
        *pReasonCode = crlEntryReasonUnspecified;
        PKIX_DECREF(cid);

        PKIX_RETURN(OCSPCHECKER);
}
Пример #2
0
/*
 * The OCSPChecker is created in an idle state, and remains in this state until
 * either (a) the default Responder has been set and enabled, and a Check
 * request is received with no responder specified, or (b) a Check request is
 * received with a specified responder. A request message is constructed and
 * given to the HttpClient. If non-blocking I/O is used the client may return
 * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
 * condition to its caller in turn. On a subsequent call the I/O is resumed.
 * When a response is received it is decoded and the results provided to the
 * caller.
 *
 */
static PKIX_Error *
pkix_OcspChecker_Check(
    PKIX_PL_Object *checkerObject,
    PKIX_PL_Cert *cert,
    PKIX_ProcessingParams *procParams,
    void **pNBIOContext,
    PKIX_UInt32 *pResultCode,
    void *plContext)
{
    SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
    PKIX_Boolean uriFound = PKIX_FALSE;
    PKIX_Boolean passed = PKIX_FALSE;
    PKIX_OcspChecker *checker = NULL;
    PKIX_PL_OcspCertID *cid = NULL;
    PKIX_PL_OcspRequest *request = NULL;
    PKIX_PL_Date *validity = NULL;
    void *nbioContext = NULL;

    PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_Check");
    PKIX_NULLCHECK_FOUR(checkerObject, cert, pNBIOContext, pResultCode);

    PKIX_CHECK(pkix_CheckType
               (checkerObject, PKIX_OCSPCHECKER_TYPE, plContext),
               PKIX_OBJECTNOTOCSPCHECKER);

    checker = (PKIX_OcspChecker *)checkerObject;

    nbioContext = *pNBIOContext;
    *pNBIOContext = 0;

    /* assert(checker->nbioContext == nbioContext) */

    if (nbioContext == 0) {
        /* We are initiating a check, not resuming previous I/O. */

        PKIX_Boolean hasFreshStatus = PKIX_FALSE;
        PKIX_Boolean statusIsGood = PKIX_FALSE;

        PKIX_CHECK(PKIX_PL_OcspCertID_Create
                   (cert,
                    validity,
                    &cid,
                    plContext),
                   PKIX_OCSPCERTIDCREATEFAILED);

        if (!cid) {
            goto cleanup;
        }

        PKIX_CHECK(PKIX_PL_OcspCertID_GetFreshCacheStatus
                   (cid,
                    validity,
                    &hasFreshStatus,
                    &statusIsGood,
                    &resultCode,
                    plContext),
                   PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);

        if (hasFreshStatus) {
            /* avoid updating the cache with a cached result... */
            passed = PKIX_TRUE;

            if (statusIsGood) {
                resultCode = 0;
            }
            goto cleanup;
        }
        PKIX_INCREF(cert);
        PKIX_DECREF(checker->cert);
        checker->cert = cert;

        /* create request */
        PKIX_CHECK(pkix_pl_OcspRequest_Create
                   (cert,
                    cid,
                    validity,
                    PKIX_FALSE,     /* PKIX_Boolean addServiceLocator */
                    NULL,           /* PKIX_PL_Cert *signerCert */
                    &uriFound,
                    &request,
                    plContext),
                   PKIX_OCSPREQUESTCREATEFAILED);

        /* No uri to check is considered passing! */
        if (uriFound == PKIX_FALSE) {
            /* no caching for certs lacking URI */
            passed = PKIX_TRUE;
            resultCode = 0;
            goto cleanup;
        }

    }

    /* Do we already have a response object? */
    if ((checker->response) == NULL) {
        /* send request and create a response object */
        PKIX_CHECK(pkix_pl_OcspResponse_Create
                   (request,
                    checker->responder,
                    checker->verifyFcn,
                    &nbioContext,
                    &(checker->response),
                    plContext),
                   PKIX_OCSPRESPONSECREATEFAILED);

        if (nbioContext != 0) {
            *pNBIOContext = nbioContext;
            goto cleanup;
        }

        PKIX_CHECK(pkix_pl_OcspResponse_Decode
                   ((checker->response), &passed, &resultCode, plContext),
                   PKIX_OCSPRESPONSEDECODEFAILED);

        if (passed == PKIX_FALSE) {
            goto cleanup;
        }

        PKIX_CHECK(pkix_pl_OcspResponse_GetStatus
                   ((checker->response), &passed, &resultCode, plContext),
                   PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);

        if (passed == PKIX_FALSE) {
            goto cleanup;
        }
    }

    PKIX_CHECK(pkix_pl_OcspResponse_VerifySignature
               ((checker->response),
                cert,
                procParams,
                &passed,
                &nbioContext,
                plContext),
               PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);

    if (nbioContext != 0) {
        *pNBIOContext = nbioContext;
        goto cleanup;
    }

    if (passed == PKIX_FALSE) {
        resultCode = PORT_GetError();
        goto cleanup;
    }

    PKIX_CHECK(pkix_pl_OcspResponse_GetStatusForCert
               (cid, (checker->response), &passed, &resultCode, plContext),
               PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);

cleanup:
    if (!passed && cid && cid->certID && !cid->certIDWasConsumed) {
        /* We still own the certID object, which means that
         * it did not get consumed to create a cache entry.
         * Let's make sure we create one.
         */
        PKIX_Error *err;
        err = PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
                  cid, plContext);
        if (err) {
            PKIX_PL_Object_DecRef((PKIX_PL_Object*)err, plContext);
        }
    }

    *pResultCode = (PKIX_UInt32)resultCode;

    PKIX_DECREF(cid);
    PKIX_DECREF(request);
    if (checker) {
        PKIX_DECREF(checker->response);
    }

    PKIX_RETURN(OCSPCHECKER);

}