You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@serf.apache.org by br...@apache.org on 2016/12/16 09:05:57 UTC

svn commit: r1774562 - in /serf/branches/ocsp-verification: BRANCH-README buckets/ssl_buckets.c serf_bucket_types.h

Author: brane
Date: Fri Dec 16 09:05:57 2016
New Revision: 1774562

URL: http://svn.apache.org/viewvc?rev=1774562&view=rev
Log:
On the ocsp-verification branch: Implement response parsing and verification.

* BRANCH-README: Update branch docs.

* serf_bucket_types.h
  (serf_ssl_ocsp_request_export): Update docstring.
  (serf_ssl_ocsp_response_parse
   serf_ssl_ocsp_response_verify): Update prototype and docstring.

* buckets/ssl_buckets.c
  (ocsp_response_status): New private helper function, extracted from ...
  (ocsp_callback): ... here, which uses it for response status checking.
  (ssl_ocsp_request_t): Replace the encoded server and issuer certificates
   with the OCSP certificate ID used to create requests and verify
   responses.
  (serf_ssl_ocsp_request_create,
   serf_ssl_ocsp_request_export,
   serf_ssl_ocsp_request_import): Update to match changed ssl_ocsp_request_t.
  (serf_ssl_ocsp_response_t): Change the type of the enclosed response.
  (free_ocsp_cert_id, free_ocsp_response): New; pool cleanup functions.
  (convert_asn1_generalized_time): New private helper function.
  (serf_ssl_ocsp_response_parse,
   serf_ssl_ocsp_response_verify): Update prototypes and implement.

Modified:
    serf/branches/ocsp-verification/BRANCH-README
    serf/branches/ocsp-verification/buckets/ssl_buckets.c
    serf/branches/ocsp-verification/serf_bucket_types.h

Modified: serf/branches/ocsp-verification/BRANCH-README
URL: http://svn.apache.org/viewvc/serf/branches/ocsp-verification/BRANCH-README?rev=1774562&r1=1774561&r2=1774562&view=diff
==============================================================================
--- serf/branches/ocsp-verification/BRANCH-README (original)
+++ serf/branches/ocsp-verification/BRANCH-README Fri Dec 16 09:05:57 2016
@@ -132,9 +132,8 @@ These are the proposed changes:
        const serf_ssl_ocsp_request_t *ocsp_request);
 
    /**
-    * Export @a ocsp_request, including request, server and issuer
-    * certificates, to a zero-terminated string, allocated from
-    * @a result_pool.
+    * Export @a ocsp_request to a zero-terminated string,
+    * allocated from @a result_pool.
     *
     * Use @a scratch_pool for temporary allocations.
     *
@@ -178,24 +177,32 @@ These are the proposed changes:
    typedef struct serf_ssl_ocsp_response_t serf_ssl_ocsp_response_t;
 
    /**
-    * Parse the body of an HTTP OCSP response, @a ocsp_response_body,
-    * of size @a ocsp_response_size, and construct an OCSP response,
-    * allocated from @a result pool.
+    * Parse the body of an OCSP response in DER form, @a ocsp_response,
+    * of size @a ocsp_response_size, and construct an internal
+    * representation, allocated from @a result_pool.
+    *
+    * If @a failures is not @c NULL, it will be set as in
+    * #serf_ssl_need_server_cert_t.
     *
     * Use @a scratch_pool for temporary allocations.
     *
-    * Returns @c NULL if the response body is not well-formed.
+    * Returns @c NULL if on failure.
     */
