Changeset 3e22b82 in mod_gnutls for src/gnutls_cache.c


Ignore:
Timestamp:
Jun 9, 2016, 7:09:22 PM (4 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
debian/master, debian/stretch-backports, master, upstream
Children:
e809fb3
Parents:
70a1e5a
Message:

Add generic store/fetch support to the memcached cache

Required to use the memcached cache for OCSP responses.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_cache.c

    r70a1e5a r3e22b82  
    1919 */
    2020
     21/***
     22 * The signatures of the (dbm|mc)_cache_...() functions may be a bit
     23 * confusing: "store" and "expire" take a server_rec, "fetch" an
     24 * mgs_handle_t, and "delete" the void* required for a
     25 * gnutls_db_remove_func. The first two have matching ..._session
     26 * functions to fit their respective GnuTLS session cache signatures.
     27 *
     28 * This is because "store", "expire" (dbm only), and "fetch" are also
     29 * needed for the OCSP cache. Their ..._session variants have been
     30 * created to take care of the session cache specific parts, mainly
     31 * calculating the DB key from the session ID. They have to match the
     32 * appropriate GnuTLS DB function signatures.
     33 *
     34 * Additionally, there are the mc_cache_(store|fetch)_generic()
     35 * functions. They exist because memcached requires string keys while
     36 * DBM accepts binary keys, and provide wrappers to turn binary keys
     37 * into hex strings with a "mod_gnutls:" prefix.
     38 *
     39 * To update cached OCSP responses independent of client connections,
     40 * "store" and "expire" have to work without a connection context. On
     41 * the other hand "fetch" does not need to do that, because cached
     42 * OCSP responses will be retrieved for use in client connections.
     43 ***/
     44
    2145#include "gnutls_cache.h"
    2246#include "mod_gnutls.h"
     
    199223}
    200224
    201 static int mc_cache_store(void *baton, gnutls_datum_t key,
    202         gnutls_datum_t data) {
     225static int mc_cache_store(server_rec *s, const char *key,
     226                          gnutls_datum_t data, apr_uint32_t timeout)
     227{
     228    apr_status_t rv = apr_memcache_set(mc, key, (char *) data.data,
     229                                       data.size, timeout, 0);
     230
     231    if (rv != APR_SUCCESS)
     232    {
     233        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
     234                     "[gnutls_cache] error setting key '%s' "
     235                     "with %d bytes of data", key, data.size);
     236        return -1;
     237    }
     238
     239    return 0;
     240}
     241
     242int mc_cache_store_generic(server_rec *s, gnutls_datum_t key,
     243                           gnutls_datum_t data, apr_time_t expiry)
     244{
     245    apr_uint32_t timeout = apr_time_sec(expiry - apr_time_now());
     246
     247    apr_pool_t *p;
     248    apr_pool_create(&p, NULL);
     249
     250    const char *hex = apr_pescape_hex(p, key.data, key.size, 1);
     251    if (hex == NULL)
     252    {
     253        apr_pool_destroy(p);
     254        return -1;
     255    }
     256
     257    const char *strkey = apr_psprintf(p, MC_TAG "%s", hex);
     258
     259    int ret = mc_cache_store(s, strkey, data, timeout);
     260
     261    apr_pool_destroy(p);
     262    return ret;
     263}
     264
     265static int mc_cache_store_session(void *baton, gnutls_datum_t key,
     266                                  gnutls_datum_t data)
     267{
     268    mgs_handle_t *ctxt = baton;
     269
     270    const char *strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
     271    if (!strkey)
     272        return -1;
     273
     274    apr_uint32_t timeout = apr_time_sec(ctxt->sc->cache_timeout);
     275
     276    return mc_cache_store(ctxt->c->base_server, strkey, data, timeout);
     277}
     278
     279static gnutls_datum_t mc_cache_fetch(conn_rec *c, const char *key)
     280{
    203281    apr_status_t rv = APR_SUCCESS;
    204     mgs_handle_t *ctxt = baton;
    205     char *strkey = NULL;
    206     apr_uint32_t timeout;
    207 
    208     strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    209     if (!strkey)
    210         return -1;
    211 
    212     timeout = apr_time_sec(ctxt->sc->cache_timeout);
    213 
    214     rv = apr_memcache_set(mc, strkey, (char *) data.data, data.size, timeout,
    215             0);
    216 
    217     if (rv != APR_SUCCESS) {
    218         ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
    219                 ctxt->c->base_server,
    220                 "[gnutls_cache] error setting key '%s' "
    221                 "with %d bytes of data", strkey, data.size);
    222         return -1;
    223     }
    224 
    225     return 0;
    226 }
    227 
    228 static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) {
    229     apr_status_t rv = APR_SUCCESS;
    230     mgs_handle_t *ctxt = baton;
    231     char *strkey = NULL;
    232282    char *value;
    233283    apr_size_t value_len;
    234284    gnutls_datum_t data = {NULL, 0};
    235285
    236     strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    237     if (!strkey) {
    238         return data;
    239     }
    240 
    241     rv = apr_memcache_getp(mc, ctxt->c->pool, strkey,
    242             &value, &value_len, NULL);
    243 
    244     if (rv != APR_SUCCESS) {
     286    rv = apr_memcache_getp(mc, c->pool, key, &value, &value_len, NULL);
     287
     288    if (rv != APR_SUCCESS)
     289    {
    245290#if MOD_GNUTLS_DEBUG
    246         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    247                 ctxt->c->base_server,
    248                 "[gnutls_cache] error fetching key '%s' ",
    249                 strkey);
    250 #endif
    251         data.size = 0;
    252         data.data = NULL;
     291        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, c,
     292                      "[gnutls_cache] error fetching key '%s' ",
     293                      key);
     294#endif
    253295        return data;
    254296    }
     
    263305
    264306    return data;
     307}
     308
     309gnutls_datum_t mc_cache_fetch_generic(mgs_handle_t *ctxt, gnutls_datum_t key)
     310{
     311    gnutls_datum_t data = {NULL, 0};
     312    const char *hex = apr_pescape_hex(ctxt->c->pool, key.data, key.size, 1);
     313    if (hex == NULL)
     314        return data;
     315
     316    const char *strkey = apr_psprintf(ctxt->c->pool, MC_TAG "%s", hex);
     317    return mc_cache_fetch(ctxt->c, strkey);
     318}
     319
     320static gnutls_datum_t mc_cache_fetch_session(void *baton, gnutls_datum_t key)
     321{
     322    mgs_handle_t *ctxt = baton;
     323    gnutls_datum_t data = {NULL, 0};
     324
     325    const char *strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
     326    if (!strkey)
     327        return data;
     328
     329    return mc_cache_fetch(ctxt->c, strkey);
    265330}
    266331
     
    297362
    298363#define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
    299 
    300 /***
    301  * The signatures of the dbm_cache_...() functions may be a bit
    302  * confusing: "store" and "expire" take a server_rec, "fetch" an
    303  * mgs_handle_t, and "delete" the void* required for a
    304  * gnutls_db_remove_func. The first two have matching ..._session
    305  * functions to fit their respective GnuTLS session cache signatures.
    306  *
    307  * This is because "store", "expire", and "fetch" are also needed for
    308  * the OCSP cache. Their ..._session variants have been created to
    309  * take care of the session cache specific parts, mainly calculating
    310  * the DB key from the session ID. They have to match the appropriate
    311  * GnuTLS DB function signatures.
    312  *
    313  * To update cached OCSP responses independent of client connections,
    314  * "store" and "expire" have to work without a connection context. On
    315  * the other hand "fetch" does not need to do that, because cached
    316  * OCSP responses will be retrieved for use in client connections.
    317  ***/
    318364
    319365static void dbm_cache_expire(server_rec *s)
     
    696742    else if (ctxt->sc->cache_type == mgs_cache_memcache) {
    697743        gnutls_db_set_retrieve_function(ctxt->session,
    698                 mc_cache_fetch);
     744                mc_cache_fetch_session);
    699745        gnutls_db_set_remove_function(ctxt->session,
    700746                mc_cache_delete);
    701747        gnutls_db_set_store_function(ctxt->session,
    702                 mc_cache_store);
     748                mc_cache_store_session);
    703749        gnutls_db_set_ptr(ctxt->session, ctxt);
    704750    }
Note: See TracChangeset for help on using the changeset viewer.