Changeset d6834e0 in mod_gnutls


Ignore:
Timestamp:
Jun 10, 2016, 9:34:08 AM (3 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, master, upstream
Children:
15b22cb
Parents:
aa68232
git-author:
Thomas Klute <thomas2.klute@…> (06/10/16 09:29:57)
git-committer:
Thomas Klute <thomas2.klute@…> (06/10/16 09:34:08)
Message:

OCSP refresh mutex: Prevent parallel requests

Add a global mutex which a thread must hold before updating a cached
OCSP response. This avoids two threads updating the same response in
parallel. The impact of parallel updates may be small with the
experimental file-based mechanism, but an extra OCSP request over HTTP
would add a lot of overhead.

Note that the new 'gnutls-ocsp' mutex is a global mutex, not one per
virtual host, because a mutex must be registered in pre_config for the
Mutex directive to work.

Files:
5 edited

Legend:

Unmodified
Added
Removed
  • include/mod_gnutls.h.in

    raa68232 rd6834e0  
    215215     * unset. */
    216216    apr_uri_t *ocsp_uri;
     217    /* Mutex to prevent parallel OCSP requests */
     218    apr_global_mutex_t *ocsp_mutex;
    217219    /* Trust list to verify OCSP responses for stapling. Should
    218220     * usually only contain the CA that signed the server
  • src/gnutls_config.c

    raa68232 rd6834e0  
    981981    sc->ocsp_response_file = NULL;
    982982    sc->ocsp_uri = NULL;
     983    sc->ocsp_mutex = NULL;
    983984    sc->ocsp_trust = NULL;
    984985    sc->ocsp_grace_time = apr_time_from_sec(MGS_GRACE_TIME);
  • src/gnutls_hooks.c

    raa68232 rd6834e0  
    127127
    128128    ap_mutex_register(pconf, MGS_CACHE_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0);
     129    ap_mutex_register(pconf, MGS_OCSP_MUTEX_NAME, NULL, APR_LOCK_DEFAULT, 0);
    129130
    130131    /* Register a pool clean-up function */
     
    342343    }
    343344
     345    if (sc_base->ocsp_mutex == NULL)
     346    {
     347        rv = ap_global_mutex_create(&sc_base->ocsp_mutex, NULL,
     348                                    MGS_OCSP_MUTEX_NAME, NULL,
     349                                    base_server, pconf, 0);
     350        if (rv != APR_SUCCESS)
     351        {
     352            ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, base_server,
     353                         "Failed to create mutex '" MGS_OCSP_MUTEX_NAME
     354                         "'.");
     355            return HTTP_INTERNAL_SERVER_ERROR;
     356        }
     357    }
     358
    344359    /* If GnuTLSP11Module is set, load the listed PKCS #11
    345360     * modules. Otherwise system defaults will be used. */
     
    370385    }
    371386
    372     for (s = base_server; s; s = s->next) {
     387    for (s = base_server; s; s = s->next)
     388    {
    373389        sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module);
    374390        sc->cache_type = sc_base->cache_type;
     
    385401        }
    386402
    387         /* init OCSP trust list if OCSP is enabled */
     403        sc->ocsp_mutex = sc_base->ocsp_mutex;
     404        /* init OCSP trust list if OCSP is enabled for this host */
    388405        if (sc->ocsp_response_file != NULL)
    389406        {
     
    522539        }
    523540    }
     541
     542    /* reinit OCSP mutex */
     543    const char *lockfile = apr_global_mutex_lockfile(sc->ocsp_mutex);
     544    rv = apr_global_mutex_child_init(&sc->ocsp_mutex, lockfile, p);
     545    if (rv != APR_SUCCESS)
     546        ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
     547                     "Failed to reinit mutex '" MGS_OCSP_MUTEX_NAME "'.");
    524548
    525549    /* Block SIGPIPE Signals */
  • src/gnutls_ocsp.c

    raa68232 rd6834e0  
    450450    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
    451451                  "No valid OCSP response in cache, trying to update.");
    452     apr_status_t rv = mgs_cache_ocsp_response(ctxt->c->base_server);
     452
     453    apr_status_t rv = apr_global_mutex_trylock(ctxt->sc->ocsp_mutex);
     454    if (APR_STATUS_IS_EBUSY(rv))
     455    {
     456        /* Another thread is currently holding the mutex, wait. */
     457        apr_global_mutex_lock(ctxt->sc->ocsp_mutex);
     458        /* Check if this other thread updated the response we need. It
     459         * would be better to have a vhost specific mutex, but at the
     460         * moment there's no good way to integrate that with the
     461         * Apache Mutex directive. */
     462        *ocsp_response = ctxt->sc->cache->fetch(ctxt, fingerprint);
     463        if (ocsp_response->size > 0
     464            && check_ocsp_response_expiry(ctxt, ocsp_response)
     465            == GNUTLS_E_SUCCESS)
     466        {
     467            /* Got a valid response now, unlock mutex and return. */
     468            apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
     469            return GNUTLS_E_SUCCESS;
     470        }
     471        else
     472        {
     473            gnutls_free(ocsp_response->data);
     474            ocsp_response->data = NULL;
     475        }
     476    }
     477
     478    rv = mgs_cache_ocsp_response(ctxt->c->base_server);
    453479    if (rv != APR_SUCCESS)
    454480    {
    455481        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
    456482                      "Updating OCSP response cache failed");
     483        apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
    457484        goto fail_cleanup;
    458485    }
     486    apr_global_mutex_unlock(ctxt->sc->ocsp_mutex);
    459487
    460488    /* retry reading from cache */
  • src/gnutls_ocsp.h

    raa68232 rd6834e0  
    2222#include "httpd.h"
    2323#include "http_config.h"
     24
     25#define MGS_OCSP_MUTEX_NAME "gnutls-ocsp"
    2426
    2527const char *mgs_store_ocsp_response_path(cmd_parms * parms,
Note: See TracChangeset for help on using the changeset viewer.