source: mod_gnutls/src/gnutls_cache.c @ 70a1e5a

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

Replace mgs_session_id2sz() with apr_(p?)escape_hex()

There's no need to carry a local bin-to-hex function if APR already
provides a converter. Using integrated pool allocation even avoids a
few string copies in gnutls_hooks.c.

The session hex buffers in gnutls_cache.c don't need room for the
memcache tag because it is added in a apr_psprintf() call if
necessary, so we can save a few bytes of stack space there.

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