source: mod_gnutls/src/gnutls_cache.c @ c005645

debian/masterdebian/stretch-backportsproxy-ticketupstream
Last change on this file since c005645 was c005645, checked in by Thomas Klute <thomas2.klute@…>, 4 years ago

Mutex for DBM cache access

I noticed that with a DBM cache enabled and session tickets disabled
even a handful of parallel connections trashed the cache database, and
consequently the error log. According to comments and documentation on
mod_socache_dbm the APR DBM module is not thread or multi-process
safe, so a global mutex is necessary. With the mutex the cache
corruption disappears in my benchmarks.

  • Property mode set to 100644
File size: 20.4 KB
RevLine 
[fcb122d]1/**
2 *  Copyright 2004-2005 Paul Querna
[e183628]3 *  Copyright 2008 Nikos Mavrogiannopoulos
4 *  Copyright 2011 Dash Shendy
[8913410]5 *  Copyright 2015-2016 Thomas Klute
[0b3bc05]6 *
7 *  Licensed under the Apache License, Version 2.0 (the "License");
8 *  you may not use this file except in compliance with the License.
9 *  You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *  Unless required by applicable law or agreed to in writing, software
14 *  distributed under the License is distributed on an "AS IS" BASIS,
15 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *  See the License for the specific language governing permissions and
17 *  limitations under the License.
18 *
19 */
20
[04e6e65]21#include "gnutls_cache.h"
[0b3bc05]22#include "mod_gnutls.h"
[6e0bfd6]23
24#if HAVE_APR_MEMCACHE
25#include "apr_memcache.h"
26#endif
27
[fcb122d]28#include "apr_dbm.h"
29
[a66e147]30#include "ap_mpm.h"
[c005645]31#include <util_mutex.h>
[0b3bc05]32
[fcb122d]33#include <unistd.h>
34#include <sys/types.h>
35
36#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
37#include "unixd.h"
38#endif
39
[c005645]40/* default cache timeout */
41#define MGS_DEFAULT_CACHE_TIMEOUT 300
42
[671b64f]43/* it seems the default has some strange errors. Use SDBM
[03a9a6b]44 */
[6e0bfd6]45#define MC_TAG "mod_gnutls:"
[c055502]46#define MC_TAG_LEN sizeof(MC_TAG)
[6e0bfd6]47#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN)
48
[7e67487]49#if MODULE_MAGIC_NUMBER_MAJOR < 20081201
50#define ap_unixd_config unixd_config
51#endif
52
[55dc3f0]53#ifdef APLOG_USE_MODULE
54APLOG_USE_MODULE(gnutls);
55#endif
56
[c055502]57char *mgs_session_id2sz(unsigned char *id, int idlen,
[e183628]58        char *str, int strsize) {
59    char *cp;
60    int n;
61
62    cp = str;
63    for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) {
64        apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]);
65        cp += 2;
66    }
67    *cp = '\0';
68    return str;
[6e0bfd6]69}
[c055502]70
71/* Name the Session ID as:
[c223c85]72 * server:port.SessionID
[c055502]73 * to disallow resuming sessions on different servers
74 */
[2f932fa]75static int mgs_session_id2dbm(conn_rec *c, unsigned char *id, int idlen,
76                              gnutls_datum_t *dbmkey)
77{
[e183628]78    char buf[STR_SESSION_LEN];
79    char *sz;
80
81    sz = mgs_session_id2sz(id, idlen, buf, sizeof (buf));
82    if (sz == NULL)
83        return -1;
84
[2f932fa]85    char *newkey = apr_psprintf(c->pool, "%s:%d.%s",
86                                c->base_server->server_hostname,
87                                c->base_server->port, sz);
88    dbmkey->size = strlen(newkey);
89    /* signedness does not matter for arbitrary bits */
90    dbmkey->data = (unsigned char*) newkey;
[e183628]91    return 0;
[c055502]92}
[7bebb42]93
94#define CTIME "%b %d %k:%M:%S %Y %Z"
[e02dd8c]95
[e183628]96char *mgs_time2sz(time_t in_time, char *str, int strsize) {
97    apr_time_exp_t vtm;
98    apr_size_t ret_size;
99    apr_time_t t;
[e02dd8c]100
101
[e183628]102    apr_time_ansi_put(&t, in_time);
103    apr_time_exp_gmt(&vtm, t);
104    apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm);
105
106    return str;
[7bebb42]107}
[6e0bfd6]108
[c055502]109#if HAVE_APR_MEMCACHE
[e183628]110
[c055502]111/* Name the Session ID as:
[c223c85]112 * server:port.SessionID
[c055502]113 * to disallow resuming sessions on different servers
114 */
[e183628]115static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) {
116    char buf[STR_SESSION_LEN];
117    char *sz;
118
119    sz = mgs_session_id2sz(id, idlen, buf, sizeof (buf));
120    if (sz == NULL)
121        return NULL;
122
123    return apr_psprintf(c->pool, MC_TAG "%s:%d.%s",
124            c->base_server->server_hostname,
125            c->base_server->port, sz);
[42307a9]126}
127
[0b3bc05]128/**
129 * GnuTLS Session Cache using libmemcached
130 *
131 */
132
[a66e147]133/* The underlying apr_memcache system is thread safe... woohoo */
[e02dd8c]134static apr_memcache_t *mc;
[a66e147]135
[e02dd8c]136static int mc_cache_child_init(apr_pool_t * p, server_rec * s,
[e183628]137        mgs_srvconf_rec * sc) {
138    apr_status_t rv = APR_SUCCESS;
139    int thread_limit = 0;
140    int nservers = 0;
141    char *cache_config;
142    char *split;
143    char *tok;
144
145    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
146
147    /* Find all the servers in the first run to get a total count */
148    cache_config = apr_pstrdup(p, sc->cache_config);
149    split = apr_strtok(cache_config, " ", &tok);
150    while (split) {
151        nservers++;
152        split = apr_strtok(NULL, " ", &tok);
153    }
154
155    rv = apr_memcache_create(p, nservers, 0, &mc);
156    if (rv != APR_SUCCESS) {
157        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
158                "[gnutls_cache] Failed to create Memcache Object of '%d' size.",
159                nservers);
160        return rv;
161    }
162
163    /* Now add each server to the memcache */
164    cache_config = apr_pstrdup(p, sc->cache_config);
165    split = apr_strtok(cache_config, " ", &tok);
166    while (split) {
167        apr_memcache_server_t *st;
168        char *host_str;
169        char *scope_id;
170        apr_port_t port;
171
172        rv = apr_parse_addr_port(&host_str, &scope_id, &port,
173                split, p);
174        if (rv != APR_SUCCESS) {
175            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
176                    "[gnutls_cache] Failed to Parse Server: '%s'",
177                    split);
178            return rv;
179        }
180
181        if (host_str == NULL) {
182            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
183                    "[gnutls_cache] Failed to Parse Server, "
184                    "no hostname specified: '%s'", split);
185            return rv;
186        }
187
188        if (port == 0) {
189            port = 11211; /* default port */
190        }
191
192        /* Should Max Conns be (thread_limit / nservers) ? */
193        rv = apr_memcache_server_create(p,
194                host_str, port,
195                0,
196                1, thread_limit, 600, &st);
197        if (rv != APR_SUCCESS) {
198            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
199                    "[gnutls_cache] Failed to Create Server: %s:%d",
200                    host_str, port);
201            return rv;
202        }
203
204        rv = apr_memcache_add_server(mc, st);
205        if (rv != APR_SUCCESS) {
206            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
207                    "[gnutls_cache] Failed to Add Server: %s:%d",
208                    host_str, port);
209            return rv;
210        }
211
212        split = apr_strtok(NULL, " ", &tok);
213    }
214    return rv;
[32f2e60]215}
[a66e147]216
[e02dd8c]217static int mc_cache_store(void *baton, gnutls_datum_t key,
[e183628]218        gnutls_datum_t data) {
219    apr_status_t rv = APR_SUCCESS;
220    mgs_handle_t *ctxt = baton;
221    char *strkey = NULL;
222    apr_uint32_t timeout;
223
224    strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
225    if (!strkey)
226        return -1;
227
228    timeout = apr_time_sec(ctxt->sc->cache_timeout);
229
230    rv = apr_memcache_set(mc, strkey, (char *) data.data, data.size, timeout,
231            0);
232
233    if (rv != APR_SUCCESS) {
234        ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
235                ctxt->c->base_server,
236                "[gnutls_cache] error setting key '%s' "
237                "with %d bytes of data", strkey, data.size);
238        return -1;
239    }
240
241    return 0;
[a66e147]242}
243
[e183628]244static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) {
245    apr_status_t rv = APR_SUCCESS;
246    mgs_handle_t *ctxt = baton;
247    char *strkey = NULL;
248    char *value;
249    apr_size_t value_len;
250    gnutls_datum_t data = {NULL, 0};
[e02dd8c]251
[e183628]252    strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
253    if (!strkey) {
254        return data;
255    }
[e02dd8c]256
[e183628]257    rv = apr_memcache_getp(mc, ctxt->c->pool, strkey,
258            &value, &value_len, NULL);
[e02dd8c]259
[e183628]260    if (rv != APR_SUCCESS) {
[316bd8c]261#if MOD_GNUTLS_DEBUG
[e183628]262        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
263                ctxt->c->base_server,
264                "[gnutls_cache] error fetching key '%s' ",
265                strkey);
[316bd8c]266#endif
[e183628]267        data.size = 0;
268        data.data = NULL;
269        return data;
270    }
[a66e147]271
[e183628]272    /* TODO: Eliminate this memcpy. gnutls-- */
273    data.data = gnutls_malloc(value_len);
274    if (data.data == NULL)
275        return data;
[a66e147]276
[e183628]277    data.size = value_len;
278    memcpy(data.data, value, value_len);
[a66e147]279
[e183628]280    return data;
[32f2e60]281}
282
[e183628]283static int mc_cache_delete(void *baton, gnutls_datum_t key) {
284    apr_status_t rv = APR_SUCCESS;
285    mgs_handle_t *ctxt = baton;
286    char *strkey = NULL;
[a66e147]287
[e183628]288    strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
289    if (!strkey)
290        return -1;
[a66e147]291
[e183628]292    rv = apr_memcache_delete(mc, strkey, 0);
[a66e147]293
[e183628]294    if (rv != APR_SUCCESS) {
295        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
296                ctxt->c->base_server,
297                "[gnutls_cache] error deleting key '%s' ",
298                strkey);
299        return -1;
300    }
[a66e147]301
[e183628]302    return 0;
[32f2e60]303}
304
[410d216]305#endif  /* have_apr_memcache */
[6e0bfd6]306
[410d216]307static const char *db_type(mgs_srvconf_rec * sc) {
[e183628]308    if (sc->cache_type == mgs_cache_gdbm)
309        return "gdbm";
310    else
311        return "db";
[771ca63]312}
313
[fcb122d]314#define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
315
[6814e48]316/***
317 * The signatures of the dbm_cache_...() functions may be a bit
318 * confusing: "store" and "expire" take a server_rec, "fetch" an
319 * mgs_handle_t, and "delete" the void* required for a
320 * gnutls_db_remove_func. The first three have matching ..._session
321 * functions to fit their respective GnuTLS session cache signatures.
322 *
323 * This is because "store", "expire", and "fetch" are also needed for
324 * the OCSP cache. Their ..._session variants have been created to
325 * take care of the session cache specific parts, mainly calculating
326 * the DB key from the session ID. They have to match the appropriate
327 * GnuTLS DB function signatures.
328 *
329 * To update cached OCSP responses independent of client connections,
330 * "store" and "expire" have to work without a connection context. On
331 * the other hand "fetch" does not need to do that, because cached
332 * OCSP responses will be retrieved for use in client connections.
333 ***/
334
[f785704]335static void dbm_cache_expire(server_rec *s)
336{
337    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
338        ap_get_module_config(s->module_config, &gnutls_module);
339
[e183628]340    apr_status_t rv;
341    apr_dbm_t *dbm;
342    apr_datum_t dbmkey;
343    apr_datum_t dbmval;
344    apr_time_t dtime;
345    apr_pool_t *spool;
346    int total, deleted;
347
[f785704]348    apr_time_t now = apr_time_now();
[e183628]349
[f785704]350    if (now - sc->last_cache_check < (sc->cache_timeout) / 2)
[e183628]351        return;
352
[f785704]353    sc->last_cache_check = now;
[e183628]354
[f785704]355    apr_pool_create(&spool, NULL);
[e183628]356
357    total = 0;
358    deleted = 0;
359
[c005645]360    apr_global_mutex_lock(sc->cache_mutex);
361
[f785704]362    rv = apr_dbm_open_ex(&dbm, db_type(sc),
363            sc->cache_config, APR_DBM_RWCREATE,
[e183628]364            SSL_DBM_FILE_MODE, spool);
365    if (rv != APR_SUCCESS) {
[f785704]366        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s,
[c005645]367                "[gnutls_cache] error opening cache '%s'",
[f785704]368                sc->cache_config);
[c005645]369        apr_global_mutex_unlock(sc->cache_mutex);
[e183628]370        apr_pool_destroy(spool);
371        return;
372    }
373
374    apr_dbm_firstkey(dbm, &dbmkey);
375    while (dbmkey.dptr != NULL) {
376        apr_dbm_fetch(dbm, dbmkey, &dbmval);
377        if (dbmval.dptr != NULL
378                && dbmval.dsize >= sizeof (apr_time_t)) {
379            memcpy(&dtime, dbmval.dptr, sizeof (apr_time_t));
380
381            if (now >= dtime) {
382                apr_dbm_delete(dbm, dbmkey);
383                deleted++;
384            }
385            apr_dbm_freedatum(dbm, dbmval);
386        } else {
387            apr_dbm_delete(dbm, dbmkey);
388            deleted++;
389        }
390        total++;
391        apr_dbm_nextkey(dbm, &dbmkey);
392    }
393    apr_dbm_close(dbm);
394
[c005645]395    rv = apr_global_mutex_unlock(sc->cache_mutex);
396
[f785704]397    ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
[e183628]398            "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d",
[f785704]399            sc->cache_config, deleted, total - deleted);
[e183628]400
401    apr_pool_destroy(spool);
402
403    return;
[fcb122d]404}
405
[6b4136c]406gnutls_datum_t dbm_cache_fetch(mgs_handle_t *ctxt, gnutls_datum_t key)
[15245bf]407{
[e183628]408    gnutls_datum_t data = {NULL, 0};
409    apr_dbm_t *dbm;
[2f932fa]410    apr_datum_t dbmkey = {(char*) key.data, key.size};
[e183628]411    apr_datum_t dbmval;
412    apr_status_t rv;
413
[c005645]414    apr_global_mutex_lock(ctxt->sc->cache_mutex);
415
[e183628]416    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
417            ctxt->sc->cache_config, APR_DBM_READONLY,
418            SSL_DBM_FILE_MODE, ctxt->c->pool);
419    if (rv != APR_SUCCESS) {
[15245bf]420        ap_log_cerror(APLOG_MARK, APLOG_NOTICE, rv, ctxt->c,
421                      "error opening cache '%s'",
422                      ctxt->sc->cache_config);
[c005645]423        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]424        return data;
425    }
426
[2f932fa]427    rv = apr_dbm_fetch(dbm, dbmkey, &dbmval);
[e183628]428
429    if (rv != APR_SUCCESS) {
430        apr_dbm_close(dbm);
[c005645]431        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]432        return data;
433    }
434
435    if (dbmval.dptr == NULL || dbmval.dsize <= sizeof (apr_time_t)) {
436        apr_dbm_freedatum(dbm, dbmval);
437        apr_dbm_close(dbm);
[c005645]438        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]439        return data;
440    }
441
442    data.size = dbmval.dsize - sizeof (apr_time_t);
443
444    data.data = gnutls_malloc(data.size);
445    if (data.data == NULL) {
446        apr_dbm_freedatum(dbm, dbmval);
447        apr_dbm_close(dbm);
[c005645]448        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]449        return data;
450    }
451
[15245bf]452    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, rv, ctxt->c,
453                  "fetched %ld bytes from cache",
454                  dbmval.dsize);
455
[e183628]456    memcpy(data.data, dbmval.dptr + sizeof (apr_time_t), data.size);
457
458    apr_dbm_freedatum(dbm, dbmval);
459    apr_dbm_close(dbm);
[c005645]460    apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]461
462    return data;
[fcb122d]463}
464
[2f932fa]465static gnutls_datum_t dbm_cache_fetch_session(void *baton, gnutls_datum_t key)
[15245bf]466{
467    gnutls_datum_t data = {NULL, 0};
[2f932fa]468    gnutls_datum_t dbmkey;
[15245bf]469    mgs_handle_t *ctxt = baton;
470
471    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
472        return data;
473
474    return dbm_cache_fetch(ctxt, dbmkey);
475}
476
[6b4136c]477int dbm_cache_store(server_rec *s, gnutls_datum_t key,
478                    gnutls_datum_t data, apr_time_t expiry)
[ae08186]479{
[1d1361f]480    mgs_srvconf_rec *sc = (mgs_srvconf_rec *)
481        ap_get_module_config(s->module_config, &gnutls_module);
482
[e183628]483    apr_dbm_t *dbm;
[2f932fa]484    apr_datum_t dbmkey = {(char*) key.data, key.size};
[e183628]485    apr_datum_t dbmval;
486    apr_status_t rv;
487    apr_pool_t *spool;
488
[1d1361f]489    /* we expire dbm only on every store */
490    dbm_cache_expire(s);
[e183628]491
[1d1361f]492    apr_pool_create(&spool, NULL);
[e183628]493
494    /* create DBM value */
495    dbmval.dsize = data.size + sizeof (apr_time_t);
496    dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize);
497
[ae08186]498    /* prepend expiration time */
[e183628]499    memcpy((char *) dbmval.dptr, &expiry, sizeof (apr_time_t));
500    memcpy((char *) dbmval.dptr + sizeof (apr_time_t),
501            data.data, data.size);
502
[c005645]503    apr_global_mutex_lock(sc->cache_mutex);
504
[1d1361f]505    rv = apr_dbm_open_ex(&dbm, db_type(sc),
506                         sc->cache_config, APR_DBM_RWCREATE,
507                         SSL_DBM_FILE_MODE, spool);
508    if (rv != APR_SUCCESS)
509    {
510        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, s,
511                     "error opening cache '%s'",
512                     sc->cache_config);
[c005645]513        apr_global_mutex_unlock(sc->cache_mutex);
[e183628]514        apr_pool_destroy(spool);
515        return -1;
516    }
517
[2f932fa]518    rv = apr_dbm_store(dbm, dbmkey, dbmval);
[1d1361f]519    if (rv != APR_SUCCESS)
520    {
521        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
522                     "error storing in cache '%s'",
523                     sc->cache_config);
[e183628]524        apr_dbm_close(dbm);
[c005645]525        apr_global_mutex_unlock(sc->cache_mutex);
[e183628]526        apr_pool_destroy(spool);
527        return -1;
528    }
529
[c005645]530    apr_dbm_close(dbm);
531    apr_global_mutex_unlock(sc->cache_mutex);
532
[1d1361f]533    ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, s,
534                 "stored %ld bytes of data (%ld byte key) in cache '%s'",
[2f932fa]535                 dbmval.dsize, dbmkey.dsize, sc->cache_config);
[1d1361f]536
[e183628]537    apr_pool_destroy(spool);
538
539    return 0;
[fcb122d]540}
541
[ae08186]542static int dbm_cache_store_session(void *baton, gnutls_datum_t key,
543                                   gnutls_datum_t data)
544{
545    mgs_handle_t *ctxt = baton;
[2f932fa]546    gnutls_datum_t dbmkey;
[ae08186]547
548    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
549        return -1;
550
551    apr_time_t expiry = apr_time_now() + ctxt->sc->cache_timeout;
552
[1d1361f]553    return dbm_cache_store(ctxt->c->base_server, dbmkey, data, expiry);
[ae08186]554}
555
[e183628]556static int dbm_cache_delete(void *baton, gnutls_datum_t key) {
557    apr_dbm_t *dbm;
[2f932fa]558    gnutls_datum_t tmpkey;
[e183628]559    mgs_handle_t *ctxt = baton;
560    apr_status_t rv;
561
[2f932fa]562    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &tmpkey) < 0)
[e183628]563        return -1;
[2f932fa]564    apr_datum_t dbmkey = {(char*) tmpkey.data, tmpkey.size};
[e183628]565
[c005645]566    apr_global_mutex_lock(ctxt->sc->cache_mutex);
567
[e183628]568    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
569            ctxt->sc->cache_config, APR_DBM_RWCREATE,
570            SSL_DBM_FILE_MODE, ctxt->c->pool);
571    if (rv != APR_SUCCESS) {
572        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
573                ctxt->c->base_server,
574                "[gnutls_cache] error opening cache '%s'",
575                ctxt->sc->cache_config);
[c005645]576        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]577        return -1;
578    }
579
580    rv = apr_dbm_delete(dbm, dbmkey);
581
582    if (rv != APR_SUCCESS) {
583        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
584                ctxt->c->base_server,
585                "[gnutls_cache] error deleting from cache '%s'",
586                ctxt->sc->cache_config);
587        apr_dbm_close(dbm);
[c005645]588        apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]589        return -1;
590    }
591
592    apr_dbm_close(dbm);
[c005645]593    apr_global_mutex_unlock(ctxt->sc->cache_mutex);
[e183628]594
595    return 0;
[fcb122d]596}
597
[e02dd8c]598static int dbm_cache_post_config(apr_pool_t * p, server_rec * s,
[e183628]599        mgs_srvconf_rec * sc) {
600    apr_status_t rv;
601    apr_dbm_t *dbm;
602    const char *path1;
603    const char *path2;
[fcb122d]604
[e183628]605    rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config,
606            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p);
[fcb122d]607
[e183628]608    if (rv != APR_SUCCESS) {
609        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
610                "GnuTLS: Cannot create DBM Cache at `%s'",
611                sc->cache_config);
612        return rv;
613    }
[fcb122d]614
[e183628]615    apr_dbm_close(dbm);
[fcb122d]616
[e183628]617    apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1,
618            &path2);
[fcb122d]619
[e183628]620    /* The Following Code takes logic directly from mod_ssl's DBM Cache */
[fcb122d]621#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
[e183628]622    /* Running as Root */
623    if (path1 && geteuid() == 0) {
[422f5b7]624        if (0 != chown(path1, ap_unixd_config.user_id, -1))
625            ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s,
626                         "GnuTLS: could not chown cache path1 `%s' to uid %d (errno: %d)",
627                         path1, ap_unixd_config.user_id, errno);
[e183628]628        if (path2 != NULL) {
[422f5b7]629            if (0 != chown(path2, ap_unixd_config.user_id, -1))
630                ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s,
631                             "GnuTLS: could not chown cache path2 `%s' to uid %d (errno: %d)",
632                             path2, ap_unixd_config.user_id, errno);
[e183628]633        }
634    }
[fcb122d]635#endif
636
[e183628]637    return rv;
[fcb122d]638}
639
[e02dd8c]640int mgs_cache_post_config(apr_pool_t * p, server_rec * s,
[e183628]641        mgs_srvconf_rec * sc) {
[040387c]642
643    /* if GnuTLSCache was never explicitly set: */
644    if (sc->cache_type == mgs_cache_unset)
645        sc->cache_type = mgs_cache_none;
646    /* if GnuTLSCacheTimeout was never explicitly set: */
[671b64f]647    if (sc->cache_timeout == -1)
[c005645]648        sc->cache_timeout = apr_time_from_sec(MGS_DEFAULT_CACHE_TIMEOUT);
649
650    /* initialize mutex only once */
651    if (sc->cache_mutex == NULL)
652    {
653        apr_status_t rv = ap_global_mutex_create(&sc->cache_mutex, NULL,
654                                                 MGS_CACHE_MUTEX_NAME,
655                                                 NULL, s, p, 0);
656        if (rv != APR_SUCCESS)
657            return rv;
658    }
[040387c]659
[e183628]660    if (sc->cache_type == mgs_cache_dbm
661            || sc->cache_type == mgs_cache_gdbm) {
662        return dbm_cache_post_config(p, s, sc);
663    }
[c005645]664
665    return APR_SUCCESS;
[fcb122d]666}
667
[e765670]668#if HAVE_APR_MEMCACHE
669int mgs_cache_child_init(apr_pool_t * p,
670                         server_rec * s,
671                         mgs_srvconf_rec * sc)
672#else
673int mgs_cache_child_init(apr_pool_t * p __attribute__((unused)),
674                         server_rec * s __attribute__((unused)),
675                         mgs_srvconf_rec * sc)
676#endif
677{
[e183628]678    if (sc->cache_type == mgs_cache_dbm
679            || sc->cache_type == mgs_cache_gdbm) {
680        return 0;
681    }
[6e0bfd6]682#if HAVE_APR_MEMCACHE
[e183628]683    else if (sc->cache_type == mgs_cache_memcache) {
684        return mc_cache_child_init(p, s, sc);
685    }
[6e0bfd6]686#endif
[e183628]687    return 0;
[6e0bfd6]688}
689
[e02dd8c]690#include <assert.h>
[fcb122d]691
[e183628]692int mgs_cache_session_init(mgs_handle_t * ctxt) {
693    if (ctxt->sc->cache_type == mgs_cache_dbm
694            || ctxt->sc->cache_type == mgs_cache_gdbm) {
695        gnutls_db_set_retrieve_function(ctxt->session,
[15245bf]696                dbm_cache_fetch_session);
[e183628]697        gnutls_db_set_remove_function(ctxt->session,
698                dbm_cache_delete);
699        gnutls_db_set_store_function(ctxt->session,
[ae08186]700                dbm_cache_store_session);
[e183628]701        gnutls_db_set_ptr(ctxt->session, ctxt);
702    }
[6e0bfd6]703#if HAVE_APR_MEMCACHE
[e183628]704    else if (ctxt->sc->cache_type == mgs_cache_memcache) {
705        gnutls_db_set_retrieve_function(ctxt->session,
706                mc_cache_fetch);
707        gnutls_db_set_remove_function(ctxt->session,
708                mc_cache_delete);
709        gnutls_db_set_store_function(ctxt->session,
710                mc_cache_store);
711        gnutls_db_set_ptr(ctxt->session, ctxt);
712    }
[6e0bfd6]713#endif
[42307a9]714
[e183628]715    return 0;
[32f2e60]716}
Note: See TracBrowser for help on using the repository browser.