Changeset de1ceab in mod_gnutls


Ignore:
Timestamp:
Apr 23, 2018, 4:39:28 PM (3 years ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
debian/master, master, proxy-ticket
Children:
14a6f41
Parents:
0470e44
Message:

Replace internal cache implementation with mod_socache

Massively simplifies mod_gnutls code, and using mod_socache_shmcb will
allow for extremely simple cache setup (no configuration needed as
long as the module is available, not implemented yet).

Files:
9 edited

Legend:

Unmodified
Added
Removed
  • include/mod_gnutls.h.in

    r0470e44 rde1ceab  
    7171    mgs_cache_memcache,
    7272#endif
     73    mgs_cache_shmcb,
    7374    mgs_cache_unset
    7475} mgs_cache_e;
  • src/gnutls_cache.c

    r0470e44 rde1ceab  
    4747#include "mod_gnutls.h"
    4848#include "gnutls_config.h"
     49
     50#include <ap_socache.h>
    4951
    5052#if HAVE_APR_MEMCACHE
     
    129131}
    130132
    131 #if HAVE_APR_MEMCACHE
    132 
    133 /**
    134  * Turn a GnuTLS session ID into the key format we use with memcached
    135  * caches. Name the Session ID as `server:port.SessionID` to disallow
    136  * resuming sessions on different servers.
    137  *
    138  * @return `0` on success, `-1` on failure
    139  */
    140 static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen)
    141 {
    142     char sz[GNUTLS_SESSION_ID_STRING_LEN];
    143     apr_status_t rv = apr_escape_hex(sz, id, idlen, 0, NULL);
     133
     134
     135static int socache_store(server_rec *server, gnutls_datum_t key,
     136                         gnutls_datum_t data, apr_time_t expiry)
     137{
     138    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     139        ap_get_module_config(server->module_config, &gnutls_module);
     140
     141    apr_pool_t *spool;
     142    apr_pool_create(&spool, NULL);
     143
     144    apr_global_mutex_lock(sc->cache->mutex);
     145    apr_status_t rv = sc->cache->prov->store(sc->cache->socache, server,
     146                                             key.data, key.size,
     147                                             expiry,
     148                                             data.data, data.size,
     149                                             spool);
     150    apr_global_mutex_unlock(sc->cache->mutex);
     151
    144152    if (rv != APR_SUCCESS)
    145         return NULL;
    146 
    147     return apr_psprintf(c->pool, MC_TAG "%s:%d.%s",
    148             c->base_server->server_hostname,
    149             c->base_server->port, sz);
    150 }
    151 
    152 /**
    153  * GnuTLS Session Cache using libmemcached
    154  *
    155  */
    156 
    157 /* The underlying apr_memcache system is thread safe... woohoo */
    158 static apr_memcache_t *mc;
    159 
    160 static int mc_cache_child_init(apr_pool_t * p, server_rec * s,
    161         mgs_srvconf_rec * sc) {
    162     apr_status_t rv = APR_SUCCESS;
    163     int thread_limit = 0;
    164     int nservers = 0;
    165     char *cache_config;
    166     char *split;
    167     char *tok;
    168 
    169     ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
    170 
    171     /* Find all the servers in the first run to get a total count */
    172     cache_config = apr_pstrdup(p, sc->cache_config);
    173     split = apr_strtok(cache_config, " ", &tok);
    174     while (split) {
    175         nservers++;
    176         split = apr_strtok(NULL, " ", &tok);
    177     }
    178 
    179     rv = apr_memcache_create(p, nservers, 0, &mc);
    180     if (rv != APR_SUCCESS) {
    181         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    182                      "Failed to create Memcache object of size '%d'.",
    183                      nservers);
    184         return rv;
    185     }
    186 
    187     /* Now add each server to the memcache */
    188     cache_config = apr_pstrdup(p, sc->cache_config);
    189     split = apr_strtok(cache_config, " ", &tok);
    190     while (split) {
    191         apr_memcache_server_t *st;
    192         char *host_str;
    193         char *scope_id;
    194         apr_port_t port;
    195 
    196         rv = apr_parse_addr_port(&host_str, &scope_id, &port,
    197                 split, p);
    198         if (rv != APR_SUCCESS) {
    199             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    200                          "Failed to parse server: '%s'", split);
    201             return rv;
    202         }
    203 
    204         if (host_str == NULL) {
    205             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    206                          "Failed to parse server, "
    207                          "no hostname specified: '%s'", split);
    208             return rv;
    209         }
    210 
    211         if (port == 0) {
    212             port = 11211; /* default port */
    213         }
    214 
    215         /* Should Max Conns be (thread_limit / nservers) ? */
    216         rv = apr_memcache_server_create(p,
    217                 host_str, port,
    218                 0,
    219                 1, thread_limit, 600, &st);
    220         if (rv != APR_SUCCESS) {
    221             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    222                          "Failed to create server: %s:%d",
    223                          host_str, port);
    224             return rv;
    225         }
    226 
    227         rv = apr_memcache_add_server(mc, st);
    228         if (rv != APR_SUCCESS) {
    229             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    230                          "Failed to add server: %s:%d",
    231                          host_str, port);
    232             return rv;
    233         }
    234 
    235         split = apr_strtok(NULL, " ", &tok);
    236     }
    237     return rv;
    238 }
    239 
    240 static int mc_cache_store(server_rec *s, const char *key,
    241                           gnutls_datum_t data, apr_uint32_t timeout)
    242 {
    243     apr_status_t rv = apr_memcache_set(mc, key, (char *) data.data,
    244                                        data.size, timeout, 0);
    245 
    246     if (rv != APR_SUCCESS)
    247     {
    248         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    249                      "error storing key '%s' with %d bytes of data",
    250                      key, data.size);
     153    {
     154        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, server,
     155                     "error storing in cache '%s:%s'",
     156                     sc->cache->prov->name, sc->cache_config);
     157        apr_pool_destroy(spool);
    251158        return -1;
    252159    }
    253160
     161    ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server,
     162                 "stored %u bytes of data (%u byte key) in cache '%s:%s'",
     163                 data.size, key.size,
     164                 sc->cache->prov->name, sc->cache_config);
     165    apr_pool_destroy(spool);
    254166    return 0;
    255167}
    256168
    257 static int mc_cache_store_generic(server_rec *s, gnutls_datum_t key,
    258                                   gnutls_datum_t data, apr_time_t expiry)
    259 {
    260     apr_uint32_t timeout = apr_time_sec(expiry - apr_time_now());
    261 
    262     apr_pool_t *p;
    263     apr_pool_create(&p, NULL);
    264 
    265     const char *hex = apr_pescape_hex(p, key.data, key.size, 1);
    266     if (hex == NULL)
    267     {
    268         apr_pool_destroy(p);
     169
     170
     171static int socache_store_session(void *baton, gnutls_datum_t key,
     172                                 gnutls_datum_t data)
     173{
     174    mgs_handle_t *ctxt = baton;
     175    gnutls_datum_t dbmkey;
     176
     177    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    269178        return -1;
    270     }
    271 
    272     const char *strkey = apr_psprintf(p, MC_TAG "%s", hex);
    273 
    274     int ret = mc_cache_store(s, strkey, data, timeout);
    275 
    276     apr_pool_destroy(p);
    277     return ret;
    278 }
    279 
    280 static int mc_cache_store_session(void *baton, gnutls_datum_t key,
    281                                   gnutls_datum_t data)
    282 {
    283     mgs_handle_t *ctxt = baton;
    284 
    285     const char *strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    286     if (!strkey)
    287         return -1;
    288 
    289     apr_uint32_t timeout = apr_time_sec(ctxt->sc->cache_timeout);
    290 
    291     return mc_cache_store(ctxt->c->base_server, strkey, data, timeout);
    292 }
    293 
    294 /**
    295  * @param s server reference for logging
    296  * @param key the key to fetch
    297  * @param pool pool from which to allocate memory for the result
    298  */
    299 static gnutls_datum_t mc_cache_fetch(server_rec *s, const char *key,
    300                                      apr_pool_t *pool)
    301 {
    302     apr_status_t rv = APR_SUCCESS;
    303     char *value;
    304     apr_size_t value_len;
     179
     180    apr_time_t expiry = apr_time_now() + ctxt->sc->cache_timeout;
     181
     182    return socache_store(ctxt->c->base_server, dbmkey, data, expiry);
     183}
     184
     185
     186
     187// 4K should be enough for OCSP responses and sessions alike
     188#define SOCACHE_FETCH_BUF_SIZE 4096
     189static gnutls_datum_t socache_fetch(server_rec *server, gnutls_datum_t key,
     190                                    apr_pool_t *pool)
     191{
     192    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     193        ap_get_module_config(server->module_config, &gnutls_module);
     194
    305195    gnutls_datum_t data = {NULL, 0};
    306 
    307     rv = apr_memcache_getp(mc, pool, key, &value, &value_len, NULL);
    308 
    309     if (rv != APR_SUCCESS)
    310     {
    311         ap_log_error(APLOG_MARK, APLOG_TRACE2, rv, s,
    312                      "error fetching key '%s'",
    313                      key);
    314         return data;
    315     }
    316 
    317     /* TODO: Eliminate this memcpy. gnutls-- */
    318     data.data = gnutls_malloc(value_len);
     196    data.data = gnutls_malloc(SOCACHE_FETCH_BUF_SIZE);
    319197    if (data.data == NULL)
    320198        return data;
    321 
    322     data.size = value_len;
    323     memcpy(data.data, value, value_len);
    324 
    325     return data;
    326 }
    327 
    328 static gnutls_datum_t mc_cache_fetch_generic(server_rec *server,
    329                                              gnutls_datum_t key,
    330                                              apr_pool_t *pool)
    331 {
    332     gnutls_datum_t data = {NULL, 0};
    333     const char *hex = apr_pescape_hex(pool, key.data, key.size, 1);
    334     if (hex == NULL)
    335         return data;
    336 
    337     const char *strkey = apr_psprintf(pool, MC_TAG "%s", hex);
    338     return mc_cache_fetch(server, strkey, pool);
    339 }
    340 
    341 static gnutls_datum_t mc_cache_fetch_session(void *baton, gnutls_datum_t key)
    342 {
    343     mgs_handle_t *ctxt = baton;
    344     gnutls_datum_t data = {NULL, 0};
    345 
    346     const char *strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    347     if (!strkey)
    348         return data;
    349 
    350     return mc_cache_fetch(ctxt->c->base_server, strkey, ctxt->c->pool);
    351 }
    352 
    353 static int mc_cache_delete(void *baton, gnutls_datum_t key) {
    354     apr_status_t rv = APR_SUCCESS;
    355     mgs_handle_t *ctxt = baton;
    356     char *strkey = NULL;
    357 
    358     strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    359     if (!strkey)
    360         return -1;
    361 
    362     rv = apr_memcache_delete(mc, strkey, 0);
    363 
    364     if (rv != APR_SUCCESS) {
    365         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    366                      ctxt->c->base_server,
    367                      "error deleting key '%s'",
    368                      strkey);
    369         return -1;
    370     }
    371 
    372     return 0;
    373 }
    374 
    375 #endif  /* have_apr_memcache */
    376 
    377 static const char *db_type(mgs_srvconf_rec * sc) {
    378     if (sc->cache_type == mgs_cache_gdbm)
    379         return "gdbm";
    380     else
    381         return "db";
    382 }
    383 
    384 #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
    385 
    386 static void dbm_cache_expire(server_rec *s)
    387 {
    388     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    389         ap_get_module_config(s->module_config, &gnutls_module);
    390 
    391     apr_status_t rv;
    392     apr_dbm_t *dbm;
    393     apr_datum_t dbmkey;
    394     apr_datum_t dbmval;
    395     apr_time_t dtime;
     199    data.size = SOCACHE_FETCH_BUF_SIZE;
     200
    396201    apr_pool_t *spool;
    397     int total, deleted;
    398 
    399     apr_time_t now = apr_time_now();
    400 
    401     if (now - sc->last_cache_check < (sc->cache_timeout) / 2)
    402         return;
    403 
    404     sc->last_cache_check = now;
    405 
    406     apr_pool_create(&spool, NULL);
    407 
    408     total = 0;
    409     deleted = 0;
     202    apr_pool_create(&spool, pool);
    410203
    411204    apr_global_mutex_lock(sc->cache->mutex);
    412 
    413     rv = apr_dbm_open_ex(&dbm, db_type(sc),
    414             sc->cache_config, APR_DBM_RWCREATE,
    415             SSL_DBM_FILE_MODE, spool);
    416     if (rv != APR_SUCCESS) {
    417         ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s,
    418                      "error opening cache '%s'",
    419                      sc->cache_config);
    420         apr_global_mutex_unlock(sc->cache->mutex);
    421         apr_pool_destroy(spool);
    422         return;
    423     }
    424 
    425     apr_dbm_firstkey(dbm, &dbmkey);
    426     while (dbmkey.dptr != NULL) {
    427         apr_dbm_fetch(dbm, dbmkey, &dbmval);
    428         if (dbmval.dptr != NULL
    429                 && dbmval.dsize >= sizeof (apr_time_t)) {
    430             memcpy(&dtime, dbmval.dptr, sizeof (apr_time_t));
    431 
    432             if (now >= dtime) {
    433                 apr_dbm_delete(dbm, dbmkey);
    434                 deleted++;
    435             }
    436             apr_dbm_freedatum(dbm, dbmval);
    437         } else {
    438             apr_dbm_delete(dbm, dbmkey);
    439             deleted++;
    440         }
    441         total++;
    442         apr_dbm_nextkey(dbm, &dbmkey);
    443     }
    444     apr_dbm_close(dbm);
    445 
    446     rv = apr_global_mutex_unlock(sc->cache->mutex);
    447 
    448     ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
    449                  "Cleaned up cache '%s'. Deleted %d and left %d",
    450                  sc->cache_config, deleted, total - deleted);
    451 
    452     apr_pool_destroy(spool);
    453 
    454     return;
    455 }
    456 
    457 
    458 
    459 static gnutls_datum_t dbm_cache_fetch(server_rec *server, gnutls_datum_t key,
    460                                       apr_pool_t *pool)
    461 {
    462     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    463         ap_get_module_config(server->module_config, &gnutls_module);
    464 
    465     gnutls_datum_t data = {NULL, 0};
    466     apr_dbm_t *dbm;
    467     apr_datum_t dbmkey = {(char*) key.data, key.size};
    468     apr_datum_t dbmval;
    469     apr_time_t expiry = 0;
    470     apr_status_t rv;
    471 
    472     /* check if it is time for cache expiration */
    473     dbm_cache_expire(server);
    474 
    475     apr_global_mutex_lock(sc->cache->mutex);
    476 
    477     rv = apr_dbm_open_ex(&dbm, db_type(sc),
    478                          sc->cache_config, APR_DBM_READONLY,
    479                          SSL_DBM_FILE_MODE, pool);
    480     if (rv != APR_SUCCESS) {
    481         ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, server,
    482                      "error opening cache '%s'",
    483                      sc->cache_config);
    484         apr_global_mutex_unlock(sc->cache->mutex);
    485         return data;
    486     }
    487 
    488     rv = apr_dbm_fetch(dbm, dbmkey, &dbmval);
     205    apr_status_t rv = sc->cache->prov->retrieve(sc->cache->socache, server,
     206                                                key.data, key.size,
     207                                                data.data, &data.size,
     208                                                spool);
     209    apr_global_mutex_unlock(sc->cache->mutex);
    489210
    490211    if (rv != APR_SUCCESS)
    491         goto close_db;
    492 
    493     if (dbmval.dptr == NULL || dbmval.dsize <= sizeof (apr_time_t))
    494         goto cleanup;
    495 
    496     data.size = dbmval.dsize - sizeof (apr_time_t);
    497     /* get data expiration tag */
    498     expiry = *((apr_time_t *) dbmval.dptr);
    499 
    500     data.data = gnutls_malloc(data.size);
    501     if (data.data == NULL)
    502     {
    503         data.size = 0;
    504         goto cleanup;
    505     }
    506 
    507     ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server,
    508                  "fetched %" APR_SIZE_T_FMT " bytes from cache",
    509                  dbmval.dsize);
    510 
    511     memcpy(data.data, dbmval.dptr + sizeof (apr_time_t), data.size);
    512 
    513  cleanup:
    514     apr_dbm_freedatum(dbm, dbmval);
    515  close_db:
    516     apr_dbm_close(dbm);
    517     apr_global_mutex_unlock(sc->cache->mutex);
    518 
    519     /* cache entry might have expired since last cache cleanup */
    520     if (expiry != 0 && expiry < apr_time_now())
    521     {
     212    {
     213        /* APR_NOTFOUND means there's no such object. */
     214        if (rv == APR_NOTFOUND)
     215            ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server,
     216                         "requested entry not found in cache '%s:%s'.",
     217                         sc->cache->prov->name, sc->cache_config);
     218        else
     219            ap_log_error(APLOG_MARK, APLOG_WARNING, rv, server,
     220                         "error fetching from cache '%s:%s'",
     221                         sc->cache->prov->name, sc->cache_config);
     222        /* free unused buffer */
    522223        gnutls_free(data.data);
    523224        data.data = NULL;
    524225        data.size = 0;
    525         ap_log_error(APLOG_MARK, APLOG_TRACE1, APR_SUCCESS, server,
    526                      "dropped expired cache data");
    527     }
     226    }
     227    else
     228    {
     229        ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, server,
     230                     "fetched %u bytes from cache '%s:%s'",
     231                     data.size, sc->cache->prov->name, sc->cache_config);
     232    }
     233    apr_pool_destroy(spool);
    528234
    529235    return data;
    530236}
    531237
    532 static gnutls_datum_t dbm_cache_fetch_session(void *baton, gnutls_datum_t key)
     238static gnutls_datum_t socache_fetch_session(void *baton, gnutls_datum_t key)
    533239{
    534240    gnutls_datum_t data = {NULL, 0};
     
    539245        return data;
    540246
    541     return dbm_cache_fetch(ctxt->c->base_server, dbmkey, ctxt->c->pool);
    542 }
    543 
    544 static int dbm_cache_store(server_rec *s, gnutls_datum_t key,
    545                            gnutls_datum_t data, apr_time_t expiry)
    546 {
    547     mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    548         ap_get_module_config(s->module_config, &gnutls_module);
    549 
    550     apr_dbm_t *dbm;
    551     apr_datum_t dbmkey = {(char*) key.data, key.size};
    552     apr_datum_t dbmval;
    553     apr_status_t rv;
    554     apr_pool_t *spool;
    555 
    556     /* check if it is time for cache expiration */
    557     dbm_cache_expire(s);
    558 
    559     apr_pool_create(&spool, NULL);
    560 
    561     /* create DBM value */
    562     dbmval.dsize = data.size + sizeof (apr_time_t);
    563     dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize);
    564 
    565     /* prepend expiration time */
    566     memcpy((char *) dbmval.dptr, &expiry, sizeof (apr_time_t));
    567     memcpy((char *) dbmval.dptr + sizeof (apr_time_t),
    568             data.data, data.size);
    569 
    570     apr_global_mutex_lock(sc->cache->mutex);
    571 
    572     rv = apr_dbm_open_ex(&dbm, db_type(sc),
    573                          sc->cache_config, APR_DBM_RWCREATE,
    574                          SSL_DBM_FILE_MODE, spool);
    575     if (rv != APR_SUCCESS)
    576     {
    577         ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s,
    578                      "error opening cache '%s'",
    579                      sc->cache_config);
    580         apr_global_mutex_unlock(sc->cache->mutex);
    581         apr_pool_destroy(spool);
    582         return -1;
    583     }
    584 
    585     rv = apr_dbm_store(dbm, dbmkey, dbmval);
    586     if (rv != APR_SUCCESS)
    587     {
    588         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
    589                      "error storing in cache '%s'",
    590                      sc->cache_config);
    591         apr_dbm_close(dbm);
    592         apr_global_mutex_unlock(sc->cache->mutex);
    593         apr_pool_destroy(spool);
    594         return -1;
    595     }
    596 
    597     apr_dbm_close(dbm);
    598     apr_global_mutex_unlock(sc->cache->mutex);
    599 
    600     ap_log_error(APLOG_MARK, APLOG_TRACE1, rv, s,
    601                  "stored %" APR_SIZE_T_FMT " bytes of data (%"
    602                  APR_SIZE_T_FMT " byte key) in cache '%s'",
    603                  dbmval.dsize, dbmkey.dsize, sc->cache_config);
    604 
    605     apr_pool_destroy(spool);
    606 
    607     return 0;
    608 }
    609 
    610 static int dbm_cache_store_session(void *baton, gnutls_datum_t key,
    611                                    gnutls_datum_t data)
    612 {
    613     mgs_handle_t *ctxt = baton;
    614     gnutls_datum_t dbmkey;
    615 
    616     if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    617         return -1;
    618 
    619     apr_time_t expiry = apr_time_now() + ctxt->sc->cache_timeout;
    620 
    621     return dbm_cache_store(ctxt->c->base_server, dbmkey, data, expiry);
    622 }
    623 
    624 static int dbm_cache_delete(void *baton, gnutls_datum_t key)
    625 {
    626     apr_dbm_t *dbm;
     247    return socache_fetch(ctxt->c->base_server, dbmkey, ctxt->c->pool);
     248}
     249
     250
     251
     252static int socache_delete(void *baton, gnutls_datum_t key)
     253{
    627254    gnutls_datum_t tmpkey;
    628255    mgs_handle_t *ctxt = baton;
    629     apr_status_t rv;
    630256
    631257    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &tmpkey) < 0)
    632258        return -1;
    633     apr_datum_t dbmkey = {(char*) tmpkey.data, tmpkey.size};
    634259
    635260    apr_global_mutex_lock(ctxt->sc->cache->mutex);
    636 
    637     rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    638             ctxt->sc->cache_config, APR_DBM_RWCREATE,
    639             SSL_DBM_FILE_MODE, ctxt->c->pool);
     261    apr_status_t rv = ctxt->sc->cache->prov->remove(ctxt->sc->cache->socache,
     262                                                    ctxt->c->base_server,
     263                                                    key.data, key.size,
     264                                                    ctxt->c->pool);
     265    apr_global_mutex_unlock(ctxt->sc->cache->mutex);
     266
    640267    if (rv != APR_SUCCESS) {
    641268        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    642269                     ctxt->c->base_server,
    643                      "error opening cache '%s'",
    644                      ctxt->sc->cache_config);
    645         apr_global_mutex_unlock(ctxt->sc->cache->mutex);
     270                     "error deleting from cache '%s:%s'",
     271                     ctxt->sc->cache->prov->name, ctxt->sc->cache_config);
    646272        return -1;
    647273    }
    648 
    649     rv = apr_dbm_delete(dbm, dbmkey);
    650 
    651     if (rv != APR_SUCCESS) {
    652         ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    653                      ctxt->c->base_server,
    654                      "error deleting from cache '%s'",
    655                      ctxt->sc->cache_config);
    656         apr_dbm_close(dbm);
    657         apr_global_mutex_unlock(ctxt->sc->cache->mutex);
    658         return -1;
    659     }
    660 
    661     apr_dbm_close(dbm);
    662     apr_global_mutex_unlock(ctxt->sc->cache->mutex);
    663 
    664274    return 0;
    665275}
    666276
    667 static int dbm_cache_post_config(apr_pool_t * p, server_rec * s,
    668         mgs_srvconf_rec * sc) {
    669     apr_status_t rv;
    670     apr_dbm_t *dbm;
    671     const char *path1;
    672     const char *path2;
    673 
    674     rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config,
    675             APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p);
    676 
    677     if (rv != APR_SUCCESS) {
    678         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
    679                 "GnuTLS: Cannot create DBM Cache at `%s'",
    680                 sc->cache_config);
    681         return rv;
    682     }
    683 
    684     apr_dbm_close(dbm);
    685 
    686     apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1,
    687             &path2);
    688 
    689     /* The Following Code takes logic directly from mod_ssl's DBM Cache */
    690 #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
    691     /* Running as Root */
    692     if (path1 && geteuid() == 0) {
    693         if (0 != chown(path1, ap_unixd_config.user_id, -1))
    694             ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s,
    695                          "GnuTLS: could not chown cache path1 `%s' to uid %d (errno: %d)",
    696                          path1, ap_unixd_config.user_id, errno);
    697         if (path2 != NULL) {
    698             if (0 != chown(path2, ap_unixd_config.user_id, -1))
    699                 ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s,
    700                              "GnuTLS: could not chown cache path2 `%s' to uid %d (errno: %d)",
    701                              path2, ap_unixd_config.user_id, errno);
    702         }
    703     }
    704 #endif
    705 
    706     return rv;
    707 }
    708 
    709 int mgs_cache_post_config(apr_pool_t * p, server_rec * s,
    710         mgs_srvconf_rec * sc) {
    711 
     277
     278
     279static apr_status_t cleanup_socache(void *data)
     280{
     281    server_rec *s = data;
     282    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
     283        ap_get_module_config(s->module_config, &gnutls_module);
     284    ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
     285                 "Cleaning up socache '%s:%s'",
     286                 sc->cache->prov->name, sc->cache_config);
     287    sc->cache->prov->destroy(sc->cache->socache, s);
     288    return APR_SUCCESS;
     289}
     290
     291
     292
     293int mgs_cache_post_config(apr_pool_t *pconf, apr_pool_t *ptemp,
     294                          server_rec *s, mgs_srvconf_rec *sc)
     295{
     296    apr_status_t rv = APR_SUCCESS;
    712297    /* if GnuTLSCache was never explicitly set: */
    713     if (sc->cache_type == mgs_cache_unset)
     298    if (sc->cache_type == mgs_cache_unset || sc->cache_type == mgs_cache_none)
     299    {
    714300        sc->cache_type = mgs_cache_none;
     301        /* Cache disabled, done. */
     302        return APR_SUCCESS;
     303    }
    715304    /* if GnuTLSCacheTimeout was never explicitly set: */
    716305    if (sc->cache_timeout == MGS_TIMEOUT_UNSET)
     
    720309    if (sc->cache == NULL)
    721310    {
    722         sc->cache = apr_palloc(p, sizeof(struct mgs_cache));
    723         apr_status_t rv = ap_global_mutex_create(&sc->cache->mutex, NULL,
    724                                                  MGS_CACHE_MUTEX_NAME,
    725                                                  NULL, s, p, 0);
     311        sc->cache = apr_palloc(pconf, sizeof(struct mgs_cache));
     312        rv = ap_global_mutex_create(&sc->cache->mutex, NULL,
     313                                    MGS_CACHE_MUTEX_NAME,
     314                                    NULL, s, pconf, 0);
    726315        if (rv != APR_SUCCESS)
    727316            return rv;
    728317    }
    729318
     319    char *pname = NULL;
     320
    730321    if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm)
    731322    {
    732         sc->cache->store = dbm_cache_store;
    733         sc->cache->fetch = dbm_cache_fetch;
    734         return dbm_cache_post_config(p, s, sc);
     323        pname = "dbm";
     324        sc->cache->store = socache_store;
     325        sc->cache->fetch = socache_fetch;
     326        //return dbm_cache_post_config(pconf, s, sc);
    735327    }
    736328#if HAVE_APR_MEMCACHE
    737329    else if (sc->cache_type == mgs_cache_memcache)
    738330    {
    739         sc->cache->store = mc_cache_store_generic;
    740         sc->cache->fetch = mc_cache_fetch_generic;
    741     }
    742 #endif
     331        pname = "memcache";
     332        sc->cache->store = socache_store;
     333        sc->cache->fetch = socache_fetch;
     334    }
     335#endif
     336    else if (sc->cache_type == mgs_cache_shmcb)
     337    {
     338        pname = "shmcb";
     339        sc->cache->store = socache_store;
     340        sc->cache->fetch = socache_fetch;
     341    }
     342
     343    /* Find the right socache provider */
     344    sc->cache->prov = ap_lookup_provider(AP_SOCACHE_PROVIDER_GROUP,
     345                                         pname,
     346                                         AP_SOCACHE_PROVIDER_VERSION);
     347    if (sc->cache->prov)
     348    {
     349        /* Cache found; create it, passing anything beyond the colon. */
     350        const char *err = sc->cache->prov->create(&sc->cache->socache,
     351                                                  sc->cache_config,
     352                                                  ptemp, pconf);
     353        if (err != NULL)
     354        {
     355            ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, s,
     356                         "Creating cache '%s:%s' failed: %s",
     357                         pname, sc->cache_config, err);
     358            return HTTP_INSUFFICIENT_STORAGE;
     359        }
     360        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
     361                     "%s: Socache '%s' created.", __func__, pname);
     362
     363        // TODO: provide hints
     364        rv = sc->cache->prov->init(sc->cache->socache,
     365                                   "mod_gnutls-session", NULL, s, pconf);
     366        if (rv != APR_SUCCESS)
     367        {
     368            ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
     369                         "Initializing cache '%s:%s' failed!",
     370                         pname, sc->cache_config);
     371            return HTTP_INSUFFICIENT_STORAGE;
     372        }
     373        ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s,
     374                     "%s: socache '%s:%s' created.", __func__,
     375                     pname, sc->cache_config);
     376    }
     377    else
     378    {
     379        ap_log_error(APLOG_MARK, APLOG_EMERG, APR_EGENERAL, s,
     380                     "Could not find socache provider '%s', please make sure "
     381                     "that the provider name is valid and the "
     382                     "appropriate mod_socache submodule is loaded.", pname);
     383        return HTTP_NOT_FOUND;
     384    }
     385
     386    apr_pool_pre_cleanup_register(pconf, s, cleanup_socache);
    743387
    744388    return APR_SUCCESS;
     
    757401                     "Failed to reinit mutex '%s'", MGS_CACHE_MUTEX_NAME);
    758402
    759     if (sc->cache_type == mgs_cache_dbm
    760             || sc->cache_type == mgs_cache_gdbm) {
    761         return 0;
    762     }
    763 #if HAVE_APR_MEMCACHE
    764     else if (sc->cache_type == mgs_cache_memcache) {
    765         return mc_cache_child_init(p, s, sc);
    766     }
    767 #endif
    768403    return 0;
    769404}
     
    771406#include <assert.h>
    772407
    773 int mgs_cache_session_init(mgs_handle_t * ctxt) {
    774     if (ctxt->sc->cache_type == mgs_cache_dbm
    775             || ctxt->sc->cache_type == mgs_cache_gdbm) {
     408int mgs_cache_session_init(mgs_handle_t * ctxt)
     409{
     410    if (ctxt->sc->cache_type != mgs_cache_none)
     411    {
    776412        gnutls_db_set_retrieve_function(ctxt->session,
    777                 dbm_cache_fetch_session);
     413                                        socache_fetch_session);
    778414        gnutls_db_set_remove_function(ctxt->session,
    779                 dbm_cache_delete);
     415                                      socache_delete);
    780416        gnutls_db_set_store_function(ctxt->session,
    781                 dbm_cache_store_session);
     417                                     socache_store_session);
    782418        gnutls_db_set_ptr(ctxt->session, ctxt);
    783419    }
    784 #if HAVE_APR_MEMCACHE
    785     else if (ctxt->sc->cache_type == mgs_cache_memcache) {
    786         gnutls_db_set_retrieve_function(ctxt->session,
    787                 mc_cache_fetch_session);
    788         gnutls_db_set_remove_function(ctxt->session,
    789                 mc_cache_delete);
    790         gnutls_db_set_store_function(ctxt->session,
    791                 mc_cache_store_session);
    792         gnutls_db_set_ptr(ctxt->session, ctxt);
    793     }
    794 #endif
    795 
    796420    return 0;
    797421}
  • src/gnutls_cache.h

    r0470e44 rde1ceab  
    2828#include "mod_gnutls.h"
    2929#include <httpd.h>
     30#include <ap_socache.h>
    3031
    3132/** Name of the mod_gnutls cache access mutex, for use with Apache's
     
    3839 * parsed.
    3940 *
    40  * @param p configuration memory pool
     41 * @param pconf configuration memory pool
     42 * @param ptemp temporary memory pool
    4143 * @param s default server of the Apache configuration, head of the
    4244 * server list
    4345 * @param sc mod_gnutls data associated with `s`
    4446 */
    45 int mgs_cache_post_config(apr_pool_t *p, server_rec *s, mgs_srvconf_rec *sc);
     47int mgs_cache_post_config(apr_pool_t *pconf, apr_pool_t *ptemp,
     48                          server_rec *s, mgs_srvconf_rec *sc);
    4649
    4750/**
     
    113116 */
    114117struct mgs_cache {
     118    /** Socache provider to use for this cache */
     119    const ap_socache_provider_t *prov;
     120    /** The actual socache instance */
     121    ap_socache_instance_t *socache;
    115122    /** Store function for this cache */
    116123    cache_store_func store;
  • src/gnutls_config.c

    r0470e44 rde1ceab  
    623623    }
    624624#endif
     625    else if (strcasecmp("shmcb", type) == 0) {
     626        sc->cache_type = mgs_cache_shmcb;
     627    }
    625628    else {
    626629        return "Invalid Type for GnuTLSCache!";
  • src/gnutls_hooks.c

    r0470e44 rde1ceab  
    577577
    578578
    579     rv = mgs_cache_post_config(pconf, s, sc_base);
     579    rv = mgs_cache_post_config(pconf, ptemp, s, sc_base);
    580580    if (rv != APR_SUCCESS)
    581581    {
  • src/gnutls_ocsp.c

    r0470e44 rde1ceab  
    10921092    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
    10931093        ap_get_module_config(server->module_config, &gnutls_module);
     1094    // TODO: check for cache!
    10941095
    10951096    if (sc->certs_x509_chain_num < 2)
  • test/base_apache.conf

    r0470e44 rde1ceab  
    1212LoadModule      authz_core_module       ${AP_LIBEXECDIR}/mod_authz_core.so
    1313LoadModule      mime_module             ${AP_LIBEXECDIR}/mod_mime.so
     14
     15LoadModule      socache_dbm_module      ${AP_LIBEXECDIR}/mod_socache_dbm.so
     16LoadModule      socache_shmcb_module    ${AP_LIBEXECDIR}/mod_socache_shmcb.so
     17
    1418TypesConfig ${srcdir}/mime.types
    1519
  • test/tests/00_basic/apache.conf

    r0470e44 rde1ceab  
    11Include ${srcdir}/base_apache.conf
    22
    3 GnuTLSCache dbm cache/gnutls_cache
     3GnuTLSCache dbm:cache/gnutls_cache_${TEST_NAME}
    44
    55<VirtualHost _default_:${TEST_PORT}>
  • test/tests/27_OCSP_server/apache.conf

    r0470e44 rde1ceab  
    11Include ${srcdir}/base_apache.conf
    2 GnuTLSCache dbm:cache/gnutls_cache_${TEST_NAME}
     2GnuTLSCache shmcb:cache/gnutls_cache_${TEST_NAME}
    33
    44<VirtualHost _default_:${TEST_PORT}>
Note: See TracChangeset for help on using the changeset viewer.