diff options
Diffstat (limited to 'src/gnutls_cache.c')
-rw-r--r-- | src/gnutls_cache.c | 153 |
1 files changed, 118 insertions, 35 deletions
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index 868568b..91e6ec9 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c | |||
@@ -32,15 +32,14 @@ | |||
32 | #include "unixd.h" | 32 | #include "unixd.h" |
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #define GNUTLS_SESSION_ID_STRING_LEN \ | 35 | |
36 | ((GNUTLS_MAX_SESSION_ID + 1) * 2) | ||
37 | #define MC_TAG "mod_gnutls:" | 36 | #define MC_TAG "mod_gnutls:" |
38 | #define MC_TAG_LEN \ | 37 | #define MC_TAG_LEN \ |
39 | (sizeof(MC_TAG)) | 38 | (sizeof(MC_TAG)) |
40 | #define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) | 39 | #define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) |
41 | 40 | ||
42 | static char *gnutls_session_id2sz(unsigned char *id, int idlen, | 41 | static char *gnutls_session_id2sz(unsigned char *id, int idlen, |
43 | char *str, int strsize) | 42 | char *str, int strsize) |
44 | { | 43 | { |
45 | char *cp; | 44 | char *cp; |
46 | int n; | 45 | int n; |
@@ -54,6 +53,21 @@ static char *gnutls_session_id2sz(unsigned char *id, int idlen, | |||
54 | return str; | 53 | return str; |
55 | } | 54 | } |
56 | 55 | ||
56 | char *mod_gnutls_session_id2sz(unsigned char *id, int idlen, | ||
57 | char *str, int strsize) | ||
58 | { | ||
59 | char *cp; | ||
60 | int n; | ||
61 | |||
62 | cp = str; | ||
63 | for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { | ||
64 | apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); | ||
65 | cp += 2; | ||
66 | } | ||
67 | *cp = '\0'; | ||
68 | return str; | ||
69 | } | ||
70 | |||
57 | 71 | ||
58 | #if HAVE_APR_MEMCACHE | 72 | #if HAVE_APR_MEMCACHE |
59 | 73 | ||
@@ -103,13 +117,13 @@ int mc_cache_child_init(apr_pool_t *p, server_rec *s, | |||
103 | apr_port_t port; | 117 | apr_port_t port; |
104 | 118 | ||
105 | rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); | 119 | rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); |
106 | if(rv != APR_SUCCESS) { | 120 | if (rv != APR_SUCCESS) { |
107 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 121 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
108 | "[gnutls_cache] Failed to Parse Server: '%s'", split); | 122 | "[gnutls_cache] Failed to Parse Server: '%s'", split); |
109 | return rv; | 123 | return rv; |
110 | } | 124 | } |
111 | 125 | ||
112 | if(host_str == NULL) { | 126 | if (host_str == NULL) { |
113 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 127 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
114 | "[gnutls_cache] Failed to Parse Server, " | 128 | "[gnutls_cache] Failed to Parse Server, " |
115 | "no hostname specified: '%s'", split); | 129 | "no hostname specified: '%s'", split); |
@@ -128,7 +142,7 @@ int mc_cache_child_init(apr_pool_t *p, server_rec *s, | |||
128 | thread_limit, | 142 | thread_limit, |
129 | 600, | 143 | 600, |
130 | &st); | 144 | &st); |
131 | if(rv != APR_SUCCESS) { | 145 | if (rv != APR_SUCCESS) { |
132 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 146 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
133 | "[gnutls_cache] Failed to Create Server: %s:%d", | 147 | "[gnutls_cache] Failed to Create Server: %s:%d", |
134 | host_str, port); | 148 | host_str, port); |
@@ -136,7 +150,7 @@ int mc_cache_child_init(apr_pool_t *p, server_rec *s, | |||
136 | } | 150 | } |
137 | 151 | ||
138 | rv = apr_memcache_add_server(mc, st); | 152 | rv = apr_memcache_add_server(mc, st); |
139 | if(rv != APR_SUCCESS) { | 153 | if (rv != APR_SUCCESS) { |
140 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, | 154 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, |
141 | "[gnutls_cache] Failed to Add Server: %s:%d", | 155 | "[gnutls_cache] Failed to Add Server: %s:%d", |
142 | host_str, port); | 156 | host_str, port); |
@@ -161,11 +175,11 @@ static int mc_cache_store(void* baton, gnutls_datum_t key, | |||
161 | if(!strkey) | 175 | if(!strkey) |
162 | return -1; | 176 | return -1; |
163 | 177 | ||
164 | timeout = ctxt->sc->cache_timeout; | 178 | timeout = apr_time_sec(ctxt->sc->cache_timeout); |
165 | 179 | ||
166 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); | 180 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); |
167 | 181 | ||
168 | if(rv != APR_SUCCESS) { | 182 | if (rv != APR_SUCCESS) { |
169 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, | 183 | ap_log_error(APLOG_MARK, APLOG_CRIT, rv, |
170 | ctxt->c->base_server, | 184 | ctxt->c->base_server, |
171 | "[gnutls_cache] error setting key '%s' " | 185 | "[gnutls_cache] error setting key '%s' " |
@@ -187,14 +201,14 @@ static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key) | |||
187 | gnutls_datum_t data = { NULL, 0 }; | 201 | gnutls_datum_t data = { NULL, 0 }; |
188 | 202 | ||
189 | strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); | 203 | strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); |
190 | if(!strkey) { | 204 | if (!strkey) { |
191 | return data; | 205 | return data; |
192 | } | 206 | } |
193 | 207 | ||
194 | rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, | 208 | rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, |
195 | &value, &value_len, NULL); | 209 | &value, &value_len, NULL); |
196 | 210 | ||
197 | if(rv != APR_SUCCESS) { | 211 | if (rv != APR_SUCCESS) { |
198 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 212 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
199 | ctxt->c->base_server, | 213 | ctxt->c->base_server, |
200 | "[gnutls_cache] error fetching key '%s' ", | 214 | "[gnutls_cache] error fetching key '%s' ", |
@@ -229,7 +243,7 @@ static int mc_cache_delete(void* baton, gnutls_datum_t key) | |||
229 | 243 | ||
230 | rv = apr_memcache_delete(mc, strkey, 0); | 244 | rv = apr_memcache_delete(mc, strkey, 0); |
231 | 245 | ||
232 | if(rv != APR_SUCCESS) { | 246 | if (rv != APR_SUCCESS) { |
233 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, | 247 | ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, |
234 | ctxt->c->base_server, | 248 | ctxt->c->base_server, |
235 | "[gnutls_cache] error deleting key '%s' ", | 249 | "[gnutls_cache] error deleting key '%s' ", |
@@ -248,18 +262,80 @@ static int dbm_cache_expire(mod_gnutls_handle_t *ctxt) | |||
248 | { | 262 | { |
249 | apr_status_t rv; | 263 | apr_status_t rv; |
250 | apr_dbm_t *dbm; | 264 | apr_dbm_t *dbm; |
251 | 265 | apr_datum_t *keylist; | |
252 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | 266 | apr_datum_t dbmkey; |
253 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 267 | apr_datum_t dbmval; |
268 | apr_time_t ex; | ||
269 | apr_time_t dtime; | ||
270 | apr_pool_t* spool; | ||
271 | int i = 0; | ||
272 | int keyidx = 0; | ||
273 | int should_delete = 0; | ||
274 | |||
275 | apr_pool_create(&spool, ctxt->c->pool); | ||
276 | ex = apr_time_now(); | ||
277 | |||
278 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, APR_DBM_READONLY, | ||
279 | SSL_DBM_FILE_MODE, spool); | ||
254 | if (rv != APR_SUCCESS) { | 280 | if (rv != APR_SUCCESS) { |
255 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 281 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
256 | ctxt->c->base_server, | 282 | ctxt->c->base_server, |
257 | "[gnutls_cache] error opening cache '%s'", | 283 | "[gnutls_cache] error opening cache searcher '%s'", |
258 | ctxt->sc->cache_config); | 284 | ctxt->sc->cache_config); |
259 | return -1; | 285 | return -1; |
260 | } | 286 | } |
287 | |||
288 | #define KEYMAX 128 | ||
289 | |||
290 | keylist = apr_palloc(spool, sizeof(dbmkey)*KEYMAX); | ||
291 | |||
292 | apr_dbm_firstkey(dbm, &dbmkey); | ||
293 | while (dbmkey.dptr != NULL) { | ||
294 | apr_dbm_fetch(dbm, dbmkey, &dbmval); | ||
295 | if (dbmval.dptr != NULL) { | ||
296 | if (dbmval.dsize >= sizeof(apr_time_t)) { | ||
297 | memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t)); | ||
298 | if (dtime < ex) { | ||
299 | should_delete = 1; | ||
300 | } | ||
301 | } | ||
302 | else { | ||
303 | should_delete = 1; | ||
304 | } | ||
305 | |||
306 | if (should_delete == 1) { | ||
307 | should_delete = 0; | ||
308 | keylist[keyidx].dptr = apr_palloc(spool, dbmkey.dsize) ; | ||
309 | memcpy(keylist[keyidx].dptr, dbmkey.dptr, dbmkey.dsize); | ||
310 | keylist[keyidx].dsize = dbmkey.dsize; | ||
311 | keyidx++; | ||
312 | if (keyidx == KEYMAX) { | ||
313 | break; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | } | ||
318 | apr_dbm_nextkey(dbm, &dbmkey); | ||
319 | } | ||
261 | apr_dbm_close(dbm); | 320 | apr_dbm_close(dbm); |
262 | 321 | ||
322 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | ||
323 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, spool); | ||
324 | if (rv != APR_SUCCESS) { | ||
325 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
326 | ctxt->c->base_server, | ||
327 | "[gnutls_cache] error opening cache writer '%s'", | ||
328 | ctxt->sc->cache_config); | ||
329 | return -1; | ||
330 | } | ||
331 | |||
332 | for (i = 0; i < keyidx; i++) { | ||
333 | apr_dbm_delete(dbm, keylist[i]); | ||
334 | } | ||
335 | |||
336 | apr_dbm_close(dbm); | ||
337 | apr_pool_destroy(spool); | ||
338 | |||
263 | return 0; | 339 | return 0; |
264 | } | 340 | } |
265 | 341 | ||
@@ -275,6 +351,8 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | |||
275 | dbmkey.dptr = key.data; | 351 | dbmkey.dptr = key.data; |
276 | dbmkey.dsize = key.size; | 352 | dbmkey.dsize = key.size; |
277 | 353 | ||
354 | dbm_cache_expire(ctxt); | ||
355 | |||
278 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | 356 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, |
279 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 357 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); |
280 | if (rv != APR_SUCCESS) { | 358 | if (rv != APR_SUCCESS) { |
@@ -286,7 +364,7 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | |||
286 | } | 364 | } |
287 | 365 | ||
288 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); | 366 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); |
289 | 367 | ||
290 | if (rv != APR_SUCCESS) { | 368 | if (rv != APR_SUCCESS) { |
291 | apr_dbm_close(dbm); | 369 | apr_dbm_close(dbm); |
292 | return data; | 370 | return data; |
@@ -296,15 +374,17 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | |||
296 | apr_dbm_close(dbm); | 374 | apr_dbm_close(dbm); |
297 | return data; | 375 | return data; |
298 | } | 376 | } |
299 | 377 | apr_dbm_close(dbm); | |
300 | data.data = gnutls_malloc(dbmval.dsize - sizeof(apr_time_t)); | ||
301 | if (data.data == NULL) | ||
302 | return data; | ||
303 | 378 | ||
304 | data.size = dbmval.dsize - sizeof(apr_time_t); | 379 | data.size = dbmval.dsize - sizeof(apr_time_t); |
380 | |||
381 | data.data = gnutls_malloc(data.size); | ||
382 | if (data.data == NULL) { | ||
383 | return data; | ||
384 | } | ||
385 | |||
305 | memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); | 386 | memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); |
306 | 387 | ||
307 | apr_dbm_close(dbm); | ||
308 | return data; | 388 | return data; |
309 | } | 389 | } |
310 | 390 | ||
@@ -316,18 +396,23 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key, | |||
316 | apr_datum_t dbmval; | 396 | apr_datum_t dbmval; |
317 | mod_gnutls_handle_t *ctxt = baton; | 397 | mod_gnutls_handle_t *ctxt = baton; |
318 | apr_status_t rv; | 398 | apr_status_t rv; |
319 | apr_time_t timeout; | 399 | apr_time_t expiry; |
320 | 400 | ||
321 | dbmkey.dptr = (char *)key.data; | 401 | dbmkey.dptr = (char *)key.data; |
322 | dbmkey.dsize = key.size; | 402 | dbmkey.dsize = key.size; |
323 | 403 | ||
324 | /* create DBM value */ | 404 | /* create DBM value */ |
325 | dbmval.dsize = data.size; | 405 | dbmval.dsize = data.size + sizeof(apr_time_t); |
326 | dbmval.dptr = (char *)malloc(dbmval.dsize+sizeof(apr_time_t)); | 406 | dbmval.dptr = (char *)malloc(dbmval.dsize); |
407 | |||
408 | expiry = apr_time_now() + ctxt->sc->cache_timeout; | ||
327 | 409 | ||
410 | memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t)); | ||
328 | memcpy((char *)dbmval.dptr+sizeof(apr_time_t), | 411 | memcpy((char *)dbmval.dptr+sizeof(apr_time_t), |
329 | data.data, data.size); | 412 | data.data, data.size); |
330 | 413 | ||
414 | dbm_cache_expire(ctxt); | ||
415 | |||
331 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | 416 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, |
332 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 417 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); |
333 | if (rv != APR_SUCCESS) { | 418 | if (rv != APR_SUCCESS) { |
@@ -340,7 +425,7 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key, | |||
340 | } | 425 | } |
341 | 426 | ||
342 | rv = apr_dbm_store(dbm, dbmkey, dbmval); | 427 | rv = apr_dbm_store(dbm, dbmkey, dbmval); |
343 | 428 | ||
344 | if (rv != APR_SUCCESS) { | 429 | if (rv != APR_SUCCESS) { |
345 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 430 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
346 | ctxt->c->base_server, | 431 | ctxt->c->base_server, |
@@ -368,6 +453,8 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key) | |||
368 | dbmkey.dptr = (char *)key.data; | 453 | dbmkey.dptr = (char *)key.data; |
369 | dbmkey.dsize = key.size; | 454 | dbmkey.dsize = key.size; |
370 | 455 | ||
456 | dbm_cache_expire(ctxt); | ||
457 | |||
371 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | 458 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, |
372 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | 459 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); |
373 | if (rv != APR_SUCCESS) { | 460 | if (rv != APR_SUCCESS) { |
@@ -383,7 +470,7 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key) | |||
383 | if (rv != APR_SUCCESS) { | 470 | if (rv != APR_SUCCESS) { |
384 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | 471 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, |
385 | ctxt->c->base_server, | 472 | ctxt->c->base_server, |
386 | "[gnutls_cache] error storing in cache '%s'", | 473 | "[gnutls_cache] error deleting from cache '%s'", |
387 | ctxt->sc->cache_config); | 474 | ctxt->sc->cache_config); |
388 | apr_dbm_close(dbm); | 475 | apr_dbm_close(dbm); |
389 | return -1; | 476 | return -1; |
@@ -394,7 +481,7 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key) | |||
394 | return 0; | 481 | return 0; |
395 | } | 482 | } |
396 | 483 | ||
397 | static int dbm_cache_child_init(apr_pool_t *p, server_rec *s, | 484 | static int dbm_cache_post_config(apr_pool_t *p, server_rec *s, |
398 | mod_gnutls_srvconf_rec *sc) | 485 | mod_gnutls_srvconf_rec *sc) |
399 | { | 486 | { |
400 | apr_status_t rv; | 487 | apr_status_t rv; |
@@ -434,7 +521,7 @@ int mod_gnutls_cache_post_config(apr_pool_t *p, server_rec *s, | |||
434 | mod_gnutls_srvconf_rec *sc) | 521 | mod_gnutls_srvconf_rec *sc) |
435 | { | 522 | { |
436 | if (sc->cache_type == mod_gnutls_cache_dbm) { | 523 | if (sc->cache_type == mod_gnutls_cache_dbm) { |
437 | return dbm_cache_child_init(p, s, sc); | 524 | return dbm_cache_post_config(p, s, sc); |
438 | } | 525 | } |
439 | return 0; | 526 | return 0; |
440 | } | 527 | } |
@@ -457,7 +544,6 @@ int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, | |||
457 | 544 | ||
458 | int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) | 545 | int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) |
459 | { | 546 | { |
460 | printf("Type: %d Params: %s\n",ctxt->sc->cache_type, ctxt->sc->cache_config); | ||
461 | if (ctxt->sc->cache_type == mod_gnutls_cache_dbm) { | 547 | if (ctxt->sc->cache_type == mod_gnutls_cache_dbm) { |
462 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); | 548 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); |
463 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); | 549 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); |
@@ -472,9 +558,6 @@ int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) | |||
472 | gnutls_db_set_ptr(ctxt->session, ctxt); | 558 | gnutls_db_set_ptr(ctxt->session, ctxt); |
473 | } | 559 | } |
474 | #endif | 560 | #endif |
475 | else { | 561 | |
476 | assert(1); | ||
477 | /* No Session Cache is Available. Opps. */ | ||
478 | } | ||
479 | return 0; | 562 | return 0; |
480 | } | 563 | } |