apr_status_t serf_ssl_ocsp_response_verify()

in buckets/ssl_buckets.c [3012:3098]


apr_status_t serf_ssl_ocsp_response_verify(
    serf_ssl_context_t *ssl_ctx,
    const serf_ssl_ocsp_response_t *ocsp_response,
    const serf_ssl_ocsp_request_t *ocsp_request,
    apr_time_t clock_skew,
    apr_time_t max_age,
    apr_time_t *this_update,
    apr_time_t *next_update,
    apr_pool_t *scratch_pool)
{
#ifndef OPENSSL_NO_OCSP
    OCSP_BASICRESP *ocsp_basic = NULL;
    apr_status_t status = SERF_ERROR_SSL_OCSP_RESPONSE_INVALID;
    ASN1_GENERALIZEDTIME *asn1_revoked_at;
    ASN1_GENERALIZEDTIME *asn1_this_update;
    ASN1_GENERALIZEDTIME *asn1_next_update;
    int cert_status, cert_reason;
    X509_STORE *store;

    ocsp_basic = OCSP_response_get1_basic(ocsp_response->response);
    if (!ocsp_basic)
        goto cleanup;

    if (0 >= OCSP_check_nonce(ocsp_request->request, ocsp_basic))
        goto cleanup;

    store = SSL_CTX_get_cert_store(ssl_ctx->ctx);
    if (0 >= OCSP_basic_verify(ocsp_basic, NULL, store, 0))
        goto cleanup;

    if (!OCSP_resp_find_status(ocsp_basic, ocsp_request->cert_id,
                               &cert_status, &cert_reason,
                               &asn1_revoked_at,
                               &asn1_this_update,
                               &asn1_next_update))
        goto cleanup;

    if (!OCSP_check_validity(asn1_this_update, asn1_next_update,
                             (long)apr_time_sec(clock_skew),
                             (long)apr_time_sec(max_age)))
      goto cleanup;

    if (this_update) {
        if (asn1_this_update) {
            status = convert_asn1_generalized_time(asn1_this_update, this_update,
                                                   scratch_pool, status);
            if (status)
                goto cleanup;
        }
        else
            *this_update = APR_TIME_C(0);
    }

    if (next_update) {
        if (asn1_next_update) {
            status = convert_asn1_generalized_time(asn1_next_update, next_update,
                                                   scratch_pool, status);
            if (status)
                goto cleanup;
        }
        else
            *next_update = APR_TIME_C(0);
    }

    switch (cert_status)
    {
    case V_OCSP_CERTSTATUS_REVOKED:
        status = SERF_ERROR_SSL_OCSP_RESPONSE_CERT_REVOKED;
        break;

    case V_OCSP_CERTSTATUS_UNKNOWN:
        status = SERF_ERROR_SSL_OCSP_RESPONSE_CERT_UNKNOWN;
        break;

    case V_OCSP_CERTSTATUS_GOOD:
    default:
        status = APR_SUCCESS;
    }

  cleanup:
    if (ocsp_basic)
        OCSP_BASICRESP_free(ocsp_basic);
    return status;
#else
    return SERF_ERROR_SSL_OCSP_RESPONSE_INVALID;
#endif  /* OPENSSL_NO_OCSP */
}