-   serf_ssl_ocsp_request_t *serf_ssl_ocsp_response_parse(
-       const void *ocsp_response_body,
+   serf_ssl_ocsp_response_t *serf_ssl_ocsp_response_parse(
+       const void *ocsp_response,
        apr_size_t ocsp_response_size,
+       int *failures,
        apr_pool_t *result_pool,
        apr_pool_t *scratch_pool);
 
    /**
     * Check if the given @a ocsp_response is valid for the given
-    * @a ocsp_request, per the algorighm documented in RFC 2560,
-    * section 3.5.
+    * @a ocsp_request in the provided @a ssl_ctx, as defined by
+    * the algorithm documented in RFC 2560, section 3.5.
+    *
+    * The OCSP responder and application wall clocks may be out of sync
+    * by @a clock_skew, and @a max_age is the acceptable age of the
+    * request. Their values are truncated to the nearest second.
     *
     * The returned value will be:
     *
@@ -208,20 +215,22 @@ These are the proposed changes:
     *   - SERF_ERROR_SSL_OCSP_RESPONSE_INVALID,
     *     if the response itself is invalid or not well-formed.
     *
-    * The @a this_update, @a next_update and @a produced_at output
-    * arguments are described in RFC 2560, section 2.4 and, when not
-    * @c NULL and if the verificateion succeeded, will be parsed from
-    * the response. Any of these times that are not present in the
-    * response will be set to the epoch, i.e., @c APR_TIME_C(0).
+    * The @a this_update and @a next_update output arguments are
+    * described in RFC 2560, section 2.4 and, when not @c NULL and if the
+    * verificateion succeeded, will be parsed from the response. Any of
+    * these times that are not present in the response will be set to the
+    * epoch, i.e., @c APR_TIME_C(0).
     *
     * Uses @a scratch_pool for temporary allocations.
     */
    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_time_t *produced_at,
        apr_pool_t *scratch_pool);
 
 

Modified: serf/branches/ocsp-verification/buckets/ssl_buckets.c
URL: http://svn.apache.org/viewvc/serf/branches/ocsp-verification/buckets/ssl_buckets.c?rev=1774562&r1=1774561&r2=1774562&view=diff
==============================================================================
--- serf/branches/ocsp-verification/buckets/ssl_buckets.c (original)
+++ serf/branches/ocsp-verification/buckets/ssl_buckets.c Fri Dec 16 09:05:57 2016
@@ -588,6 +588,28 @@ static void bio_meth_free(BIO_METHOD *bi
 }
 
 #ifndef OPENSSL_NO_TLSEXT
+static int ocsp_response_status(int failures, OCSP_RESPONSE *response)
+{
+    long resp_status = OCSP_response_status(response);
+    switch (resp_status) {
+        case OCSP_RESPONSE_STATUS_SUCCESSFUL:
+            break;
+        case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
+        case OCSP_RESPONSE_STATUS_INTERNALERROR:
+        case OCSP_RESPONSE_STATUS_SIGREQUIRED:
+        case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
+            failures |= SERF_SSL_OCSP_RESPONDER_ERROR;
+            break;
+        case OCSP_RESPONSE_STATUS_TRYLATER:
+            failures |= SERF_SSL_OCSP_RESPONDER_TRYLATER;
+            break;
+        default:
+            failures |= SERF_SSL_OCSP_RESPONDER_UNKNOWN_FAILURE;
+            break;
+    }
+    return failures;
+}
+
 /* Callback called when the server response has some OCSP info.
    Returns 1 if the application accepts the OCSP response as successful,
            0 in case of error.
@@ -598,7 +620,6 @@ static int ocsp_callback(SSL *ssl, void
     OCSP_RESPONSE *response;
     const unsigned char *resp_der;
     int len;
-    long resp_status;
     int failures = 0;
     int cert_valid = 0;
 
@@ -618,23 +639,7 @@ static int ocsp_callback(SSL *ssl, void
     }
 
     /* Did the server get a valid response from the OCSP responder */
-    resp_status = OCSP_response_status(response);
-    switch (resp_status) {
-        case OCSP_RESPONSE_STATUS_SUCCESSFUL:
-            break;
-        case OCSP_RESPONSE_STATUS_MALFORMEDREQUEST:
-        case OCSP_RESPONSE_STATUS_INTERNALERROR:
-        case OCSP_RESPONSE_STATUS_SIGREQUIRED:
-        case OCSP_RESPONSE_STATUS_UNAUTHORIZED:
-            failures |= SERF_SSL_OCSP_RESPONDER_ERROR;
-            break;
-        case OCSP_RESPONSE_STATUS_TRYLATER:
-            failures |= SERF_SSL_OCSP_RESPONDER_TRYLATER;
-            break;
-        default:
-            failures |= SERF_SSL_OCSP_RESPONDER_UNKNOWN_FAILURE;
-            break;
-    }
+    failures = ocsp_response_status(failures, response);
 
     /* TODO: check certificate status */
 
