Changeset 6b4136c in mod_gnutls


Ignore:
Timestamp:
Jun 5, 2016, 3:42:32 PM (2 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, master, upstream
Children:
4bf4ce2
Parents:
2f932fa
git-author:
Thomas Klute <thomas2.klute@…> (06/05/16 08:38:49)
git-committer:
Thomas Klute <thomas2.klute@…> (06/05/16 15:42:32)
Message:

Store OCSP responses in DBM cache before use

This is not proper caching yet (the cached response is updated on
every use), but it shows the approach to be used. Memcached support to
be added once DBM works properly.

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_cache.c

    r2f932fa r6b4136c  
    395395}
    396396
    397 static gnutls_datum_t dbm_cache_fetch(mgs_handle_t *ctxt, gnutls_datum_t key)
     397gnutls_datum_t dbm_cache_fetch(mgs_handle_t *ctxt, gnutls_datum_t key)
    398398{
    399399    gnutls_datum_t data = {NULL, 0};
     
    459459}
    460460
    461 static int dbm_cache_store(server_rec *s, gnutls_datum_t key,
    462                            gnutls_datum_t data, apr_time_t expiry)
     461int dbm_cache_store(server_rec *s, gnutls_datum_t key,
     462                    gnutls_datum_t data, apr_time_t expiry)
    463463{
    464464    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
  • src/gnutls_cache.h

    r2f932fa r6b4136c  
    6161char *mgs_time2sz(time_t t, char *str, int strsize);
    6262
     63/*
     64 * EXPERIMENTAL: Make DBM cache available for OCSP caching. To be
     65 * replaced with properly configurable caching that can also use
     66 * memcached later.
     67 */
     68#include <apr_dbm.h>
     69int dbm_cache_store(server_rec *s, gnutls_datum_t key,
     70                    gnutls_datum_t data, apr_time_t expiry);
     71gnutls_datum_t dbm_cache_fetch(mgs_handle_t *ctxt, gnutls_datum_t key);
     72
    6373#endif /** __MOD_GNUTLS_CACHE_H__ */
  • src/gnutls_ocsp.c

    r2f932fa r6b4136c  
    1717#include "gnutls_ocsp.h"
    1818#include "mod_gnutls.h"
     19#include "gnutls_cache.h"
    1920
    2021#include <apr_lib.h>
     
    214215
    215216
     217/*
     218 * Returns the certificate fingerprint, memory is allocated from p.
     219 */
     220static gnutls_datum_t mgs_get_cert_fingerprint(apr_pool_t *p,
     221                                               gnutls_x509_crt_t cert)
     222{
     223    gnutls_datum_t fingerprint = {NULL, 0};
     224    size_t fplen;
     225    gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, NULL, &fplen);
     226    unsigned char * fp = apr_palloc(p, fplen);
     227    gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA1, fp, &fplen);
     228    // TODO: Prevent overflow
     229    fingerprint.size = fplen;
     230    fingerprint.data = fp;
     231    return fingerprint;
     232}
     233
     234
     235
     236/* TODO: response should be fetched from sc->ocsp_uri */
     237apr_status_t mgs_cache_ocsp_response(server_rec *s)
     238{
     239    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     240        ap_get_module_config(s->module_config, &gnutls_module);
     241
     242    if (sc->cache_type != mgs_cache_dbm && sc->cache_type != mgs_cache_gdbm)
     243    {
     244        /* experimental OCSP cache requires DBM cache */
     245        return APR_ENOTIMPL;
     246    }
     247
     248    apr_pool_t *tmp;
     249    apr_status_t rv = apr_pool_create(&tmp, NULL);
     250
     251    /* the fingerprint will be used as cache key */
     252    gnutls_datum_t fingerprint =
     253        mgs_get_cert_fingerprint(tmp, sc->certs_x509_crt_chain[0]);
     254    if (fingerprint.data == NULL)
     255        return APR_EINVAL;
     256
     257    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
     258                 "Loading OCSP response from %s",
     259                 sc->ocsp_response_file);
     260    apr_file_t *file;
     261    apr_finfo_t finfo;
     262    apr_size_t br = 0;
     263    rv = apr_file_open(&file, sc->ocsp_response_file,
     264                       APR_READ | APR_BINARY, APR_OS_DEFAULT, tmp);
     265    if (rv != APR_SUCCESS)
     266    {
     267        apr_pool_destroy(tmp);
     268        return rv;
     269    }
     270    rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, file);
     271    if (rv != APR_SUCCESS)
     272    {
     273        apr_pool_destroy(tmp);
     274        return rv;
     275    }
     276
     277    gnutls_datum_t resp;
     278    resp.data = apr_palloc(tmp, finfo.size);
     279    rv = apr_file_read_full(file, resp.data, finfo.size, &br);
     280    if (rv != APR_SUCCESS)
     281    {
     282        apr_pool_destroy(tmp);
     283        return rv;
     284    }
     285    apr_file_close(file);
     286    // TODO: Prevent overflow
     287    resp.size = br;
     288
     289
     290    /* TODO: make cache lifetime configurable */
     291    int r = dbm_cache_store(s, fingerprint,
     292                            resp, apr_time_now() + apr_time_from_sec(120));
     293    /* destroy pool, and original copy of the OCSP response with it */
     294    apr_pool_destroy(tmp);
     295    if (r != 0)
     296    {
     297        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, s,
     298                      "Storing OCSP response in cache failed.");
     299        return APR_EGENERAL;
     300    }
     301    return APR_SUCCESS;
     302}
     303
     304
     305
    216306int mgs_get_ocsp_response(gnutls_session_t session __attribute__((unused)),
    217307                          void *ptr,
     
    219309{
    220310    mgs_handle_t *ctxt = (mgs_handle_t *) ptr;
    221     ap_log_cerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, ctxt->c,
    222                   "Loading OCSP response from %s",
    223                   ctxt->sc->ocsp_response_file);
    224 
    225     /* TODO: response should come from cache, which must be filled
    226      * from sc->ocsp_uri */
    227     int ret = gnutls_load_file(ctxt->sc->ocsp_response_file, ocsp_response);
    228     if (ret != GNUTLS_E_SUCCESS)
    229     {
    230         ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
    231                       "Loading OCSP response failed: %s (%d)",
    232                       gnutls_strerror(ret), ret);
     311
     312    apr_status_t rv = mgs_cache_ocsp_response(ctxt->c->base_server);
     313    if (rv != APR_SUCCESS)
     314    {
     315        ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, ctxt->c,
     316                      "Updating OCSP response cache failed");
     317        return GNUTLS_E_NO_CERTIFICATE_STATUS;
     318    }
     319
     320    gnutls_datum_t fingerprint =
     321        mgs_get_cert_fingerprint(ctxt->c->pool,
     322                                 ctxt->sc->certs_x509_crt_chain[0]);
     323    if (fingerprint.data == NULL)
     324        return GNUTLS_E_NO_CERTIFICATE_STATUS;
     325
     326    *ocsp_response = dbm_cache_fetch(ctxt, fingerprint);
     327    if (ocsp_response->size == 0)
     328    {
     329        ap_log_cerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, ctxt->c,
     330                      "Fetching OCSP response from cache failed.");
    233331    }
    234332    else
Note: See TracChangeset for help on using the changeset viewer.