summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
-rw-r--r--include/mod_gnutls.h.in35
-rw-r--r--mod_gnutls.xcode/project.pbxproj75
-rw-r--r--src/gnutls_cache.c247
-rw-r--r--src/gnutls_io.c61
-rw-r--r--src/mod_gnutls.c250
5 files changed, 568 insertions, 100 deletions
diff --git a/include/mod_gnutls.h.in b/include/mod_gnutls.h.in
index 469e678..f9ff32b 100644
--- a/include/mod_gnutls.h.in
+++ b/include/mod_gnutls.h.in
@@ -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.
@@ -42,21 +42,14 @@ module AP_MODULE_DECLARE_DATA gnutls_module;
42#define GNUTLS_ENABLED_FALSE 0 42#define GNUTLS_ENABLED_FALSE 0
43#define GNUTLS_ENABLED_TRUE 1 43#define GNUTLS_ENABLED_TRUE 1
44 44
45 45typedef enum
46/** 46{
47 * GnuTLS changed the names of several structures between 1.0.X and 1.1.X 47 mod_gnutls_cache_none,
48 * This is just a simple hack so we can compile with both versions. 48 mod_gnutls_cache_dbm,
49 * There is a full list in <gnutls/compat.h>, But I am just 49#if HAVE_APR_MEMCACHE
50 * doing this for a few types we use. 50 mod_gnutls_cache_memcache
51 */
52#ifndef gnutls_certificate_credentials_t
53#define gnutls_certificate_credentials_t gnutls_certificate_credentials
54#define gnutls_anon_server_credentials_t gnutls_anon_server_credentials
55#define gnutls_session_t gnutls_session
56#define gnutls_transport_ptr_t gnutls_transport_ptr
57#define gnutls_dh_params_t gnutls_dh_params
58#define gnutls_rsa_params_t gnutls_rsa_params
59#endif 51#endif
52} mod_gnutls_cache_e;
60 53
61typedef struct 54typedef struct
62{ 55{
@@ -70,7 +63,12 @@ typedef struct
70 int macs[16]; 63 int macs[16];
71 int protocol[16]; 64 int protocol[16];
72 int compression[16]; 65 int compression[16];
66 int cert_types[16];
67 apr_time_t cache_timeout;
68 mod_gnutls_cache_e cache_type;
73 const char* cache_config; 69 const char* cache_config;
70 const char* rsa_params_file;
71 const char* dh_params_file;
74} mod_gnutls_srvconf_rec; 72} mod_gnutls_srvconf_rec;
75 73
76typedef struct { 74typedef struct {
@@ -159,6 +157,11 @@ ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr,
159 157
160 158
161/** 159/**
160 * Init the Cache after Configuration is done
161 */
162int mod_gnutls_cache_post_config(apr_pool_t *p, server_rec *s,
163 mod_gnutls_srvconf_rec *sc);
164/**
162 * Init the Cache inside each Process 165 * Init the Cache inside each Process
163 */ 166 */
164int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, 167int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s,
diff --git a/mod_gnutls.xcode/project.pbxproj b/mod_gnutls.xcode/project.pbxproj
new file mode 100644
index 0000000..6d79e40
--- /dev/null
+++ b/mod_gnutls.xcode/project.pbxproj
@@ -0,0 +1,75 @@
1// !$*UTF8*$!
2{
3 archiveVersion = 1;
4 classes = {
5 };
6 objectVersion = 39;
7 objects = {
8 45B624630802F1E200CBFD9A = {
9 children = (
10 45B6246D0802F20D00CBFD9A,
11 45B6246E0802F20D00CBFD9A,
12 45B6246F0802F20D00CBFD9A,
13 );
14 isa = PBXGroup;
15 refType = 4;
16 sourceTree = "<group>";
17 };
18 45B624650802F1E200CBFD9A = {
19 buildSettings = {
20 COPY_PHASE_STRIP = NO;
21 };
22 isa = PBXBuildStyle;
23 name = Development;
24 };
25 45B624660802F1E200CBFD9A = {
26 buildSettings = {
27 COPY_PHASE_STRIP = YES;
28 };
29 isa = PBXBuildStyle;
30 name = Deployment;
31 };
32 45B624670802F1E200CBFD9A = {
33 buildSettings = {
34 };
35 buildStyles = (
36 45B624650802F1E200CBFD9A,
37 45B624660802F1E200CBFD9A,
38 );
39 hasScannedForEncodings = 0;
40 isa = PBXProject;
41 mainGroup = 45B624630802F1E200CBFD9A;
42 projectDirPath = "";
43 targets = (
44 );
45 };
46 45B6246D0802F20D00CBFD9A = {
47 fileEncoding = 4;
48 isa = PBXFileReference;
49 lastKnownFileType = sourcecode.c.c;
50 name = gnutls_cache.c;
51 path = src/gnutls_cache.c;
52 refType = 2;
53 sourceTree = SOURCE_ROOT;
54 };
55 45B6246E0802F20D00CBFD9A = {
56 fileEncoding = 4;
57 isa = PBXFileReference;
58 lastKnownFileType = sourcecode.c.c;
59 name = gnutls_io.c;
60 path = src/gnutls_io.c;
61 refType = 2;
62 sourceTree = SOURCE_ROOT;
63 };
64 45B6246F0802F20D00CBFD9A = {
65 fileEncoding = 4;
66 isa = PBXFileReference;
67 lastKnownFileType = sourcecode.c.c;
68 name = mod_gnutls.c;
69 path = src/mod_gnutls.c;
70 refType = 2;
71 sourceTree = SOURCE_ROOT;
72 };
73 };
74 rootObject = 45B624670802F1E200CBFD9A;
75}
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
247static 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
266static 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
311static 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
361static 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
397static 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
433int 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
236int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s, 442int 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
246int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) 458int 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 349tryagain:
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
371apr_status_t mod_gnutls_filter_input(ap_filter_t * f, 384apr_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 @@
21GCRY_THREAD_OPTION_PTHREAD_IMPL; 21GCRY_THREAD_OPTION_PTHREAD_IMPL;
22#endif 22#endif
23 23
24static apr_file_t* debug_log_fp;
25
24static apr_status_t mod_gnutls_cleanup_pre_config(void *data) 26static 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
32static 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
30static int mod_gnutls_hook_pre_config(apr_pool_t * pconf, 37static 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 61static 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
50static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 101static 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
273static const char *gnutls_set_cache(cmd_parms * parms, void *dummy, 391static 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