@@ -2626,13 +2631,12 @@ struct serf_ssl_ocsp_request_t {
     /* OpenSSL's internal representation of the OCSP request. */
     OCSP_REQUEST *request;
 
+    /* The certificate ID of the request. */
+    OCSP_CERTID *cert_id;
+
     /* DER-encoded request and size. */
     const void *der_request;
     apr_size_t der_request_size;
-
-    /* Exported server and issuer certificates. */
-    const char *encoded_server_cert;
-    const char *encoded_issuer_cert;
 };
 
 static apr_status_t free_ocsp_request(void *data)
@@ -2640,6 +2644,12 @@ static apr_status_t free_ocsp_request(vo
     OCSP_REQUEST_free(data);
     return APR_SUCCESS;
 }
+
+static apr_status_t free_ocsp_cert_id(void *data)
+{
+    OCSP_CERTID_free(data);
+    return APR_SUCCESS;
+}
 #endif  /* OPENSSL_NO_OCSP */
 
 
@@ -2675,7 +2685,12 @@ serf_ssl_ocsp_request_t *serf_ssl_ocsp_r
 
     if (!OCSP_request_add0_id(ocsp_req, cert_id))
         goto cleanup;
-    cert_id = NULL;
+
+    /* Generate another ID to put into the result struct.
+       TODO: see above re hash algorithms. */
+    cert_id = OCSP_cert_to_id(NULL, cert, issuer);
+    if (!cert_id)
+        goto cleanup;
 
     if (generate_nonce) {
         /* Generates a random nonce, using the internal random generator. */
@@ -2696,18 +2711,19 @@ serf_ssl_ocsp_request_t *serf_ssl_ocsp_r
     req = apr_palloc(result_pool, sizeof(*req));
     req->der_request = der;
     req->der_request_size = len;
-    req->encoded_server_cert =
-        serf_ssl_cert_export2(server_cert, result_pool, scratch_pool);
-    req->encoded_issuer_cert =
-        serf_ssl_cert_export2(issuer_cert, result_pool, scratch_pool);
 
-    /* Now move the unencoded request to the result. */
     req->request = ocsp_req;
     apr_pool_cleanup_register(result_pool, ocsp_req,
                               free_ocsp_request,
                               apr_pool_cleanup_null);
     ocsp_req = NULL;
 
+    req->cert_id = cert_id;
+    apr_pool_cleanup_register(result_pool, cert_id,
+                              free_ocsp_cert_id,
+                              apr_pool_cleanup_null);
+    cert_id = NULL;
+
   cleanup:
     if (ocsp_req)
         OCSP_REQUEST_free(ocsp_req);
@@ -2719,6 +2735,7 @@ serf_ssl_ocsp_request_t *serf_ssl_ocsp_r
 #endif  /* OPENSSL_NO_OCSP */
 }
 
+
 const void *serf_ssl_ocsp_request_body(
     const serf_ssl_ocsp_request_t *ocsp_request)
 {
@@ -2739,6 +2756,7 @@ apr_size_t serf_ssl_ocsp_request_body_si
 #endif  /* OPENSSL_NO_OCSP */
 }
 
