Changeset e02dd8c in mod_gnutls for src/gnutls_cache.c


Ignore:
Timestamp:
Oct 25, 2010, 3:21:04 PM (9 years ago)
Author:
Nikos Mavrogiannopoulos <nmav@…>
Branches:
debian/master, debian/stretch-backports, jessie-backports, master, msva, upstream
Children:
b59327c
Parents:
62def2f
Message:

indented code

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_cache.c

    r62def2f re02dd8c  
    4545
    4646char *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;
     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;
    5959}
    6060
     
    6464 * to disallow resuming sessions on different servers
    6565 */
    66 static 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 = apr_psprintf(c->pool, "%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz);
    77     dbmkey->dsize = strlen( dbmkey->dptr);
    78    
    79     return 0;
     66static 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;
    8083}
    8184
     
    8386char *mgs_time2sz(time_t in_time, char *str, int strsize)
    8487{
    85     apr_time_exp_t vtm;
    86     apr_size_t ret_size;
    87     apr_time_t t;
    88    
    89  
    90     apr_time_ansi_put (&t, in_time);
    91     apr_time_exp_gmt (&vtm, t);
    92     apr_strftime(str, &ret_size, strsize-1, CTIME, &vtm);
    93 
    94     return str;
     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;
    9598}
    9699
     
    100103 * to disallow resuming sessions on different servers
    101104 */
    102 static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen)
    103 {
    104 char buf[STR_SESSION_LEN];
    105 char *sz;
    106    
    107     sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf));
    108     if (sz == NULL)
    109       return NULL;
    110      
    111     return apr_psprintf(c->pool, MC_TAG"%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz);
     105static 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);
    112117}
    113118
     
    118123
    119124/* The underlying apr_memcache system is thread safe... woohoo */
    120 static apr_memcache_t* mc;
    121 
    122 static int mc_cache_child_init(apr_pool_t *p, server_rec *s,
    123                                 mgs_srvconf_rec *sc)
    124 {
    125     apr_status_t rv = APR_SUCCESS;
    126     int thread_limit = 0;
    127     int nservers = 0;
    128     char* cache_config;
    129     char* split;
    130     char* tok;
    131 
    132     ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
    133 
    134     /* Find all the servers in the first run to get a total count */
    135     cache_config = apr_pstrdup(p, sc->cache_config);
    136     split = apr_strtok(cache_config, " ", &tok);
    137     while (split) {
    138         nservers++;
    139         split = apr_strtok(NULL," ", &tok);
    140     }
    141 
    142     rv = apr_memcache_create(p, nservers, 0, &mc);
    143     if (rv != APR_SUCCESS) {
    144         ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    145                         "[gnutls_cache] Failed to create Memcache Object of '%d' size.",
    146                          nservers);
    147         return rv;
    148     }
    149 
    150     /* Now add each server to the memcache */
    151     cache_config = apr_pstrdup(p, sc->cache_config);
    152     split = apr_strtok(cache_config, " ", &tok);
    153     while (split) {
    154         apr_memcache_server_t* st;
    155         char* host_str;
    156         char* scope_id;
    157         apr_port_t port;
    158 
    159         rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
    160         if (rv != APR_SUCCESS) {
    161             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    162                          "[gnutls_cache] Failed to Parse Server: '%s'", split);
    163             return rv;
    164         }
    165 
    166         if (host_str == NULL) {
    167             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    168                          "[gnutls_cache] Failed to Parse Server, "
    169                          "no hostname specified: '%s'", split);
    170             return rv;
    171         }
    172 
    173         if (port == 0) {
    174             port = 11211; /* default port */
    175         }
    176 
    177         /* Should Max Conns be (thread_limit / nservers) ? */
    178         rv = apr_memcache_server_create(p,
    179                                         host_str, port,
    180                                         0,
    181                                         1,
    182                                         thread_limit,
    183                                         600,
    184                                         &st);
    185         if (rv != APR_SUCCESS) {
    186             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    187                          "[gnutls_cache] Failed to Create Server: %s:%d",
    188                          host_str, port);
    189             return rv;
    190         }
    191 
    192         rv = apr_memcache_add_server(mc, st);
    193         if (rv != APR_SUCCESS) {
    194             ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
    195                          "[gnutls_cache] Failed to Add Server: %s:%d",
    196                          host_str, port);
    197             return rv;
    198         }
    199 
    200         split = apr_strtok(NULL," ", &tok);
    201     }
    202     return rv;
    203 }
    204 
    205 static int mc_cache_store(void* baton, gnutls_datum_t key,
    206                           gnutls_datum_t data)
    207 {
    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, data.data, data.size, timeout, 0);
    220 
    221     if (rv != APR_SUCCESS) {
    222         ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
    223                      ctxt->c->base_server,
    224                      "[gnutls_cache] error setting key '%s' "
    225                      "with %d bytes of data", strkey, data.size);
    226         return -1;
    227     }
    228 
    229     return 0;
    230 }
    231 
    232 static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key)
    233 {
    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) {
     125static apr_memcache_t *mc;
     126
     127static 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;
     207}
     208
     209static 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
     237static 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) {
    250255#if MOD_GNUTLS_DEBUG
    251         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    252                      ctxt->c->base_server,
    253                      "[gnutls_cache] error fetching key '%s' ",
    254                      strkey);
     256                ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
     257                             ctxt->c->base_server,
     258                             "[gnutls_cache] error fetching key '%s' ",
     259                             strkey);
    255260#endif
    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 
    272 static int mc_cache_delete(void* baton, gnutls_datum_t key)
    273 {
    274     apr_status_t rv = APR_SUCCESS;
    275     mgs_handle_t *ctxt = baton;
    276     char* strkey = NULL;
    277 
    278     strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
    279     if(!strkey)
    280         return -1;
    281 
    282     rv = apr_memcache_delete(mc, strkey, 0);
    283 
    284     if (rv != APR_SUCCESS) {
    285         ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
    286                      ctxt->c->base_server,
    287                      "[gnutls_cache] error deleting key '%s' ",
    288                       strkey);
    289         return -1;
    290     }
    291 
    292     return 0;
    293 }
    294 
    295 #endif /* have_apr_memcache */
    296 
    297 const char* db_type(mgs_srvconf_rec * sc)
    298 {
    299         if (sc->cache_type == mgs_cache_gdbm)
    300                 return "gdbm";
    301         else
    302                 return "db";
     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
     277static 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
     302const char *db_type(mgs_srvconf_rec * sc)
     303{
     304        if (sc->cache_type == mgs_cache_gdbm)
     305                return "gdbm";
     306        else
     307                return "db";
    303308}
    304309
    305310#define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD )
    306311
    307 static void dbm_cache_expire(mgs_handle_t *ctxt)
    308 {
    309     apr_status_t rv;
    310     apr_dbm_t *dbm;
    311     apr_datum_t dbmkey;
    312     apr_datum_t dbmval;
    313     apr_time_t now;
    314     apr_time_t dtime;
    315     apr_pool_t* spool;
    316     int total, deleted;
    317 
    318     now = apr_time_now();
    319    
    320     if (now - ctxt->sc->last_cache_check < (ctxt->sc->cache_timeout)/2)
    321         return;
    322 
    323     ctxt->sc->last_cache_check = now;
    324 
    325     apr_pool_create(&spool, ctxt->c->pool);
    326 
    327     total = 0;
    328     deleted = 0;
    329 
    330     rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config, APR_DBM_RWCREATE,
    331                       SSL_DBM_FILE_MODE, spool);
    332     if (rv != APR_SUCCESS) {
    333         ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
    334                      ctxt->c->base_server,
    335                      "[gnutls_cache] error opening cache searcher '%s'",
    336                      ctxt->sc->cache_config);
    337         apr_pool_destroy(spool);
    338         return;
    339     }
    340 
    341     apr_dbm_firstkey(dbm, &dbmkey);
    342     while (dbmkey.dptr != NULL) {
    343         apr_dbm_fetch(dbm, dbmkey, &dbmval);
    344         if (dbmval.dptr != NULL && 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 
    371 static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key)
    372 {
    373     gnutls_datum_t data = { NULL, 0 };
    374     apr_dbm_t *dbm;
    375     apr_datum_t dbmkey;
    376     apr_datum_t dbmval;
    377     mgs_handle_t *ctxt = baton;
    378     apr_status_t rv;
    379 
    380     if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    381         return data;
    382 
    383     rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config,
    384                       APR_DBM_READONLY, 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;
    421 }
    422 
    423 static int dbm_cache_store(void* baton, gnutls_datum_t key,
    424                           gnutls_datum_t data)
    425 {
    426     apr_dbm_t *dbm;
    427     apr_datum_t dbmkey;
    428     apr_datum_t dbmval;
    429     mgs_handle_t *ctxt = baton;
    430     apr_status_t rv;
    431     apr_time_t expiry;
    432     apr_pool_t* spool;
    433 
    434     if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    435         return -1;
    436 
    437     /* we expire dbm only on every store
    438      */
    439     dbm_cache_expire(ctxt);
    440 
    441     apr_pool_create(&spool, ctxt->c->pool);
    442 
    443     /* create DBM value */
    444     dbmval.dsize = data.size + sizeof(apr_time_t);
    445     dbmval.dptr  = (char *)apr_palloc(spool, dbmval.dsize);
    446 
    447     expiry = apr_time_now() + ctxt->sc->cache_timeout;
    448 
    449     memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t));
    450     memcpy((char *)dbmval.dptr+sizeof(apr_time_t),
    451            data.data, data.size);
    452 
    453     rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config,
    454                       APR_DBM_RWCREATE, 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 
    483 static int dbm_cache_delete(void* baton, gnutls_datum_t key)
    484 {
    485     apr_dbm_t *dbm;
    486     apr_datum_t dbmkey;
    487     mgs_handle_t *ctxt = baton;
    488     apr_status_t rv;
    489 
    490     if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
    491         return -1;
    492 
    493     rv = apr_dbm_open_ex(&dbm, db_type(ctxt->sc), ctxt->sc->cache_config,
    494                       APR_DBM_RWCREATE, 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;
    517 }
    518 
    519 static int dbm_cache_post_config(apr_pool_t *p, server_rec *s,
    520                                 mgs_srvconf_rec *sc)
    521 {
    522     apr_status_t rv;
    523     apr_dbm_t *dbm;
    524     const char* path1;
    525     const char* path2;
    526 
    527     rv = apr_dbm_open_ex(&dbm, db_type(sc), sc->cache_config, APR_DBM_RWCREATE,
    528                       SSL_DBM_FILE_MODE, p);
    529 
    530     if (rv != APR_SUCCESS) {
    531         ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
    532                      "GnuTLS: Cannot create DBM Cache at `%s'",
    533                      sc->cache_config);
    534         return rv;
    535     }
    536 
    537     apr_dbm_close(dbm);
    538 
    539     apr_dbm_get_usednames_ex(p, db_type(sc), sc->cache_config, &path1, &path2);
    540 
    541     /* The Following Code takes logic directly from mod_ssl's DBM Cache */
     312static 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
     379static 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;
     430}
     431
     432static 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
     493static 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;
     528}
     529
     530static 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 */
    542554#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
    543     /* Running as Root */
    544     if (path1 && geteuid() == 0) {
    545         chown(path1, ap_unixd_config.user_id, -1);
    546         if (path2 != NULL) {
    547             chown(path2, ap_unixd_config.user_id, -1);
    548         }
    549     }
     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        }
    550562#endif
    551563
    552     return rv;
    553 }
    554 
    555 int mgs_cache_post_config(apr_pool_t *p, server_rec *s,
    556                                  mgs_srvconf_rec *sc)
    557 {
    558     if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) {
    559         return dbm_cache_post_config(p, s, sc);
    560     }
    561     return 0;
    562 }
    563 
    564 int mgs_cache_child_init(apr_pool_t *p, server_rec *s,
    565                                 mgs_srvconf_rec *sc)
    566 {
    567     if (sc->cache_type == mgs_cache_dbm || sc->cache_type == mgs_cache_gdbm) {
    568         return 0;
    569     }
     564        return rv;
     565}
     566
     567int 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;
     575}
     576
     577int 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        }
    570584#if HAVE_APR_MEMCACHE
    571     else if (sc->cache_type == mgs_cache_memcache) {
    572         return mc_cache_child_init(p, s, sc);
    573     }
     585        else if (sc->cache_type == mgs_cache_memcache) {
     586                return mc_cache_child_init(p, s, sc);
     587        }
    574588#endif
    575     return 0;
    576 }
    577 
    578  #include <assert.h>
    579 
    580 int mgs_cache_session_init(mgs_handle_t *ctxt)
    581 {
    582     if (ctxt->sc->cache_type == mgs_cache_dbm || ctxt->sc->cache_type == mgs_cache_gdbm) {
    583         gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch);
    584         gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete);
    585         gnutls_db_set_store_function(ctxt->session, dbm_cache_store);
    586         gnutls_db_set_ptr(ctxt->session, ctxt);
    587     }
     589        return 0;
     590}
     591
     592#include <assert.h>
     593
     594int 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        }
    588606#if HAVE_APR_MEMCACHE
    589     else if (ctxt->sc->cache_type == mgs_cache_memcache) {
    590         gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch);
    591         gnutls_db_set_remove_function(ctxt->session, mc_cache_delete);
    592         gnutls_db_set_store_function(ctxt->session, mc_cache_store);
    593         gnutls_db_set_ptr(ctxt->session, ctxt);
    594     }
     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        }
    595616#endif
    596617
    597     return 0;
    598 }
     618        return 0;
     619}
Note: See TracChangeset for help on using the changeset viewer.