Changeset ae29683 in mod_gnutls for src/gnutls_cache.c


Ignore:
Timestamp:
Feb 21, 2014, 12:15:56 AM (6 years ago)
Author:
Daniel Kahn Gillmor <dkg@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, upstream
Children:
4addf74, 62f781c
Parents:
180e49f (diff), 1a99240 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Imported Upstream version 0.6

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_cache.c

    r180e49f rae29683  
    11/**
    22 *  Copyright 2004-2005 Paul Querna
    3  *  Portions Copyright 2008 Nikos Mavrogiannopoulos
     3 *  Copyright 2008 Nikos Mavrogiannopoulos
     4 *  Copyright 2011 Dash Shendy
    45 *
    56 *  Licensed under the Apache License, Version 2.0 (the "License");
     
    3435#endif
    3536
    36 /* it seems the default has some strange errors. Use SDBM 
     37/* it seems the default has some strange errors. Use SDBM
    3738 */
    3839#define MC_TAG "mod_gnutls:"
     
    4546
    4647char *mgs_session_id2sz(unsigned char *id, int idlen,
    47                         char *str, int strsize)
    48 {
    49         char *cp;
    50         int n;
    51 
    52         cp = str;
    53         for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) {
    54                 apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]);
    55                 cp += 2;
    56         }
    57         *cp = '\0';
    58         return str;
    59 }
    60 
     48        char *str, int strsize) {
     49    char *cp;
     50    int n;
     51
     52    cp = str;
     53    for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) {
     54        apr_snprintf(cp, strsize - (cp - str), "%02X", id[n]);
     55        cp += 2;
     56    }
     57    *cp = '\0';
     58    return str;
     59}
    6160
    6261/* Name the Session ID as:
     
    6564 */
    6665static int mgs_session_id2dbm(conn_rec * c, unsigned char *id, int idlen,
    67                               apr_datum_t * dbmkey)
    68 {
    69         char buf[STR_SESSION_LEN];
    70         char *sz;
    71 
    72         sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf));
    73         if (sz == NULL)
    74                 return -1;
    75 
    76         dbmkey->dptr =
    77             apr_psprintf(c->pool, "%s:%d.%s",
    78                          c->base_server->server_hostname,
    79                          c->base_server->port, sz);
    80         dbmkey->dsize = strlen(dbmkey->dptr);
    81 
    82         return 0;
     66        apr_datum_t * dbmkey) {
     67    char buf[STR_SESSION_LEN];
     68    char *sz;
     69
     70    sz = mgs_session_id2sz(id, idlen, buf, sizeof (buf));
     71    if (sz == NULL)
     72        return -1;
     73
     74    dbmkey->dptr =
     75            apr_psprintf(c->pool, "%s:%d.%s",
     76            c->base_server->server_hostname,
     77            c->base_server->port, sz);
     78    dbmkey->dsize = strlen(dbmkey->dptr);
     79
     80    return 0;
    8381}
    8482
    8583#define CTIME "%b %d %k:%M:%S %Y %Z"
    86 char *mgs_time2sz(time_t in_time, char *str, int strsize)
    87 {
    88         apr_time_exp_t vtm;
    89         apr_size_t ret_size;
    90         apr_time_t t;
    91 
    92 
    93         apr_time_ansi_put(&t, in_time);
    94         apr_time_exp_gmt(&vtm, t);
    95         apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm);
    96 
    97         return str;
     84
     85char *mgs_time2sz(time_t in_time, char *str, int strsize) {
     86    apr_time_exp_t vtm;
     87    apr_size_t ret_size;
     88    apr_time_t t;
     89
     90
     91    apr_time_ansi_put(&t, in_time);
     92    apr_time_exp_gmt(&vtm, t);
     93    apr_strftime(str, &ret_size, strsize - 1, CTIME, &vtm);
     94
     95    return str;
    9896}
    9997
    10098#if HAVE_APR_MEMCACHE
     99
    101100/* Name the Session ID as:
    102101 * server:port.SessionID
    103102 * to disallow resuming sessions on different servers
    104103 */
    105 static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen)
    106 {
    107         char buf[STR_SESSION_LEN];
    108         char *sz;
    109 
    110         sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf));
    111         if (sz == NULL)
    112                 return NULL;
    113 
    114         return apr_psprintf(c->pool, MC_TAG "%s:%d.%s",
    115                             c->base_server->server_hostname,
    116                             c->base_server->port, sz);
     104static char *mgs_session_id2mc(conn_rec * c, unsigned char *id, int idlen) {
     105    char buf[STR_SESSION_LEN];
     106    char *sz;
     107
     108    sz = mgs_session_id2sz(id, idlen, buf, sizeof (buf));
     109    if (sz == NULL)
     110        return NULL;
     111
     112    return apr_psprintf(c->pool, MC_TAG "%s:%d.%s",
     113            c->base_server->server_hostname,
     114            c->base_server->port, sz);
    117115}
    118116
     
    126124
    127125static int mc_cache_child_init(apr_pool_t * p, server_rec * s,
    128                                mgs_srvconf_rec * sc)
    129 {
    130         apr_status_t rv = APR_SUCCESS;
    131         int thread_limit = 0;
    132         int nservers = 0;
    133         char *cache_config;
    134         char *split;
    135         char *tok;
    136 
    137         ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
    138 
    139         /* Find all the servers in the first run to get a total count */
    140         cache_config = apr_pstrdup(p, sc->cache_config);
    141         split = apr_strtok(cache_config, " ", &tok);
    142         while (split) {
    143                 nservers++;
    144                 split = apr_strtok(NULL, " ", &tok);
    145         }
    146 
    147         rv = apr_memcache_create(p, nservers, 0, &mc);
    148         if (rv != APR_SUCCESS) {
    149                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    150                              "[gnutls_cache] Failed to create Memcache Object of '%d' size.",
    151                              nservers);
    152                 return rv;
    153         }
    154 
    155         /* Now add each server to the memcache */
    156         cache_config = apr_pstrdup(p, sc->cache_config);
    157         split = apr_strtok(cache_config, " ", &tok);
    158         while (split) {
    159                 apr_memcache_server_t *st;
    160                 char *host_str;
    161                 char *scope_id;
    162                 apr_port_t port;
    163 
    164                 rv = apr_parse_addr_port(&host_str, &scope_id, &port,
    165                                          split, p);
    166                 if (rv != APR_SUCCESS) {
    167                         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    168                                      "[gnutls_cache] Failed to Parse Server: '%s'",
    169                                      split);
    170                         return rv;
    171                 }
    172 
    173                 if (host_str == NULL) {
    174                         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    175                                      "[gnutls_cache] Failed to Parse Server, "
    176                                      "no hostname specified: '%s'", split);
    177                         return rv;
    178                 }
    179 
    180                 if (port == 0) {
    181                         port = 11211;   /* default port */
    182                 }
    183 
    184                 /* Should Max Conns be (thread_limit / nservers) ? */
    185                 rv = apr_memcache_server_create(p,
    186                                                 host_str, port,
    187                                                 0,
    188                                                 1, thread_limit, 600, &st);
    189                 if (rv != APR_SUCCESS) {
    190                         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    191                                      "[gnutls_cache] Failed to Create Server: %s:%d",
    192                                      host_str, port);
    193                         return rv;
    194                 }
    195 
    196                 rv = apr_memcache_add_server(mc, st);
    197                 if (rv != APR_SUCCESS) {
    198                         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    199                                      "[gnutls_cache] Failed to Add Server: %s:%d",
    200                                      host_str, port);
    201                         return rv;
    202                 }
    203 
    204                 split = apr_strtok(NULL, " ", &tok);
    205         }
    206         return rv;
     126        mgs_srvconf_rec * sc) {
     127    apr_status_t rv = APR_SUCCESS;
     128    int thread_limit = 0;
     129    int nservers = 0;
     130    char *cache_config;
     131    char *split;
     132    char *tok;
     133
     134    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
     135
     136    /* Find all the servers in the first run to get a total count */
     137    cache_config = apr_pstrdup(p, sc->cache_config);
     138    split = apr_strtok(cache_config, " ", &tok);
     139    while (split) {
     140        nservers++;
     141        split = apr_strtok(NULL, " ", &tok);
     142    }
     143
     144    rv = apr_memcache_create(p, nservers, 0, &mc);
     145    if (rv != APR_SUCCESS) {
     146        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
     147                "[gnutls_cache] Failed to create Memcache Object of '%d' size.",
     148                nservers);
     149        return rv;
     150    }
     151
     152    /* Now add each server to the memcache */
     153    cache_config = apr_pstrdup(p, sc->cache_config);
     154    split = apr_strtok(cache_config, " ", &tok);
     155    while (split) {
     156        apr_memcache_server_t *st;
     157        char *host_str;
     158        char *scope_id;
     159        apr_port_t port;
     160
     161        rv = apr_parse_addr_port(&host_str, &scope_id, &port,
     162                split, p);
     163        if (rv != APR_SUCCESS) {
     164            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
     165                    "[gnutls_cache] Failed to Parse Server: '%s'",
     166                    split);
     167            return rv;
     168        }
     169
     170        if (host_str == NULL) {
     171            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
     172                    "[gnutls_cache] Failed to Parse Server, "
     173                    "no hostname specified: '%s'", split);
     174            return rv;
     175        }
     176
     177        if (port == 0) {
     178            port = 11211; /* default port */
     179        }
     180
     181        /* Should Max Conns be (thread_limit / nservers) ? */
     182        rv = apr_memcache_server_create(p,
     183                host_str, port,
     184                0,
     185                1, thread_limit, 600, &st);
     186        if (rv != APR_SUCCESS) {
     187            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
     188                    "[gnutls_cache] Failed to Create Server: %s:%d",
     189                    host_str, port);
     190            return rv;
     191        }
     192
     193        rv = apr_memcache_add_server(mc, st);
     194        if (rv != APR_SUCCESS) {
     195            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
     196                    "[gnutls_cache] Failed to Add Server: %s:%d",
     197                    host_str, port);
     198            return rv;
     199        }
     200
     201        split = apr_strtok(NULL, " ", &tok);
     202    }
     203    return rv;
    207204}
    208205
    209206static int mc_cache_store(void *baton, gnutls_datum_t key,
    210                           gnutls_datum_t data)
    211 {
    212         apr_status_t rv = APR_SUCCESS;
    213         mgs_handle_t *ctxt = baton;
    214         char *strkey = NULL;
    215         apr_uint32_t timeout;
    216 
    217         strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    218         if (!strkey)
    219                 return -1;
    220 
    221         timeout = apr_time_sec(ctxt->sc->cache_timeout);
    222 
    223         rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout,
    224                               0);
    225 
    226         if (rv != APR_SUCCESS) {
    227                 ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
    228                              ctxt->c->base_server,
    229                              "[gnutls_cache] error setting key '%s' "
    230                              "with %d bytes of data", strkey, data.size);
    231                 return -1;
    232         }
    233 
    234         return 0;
    235 }
    236 
    237 static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key)
    238 {
    239         apr_status_t rv = APR_SUCCESS;
    240         mgs_handle_t *ctxt = baton;
    241         char *strkey = NULL;
    242         char *value;
    243         apr_size_t value_len;
    244         gnutls_datum_t data = { NULL, 0 };
    245 
    246         strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    247         if (!strkey) {
    248                 return data;
    249         }
    250 
    251         rv = apr_memcache_getp(mc, ctxt->c->pool, strkey,
    252                                &value, &value_len, NULL);
    253 
    254         if (rv != APR_SUCCESS) {
     207        gnutls_datum_t data) {
     208    apr_status_t rv = APR_SUCCESS;
     209    mgs_handle_t *ctxt = baton;
     210    char *strkey = NULL;
     211    apr_uint32_t timeout;
     212
     213    strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
     214    if (!strkey)
     215        return -1;
     216
     217    timeout = apr_time_sec(ctxt->sc->cache_timeout);
     218
     219    rv = apr_memcache_set(mc, strkey, (char *) data.data, data.size, timeout,
     220            0);
     221
     222    if (rv != APR_SUCCESS) {
     223        ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
     224                ctxt->c->base_server,
     225                "[gnutls_cache] error setting key '%s' "
     226                "with %d bytes of data", strkey, data.size);
     227        return -1;
     228    }
     229
     230    return 0;
     231}
     232
     233static gnutls_datum_t mc_cache_fetch(void *baton, gnutls_datum_t key) {
     234    apr_status_t rv = APR_SUCCESS;
     235    mgs_handle_t *ctxt = baton;
     236    char *strkey = NULL;
     237    char *value;
     238    apr_size_t value_len;
     239    gnutls_datum_t data = {NULL, 0};
     240
     241    strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
     242    if (!strkey) {
     243        return data;
     244    }
     245
     246    rv = apr_memcache_getp(mc, ctxt->c->pool, strkey,
     247            &value, &value_len, NULL);
     248
     249    if (rv != APR_SUCCESS) {
    255250#if MOD_GNUTLS_DEBUG
    256                 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    257                              ctxt->c->base_server,
    258                              "[gnutls_cache] error fetching key '%s' ",
    259                              strkey);
     251        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
     252                ctxt->c->base_server,
     253                "[gnutls_cache] error fetching key '%s' ",
     254                strkey);
    260255#endif
    261                 data.size = 0;
    262                 data.data = NULL;
    263                 return data;
    264         }
    265 
    266         /* TODO: Eliminate this memcpy. gnutls-- */
    267         data.data = gnutls_malloc(value_len);
    268         if (data.data == NULL)
    269                 return data;
    270 
    271         data.size = value_len;
    272         memcpy(data.data, value, value_len);
    273 
    274         return data;
    275 }
    276 
    277 static int mc_cache_delete(void *baton, gnutls_datum_t key)
    278 {
    279         apr_status_t rv = APR_SUCCESS;
    280         mgs_handle_t *ctxt = baton;
    281         char *strkey = NULL;
    282 
    283         strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    284         if (!strkey)
    285                 return -1;
    286 
    287         rv = apr_memcache_delete(mc, strkey, 0);
    288 
    289         if (rv != APR_SUCCESS) {
    290                 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    291                              ctxt->c->base_server,
    292                              "[gnutls_cache] error deleting key '%s' ",
    293                              strkey);
    294                 return -1;
    295         }
    296 
    297         return 0;
    298 }
    299 
    300 #endif                          /* have_apr_memcache */
    301 
    302 const char *db_type(mgs_srvconf_rec * sc)
    303 {
    304         if (sc->cache_type == mgs_cache_gdbm)
    305                 return "gdbm";
    306         else
    307                 return "db";
     256        data.size = 0;
     257        data.data = NULL;
     258        return data;
     259    }
     260
     261    /* TODO: Eliminate this memcpy. gnutls-- */
     262    data.data = gnutls_malloc(value_len);
     263    if (data.data == NULL)
     264        return data;
     265
     266    data.size = value_len;
     267    memcpy(data.data, value, value_len);
     268
     269    return data;
     270}
     271
     272static int mc_cache_delete(void *baton, gnutls_datum_t key) {
     273    apr_status_t rv = APR_SUCCESS;
     274    mgs_handle_t *ctxt = baton;
     275    char *strkey = NULL;
     276
     277    strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
     278    if (!strkey)
     279        return -1;
     280
     281    rv = apr_memcache_delete(mc, strkey, 0);
     282
     283    if (rv != APR_SUCCESS) {
     284        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
     285                ctxt->c->base_server,
     286                "[gnutls_cache] error deleting key '%s' ",
     287                strkey);
     288        return -1;
     289    }
     290
     291    return 0;
     292}
     293
     294#endif  /* have_apr_memcache */
     295
     296static const char *db_type(mgs_srvconf_rec * sc) {
     297    if (sc->cache_type == mgs_cache_gdbm)
     298        return "gdbm";
     299    else
     300        return "db";
    308301}
    309302
    310303#define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
    311304
    312 static void dbm_cache_expire(mgs_handle_t * ctxt)
    313 {
    314         apr_status_t rv;
    315         apr_dbm_t *dbm;
    316         apr_datum_t dbmkey;
    317         apr_datum_t dbmval;
    318         apr_time_t now;
    319         apr_time_t dtime;
    320         apr_pool_t *spool;
    321         int total, deleted;
    322 
    323         now = apr_time_now();
    324 
    325         if (now - ctxt->sc->last_cache_check <
    326             (ctxt->sc->cache_timeout) / 2)
    327                 return;
    328 
    329         ctxt->sc->last_cache_check = now;
    330 
    331         apr_pool_create(&spool, ctxt->c->pool);
    332 
    333         total = 0;
    334         deleted = 0;
    335 
    336         rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    337                              ctxt->sc->cache_config, APR_DBM_RWCREATE,
    338                              SSL_DBM_FILE_MODE, spool);
    339         if (rv != APR_SUCCESS) {
    340                 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    341                              ctxt->c->base_server,
    342                              "[gnutls_cache] error opening cache searcher '%s'",
    343                              ctxt->sc->cache_config);
    344                 apr_pool_destroy(spool);
    345                 return;
    346         }
    347 
    348         apr_dbm_firstkey(dbm, &dbmkey);
    349         while (dbmkey.dptr != NULL) {
    350                 apr_dbm_fetch(dbm, dbmkey, &dbmval);
    351                 if (dbmval.dptr != NULL
    352                     && dbmval.dsize >= sizeof(apr_time_t)) {
    353                         memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t));
    354 
    355                         if (now >= dtime) {
    356                                 apr_dbm_delete(dbm, dbmkey);
    357                                 deleted++;
    358                         }
    359                         apr_dbm_freedatum(dbm, dbmval);
    360                 } else {
    361                         apr_dbm_delete(dbm, dbmkey);
    362                         deleted++;
    363                 }
    364                 total++;
    365                 apr_dbm_nextkey(dbm, &dbmkey);
    366         }
    367         apr_dbm_close(dbm);
    368 
    369         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    370                      ctxt->c->base_server,
    371                      "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d",
    372                      ctxt->sc->cache_config, deleted, total - deleted);
    373 
    374         apr_pool_destroy(spool);
    375 
    376         return;
    377 }
    378 
    379 static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key)
    380 {
    381         gnutls_datum_t data = { NULL, 0 };
    382         apr_dbm_t *dbm;
    383         apr_datum_t dbmkey;
    384         apr_datum_t dbmval;
    385         mgs_handle_t *ctxt = baton;
    386         apr_status_t rv;
    387 
    388         if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    389                 return data;
    390 
    391         rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    392                              ctxt->sc->cache_config, APR_DBM_READONLY,
    393                              SSL_DBM_FILE_MODE, ctxt->c->pool);
    394         if (rv != APR_SUCCESS) {
    395                 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    396                              ctxt->c->base_server,
    397                              "[gnutls_cache] error opening cache '%s'",
    398                              ctxt->sc->cache_config);
    399                 return data;
    400         }
    401 
    402         rv = apr_dbm_fetch(dbm, dbmkey, &dbmval);
    403 
    404         if (rv != APR_SUCCESS) {
    405                 apr_dbm_close(dbm);
    406                 return data;
    407         }
    408 
    409         if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) {
    410                 apr_dbm_freedatum(dbm, dbmval);
    411                 apr_dbm_close(dbm);
    412                 return data;
    413         }
    414 
    415         data.size = dbmval.dsize - sizeof(apr_time_t);
    416 
    417         data.data = gnutls_malloc(data.size);
    418         if (data.data == NULL) {
    419                 apr_dbm_freedatum(dbm, dbmval);
    420                 apr_dbm_close(dbm);
    421                 return data;
    422         }
    423 
    424         memcpy(data.data, dbmval.dptr + sizeof(apr_time_t), data.size);
    425 
    426         apr_dbm_freedatum(dbm, dbmval);
    427         apr_dbm_close(dbm);
    428 
    429         return data;
     305static void dbm_cache_expire(mgs_handle_t * ctxt) {
     306    apr_status_t rv;
     307    apr_dbm_t *dbm;
     308    apr_datum_t dbmkey;
     309    apr_datum_t dbmval;
     310    apr_time_t now;
     311    apr_time_t dtime;
     312    apr_pool_t *spool;
     313    int total, deleted;
     314
     315    now = apr_time_now();
     316
     317    if (now - ctxt->sc->last_cache_check <
     318            (ctxt->sc->cache_timeout) / 2)
     319        return;
     320
     321    ctxt->sc->last_cache_check = now;
     322
     323    apr_pool_create(&spool, ctxt->c->pool);
     324
     325    total = 0;
     326    deleted = 0;
     327
     328    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
     329            ctxt->sc->cache_config, APR_DBM_RWCREATE,
     330            SSL_DBM_FILE_MODE, spool);
     331    if (rv != APR_SUCCESS) {
     332        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
     333                ctxt->c->base_server,
     334                "[gnutls_cache] error opening cache searcher '%s'",
     335                ctxt->sc->cache_config);
     336        apr_pool_destroy(spool);
     337        return;
     338    }
     339
     340    apr_dbm_firstkey(dbm, &dbmkey);
     341    while (dbmkey.dptr != NULL) {
     342        apr_dbm_fetch(dbm, dbmkey, &dbmval);
     343        if (dbmval.dptr != NULL
     344                && dbmval.dsize >= sizeof (apr_time_t)) {
     345            memcpy(&dtime, dbmval.dptr, sizeof (apr_time_t));
     346
     347            if (now >= dtime) {
     348                apr_dbm_delete(dbm, dbmkey);
     349                deleted++;
     350            }
     351            apr_dbm_freedatum(dbm, dbmval);
     352        } else {
     353            apr_dbm_delete(dbm, dbmkey);
     354            deleted++;
     355        }
     356        total++;
     357        apr_dbm_nextkey(dbm, &dbmkey);
     358    }
     359    apr_dbm_close(dbm);
     360
     361    ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
     362            ctxt->c->base_server,
     363            "[gnutls_cache] Cleaned up cache '%s'. Deleted %d and left %d",
     364            ctxt->sc->cache_config, deleted, total - deleted);
     365
     366    apr_pool_destroy(spool);
     367
     368    return;
     369}
     370
     371static gnutls_datum_t dbm_cache_fetch(void *baton, gnutls_datum_t key) {
     372    gnutls_datum_t data = {NULL, 0};
     373    apr_dbm_t *dbm;
     374    apr_datum_t dbmkey;
     375    apr_datum_t dbmval;
     376    mgs_handle_t *ctxt = baton;
     377    apr_status_t rv;
     378
     379    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
     380        return data;
     381
     382    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
     383            ctxt->sc->cache_config, APR_DBM_READONLY,
     384            SSL_DBM_FILE_MODE, ctxt->c->pool);
     385    if (rv != APR_SUCCESS) {
     386        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
     387                ctxt->c->base_server,
     388                "[gnutls_cache] error opening cache '%s'",
     389                ctxt->sc->cache_config);
     390        return data;
     391    }
     392
     393    rv = apr_dbm_fetch(dbm, dbmkey, &dbmval);
     394
     395    if (rv != APR_SUCCESS) {
     396        apr_dbm_close(dbm);
     397        return data;
     398    }
     399
     400    if (dbmval.dptr == NULL || dbmval.dsize <= sizeof (apr_time_t)) {
     401        apr_dbm_freedatum(dbm, dbmval);
     402        apr_dbm_close(dbm);
     403        return data;
     404    }
     405
     406    data.size = dbmval.dsize - sizeof (apr_time_t);
     407
     408    data.data = gnutls_malloc(data.size);
     409    if (data.data == NULL) {
     410        apr_dbm_freedatum(dbm, dbmval);
     411        apr_dbm_close(dbm);
     412        return data;
     413    }
     414
     415    memcpy(data.data, dbmval.dptr + sizeof (apr_time_t), data.size);
     416
     417    apr_dbm_freedatum(dbm, dbmval);
     418    apr_dbm_close(dbm);
     419
     420    return data;
    430421}
    431422
    432423static int dbm_cache_store(void *baton, gnutls_datum_t key,
    433                            gnutls_datum_t data)
    434 {
    435         apr_dbm_t *dbm;
    436         apr_datum_t dbmkey;
    437         apr_datum_t dbmval;
    438         mgs_handle_t *ctxt = baton;
    439         apr_status_t rv;
    440         apr_time_t expiry;
    441         apr_pool_t *spool;
    442 
    443         if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    444                 return -1;
    445 
    446         /* we expire dbm only on every store
    447          */
    448         dbm_cache_expire(ctxt);
    449 
    450         apr_pool_create(&spool, ctxt->c->pool);
    451 
    452         /* create DBM value */
    453         dbmval.dsize = data.size + sizeof(apr_time_t);
    454         dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize);
    455 
    456         expiry = apr_time_now() + ctxt->sc->cache_timeout;
    457 
    458         memcpy((char *) dbmval.dptr, &expiry, sizeof(apr_time_t));
    459         memcpy((char *) dbmval.dptr + sizeof(apr_time_t),
    460                data.data, data.size);
    461 
    462         rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    463                              ctxt->sc->cache_config, APR_DBM_RWCREATE,
    464                              SSL_DBM_FILE_MODE, ctxt->c->pool);
    465         if (rv != APR_SUCCESS) {
    466                 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    467                              ctxt->c->base_server,
    468                              "[gnutls_cache] error opening cache '%s'",
    469                              ctxt->sc->cache_config);
    470                 apr_pool_destroy(spool);
    471                 return -1;
    472         }
    473 
    474         rv = apr_dbm_store(dbm, dbmkey, dbmval);
    475 
    476         if (rv != APR_SUCCESS) {
    477                 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    478                              ctxt->c->base_server,
    479                              "[gnutls_cache] error storing in cache '%s'",
    480                              ctxt->sc->cache_config);
    481                 apr_dbm_close(dbm);
    482                 apr_pool_destroy(spool);
    483                 return -1;
    484         }
    485 
    486         apr_dbm_close(dbm);
    487 
    488         apr_pool_destroy(spool);
    489 
    490         return 0;
    491 }
    492 
    493 static int dbm_cache_delete(void *baton, gnutls_datum_t key)
    494 {
    495         apr_dbm_t *dbm;
    496         apr_datum_t dbmkey;
    497         mgs_handle_t *ctxt = baton;
    498         apr_status_t rv;
    499 
    500         if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    501                 return -1;
    502 
    503         rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
    504                              ctxt->sc->cache_config, APR_DBM_RWCREATE,
    505                              SSL_DBM_FILE_MODE, ctxt->c->pool);
    506         if (rv != APR_SUCCESS) {
    507                 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    508                              ctxt->c->base_server,
    509                              "[gnutls_cache] error opening cache '%s'",
    510                              ctxt->sc->cache_config);
    511                 return -1;
    512         }
    513 
    514         rv = apr_dbm_delete(dbm, dbmkey);
    515 
    516         if (rv != APR_SUCCESS) {
    517                 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    518                              ctxt->c->base_server,
    519                              "[gnutls_cache] error deleting from cache '%s'",
    520                              ctxt->sc->cache_config);
    521                 apr_dbm_close(dbm);
    522                 return -1;
    523         }
    524 
    525         apr_dbm_close(dbm);
    526 
    527         return 0;
     424        gnutls_datum_t data) {
     425    apr_dbm_t *dbm;
     426    apr_datum_t dbmkey;
     427    apr_datum_t dbmval;
     428    mgs_handle_t *ctxt = baton;
     429    apr_status_t rv;
     430    apr_time_t expiry;
     431    apr_pool_t *spool;
     432
     433    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
     434        return -1;
     435
     436    /* we expire dbm only on every store
     437     */
     438    dbm_cache_expire(ctxt);
     439
     440    apr_pool_create(&spool, ctxt->c->pool);
     441
     442    /* create DBM value */
     443    dbmval.dsize = data.size + sizeof (apr_time_t);
     444    dbmval.dptr = (char *) apr_palloc(spool, dbmval.dsize);
     445
     446    expiry = apr_time_now() + ctxt->sc->cache_timeout;
     447
     448    memcpy((char *) dbmval.dptr, &expiry, sizeof (apr_time_t));
     449    memcpy((char *) dbmval.dptr + sizeof (apr_time_t),
     450            data.data, data.size);
     451
     452    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
     453            ctxt->sc->cache_config, APR_DBM_RWCREATE,
     454            SSL_DBM_FILE_MODE, ctxt->c->pool);
     455    if (rv != APR_SUCCESS) {
     456        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
     457                ctxt->c->base_server,
     458                "[gnutls_cache] error opening cache '%s'",
     459                ctxt->sc->cache_config);
     460        apr_pool_destroy(spool);
     461        return -1;
     462    }
     463
     464    rv = apr_dbm_store(dbm, dbmkey, dbmval);
     465
     466    if (rv != APR_SUCCESS) {
     467        ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
     468                ctxt->c->base_server,
     469                "[gnutls_cache] error storing in cache '%s'",
     470                ctxt->sc->cache_config);
     471        apr_dbm_close(dbm);
     472        apr_pool_destroy(spool);
     473        return -1;
     474    }
     475
     476    apr_dbm_close(dbm);
     477
     478    apr_pool_destroy(spool);
     479
     480    return 0;
     481}
     482
     483static int dbm_cache_delete(void *baton, gnutls_datum_t key) {
     484    apr_dbm_t *dbm;
     485    apr_datum_t dbmkey;
     486    mgs_handle_t *ctxt = baton;
     487    apr_status_t rv;
     488
     489    if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
     490        return -1;
     491
     492    rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc),
     493            ctxt->sc->cache_config, APR_DBM_RWCREATE,
     494            SSL_DBM_FILE_MODE, ctxt->c->pool);
     495    if (rv != APR_SUCCESS) {
     496        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
     497                ctxt->c->base_server,
     498                "[gnutls_cache] error opening cache '%s'",
     499                ctxt->sc->cache_config);
     500        return -1;
     501    }
     502
     503    rv = apr_dbm_delete(dbm, dbmkey);
     504
     505    if (rv != APR_SUCCESS) {
     506        ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
     507                ctxt->c->base_server,
     508                "[gnutls_cache] error deleting from cache '%s'",
     509                ctxt->sc->cache_config);
     510        apr_dbm_close(dbm);
     511        return -1;
     512    }
     513
     514    apr_dbm_close(dbm);
     515
     516    return 0;
    528517}
    529518
    530519static int dbm_cache_post_config(apr_pool_t * p, server_rec * s,
    531                                  mgs_srvconf_rec * sc)
    532 {
    533         apr_status_t rv;
    534         apr_dbm_t *dbm;
    535         const char *path1;
    536         const char *path2;
    537 
    538         rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config,
    539                              APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p);
    540 
    541         if (rv != APR_SUCCESS) {
    542                 ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
    543                              "GnuTLS: Cannot create DBM Cache at `%s'",
    544                              sc->cache_config);
    545                 return rv;
    546         }
    547 
    548         apr_dbm_close(dbm);
    549 
    550         apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1,
    551                                  &path2);
    552 
    553         /* The Following Code takes logic directly from mod_ssl's DBM Cache */
     520        mgs_srvconf_rec * sc) {
     521    apr_status_t rv;
     522    apr_dbm_t *dbm;
     523    const char *path1;
     524    const char *path2;
     525
     526    rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config,
     527            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, p);
     528
     529    if (rv != APR_SUCCESS) {
     530        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
     531                "GnuTLS: Cannot create DBM Cache at `%s'",
     532                sc->cache_config);
     533        return rv;
     534    }
     535
     536    apr_dbm_close(dbm);
     537
     538    apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1,
     539            &path2);
     540
     541    /* The Following Code takes logic directly from mod_ssl's DBM Cache */
    554542#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
    555         /* Running as Root */
    556         if (path1 && geteuid() == 0) {
    557                 chown(path1, ap_unixd_config.user_id, -1);
    558                 if (path2 != NULL) {
    559                         chown(path2, ap_unixd_config.user_id, -1);
    560                 }
    561         }
     543    /* Running as Root */
     544    if (path1 && geteuid() == 0) {
     545        if (0 != chown(path1, ap_unixd_config.user_id, -1))
     546            ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s,
     547                         "GnuTLS: could not chown cache path1 `%s' to uid %d (errno: %d)",
     548                         path1, ap_unixd_config.user_id, errno);
     549        if (path2 != NULL) {
     550            if (0 != chown(path2, ap_unixd_config.user_id, -1))
     551                ap_log_error(APLOG_MARK, APLOG_NOTICE, -1, s,
     552                             "GnuTLS: could not chown cache path2 `%s' to uid %d (errno: %d)",
     553                             path2, ap_unixd_config.user_id, errno);
     554        }
     555    }
    562556#endif
    563557
    564         return rv;
     558    return rv;
    565559}
    566560
    567561int mgs_cache_post_config(apr_pool_t * p, server_rec * s,
    568                           mgs_srvconf_rec * sc)
    569 {
    570         if (sc->cache_type == mgs_cache_dbm
    571             || sc->cache_type == mgs_cache_gdbm) {
    572                 return dbm_cache_post_config(p, s, sc);
    573         }
    574         return 0;
     562        mgs_srvconf_rec * sc) {
     563
     564    /* if GnuTLSCache was never explicitly set: */
     565    if (sc->cache_type == mgs_cache_unset)
     566        sc->cache_type = mgs_cache_none;
     567    /* if GnuTLSCacheTimeout was never explicitly set: */
     568    if (sc->cache_timeout == -1)
     569        sc->cache_timeout = apr_time_from_sec(300);
     570
     571    if (sc->cache_type == mgs_cache_dbm
     572            || sc->cache_type == mgs_cache_gdbm) {
     573        return dbm_cache_post_config(p, s, sc);
     574    }
     575    return 0;
    575576}
    576577
    577578int mgs_cache_child_init(apr_pool_t * p, server_rec * s,
    578                          mgs_srvconf_rec * sc)
    579 {
    580         if (sc->cache_type == mgs_cache_dbm
    581             || sc->cache_type == mgs_cache_gdbm) {
    582                 return 0;
    583         }
     579        mgs_srvconf_rec * sc) {
     580    if (sc->cache_type == mgs_cache_dbm
     581            || sc->cache_type == mgs_cache_gdbm) {
     582        return 0;
     583    }
    584584#if HAVE_APR_MEMCACHE
    585         else if (sc->cache_type == mgs_cache_memcache) {
    586                 return mc_cache_child_init(p, s, sc);
    587         }
     585    else if (sc->cache_type == mgs_cache_memcache) {
     586        return mc_cache_child_init(p, s, sc);
     587    }
    588588#endif
    589         return 0;
     589    return 0;
    590590}
    591591
    592592#include <assert.h>
    593593
    594 int mgs_cache_session_init(mgs_handle_t * ctxt)
    595 {
    596         if (ctxt->sc->cache_type == mgs_cache_dbm
    597             || ctxt->sc->cache_type == mgs_cache_gdbm) {
    598                 gnutls_db_set_retrieve_function(ctxt->session,
    599                                                 dbm_cache_fetch);
    600                 gnutls_db_set_remove_function(ctxt->session,
    601                                               dbm_cache_delete);
    602                 gnutls_db_set_store_function(ctxt->session,
    603                                              dbm_cache_store);
    604                 gnutls_db_set_ptr(ctxt->session, ctxt);
    605         }
     594int mgs_cache_session_init(mgs_handle_t * ctxt) {
     595    if (ctxt->sc->cache_type == mgs_cache_dbm
     596            || ctxt->sc->cache_type == mgs_cache_gdbm) {
     597        gnutls_db_set_retrieve_function(ctxt->session,
     598                dbm_cache_fetch);
     599        gnutls_db_set_remove_function(ctxt->session,
     600                dbm_cache_delete);
     601        gnutls_db_set_store_function(ctxt->session,
     602                dbm_cache_store);
     603        gnutls_db_set_ptr(ctxt->session, ctxt);
     604    }
    606605#if HAVE_APR_MEMCACHE
    607         else if (ctxt->sc->cache_type == mgs_cache_memcache) {
    608                 gnutls_db_set_retrieve_function(ctxt->session,
    609                                                 mc_cache_fetch);
    610                 gnutls_db_set_remove_function(ctxt->session,
    611                                               mc_cache_delete);
    612                 gnutls_db_set_store_function(ctxt->session,
    613                                              mc_cache_store);
    614                 gnutls_db_set_ptr(ctxt->session, ctxt);
    615         }
     606    else if (ctxt->sc->cache_type == mgs_cache_memcache) {
     607        gnutls_db_set_retrieve_function(ctxt->session,
     608                mc_cache_fetch);
     609        gnutls_db_set_remove_function(ctxt->session,
     610                mc_cache_delete);
     611        gnutls_db_set_store_function(ctxt->session,
     612                mc_cache_store);
     613        gnutls_db_set_ptr(ctxt->session, ctxt);
     614    }
    616615#endif
    617616
    618         return 0;
    619 }
     617    return 0;
     618}
Note: See TracChangeset for help on using the changeset viewer.