+
 const char *serf_ssl_ocsp_request_export(
     const serf_ssl_ocsp_request_t *ocsp_request,
     apr_pool_t *result_pool,
@@ -2749,30 +2767,36 @@ const char *serf_ssl_ocsp_request_export
     /*
       The structure of the exported request is:
 
-        "Base64-server-cert" "\x1"
-        "Base64-issuer-cert" "\x1"
-        "Base64-DER-formatted-request" "\0"
+        "Base64-DER-formatted-request" "\x1"
+        "Base64-DER-formatted-cert-id" "\0"
     */
 
-    const apr_size_t s_size = strlen(ocsp_request->encoded_server_cert);
-    const apr_size_t i_size = strlen(ocsp_request->encoded_issuer_cert);
-    const apr_size_t all_size = (
-        apr_base64_encode_len(ocsp_request->der_request_size)
-        + s_size + i_size + 3); /* Three terminator bytes */
+    OCSP_CERTID *const cert_id = ocsp_request->cert_id;
+    int id_len, req_size, id_size;
+    unsigned char *unused;
+    char *buffer = NULL;
+    char *p;
+    void *id_der;
+
+    /* Generate the DER form of the certificate ID. */
+    id_len = i2d_OCSP_CERTID(cert_id, NULL);
+    if (id_len < 0)
+        return NULL;
 
-    char *const buffer = apr_palloc(result_pool, all_size);
-    char *p = buffer;
+    unused = id_der = apr_palloc(scratch_pool, id_len);
+    id_len = i2d_OCSP_CERTID(cert_id, &unused); /* unused is incremented */
+    if (id_len < 0)
+        return NULL;
 
-    memcpy(p, ocsp_request->encoded_server_cert, s_size);
-    p += s_size;
-    *p++ = '\x1';
+    req_size = apr_base64_encode_len(ocsp_request->der_request_size);
+    id_size = apr_base64_encode_len(id_len);
 
-    memcpy(p, ocsp_request->encoded_issuer_cert, i_size);
-    p += i_size;
+    buffer = apr_palloc(result_pool, req_size + id_size + 2);
+    req_size = apr_base64_encode(buffer, ocsp_request->der_request,
+                                 ocsp_request->der_request_size);
+    p = buffer + req_size - 1;  /* The trailing \0 is part of the size! */
     *p++ = '\x1';
-
-    apr_base64_encode(p, ocsp_request->der_request,
-                      ocsp_request->der_request_size);
+    apr_base64_encode(p, id_der, id_len);
 
     return buffer;
 #else
@@ -2780,6 +2804,7 @@ const char *serf_ssl_ocsp_request_export
 #endif  /* OPENSSL_NO_OCSP */
 }
 
