Changeset c6dda6d in mod_gnutls for src/gnutls_ocsp.c


Ignore:
Timestamp:
Oct 21, 2016, 6:40:02 PM (3 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, master, upstream
Children:
333bbc7
Parents:
d26fa55
Message:

Rate limit OCSP requests

Retries after failed OCSP requests must be rate limited. If the
responder is overloaded or buggy we don't want to add too much more
load, and if a MITM is messing with requests a repetition loop might
end up being a self-inflicted denial of service.

The minimum time to wait between retries can be configured using the
GnuTLSOCSPFailureTimeout directive.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_ocsp.c

    rd26fa55 rc6dda6d  
    3939 * or received", not the whole connection. 10 seconds in mod_ssl. */
    4040#define OCSP_SOCKET_TIMEOUT 2
     41
     42/* Dummy data for failure cache entries (one byte). */
     43#define OCSP_FAILURE_CACHE_DATA 0x0f
    4144
    4245
     
    684687
    685688
     689/*
     690 * Retries after failed OCSP requests must be rate limited. If the
     691 * responder is overloaded or buggy we don't want to add too much more
     692 * load, and if a MITM is messing with requests a repetition loop
     693 * might end up being a self-inflicted denial of service.
     694 */
     695void mgs_cache_ocsp_failure(server_rec *s)
     696{
     697    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     698        ap_get_module_config(s->module_config, &gnutls_module);
     699
     700    unsigned char c = OCSP_FAILURE_CACHE_DATA;
     701    gnutls_datum_t dummy = {
     702        .data = &c,
     703        .size = sizeof(c)
     704    };
     705    apr_time_t expiry = apr_time_now() + sc->ocsp_failure_timeout;
     706
     707    char date_str[APR_RFC822_DATE_LEN];
     708    apr_rfc822_date(date_str, expiry);
     709    ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
     710                 "OCSP request for %s failed, next try after %s.",
     711                 s->server_hostname, date_str);
     712
     713    int r = sc->cache->store(s, sc->ocsp->fingerprint, dummy, expiry);
     714    if (r != 0)
     715        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     716                     "Caching OCSP failure failed.");
     717}
     718
     719
     720
    686721int mgs_get_ocsp_response(gnutls_session_t session __attribute__((unused)),
    687722                          void *ptr,
     
    702737                      "Fetching OCSP response from cache failed.");
    703738    }
     739    else if ((ocsp_response->size == sizeof(unsigned char)) &&
     740             (*((unsigned char *) ocsp_response->data) == OCSP_FAILURE_CACHE_DATA))
     741    {
     742        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_EGENERAL, ctxt->c,
     743                      "Cached OCSP failure found for %s.",
     744                      ctxt->c->base_server->server_hostname);
     745        goto fail_cleanup;
     746    }
    704747    else
    705748    {
     
    714757                  "No valid OCSP response in cache, trying to update.");
    715758
    716     /* TODO: Once sending OCSP requests is implemented we need a rate
    717      * limit for retries on error. If the responder is overloaded or
    718      * buggy we don't want to add too much more load, and if a MITM is
    719      * messing with requests a repetition loop might end up being a
    720      * self-inflicted denial of service. */
    721759    apr_status_t rv = apr_global_mutex_trylock(ctxt->sc->ocsp_mutex);
    722760    if (APR_STATUS_IS_EBUSY(rv))
     
    747785    {
    748786        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
    749                       "Updating OCSP response cache failed");
     787                      "Caching a fresh OCSP response failed");
     788        /* cache failure to rate limit retries */
     789        mgs_cache_ocsp_failure(ctxt->c->base_server);
    750790        apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
    751791        goto fail_cleanup;
Note: See TracChangeset for help on using the changeset viewer.