Changeset 08817d0 in mod_gnutls


Ignore:
Timestamp:
Jun 5, 2016, 3:42:32 PM (7 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
asyncio, debian/master, debian/stretch-backports, main, master, proxy-ticket, upstream
Children:
366d1a1
Parents:
368e581
git-author:
Thomas Klute <thomas2.klute@…> (06/05/16 11:53:31)
git-committer:
Thomas Klute <thomas2.klute@…> (06/05/16 15:42:32)
Message:

Check OCSP response before caching

Only verified responses should be cached. This improves both security
and performance: The cache does not need to touch untrusted data, and
if only verified responses are cached there is no need to do full
verification every time a response is fetched from the cache.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_ocsp.c

    r368e581 r08817d0  
    3030
    3131
    32 #define _log_one_ocsp_fail(s, c)                                      \
    33     ap_log_cerror(APLOG_MARK, APLOG_INFO, APR_EGENERAL, (c),           \
    34                   "Reason for failed OCSP response verification: %s", (s))
     32#define _log_one_ocsp_fail(str, srv)                                    \
     33    ap_log_error(APLOG_MARK, APLOG_INFO, APR_EGENERAL, (srv),           \
     34                 "Reason for failed OCSP response verification: %s", (str))
    3535/*
    3636 * Log all matching reasons for verification failure
    3737 */
    38 static void _log_verify_fail_reason(const unsigned int verify, conn_rec *c)
     38static void _log_verify_fail_reason(const unsigned int verify, server_rec *s)
    3939{
    4040    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_NOT_FOUND)
    41         _log_one_ocsp_fail("Signer cert not found", c);
     41        _log_one_ocsp_fail("Signer cert not found", s);
    4242
    4343    if (verify & GNUTLS_OCSP_VERIFY_SIGNER_KEYUSAGE_ERROR)
    44         _log_one_ocsp_fail("Signer cert keyusage error", c);
     44        _log_one_ocsp_fail("Signer cert keyusage error", s);
    4545
    4646    if (verify & GNUTLS_OCSP_VERIFY_UNTRUSTED_SIGNER)
    47         _log_one_ocsp_fail("Signer cert is not trusted", c);
     47        _log_one_ocsp_fail("Signer cert is not trusted", s);
    4848
    4949    if (verify & GNUTLS_OCSP_VERIFY_INSECURE_ALGORITHM)
    50         _log_one_ocsp_fail("Insecure algorithm", c);
     50        _log_one_ocsp_fail("Insecure algorithm", s);
    5151
    5252    if (verify & GNUTLS_OCSP_VERIFY_SIGNATURE_FAILURE)
    53         _log_one_ocsp_fail("Signature failure", c);
     53        _log_one_ocsp_fail("Signature failure", s);
    5454
    5555    if (verify & GNUTLS_OCSP_VERIFY_CERT_NOT_ACTIVATED)
    56         _log_one_ocsp_fail("Signer cert not yet activated", c);
     56        _log_one_ocsp_fail("Signer cert not yet activated", s);
    5757
    5858    if (verify & GNUTLS_OCSP_VERIFY_CERT_EXPIRED)
    59         _log_one_ocsp_fail("Signer cert expired", c);
     59        _log_one_ocsp_fail("Signer cert expired", s);
    6060}
    6161
     
    7676
    7777/**
    78  * Check if the provided OCSP response is usable for stapling in this
    79  * connection context. Returns GNUTLS_E_SUCCESS if yes.
     78 * Check if the provided OCSP response is usable for stapling in
     79 * connections to this server. Returns GNUTLS_E_SUCCESS if yes.
     80 *
     81 * Supports only one certificate status per response.
    8082 */
    81 int check_ocsp_response(mgs_handle_t *ctxt, const gnutls_datum_t *ocsp_response)
    82 {
    83     if (ctxt->sc->ocsp_trust == NULL)
    84     {
    85         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    86                       "No OCSP trust list available for server \"%s\"!",
    87                       ctxt->c->base_server->server_hostname);
     83int check_ocsp_response(server_rec *s, const gnutls_datum_t *ocsp_response)
     84{
     85    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     86        ap_get_module_config(s->module_config, &gnutls_module);
     87
     88    if (sc->ocsp_trust == NULL)
     89    {
     90        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     91                     "No OCSP trust list available for server \"%s\"!",
     92                     s->server_hostname);
    8893        return GNUTLS_E_NO_CERTIFICATE_FOUND;
    8994    }
     
    9398    if (ret != GNUTLS_E_SUCCESS)
    9499    {
    95         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    96                       "Could not initialize OCSP response structure: %s (%d)",
    97                       gnutls_strerror(ret), ret);
     100        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     101                     "Could not initialize OCSP response structure: %s (%d)",
     102                     gnutls_strerror(ret), ret);
    98103        goto resp_cleanup;
    99104    }
     
    101106    if (ret != GNUTLS_E_SUCCESS)
    102107    {
    103         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    104                       "Importing OCSP response failed: %s (%d)",
    105                       gnutls_strerror(ret), ret);
     108        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     109                     "Importing OCSP response failed: %s (%d)",
     110                     gnutls_strerror(ret), ret);
    106111        goto resp_cleanup;
    107112    }
    108113
    109     ret = gnutls_ocsp_resp_check_crt(resp, 0,
    110                                      ctxt->sc->certs_x509_crt_chain[0]);
    111     if (ret != GNUTLS_E_SUCCESS)
    112     {
    113         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    114                       "OCSP response is not for server certificate: %s (%d)",
    115                       gnutls_strerror(ret), ret);
     114    ret = gnutls_ocsp_resp_check_crt(resp, 0, sc->certs_x509_crt_chain[0]);
     115    if (ret != GNUTLS_E_SUCCESS)
     116    {
     117        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     118                     "OCSP response is not for server certificate: %s (%d)",
     119                     gnutls_strerror(ret), ret);
    116120        goto resp_cleanup;
    117121    }
    118122
    119123    unsigned int verify;
    120     ret = gnutls_ocsp_resp_verify(resp, *(ctxt->sc->ocsp_trust), &verify, 0);
    121     if (ret != GNUTLS_E_SUCCESS)
    122     {
    123         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    124                       "OCSP response verification failed: %s (%d)",
    125                       gnutls_strerror(ret), ret);
     124    ret = gnutls_ocsp_resp_verify(resp, *(sc->ocsp_trust), &verify, 0);
     125    if (ret != GNUTLS_E_SUCCESS)
     126    {
     127        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     128                     "OCSP response verification failed: %s (%d)",
     129                     gnutls_strerror(ret), ret);
    126130        goto resp_cleanup;
    127131    }
     
    131135        if (verify != 0)
    132136        {
    133             _log_verify_fail_reason(verify, ctxt->c);
     137            _log_verify_fail_reason(verify, s);
    134138            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
    135139            goto resp_cleanup;
    136140        }
    137141        else
    138             ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
    139                           "OCSP response is valid.");
     142            ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
     143                         "OCSP response is valid.");
    140144    }
    141145
     
    150154    if (ret != GNUTLS_E_SUCCESS)
    151155    {
    152         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    153                       "Could not get OCSP response data: %s (%d)",
    154                       gnutls_strerror(ret), ret);
     156        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     157                     "Could not get OCSP response data: %s (%d)",
     158                     gnutls_strerror(ret), ret);
    155159        goto resp_cleanup;
    156160    }
     
    168172        /* We don't know if our clock or that of the OCSP responder is
    169173         * out of sync, so warn but continue. */
    170         ap_log_cerror(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, ctxt->c,
    171                       "OSCP response claims to be from future (%s), check "
    172                       "time synchronization!", date_str);
     174        ap_log_error(APLOG_MARK, APLOG_WARNING, APR_EGENERAL, s,
     175                     "OSCP response claims to be from future (%s), check "
     176                     "time synchronization!", date_str);
    173177    }
    174178
    175179    if (next_update == (time_t) -1)
    176         ap_log_cerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, ctxt->c,
    177                       "OSCP response does not contain nextUpdate info.");
     180        ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s,
     181                     "OSCP response does not contain nextUpdate info.");
    178182    else
    179183    {
     
    183187        {
    184188            apr_rfc822_date(date_str, valid_to);
    185             ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    186                           "OCSP response has expired at %s!", date_str);
     189            ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     190                         "OCSP response has expired at %s!", date_str);
    187191            /* Do not send a stale response */
    188192            ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
     
    196200    {
    197201        /* Yay, everything's good! */
    198         ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
    199                       "CA flagged certificate as valid at %s.", date_str);
     202        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
     203                     "CA flagged certificate as valid at %s.", date_str);
    200204    }
    201205    else
    202206    {
    203         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    204                       "CA flagged certificate as %s at %s.",
    205                       cert_status == GNUTLS_OCSP_CERT_REVOKED ?
    206                       "revoked" : "unknown", date_str);
     207        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     208                     "CA flagged certificate as %s at %s.",
     209                     cert_status == GNUTLS_OCSP_CERT_REVOKED ?
     210                     "revoked" : "unknown", date_str);
    207211        ret = GNUTLS_E_OCSP_RESPONSE_ERROR;
    208212    }
     
    295299    }
    296300
     301    if (check_ocsp_response(s, &resp) != GNUTLS_E_SUCCESS)
     302    {
     303        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, s,
     304                     "OCSP response validation failed, cannot "
     305                     "update cache.");
     306        apr_pool_destroy(tmp);
     307        return APR_EGENERAL;
     308    }
     309
    297310    /* TODO: make cache lifetime configurable, make sure expiration
    298311     * happens without storing new data */
     
    333346    {
    334347        /* Succeed if response is present and valid. */
    335         if (check_ocsp_response(ctxt, ocsp_response) == GNUTLS_E_SUCCESS)
     348        if (check_ocsp_response(ctxt->c->base_server, ocsp_response)
     349            == GNUTLS_E_SUCCESS)
    336350            return GNUTLS_E_SUCCESS;
    337351    }
    338352    /* get rid of invalid response (if any) */
    339353    gnutls_free(ocsp_response->data);
     354    ocsp_response->data = NULL;
    340355
    341356    /* If the cache had no response or an invalid one, try to update. */
     
    360375    {
    361376        /* Succeed if response is present and valid. */
    362         if (check_ocsp_response(ctxt, ocsp_response) == GNUTLS_E_SUCCESS)
     377        if (check_ocsp_response(ctxt->c->base_server, ocsp_response)
     378            == GNUTLS_E_SUCCESS)
    363379            return GNUTLS_E_SUCCESS;
    364380    }
Note: See TracChangeset for help on using the changeset viewer.