+
 serf_ssl_ocsp_request_t *serf_ssl_ocsp_request_import(
     const char *encoded_ocsp_request,
     apr_pool_t *result_pool,
@@ -2787,45 +2812,47 @@ serf_ssl_ocsp_request_t *serf_ssl_ocsp_r
 {
 #ifndef OPENSSL_NO_OCSP
     serf_ssl_ocsp_request_t *req = NULL;
-    const char *encoded_server_cert = encoded_ocsp_request;
-    const char *encoded_issuer_cert;
-    const char *end_server_cert;
-    const char *end_issuer_cert;
+    const char *end_request = strchr(encoded_ocsp_request, '\x1');
 
-    end_server_cert = strchr(encoded_server_cert, '\x1');
-    if (!end_server_cert)
-        return NULL;
-
-    encoded_issuer_cert = end_server_cert + 1;
-    end_issuer_cert = strchr(encoded_issuer_cert, '\x1');
+    if (end_request) {
+        const char *base64_id = end_request + 1;
+        const char *base64_request = apr_pstrmemdup(
+            scratch_pool, encoded_ocsp_request,
+            end_request - encoded_ocsp_request);
+        long der_request_size = apr_base64_decode_len(base64_request);
+        long der_id_size = apr_base64_decode_len(base64_id);
 
-    if (end_issuer_cert) {
         OCSP_REQUEST *ocsp_req;
-        const char *base64_request = end_issuer_cert + 1;
-        long der_request_size = apr_base64_decode_len(base64_request);
-        /* FIXME: Use scratch pool instead and pmemdup later? */
-        void *der_request = apr_palloc(result_pool, der_request_size);
-        const unsigned char *unused = der_request;
+        OCSP_CERTID *cert_id;
+        const unsigned char *unused;
+        void *der_request;
+        void *der_id;
 
+        unused = der_request = apr_palloc(result_pool, der_request_size);
         der_request_size = apr_base64_decode(der_request, base64_request);
         ocsp_req = d2i_OCSP_REQUEST(NULL, &unused, der_request_size);
         if (!ocsp_req)
             return NULL;
 
+        unused = der_id = apr_palloc(scratch_pool, der_id_size);
+        der_id_size = apr_base64_decode(der_id, base64_id);
+        cert_id = d2i_OCSP_CERTID(NULL, &unused, der_id_size);
+        if (!cert_id)
+            return NULL;
+
         req = apr_palloc(result_pool, sizeof(*req));
         req->der_request = der_request;
         req->der_request_size = der_request_size;
-        req->encoded_server_cert =
-            apr_pstrmemdup(result_pool, encoded_server_cert,
-                           end_server_cert - encoded_server_cert);
-        req->encoded_issuer_cert =
-            apr_pstrmemdup(result_pool, encoded_issuer_cert,
-                           end_issuer_cert - encoded_issuer_cert);
 
         req->request = ocsp_req;
         apr_pool_cleanup_register(result_pool, ocsp_req,
                                   free_ocsp_request,
                                   apr_pool_cleanup_null);
+
+        req->cert_id = cert_id;
+        apr_pool_cleanup_register(result_pool, cert_id,
+                                  free_ocsp_cert_id,
+                                  apr_pool_cleanup_null);
     }
 
     return req;
@@ -2834,36 +2861,189 @@ serf_ssl_ocsp_request_t *serf_ssl_ocsp_r
 #endif  /* OPENSSL_NO_OCSP */
 }
 
+
 #ifndef OPENSSL_NO_OCSP
 struct serf_ssl_ocsp_response_t {
     /* OpenSSL's internal representation of the OCSP response. */
-    OCSP_BASICRESP *response;
+    OCSP_RESPONSE *response;
 };
+
+static apr_status_t free_ocsp_response(void *data)
+{
+    OCSP_RESPONSE_free(data);
+    return APR_SUCCESS;
+}
 #endif  /* OPENSSL_NO_OCSP */
 
+
 serf_ssl_ocsp_response_t *serf_ssl_ocsp_response_parse(
-    const void *ocsp_response_body,
+    const void *ocsp_response,
     apr_size_t ocsp_response_size,
+    int *failures,
     apr_pool_t *result_pool,
     apr_pool_t *scratch_pool)
 {
 #ifndef OPENSSL_NO_OCSP
-    return NULL;
+    serf_ssl_ocsp_response_t *rsp = NULL;
+    OCSP_RESPONSE *ocsp_rsp = NULL;
+    const unsigned char *unused;
+    int rsp_failures = 0;
+
+    unused = ocsp_response;
+    ocsp_rsp = d2i_OCSP_RESPONSE(NULL, &unused, ocsp_response_size);
+    if (!ocsp_rsp)
+        goto cleanup;
+
+    rsp_failures = ocsp_response_status(rsp_failures, ocsp_rsp);
+    if (rsp_failures)
+        goto cleanup;
+
+    rsp = apr_palloc(result_pool, sizeof(*rsp));
+    rsp->response = ocsp_rsp;
+    apr_pool_cleanup_register(result_pool, ocsp_rsp,
+                              free_ocsp_response,
+                              apr_pool_cleanup_null);
+    ocsp_rsp = NULL;
+
+  cleanup:
+    if (failures)
+        *failures = rsp_failures;
+    if (ocsp_rsp)
+        OCSP_RESPONSE_free(ocsp_rsp);
+    return rsp;
 #else
     return NULL;
 #endif  /* OPENSSL_NO_OCSP */
 }
 
+
+#ifndef OPENSSL_NO_OCSP
+/* Ripped from Subversion and well kneaded. */
+static apr_status_t
+convert_asn1_generalized_time(ASN1_GENERALIZEDTIME *asn1_time,
+                              apr_time_t *humane_time,
+                              apr_pool_t *scratch_pool,
+                              apr_status_t parse_error)
+{
+    apr_time_exp_t xt = { 0 };
+    void *data;
+    char *date;
+    int len;
+    char tz;
+
+    if (ASN1_STRING_type(asn1_time) != V_ASN1_GENERALIZEDTIME)
+        return 0;
+
+    len = ASN1_STRING_length(asn1_time);
+    data = ASN1_STRING_data(asn1_time);
+    date = apr_pstrndup(scratch_pool, data, len);
+
+    if (6 > sscanf(date, "%4d%2d%2d%2d%2d%2d%c",
+                   &xt.tm_year, &xt.tm_mon, &xt.tm_mday,
+                   &xt.tm_hour, &xt.tm_min, &xt.tm_sec, &tz))
+        return parse_error;
+
+    /* GeneralizedTime has the full 4 digit year.  But apr_time_exp_t
+       wants years as the number of years since 1900. */
+    xt.tm_year -= 1900;
+
+    /* Check that the timezone is GMT.
+       ASN.1 allows for the timezone to be specified but X.509 says it
+       must always be GMT.  A little bit of extra paranoia here seems
+       like a good idea. */
+    if (tz != 'Z')
+        return parse_error;
+
+    /* apr_time_exp_t expects months to be zero indexed, 0=Jan, 11=Dec. */
+    xt.tm_mon -= 1;
+
+    return apr_time_exp_gmt_get(humane_time, &xt);
+}
+#endif  /* OPENSSL_NO_OCSP */
+
 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_time_t *produced_at,
     apr_pool_t *scratch_pool)
 {
 #ifndef OPENSSL_NO_OCSP
-    return SERF_ERROR_SSL_OCSP_RESPONSE_INVALID;
+    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 */

Modified: serf/branches/ocsp-verification/serf_bucket_types.h
URL: http://svn.apache.org/viewvc/serf/branches/ocsp-verification/serf_bucket_types.h?rev=1774562&r1=1774561&r2=1774562&view=diff
==============================================================================
--- serf/branches/ocsp-verification/serf_bucket_types.h (original)
+++ serf/branches/ocsp-verification/serf_bucket_types.h Fri Dec 16 09:05:57 2016
@@ -850,9 +850,8 @@ apr_size_t serf_ssl_ocsp_request_body_si
     const serf_ssl_ocsp_request_t *ocsp_request);
 
 /**
- * Export @a ocsp_request, including request, server and issuer
- * certificates, to a zero-terminated string, allocated from
- * @a result_pool.
+ * Export @a ocsp_request to a zero-terminated string,
+ * allocated from @a result_pool.
  *
  * Use @a scratch_pool for temporary allocations.
  *
@@ -883,24 +882,32 @@ serf_ssl_ocsp_request_t *serf_ssl_ocsp_r
 typedef struct serf_ssl_ocsp_response_t serf_ssl_ocsp_response_t;
 
 /**
- * Parse the body of an HTTP OCSP response, @a ocsp_response_body,
- * of size @a ocsp_response_size, and construct an OCSP response,
- * allocated from @a result pool.
+ * Parse the body of an OCSP response in DER form, @a ocsp_response,
+ * of size @a ocsp_response_size, and construct an internal
+ * representation, allocated from @a result_pool.
+ *
+ * If @a failures is not @c NULL, it will be set as in
+ * #serf_ssl_need_server_cert_t.
  *
  * Use @a scratch_pool for temporary allocations.
  *
- * Returns @c NULL if the response body is not well-formed.
+ * Returns @c NULL if on failure.
  */
 serf_ssl_ocsp_response_t *serf_ssl_ocsp_response_parse(
-    const void *ocsp_response_body,
+    const void *ocsp_response,
     apr_size_t ocsp_response_size,
+    int *failures,
     apr_pool_t *result_pool,
     apr_pool_t *scratch_pool);
 
 /**
  * Check if the given @a ocsp_response is valid for the given
- * @a ocsp_request, per the algorighm documented in RFC 2560,
- * section 3.5.
+ * @a ocsp_request in the provided @a ssl_ctx, as defined by
+ * the algorithm documented in RFC 2560, section 3.5.
+ *
+ * The OCSP responder and application wall clocks may be out of sync
+ * by @a clock_skew, and @a max_age is the acceptable age of the
+ * request. Their values are truncated to the nearest second.
  *
  * The returned value will be:
  *
@@ -913,20 +920,22 @@ serf_ssl_ocsp_response_t *serf_ssl_ocsp_
  *   - SERF_ERROR_SSL_OCSP_RESPONSE_INVALID,
  *     if the response itself is invalid or not well-formed.
  *
- * The @a this_update, @a next_update and @a produced_at output
- * arguments are described in RFC 2560, section 2.4 and, when not
- * @c NULL and if the verificateion succeeded, will be parsed from
- * the response. Any of these times that are not present in the
- * response will be set to the epoch, i.e., @c APR_TIME_C(0).
+ * The @a this_update and @a next_update output arguments are
+ * described in RFC 2560, section 2.4 and, when not @c NULL and if the
+ * verificateion succeeded, will be parsed from the response. Any of
+ * these times that are not present in the response will be set to the
+ * epoch, i.e., @c APR_TIME_C(0).
  *
  * Uses @a scratch_pool for temporary allocations.
  */
 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_time_t *produced_at,
     apr_pool_t *scratch_pool);
 
 /* ==================================================================== */