diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gnutls_cache.c | 247 | ||||
-rw-r--r-- | src/gnutls_io.c | 61 | ||||
-rw-r--r-- | src/mod_gnutls.c | 250 |
3 files changed, 474 insertions, 84 deletions
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c index c1a6f37..868568b 100644 --- a/src/gnutls_cache.c +++ b/src/gnutls_cache.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* ==================================================================== | 1 | /** |
2 | * Copyright 2004 Paul Querna | 2 | * Copyright 2004-2005 Paul Querna |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
@@ -21,8 +21,17 @@ | |||
21 | #include "apr_memcache.h" | 21 | #include "apr_memcache.h" |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | #include "apr_dbm.h" | ||
25 | |||
24 | #include "ap_mpm.h" | 26 | #include "ap_mpm.h" |
25 | 27 | ||
28 | #include <unistd.h> | ||
29 | #include <sys/types.h> | ||
30 | |||
31 | #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) | ||
32 | #include "unixd.h" | ||
33 | #endif | ||
34 | |||
26 | #define GNUTLS_SESSION_ID_STRING_LEN \ | 35 | #define GNUTLS_SESSION_ID_STRING_LEN \ |
27 | ((GNUTLS_MAX_SESSION_ID + 1) * 2) | 36 | ((GNUTLS_MAX_SESSION_ID + 1) * 2) |
28 | #define MC_TAG "mod_gnutls:" | 37 | #define MC_TAG "mod_gnutls:" |
@@ -152,7 +161,7 @@ static int mc_cache_store(void* baton, gnutls_datum_t key, | |||
152 | if(!strkey) | 161 | if(!strkey) |
153 | return -1; | 162 | return -1; |
154 | 163 | ||
155 | timeout = 3600; | 164 | timeout = ctxt->sc->cache_timeout; |
156 | 165 | ||
157 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); | 166 | rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); |
158 | 167 | ||
@@ -233,25 +242,239 @@ static int mc_cache_delete(void* baton, gnutls_datum_t key) | |||
233 | 242 | ||
234 | #endif /* have_apr_memcache */ | 243 | #endif /* have_apr_memcache */ |
235 | 244 | ||
245 | #define SSL_DBM_FILE_MODE ( APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD ) | ||
246 | |||
247 | static int dbm_cache_expire(mod_gnutls_handle_t *ctxt) | ||
248 | { | ||
249 | apr_status_t rv; | ||
250 | apr_dbm_t *dbm; | ||
251 | |||
252 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | ||
253 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | ||
254 | if (rv != APR_SUCCESS) { | ||
255 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
256 | ctxt->c->base_server, | ||
257 | "[gnutls_cache] error opening cache '%s'", | ||
258 | ctxt->sc->cache_config); | ||
259 | return -1; | ||
260 | } | ||
261 | apr_dbm_close(dbm); | ||
262 | |||
263 | return 0; | ||
264 | } | ||
265 | |||
266 | static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key) | ||
267 | { | ||
268 | gnutls_datum_t data = { NULL, 0 }; | ||
269 | apr_dbm_t *dbm; | ||
270 | apr_datum_t dbmkey; | ||
271 | apr_datum_t dbmval; | ||
272 | mod_gnutls_handle_t *ctxt = baton; | ||
273 | apr_status_t rv; | ||
274 | |||
275 | dbmkey.dptr = key.data; | ||
276 | dbmkey.dsize = key.size; | ||
277 | |||
278 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | ||
279 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | ||
280 | if (rv != APR_SUCCESS) { | ||
281 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
282 | ctxt->c->base_server, | ||
283 | "[gnutls_cache] error opening cache '%s'", | ||
284 | ctxt->sc->cache_config); | ||
285 | return data; | ||
286 | } | ||
287 | |||
288 | rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); | ||
289 | |||
290 | if (rv != APR_SUCCESS) { | ||
291 | apr_dbm_close(dbm); | ||
292 | return data; | ||
293 | } | ||
294 | |||
295 | if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(apr_time_t)) { | ||
296 | apr_dbm_close(dbm); | ||
297 | return data; | ||
298 | } | ||
299 | |||
300 | data.data = gnutls_malloc(dbmval.dsize - sizeof(apr_time_t)); | ||
301 | if (data.data == NULL) | ||
302 | return data; | ||
303 | |||
304 | data.size = dbmval.dsize - sizeof(apr_time_t); | ||
305 | memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); | ||
306 | |||
307 | apr_dbm_close(dbm); | ||
308 | return data; | ||
309 | } | ||
310 | |||
311 | static int dbm_cache_store(void* baton, gnutls_datum_t key, | ||
312 | gnutls_datum_t data) | ||
313 | { | ||
314 | apr_dbm_t *dbm; | ||
315 | apr_datum_t dbmkey; | ||
316 | apr_datum_t dbmval; | ||
317 | mod_gnutls_handle_t *ctxt = baton; | ||
318 | apr_status_t rv; | ||
319 | apr_time_t timeout; | ||
320 | |||
321 | dbmkey.dptr = (char *)key.data; | ||
322 | dbmkey.dsize = key.size; | ||
323 | |||
324 | /* create DBM value */ | ||
325 | dbmval.dsize = data.size; | ||
326 | dbmval.dptr = (char *)malloc(dbmval.dsize+sizeof(apr_time_t)); | ||
327 | |||
328 | memcpy((char *)dbmval.dptr+sizeof(apr_time_t), | ||
329 | data.data, data.size); | ||
330 | |||
331 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | ||
332 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | ||
333 | if (rv != APR_SUCCESS) { | ||
334 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
335 | ctxt->c->base_server, | ||
336 | "[gnutls_cache] error opening cache '%s'", | ||
337 | ctxt->sc->cache_config); | ||
338 | free(dbmval.dptr); | ||
339 | return -1; | ||
340 | } | ||
341 | |||
342 | rv = apr_dbm_store(dbm, dbmkey, dbmval); | ||
343 | |||
344 | if (rv != APR_SUCCESS) { | ||
345 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
346 | ctxt->c->base_server, | ||
347 | "[gnutls_cache] error storing in cache '%s'", | ||
348 | ctxt->sc->cache_config); | ||
349 | apr_dbm_close(dbm); | ||
350 | free(dbmval.dptr); | ||
351 | return -1; | ||
352 | } | ||
353 | |||
354 | apr_dbm_close(dbm); | ||
355 | |||
356 | free(dbmval.dptr); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static int dbm_cache_delete(void* baton, gnutls_datum_t key) | ||
362 | { | ||
363 | apr_dbm_t *dbm; | ||
364 | apr_datum_t dbmkey; | ||
365 | mod_gnutls_handle_t *ctxt = baton; | ||
366 | apr_status_t rv; | ||
367 | |||
368 | dbmkey.dptr = (char *)key.data; | ||
369 | dbmkey.dsize = key.size; | ||
370 | |||
371 | rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, | ||
372 | APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); | ||
373 | if (rv != APR_SUCCESS) { | ||
374 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
375 | ctxt->c->base_server, | ||
376 | "[gnutls_cache] error opening cache '%s'", | ||
377 | ctxt->sc->cache_config); | ||
378 | return -1; | ||
379 | } | ||
380 | |||
381 | rv = apr_dbm_delete(dbm, dbmkey); | ||
382 | |||
383 | if (rv != APR_SUCCESS) { | ||
384 | ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, | ||
385 | ctxt->c->base_server, | ||
386 | "[gnutls_cache] error storing in cache '%s'", | ||
387 | ctxt->sc->cache_config); | ||
388 | apr_dbm_close(dbm); | ||
389 | return -1; | ||
390 | } | ||
391 | |||
392 | apr_dbm_close(dbm); | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | static int dbm_cache_child_init(apr_pool_t *p, server_rec *s, | ||
398 | mod_gnutls_srvconf_rec *sc) | ||
399 | { | ||
400 | apr_status_t rv; | ||
401 | apr_dbm_t *dbm; | ||
402 | const char* path1; | ||
403 | const char* path2; | ||
404 | |||
405 | rv = apr_dbm_open(&dbm, sc->cache_config, APR_DBM_RWCREATE, | ||
406 | SSL_DBM_FILE_MODE, p); | ||
407 | |||
408 | if (rv != APR_SUCCESS) { | ||
409 | ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, | ||
410 | "GnuTLS: Cannot create DBM Cache at `%s'", | ||
411 | sc->cache_config); | ||
412 | return rv; | ||
413 | } | ||
414 | |||
415 | apr_dbm_close(dbm); | ||
416 | |||
417 | apr_dbm_get_usednames(p, sc->cache_config, &path1, &path2); | ||
418 | |||
419 | /* The Following Code takes logic directly from mod_ssl's DBM Cache */ | ||
420 | #if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE) | ||
421 | /* Running as Root */ | ||
422 | if (geteuid() == 0) { | ||
423 | chown(path1, unixd_config.user_id, -1); | ||
424 | if (path2 != NULL) { | ||
425 | chown(path2, unixd_config.user_id, -1); | ||
426 | } | ||
427 | } | ||
428 | #endif | ||
429 | |||
430 | return rv; | ||
431 | } | ||
432 | |||
433 | int mod_gnutls_cache_post_config(apr_pool_t *p, server_rec *s, | ||
434 | mod_gnutls_srvconf_rec *sc) | ||
435 | { | ||
436 | if (sc->cache_type == mod_gnutls_cache_dbm) { | ||
437 | return dbm_cache_child_init(p, s, sc); | ||
438 | } | ||
439 | return 0; | ||
440 | } | ||
441 | |||
236 | int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, | 442 | int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, |
237 | mod_gnutls_srvconf_rec *sc) | 443 | mod_gnutls_srvconf_rec *sc) |
238 | { | 444 | { |
445 | if (sc->cache_type == mod_gnutls_cache_dbm) { | ||
446 | return 0; | ||
447 | } | ||
239 | #if HAVE_APR_MEMCACHE | 448 | #if HAVE_APR_MEMCACHE |
240 | return mc_cache_child_init(p, s, sc); | 449 | else if (sc->cache_type == mod_gnutls_cache_memcache) { |
241 | #else | 450 | return mc_cache_child_init(p, s, sc); |
242 | return 0; | 451 | } |
243 | #endif | 452 | #endif |
453 | return 0; | ||
244 | } | 454 | } |
245 | 455 | ||
456 | #include <assert.h> | ||
457 | |||
246 | int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) | 458 | int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) |
247 | { | 459 | { |
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) { | ||
462 | gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); | ||
463 | gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); | ||
464 | gnutls_db_set_store_function(ctxt->session, dbm_cache_store); | ||
465 | gnutls_db_set_ptr(ctxt->session, ctxt); | ||
466 | } | ||
248 | #if HAVE_APR_MEMCACHE | 467 | #if HAVE_APR_MEMCACHE |
249 | gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); | 468 | else if (ctxt->sc->cache_type == mod_gnutls_cache_memcache) { |
250 | gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); | 469 | gnutls_db_set_retrieve_function(ctxt->session, mc_cache_fetch); |
251 | gnutls_db_set_store_function(ctxt->session, mc_cache_store); | 470 | gnutls_db_set_remove_function(ctxt->session, mc_cache_delete); |
252 | gnutls_db_set_ptr(ctxt->session, ctxt); | 471 | gnutls_db_set_store_function(ctxt->session, mc_cache_store); |
253 | #else | 472 | gnutls_db_set_ptr(ctxt->session, ctxt); |
254 | /* TODO: Alternative Cache Backends */ | 473 | } |
255 | #endif | 474 | #endif |
475 | else { | ||
476 | assert(1); | ||
477 | /* No Session Cache is Available. Opps. */ | ||
478 | } | ||
256 | return 0; | 479 | return 0; |
257 | } | 480 | } |
diff --git a/src/gnutls_io.c b/src/gnutls_io.c index e92646b..a44ba9c 100644 --- a/src/gnutls_io.c +++ b/src/gnutls_io.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* ==================================================================== | 1 | /** |
2 | * Copyright 2004 Paul Querna | 2 | * Copyright 2004-2005 Paul Querna |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
@@ -342,33 +342,46 @@ static void gnutls_do_handshake(mod_gnutls_handle_t * ctxt) | |||
342 | { | 342 | { |
343 | int ret; | 343 | int ret; |
344 | 344 | ||
345 | if (ctxt->status != 0) | 345 | if (ctxt->status != 0) { |
346 | return; | 346 | return; |
347 | ret = gnutls_handshake(ctxt->session); | 347 | } |
348 | if (ret < 0) { | 348 | |
349 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED | 349 | tryagain: |
350 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { | 350 | |
351 | ret = gnutls_alert_get(ctxt->session); | 351 | ret = gnutls_handshake(ctxt->session); |
352 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, | 352 | if (ret < 0) { |
353 | "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, | 353 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED |
354 | gnutls_alert_get_name(ret)); | 354 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
355 | } | 355 | ret = gnutls_alert_get(ctxt->session); |
356 | |||
357 | gnutls_deinit(ctxt->session); | ||
358 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, | 356 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, |
359 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | 357 | "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, |
360 | gnutls_strerror(ret)); | 358 | gnutls_alert_get_name(ret)); |
361 | ctxt->status = -1; | ||
362 | return; | ||
363 | } | 359 | } |
364 | else { | 360 | |
365 | ctxt->status = 1; | 361 | if (!gnutls_error_is_fatal(ret)) { |
366 | return; /* all done with the handshake */ | 362 | ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, |
363 | "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", ret, | ||
364 | gnutls_strerror(ret)); | ||
365 | goto tryagain; | ||
367 | } | 366 | } |
367 | |||
368 | ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, | ||
369 | "GnuTLS: Handshake Failed (%d) '%s'", ret, | ||
370 | gnutls_strerror(ret)); | ||
371 | ctxt->status = -1; | ||
372 | gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, | ||
373 | gnutls_error_to_alert(ret, NULL)); | ||
374 | gnutls_deinit(ctxt->session); | ||
375 | return; | ||
376 | } | ||
377 | else { | ||
378 | ctxt->status = 1; | ||
379 | return; /* all done with the handshake */ | ||
380 | } | ||
368 | } | 381 | } |
369 | 382 | ||
370 | 383 | ||
371 | apr_status_t mod_gnutls_filter_input(ap_filter_t * f, | 384 | apr_status_t mod_gnutls_filter_input(ap_filter_t* f, |
372 | apr_bucket_brigade * bb, | 385 | apr_bucket_brigade * bb, |
373 | ap_input_mode_t mode, | 386 | ap_input_mode_t mode, |
374 | apr_read_type_e block, | 387 | apr_read_type_e block, |
@@ -455,7 +468,7 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | |||
455 | 468 | ||
456 | while (!APR_BRIGADE_EMPTY(bb)) { | 469 | while (!APR_BRIGADE_EMPTY(bb)) { |
457 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); | 470 | apr_bucket *bucket = APR_BRIGADE_FIRST(bb); |
458 | if (APR_BUCKET_IS_EOS(bucket) || AP_BUCKET_IS_EOC(bucket)) { | 471 | if (AP_BUCKET_IS_EOC(bucket)) { |
459 | 472 | ||
460 | gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); | 473 | gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); |
461 | gnutls_deinit(ctxt->session); | 474 | gnutls_deinit(ctxt->session); |
@@ -465,7 +478,7 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f, | |||
465 | } | 478 | } |
466 | break; | 479 | break; |
467 | 480 | ||
468 | } else if (APR_BUCKET_IS_FLUSH(bucket)) { | 481 | } else if (APR_BUCKET_IS_FLUSH(bucket) || APR_BUCKET_IS_EOS(bucket)) { |
469 | 482 | ||
470 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { | 483 | if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { |
471 | return status; | 484 | return status; |
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index a1668f3..edf7068 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* ==================================================================== | 1 | /** |
2 | * Copyright 2004 Paul Querna | 2 | * Copyright 2004-2005 Paul Querna |
3 | * | 3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | 5 | * you may not use this file except in compliance with the License. |
@@ -21,17 +21,25 @@ | |||
21 | GCRY_THREAD_OPTION_PTHREAD_IMPL; | 21 | GCRY_THREAD_OPTION_PTHREAD_IMPL; |
22 | #endif | 22 | #endif |
23 | 23 | ||
24 | static apr_file_t* debug_log_fp; | ||
25 | |||
24 | static apr_status_t mod_gnutls_cleanup_pre_config(void *data) | 26 | static apr_status_t mod_gnutls_cleanup_pre_config(void *data) |
25 | { | 27 | { |
26 | gnutls_global_deinit(); | 28 | gnutls_global_deinit(); |
27 | return APR_SUCCESS; | 29 | return APR_SUCCESS; |
28 | } | 30 | } |
29 | 31 | ||
32 | static void gnutls_debug_log_all( int level, const char* str) | ||
33 | { | ||
34 | apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); | ||
35 | } | ||
36 | |||
30 | static int mod_gnutls_hook_pre_config(apr_pool_t * pconf, | 37 | static int mod_gnutls_hook_pre_config(apr_pool_t * pconf, |
31 | apr_pool_t * plog, apr_pool_t * ptemp) | 38 | apr_pool_t * plog, apr_pool_t * ptemp) |
32 | { | 39 | { |
33 | 40 | ||
34 | #if APR_HAS_THREADS | 41 | #if APR_HAS_THREADS |
42 | /* TODO: Check MPM Type here */ | ||
35 | gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); | 43 | gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); |
36 | #endif | 44 | #endif |
37 | 45 | ||
@@ -40,25 +48,68 @@ static int mod_gnutls_hook_pre_config(apr_pool_t * pconf, | |||
40 | apr_pool_cleanup_register(pconf, NULL, mod_gnutls_cleanup_pre_config, | 48 | apr_pool_cleanup_register(pconf, NULL, mod_gnutls_cleanup_pre_config, |
41 | apr_pool_cleanup_null); | 49 | apr_pool_cleanup_null); |
42 | 50 | ||
51 | apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", | ||
52 | APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, pconf); | ||
53 | |||
54 | gnutls_global_set_log_level(9); | ||
55 | gnutls_global_set_log_function(gnutls_debug_log_all); | ||
56 | |||
43 | return OK; | 57 | return OK; |
44 | } | 58 | } |
45 | 59 | ||
46 | #define DH_BITS 1024 | 60 | |
47 | #ifdef USE_RSA | 61 | static gnutls_datum load_params(const char* file, server_rec* s, |
48 | #define RSA_BITS 512 | 62 | apr_pool_t* pool) |
49 | #endif | 63 | { |
64 | gnutls_datum ret = { NULL, 0 }; | ||
65 | apr_file_t* fp; | ||
66 | apr_finfo_t finfo; | ||
67 | apr_status_t rv; | ||
68 | apr_size_t br = 0; | ||
69 | |||
70 | rv = apr_file_open(&fp, file, APR_READ|APR_BINARY, APR_OS_DEFAULT, | ||
71 | pool); | ||
72 | if (rv != APR_SUCCESS) { | ||
73 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
74 | "GnuTLS failed to load params file at: %s", file); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); | ||
79 | |||
80 | if (rv != APR_SUCCESS) { | ||
81 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
82 | "GnuTLS failed to stat params file at: %s", file); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | ret.data = apr_palloc(pool, finfo.size+1); | ||
87 | rv = apr_file_read_full(fp, ret.data, finfo.size, &br); | ||
88 | |||
89 | if (rv != APR_SUCCESS) { | ||
90 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
91 | "GnuTLS failed to read params file at: %s", file); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | ret.data[br] = '\0'; | ||
96 | ret.size = br; | ||
97 | |||
98 | return ret; | ||
99 | } | ||
100 | |||
50 | static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | 101 | static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, |
51 | apr_pool_t * ptemp, | 102 | apr_pool_t * ptemp, |
52 | server_rec * base_server) | 103 | server_rec * base_server) |
53 | { | 104 | { |
54 | mod_gnutls_srvconf_rec *sc; | 105 | int rv; |
55 | void *data = NULL; | ||
56 | int first_run = 0; | ||
57 | server_rec *s; | 106 | server_rec *s; |
58 | gnutls_dh_params_t dh_params; | 107 | gnutls_dh_params_t dh_params; |
59 | #ifdef USE_RSA | ||
60 | gnutls_rsa_params_t rsa_params; | 108 | gnutls_rsa_params_t rsa_params; |
61 | #endif | 109 | mod_gnutls_srvconf_rec *sc; |
110 | mod_gnutls_srvconf_rec *sc_base; | ||
111 | void *data = NULL; | ||
112 | int first_run = 0; | ||
62 | const char *userdata_key = "mod_gnutls_init"; | 113 | const char *userdata_key = "mod_gnutls_init"; |
63 | 114 | ||
64 | apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); | 115 | apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); |
@@ -70,35 +121,98 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
70 | } | 121 | } |
71 | 122 | ||
72 | 123 | ||
73 | // if(first_run) { | 124 | if (!first_run) { |
74 | /* TODO: Should we regenerate these after X requests / X time ? */ | 125 | gnutls_datum pdata; |
126 | apr_pool_t* tpool; | ||
127 | s = base_server; | ||
128 | sc_base = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
129 | &gnutls_module); | ||
130 | |||
131 | apr_pool_create(&tpool, p); | ||
132 | |||
75 | gnutls_dh_params_init(&dh_params); | 133 | gnutls_dh_params_init(&dh_params); |
76 | gnutls_dh_params_generate2(dh_params, DH_BITS); | 134 | |
77 | #ifdef USE_RSA | 135 | pdata = load_params(sc_base->dh_params_file, s, tpool); |
136 | |||
137 | if (pdata.size != 0) { | ||
138 | rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, | ||
139 | GNUTLS_X509_FMT_PEM); | ||
140 | if (rv != 0) { | ||
141 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
142 | "GnuTLS: Unable to load DH Params: (%d) %s", | ||
143 | rv, gnutls_strerror(rv)); | ||
144 | exit(rv); | ||
145 | } | ||
146 | } | ||
147 | else { | ||
148 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
149 | "GnuTLS: Unable to load DH Params." | ||
150 | " Shutting Down."); | ||
151 | exit(-1); | ||
152 | } | ||
153 | apr_pool_clear(tpool); | ||
154 | |||
78 | gnutls_rsa_params_init(&rsa_params); | 155 | gnutls_rsa_params_init(&rsa_params); |
79 | gnutls_rsa_params_generate2(rsa_params, RSA_BITS); | ||
80 | #endif | ||
81 | // } | ||
82 | 156 | ||
83 | for (s = base_server; s; s = s->next) { | 157 | pdata = load_params(sc_base->rsa_params_file, s, tpool); |
84 | sc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | 158 | |
85 | &gnutls_module); | 159 | if (pdata.size != 0) { |
86 | if (sc->cert_file != NULL && sc->key_file != NULL) { | 160 | rv = gnutls_rsa_params_import_pkcs1(rsa_params, &pdata, |
87 | gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, | 161 | GNUTLS_X509_FMT_PEM); |
162 | if (rv != 0) { | ||
163 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
164 | "GnuTLS: Unable to load RSA Params: (%d) %s", | ||
165 | rv, gnutls_strerror(rv)); | ||
166 | exit(rv); | ||
167 | } | ||
168 | } | ||
169 | else { | ||
170 | ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, | ||
171 | "GnuTLS: Unable to load RSA Params." | ||
172 | " Shutting Down."); | ||
173 | exit(-1); | ||
174 | } | ||
175 | |||
176 | apr_pool_destroy(tpool); | ||
177 | rv = mod_gnutls_cache_post_config(p, s, sc_base); | ||
178 | if (rv != 0) { | ||
179 | ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, | ||
180 | "GnuTLS: Post Config for GnuTLSCache Failed." | ||
181 | " Shutting Down."); | ||
182 | exit(-1); | ||
183 | } | ||
184 | |||
185 | for (s = base_server; s; s = s->next) { | ||
186 | sc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
187 | &gnutls_module); | ||
188 | sc->cache_type = sc_base->cache_type; | ||
189 | sc->cache_config = sc_base->cache_config; | ||
190 | |||
191 | if (sc->cert_file != NULL && sc->key_file != NULL) { | ||
192 | rv = gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, | ||
88 | sc->key_file, | 193 | sc->key_file, |
89 | GNUTLS_X509_FMT_PEM); | 194 | GNUTLS_X509_FMT_PEM); |
90 | #ifdef USE_RSA | 195 | if (rv != 0) { |
91 | gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params); | 196 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, |
92 | #endif | 197 | "[GnuTLS] - Host '%s:%d' has an invalid key or certificate:" |
93 | gnutls_certificate_set_dh_params(sc->certs, dh_params); | 198 | "(%s,%s) (%d) %s", |
94 | } | 199 | s->server_hostname, s->port, sc->cert_file, sc->key_file, |
95 | else if (sc->enabled == GNUTLS_ENABLED_TRUE) { | 200 | rv, gnutls_strerror(rv)); |
96 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | 201 | } |
97 | "[GnuTLS] - Host '%s:%d' is missing a Cert and Key File!", | 202 | else { |
203 | gnutls_certificate_set_rsa_export_params(sc->certs, | ||
204 | rsa_params); | ||
205 | gnutls_certificate_set_dh_params(sc->certs, dh_params); | ||
206 | } | ||
207 | } | ||
208 | else if (sc->enabled == GNUTLS_ENABLED_TRUE) { | ||
209 | ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, | ||
210 | "[GnuTLS] - Host '%s:%d' is missing a " | ||
211 | "Cert and Key File!", | ||
98 | s->server_hostname, s->port); | 212 | s->server_hostname, s->port); |
213 | } | ||
99 | } | 214 | } |
100 | } | 215 | } /* first_run */ |
101 | |||
102 | 216 | ||
103 | ap_add_version_component(p, "GnuTLS/" LIBGNUTLS_VERSION); | 217 | ap_add_version_component(p, "GnuTLS/" LIBGNUTLS_VERSION); |
104 | 218 | ||
@@ -111,7 +225,7 @@ static void mod_gnutls_hook_child_init(apr_pool_t *p, server_rec *s) | |||
111 | mod_gnutls_srvconf_rec *sc = ap_get_module_config(s->module_config, | 225 | mod_gnutls_srvconf_rec *sc = ap_get_module_config(s->module_config, |
112 | &gnutls_module); | 226 | &gnutls_module); |
113 | 227 | ||
114 | if(sc->cache_config != NULL) { | 228 | if (sc->cache_type != mod_gnutls_cache_none) { |
115 | rv = mod_gnutls_cache_child_init(p, s, sc); | 229 | rv = mod_gnutls_cache_child_init(p, s, sc); |
116 | if(rv != APR_SUCCESS) { | 230 | if(rv != APR_SUCCESS) { |
117 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, | 231 | ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, |
@@ -119,8 +233,8 @@ static void mod_gnutls_hook_child_init(apr_pool_t *p, server_rec *s) | |||
119 | } | 233 | } |
120 | } | 234 | } |
121 | else { | 235 | else { |
122 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, | 236 | ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, |
123 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); | 237 | "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache"); |
124 | } | 238 | } |
125 | } | 239 | } |
126 | 240 | ||
@@ -176,21 +290,21 @@ static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c) | |||
176 | 290 | ||
177 | gnutls_init(&ctxt->session, GNUTLS_SERVER); | 291 | gnutls_init(&ctxt->session, GNUTLS_SERVER); |
178 | 292 | ||
293 | gnutls_protocol_set_priority(ctxt->session, sc->protocol); | ||
179 | gnutls_cipher_set_priority(ctxt->session, sc->ciphers); | 294 | gnutls_cipher_set_priority(ctxt->session, sc->ciphers); |
180 | gnutls_compression_set_priority(ctxt->session, sc->compression); | 295 | gnutls_compression_set_priority(ctxt->session, sc->compression); |
181 | gnutls_kx_set_priority(ctxt->session, sc->key_exchange); | 296 | gnutls_kx_set_priority(ctxt->session, sc->key_exchange); |
182 | gnutls_protocol_set_priority(ctxt->session, sc->protocol); | ||
183 | gnutls_mac_set_priority(ctxt->session, sc->macs); | 297 | gnutls_mac_set_priority(ctxt->session, sc->macs); |
298 | gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types); | ||
184 | 299 | ||
185 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); | 300 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); |
301 | |||
186 | // if(anon) { | 302 | // if(anon) { |
187 | // gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred); | 303 | // gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred); |
188 | // } | 304 | // } |
189 | 305 | ||
190 | gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); | 306 | gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); |
191 | 307 | ||
192 | gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); | ||
193 | |||
194 | mod_gnutls_cache_session_init(ctxt); | 308 | mod_gnutls_cache_session_init(ctxt); |
195 | return ctxt; | 309 | return ctxt; |
196 | } | 310 | } |
@@ -216,8 +330,11 @@ static int mod_gnutls_hook_pre_connection(conn_rec * c, void *csd) | |||
216 | gnutls_transport_set_push_function(ctxt->session, | 330 | gnutls_transport_set_push_function(ctxt->session, |
217 | mod_gnutls_transport_write); | 331 | mod_gnutls_transport_write); |
218 | gnutls_transport_set_ptr(ctxt->session, ctxt); | 332 | gnutls_transport_set_ptr(ctxt->session, ctxt); |
219 | ctxt->input_filter = ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); | 333 | |
220 | ctxt->output_filter = ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); | 334 | ctxt->input_filter = ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, |
335 | NULL, c); | ||
336 | ctxt->output_filter = ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, | ||
337 | NULL, c); | ||
221 | 338 | ||
222 | return OK; | 339 | return OK; |
223 | } | 340 | } |
@@ -233,6 +350,7 @@ static int mod_gnutls_hook_fixups(request_rec *r) | |||
233 | if(!ctxt) { | 350 | if(!ctxt) { |
234 | return DECLINED; | 351 | return DECLINED; |
235 | } | 352 | } |
353 | |||
236 | apr_table_setn(env, "HTTPS", "on"); | 354 | apr_table_setn(env, "HTTPS", "on"); |
237 | apr_table_setn(env, "SSL_PROTOCOL", | 355 | apr_table_setn(env, "SSL_PROTOCOL", |
238 | gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session))); | 356 | gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session))); |
@@ -271,7 +389,7 @@ static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, | |||
271 | } | 389 | } |
272 | 390 | ||
273 | static const char *gnutls_set_cache(cmd_parms * parms, void *dummy, | 391 | static const char *gnutls_set_cache(cmd_parms * parms, void *dummy, |
274 | const char *arg) | 392 | const char *type, const char* arg) |
275 | { | 393 | { |
276 | const char* err; | 394 | const char* err; |
277 | mod_gnutls_srvconf_rec *sc = ap_get_module_config(parms->server-> | 395 | mod_gnutls_srvconf_rec *sc = ap_get_module_config(parms->server-> |
@@ -281,7 +399,28 @@ static const char *gnutls_set_cache(cmd_parms * parms, void *dummy, | |||
281 | return err; | 399 | return err; |
282 | } | 400 | } |
283 | 401 | ||
284 | sc->cache_config = apr_pstrdup(parms->pool, arg); | 402 | if (strcasecmp("none", type) == 0) { |
403 | sc->cache_type = mod_gnutls_cache_none; | ||
404 | } | ||
405 | else if (strcasecmp("dbm", type) == 0) { | ||
406 | sc->cache_type = mod_gnutls_cache_dbm; | ||
407 | } | ||
408 | #if HAVE_APR_MEMCACHE | ||
409 | else if (strcasecmp("memcache", type) == 0) { | ||
410 | sc->cache_type = mod_gnutls_cache_memcache; | ||
411 | } | ||
412 | #endif | ||
413 | else { | ||
414 | return "Invalid Type for GnuTLSCache!"; | ||
415 | } | ||
416 | |||
417 | if (sc->cache_type == mod_gnutls_cache_dbm) { | ||
418 | sc->cache_config = ap_server_root_relative(parms->pool, arg); | ||
419 | } | ||
420 | else { | ||
421 | sc->cache_config = apr_pstrdup(parms->pool, arg); | ||
422 | } | ||
423 | |||
285 | return NULL; | 424 | return NULL; |
286 | } | 425 | } |
287 | 426 | ||
@@ -314,10 +453,10 @@ static const command_rec gnutls_cmds[] = { | |||
314 | NULL, | 453 | NULL, |
315 | RSRC_CONF, | 454 | RSRC_CONF, |
316 | "SSL Server Certificate file"), | 455 | "SSL Server Certificate file"), |
317 | AP_INIT_TAKE1("GnuTLSCache", gnutls_set_cache, | 456 | AP_INIT_TAKE2("GnuTLSCache", gnutls_set_cache, |
318 | NULL, | 457 | NULL, |
319 | RSRC_CONF, | 458 | RSRC_CONF, |
320 | "SSL Server Certificate file"), | 459 | "Cache Configuration"), |
321 | AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, | 460 | AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, |
322 | NULL, RSRC_CONF, | 461 | NULL, RSRC_CONF, |
323 | "Whether this server has GnuTLS Enabled. Default: Off"), | 462 | "Whether this server has GnuTLS Enabled. Default: Off"), |
@@ -372,8 +511,16 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | |||
372 | gnutls_anon_allocate_server_credentials(&sc->anoncred); | 511 | gnutls_anon_allocate_server_credentials(&sc->anoncred); |
373 | sc->key_file = NULL; | 512 | sc->key_file = NULL; |
374 | sc->cert_file = NULL; | 513 | sc->cert_file = NULL; |
375 | sc->cache_config = NULL; | 514 | sc->cache_timeout = apr_time_from_sec(3600); |
515 | sc->cache_type = mod_gnutls_cache_dbm; | ||
516 | sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); | ||
517 | |||
518 | /* TODO: Make this Configurable ! */ | ||
519 | sc->dh_params_file = ap_server_root_relative(p, "conf/dhfile"); | ||
520 | sc->rsa_params_file = ap_server_root_relative(p, "conf/rsafile"); | ||
376 | 521 | ||
522 | /* TODO: Make this Configurable ! */ | ||
523 | /* meh. mod_ssl uses a flex based parser for this part.. sigh */ | ||
377 | i = 0; | 524 | i = 0; |
378 | sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC; | 525 | sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC; |
379 | sc->ciphers[i++] = GNUTLS_CIPHER_AES_128_CBC; | 526 | sc->ciphers[i++] = GNUTLS_CIPHER_AES_128_CBC; |
@@ -383,11 +530,14 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | |||
383 | sc->ciphers[i] = 0; | 530 | sc->ciphers[i] = 0; |
384 | 531 | ||
385 | i = 0; | 532 | i = 0; |
386 | sc->key_exchange[i++] = GNUTLS_KX_DHE_DSS; | ||
387 | sc->key_exchange[i++] = GNUTLS_KX_RSA; | 533 | sc->key_exchange[i++] = GNUTLS_KX_RSA; |
388 | sc->key_exchange[i++] = GNUTLS_KX_DHE_RSA; | ||
389 | sc->key_exchange[i++] = GNUTLS_KX_RSA_EXPORT; | 534 | sc->key_exchange[i++] = GNUTLS_KX_RSA_EXPORT; |
390 | sc->key_exchange[i++] = GNUTLS_KX_DHE_DSS; | 535 | sc->key_exchange[i++] = GNUTLS_KX_DHE_DSS; |
536 | sc->key_exchange[i++] = GNUTLS_KX_DHE_RSA; | ||
537 | sc->key_exchange[i++] = GNUTLS_KX_ANON_DH; | ||
538 | sc->key_exchange[i++] = GNUTLS_KX_SRP; | ||
539 | sc->key_exchange[i++] = GNUTLS_KX_SRP_RSA; | ||
540 | sc->key_exchange[i++] = GNUTLS_KX_SRP_DSS; | ||
391 | sc->key_exchange[i] = 0; | 541 | sc->key_exchange[i] = 0; |
392 | 542 | ||
393 | i = 0; | 543 | i = 0; |
@@ -408,6 +558,10 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) | |||
408 | sc->compression[i++] = GNUTLS_COMP_LZO; | 558 | sc->compression[i++] = GNUTLS_COMP_LZO; |
409 | sc->compression[i] = 0; | 559 | sc->compression[i] = 0; |
410 | 560 | ||
561 | i = 0; | ||
562 | sc->cert_types[i++] = GNUTLS_CRT_X509; | ||
563 | sc->cert_types[i] = 0; | ||
564 | |||
411 | return sc; | 565 | return sc; |
412 | } | 566 | } |
413 | 567 | ||