aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--include/mod_gnutls.h.in17
-rw-r--r--src/gnutls_io.c54
-rw-r--r--src/mod_gnutls.c363
4 files changed, 362 insertions, 74 deletions
diff --git a/configure.ac b/configure.ac
index b504eca..a16da41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
1AC_INIT(mod_gnutls, 0.1.1) 1AC_INIT(mod_gnutls, 0.2.0)
2OOO_CONFIG_NICE(config.nice) 2OOO_CONFIG_NICE(config.nice)
3MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION 3MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION
4AC_PREREQ(2.53) 4AC_PREREQ(2.53)
diff --git a/include/mod_gnutls.h.in b/include/mod_gnutls.h.in
index d9b989e..6eff460 100644
--- a/include/mod_gnutls.h.in
+++ b/include/mod_gnutls.h.in
@@ -27,14 +27,15 @@
27#include "apr_tables.h" 27#include "apr_tables.h"
28#include "ap_release.h" 28#include "ap_release.h"
29 29
30#include <gcrypt.h>
31#include <gnutls/gnutls.h>
32#include <gnutls/x509.h>
33
30#ifndef __mod_gnutls_h_inc 34#ifndef __mod_gnutls_h_inc
31#define __mod_gnutls_h_inc 35#define __mod_gnutls_h_inc
32 36
33#define HAVE_APR_MEMCACHE @have_apr_memcache@ 37#define HAVE_APR_MEMCACHE @have_apr_memcache@
34 38
35#include <gcrypt.h>
36#include <gnutls/gnutls.h>
37
38module AP_MODULE_DECLARE_DATA gnutls_module; 39module AP_MODULE_DECLARE_DATA gnutls_module;
39 40
40#define GNUTLS_OUTPUT_FILTER_NAME "gnutls_output_filter" 41#define GNUTLS_OUTPUT_FILTER_NAME "gnutls_output_filter"
@@ -70,9 +71,14 @@ typedef enum
70 71
71typedef struct 72typedef struct
72{ 73{
74 gnutls_certificate_request_t client_verify_mode;
75} mod_gnutls_dirconf_rec;
76
77typedef struct
78{
73 gnutls_certificate_credentials_t certs; 79 gnutls_certificate_credentials_t certs;
74 char *key_file; 80 gnutls_x509_crt_t cert_x509;
75 char *cert_file; 81 gnutls_x509_privkey_t privkey_x509;
76 int enabled; 82 int enabled;
77 int ciphers[16]; 83 int ciphers[16];
78 int key_exchange[16]; 84 int key_exchange[16];
@@ -85,6 +91,7 @@ typedef struct
85 const char* cache_config; 91 const char* cache_config;
86 const char* rsa_params_file; 92 const char* rsa_params_file;
87 const char* dh_params_file; 93 const char* dh_params_file;
94 gnutls_certificate_request_t client_verify_mode;
88} mod_gnutls_srvconf_rec; 95} mod_gnutls_srvconf_rec;
89 96
90typedef struct { 97typedef struct {
diff --git a/src/gnutls_io.c b/src/gnutls_io.c
index f761f96..f081284 100644
--- a/src/gnutls_io.c
+++ b/src/gnutls_io.c
@@ -353,13 +353,12 @@ static apr_status_t gnutls_io_input_getline(mod_gnutls_handle_t * ctxt,
353 return APR_SUCCESS; 353 return APR_SUCCESS;
354} 354}
355 355
356 356static int gnutls_do_handshake(mod_gnutls_handle_t * ctxt)
357static void gnutls_do_handshake(mod_gnutls_handle_t * ctxt)
358{ 357{
359 int ret; 358 int ret;
360 int errcode; 359 int errcode;
361 if (ctxt->status != 0) { 360 if (ctxt->status != 0) {
362 return; 361 return 0;
363 } 362 }
364 363
365tryagain: 364tryagain:
@@ -388,11 +387,37 @@ tryagain:
388 gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, 387 gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL,
389 gnutls_error_to_alert(ret, NULL)); 388 gnutls_error_to_alert(ret, NULL));
390 gnutls_deinit(ctxt->session); 389 gnutls_deinit(ctxt->session);
391 return; 390 return ret;
392 } 391 }
393 else { 392 else {
393 /* all done with the handshake */
394 ctxt->status = 1; 394 ctxt->status = 1;
395 return; /* all done with the handshake */ 395 return ret;
396 }
397}
398
399int mod_gnutls_rehandshake(mod_gnutls_handle_t * ctxt)
400{
401 int rv;
402
403 rv = gnutls_rehandshake(ctxt->session);
404
405 if (rv != 0) {
406 /* the client did not want to rehandshake. goodbye */
407 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server,
408 "GnuTLS: Client Refused Rehandshake request.");
409 return -1;
410 }
411
412 ctxt->status = 0;
413
414 gnutls_do_handshake(ctxt);
415
416 if (ctxt->status == 1) {
417 return 0;
418 }
419 else {
420 return -1;
396 } 421 }
397} 422}
398 423
@@ -414,26 +439,7 @@ apr_status_t mod_gnutls_filter_input(ap_filter_t* f,
414 } 439 }
415 440
416 if (ctxt->status == 0) { 441 if (ctxt->status == 0) {
417 char* server_name;
418 int server_type;
419 int data_len = 256;
420
421 gnutls_do_handshake(ctxt); 442 gnutls_do_handshake(ctxt);
422
423 /**
424 * Due to issues inside the GnuTLS API, we cannot currently do TLS 1.1
425 * Server Name Indication.
426 */
427 server_name = apr_palloc(ctxt->c->pool, data_len);
428 if (gnutls_server_name_get(ctxt->session, server_name, &data_len, &server_type, 0) == 0) {
429 if (server_type == GNUTLS_NAME_DNS) {
430 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
431 ctxt->c->base_server,
432 "GnuTLS: TLS 1.1 Server Name: "
433 "%s", server_name);
434
435 }
436 }
437 } 443 }
438 444
439 if (ctxt->status < 0) { 445 if (ctxt->status < 0) {
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index 71076ef..be150a9 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -17,6 +17,8 @@
17 17
18#include "mod_gnutls.h" 18#include "mod_gnutls.h"
19 19
20extern server_rec *ap_server_conf;
21
20#if APR_HAS_THREADS 22#if APR_HAS_THREADS
21GCRY_THREAD_OPTION_PTHREAD_IMPL; 23GCRY_THREAD_OPTION_PTHREAD_IMPL;
22#endif 24#endif
@@ -97,7 +99,7 @@ static gnutls_datum load_params(const char* file, server_rec* s,
97 "GnuTLS failed to read params file at: %s", file); 99 "GnuTLS failed to read params file at: %s", file);
98 return ret; 100 return ret;
99 } 101 }
100 102 apr_file_close(fp);
101 ret.data[br] = '\0'; 103 ret.data[br] = '\0';
102 ret.size = br; 104 ret.size = br;
103 105
@@ -127,7 +129,7 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
127 } 129 }
128 130
129 131
130 if (!first_run) { 132 {
131 gnutls_datum pdata; 133 gnutls_datum pdata;
132 apr_pool_t* tpool; 134 apr_pool_t* tpool;
133 s = base_server; 135 s = base_server;
@@ -194,32 +196,44 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
194 sc->cache_type = sc_base->cache_type; 196 sc->cache_type = sc_base->cache_type;
195 sc->cache_config = sc_base->cache_config; 197 sc->cache_config = sc_base->cache_config;
196 198
197 if (sc->cert_file != NULL && sc->key_file != NULL) { 199 gnutls_certificate_set_rsa_export_params(sc->certs,
198
199 rv = gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file,
200 sc->key_file,
201 GNUTLS_X509_FMT_PEM);
202 if (rv != 0) {
203 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
204 "[GnuTLS] - Host '%s:%d' has an invalid key or certificate:"
205 "(%s,%s) (%d) %s",
206 s->server_hostname, s->port, sc->cert_file, sc->key_file,
207 rv, gnutls_strerror(rv));
208 }
209 else {
210 gnutls_certificate_set_rsa_export_params(sc->certs,
211 rsa_params); 200 rsa_params);
212 gnutls_certificate_set_dh_params(sc->certs, dh_params); 201 gnutls_certificate_set_dh_params(sc->certs, dh_params);
213 } 202
214 } 203 if (sc->cert_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
215 else if (sc->enabled == GNUTLS_ENABLED_TRUE) {
216 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, 204 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
217 "[GnuTLS] - Host '%s:%d' is missing a " 205 "[GnuTLS] - Host '%s:%d' is missing a "
218 "Cert and Key File!", 206 "Certificate File!",
219 s->server_hostname, s->port); 207 s->server_hostname, s->port);
208 exit(-1);
209 }
210
211 if (sc->privkey_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
212 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
213 "[GnuTLS] - Host '%s:%d' is missing a "
214 "Private Key File!",
215 s->server_hostname, s->port);
216 exit(-1);
217 }
218 {
219 int rv;
220 int data_len = 255;
221 char crt_name[255];
222 for (rv = 0; rv < data_len; rv++) {
223 crt_name[rv] = '\0';
224 }
225 rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509,
226 GNUTLS_OID_X520_COMMON_NAME, 0, 0,
227 crt_name, &data_len);
228
229 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
230 s,
231 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", crt_name, rv,
232 gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)),
233 (unsigned int)s, (unsigned int)sc);
220 } 234 }
221 } 235 }
222 } /* first_run */ 236 }
223 237
224 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); 238 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION);
225 239
@@ -273,27 +287,112 @@ static apr_port_t mod_gnutls_hook_default_port(const request_rec * r)
273 return 443; 287 return 443;
274} 288}
275 289
276/* TODO: Complete support for Server Name Indication */ 290#define MAX_HOST_LEN 255
277static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) 291static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret)
278{ 292{
279 char* server_name; 293 int rv;
280 int server_type; 294 int sni_type;
281 int data_len = 256; 295 int data_len = MAX_HOST_LEN;
282 mod_gnutls_handle_t *ctxt; 296 char sni_name[MAX_HOST_LEN];
297 char crt_name[MAX_HOST_LEN];
298 mod_gnutls_handle_t *ctxt;
299 mod_gnutls_srvconf_rec *tsc;
300 server_rec* s;
301
283 ctxt = gnutls_transport_get_ptr(session); 302 ctxt = gnutls_transport_get_ptr(session);
303
304 sni_type = gnutls_certificate_type_get(session);
305 if (sni_type != GNUTLS_CRT_X509) {
306 /* In theory, we could support OpenPGP Certificates. Theory != code. */
307 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
308 ctxt->c->base_server,
309 "GnuTLS: Only x509 Certificates are currently supported.");
310 return -1;
311 }
284 312
285 ret->type = GNUTLS_CRT_X509; 313 ret->type = GNUTLS_CRT_X509;
286 ret->ncerts = 1; 314 ret->ncerts = 1;
287 server_name = apr_palloc(ctxt->c->pool, data_len); 315 ret->deinit_all = 0;
288 if (gnutls_server_name_get(ctxt->session, server_name, &data_len, &server_type, 0) == 0) { 316
289 if (server_type == GNUTLS_NAME_DNS) { 317 rv = gnutls_server_name_get(ctxt->session, sni_name,
290 ap_log_error(APLOG_MARK, APLOG_INFO, 0, 318 &data_len, &sni_type, 0);
319
320 if (rv != 0) {
321 goto use_default_crt;
322 }
323
324 if (sni_type != GNUTLS_NAME_DNS) {
325 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
326 ctxt->c->base_server,
327 "GnuTLS: Unknown type '%d' for SNI: "
328 "'%s'", sni_type, sni_name);
329 goto use_default_crt;
330 }
331
332 /**
333 * Code in the Core already sets up the c->base_server as the base
334 * for this IP/Port combo. Trust that the core did the 'right' thing.
335 */
336 for (s = ap_server_conf; s; s = s->next) {
337
338 tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config,
339 &gnutls_module);
340 if (tsc->enabled != GNUTLS_ENABLED_TRUE) {
341 continue;
342 }
343
344 data_len = MAX_HOST_LEN;
345 rv = gnutls_x509_crt_get_dn_by_oid(tsc->cert_x509,
346 GNUTLS_OID_X520_COMMON_NAME, 0, 0,
347 crt_name, &data_len);
348 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
349 ctxt->c->base_server,
350 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", crt_name, rv,
351 gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)),
352 (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc);
353
354 if (rv != 0) {
355 continue;
356 }
357
358 /* The CN can contain a * -- this will match those too. */
359 if (ap_strcasecmp_match(sni_name, crt_name) == 0) {
360 /* found a match */
361 ret->cert.x509 = &tsc->cert_x509;
362 ret->key.x509 = tsc->privkey_x509;
363#if MOD_GNUTLS_DEBUG
364 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
291 ctxt->c->base_server, 365 ctxt->c->base_server,
292 "GnuTLS: Virtual Host: " 366 "GnuTLS: Virtual Host: "
293 "%s", server_name); 367 "'%s' == '%s'", crt_name, sni_name);
368#endif
369 return 0;
294 } 370 }
295 } 371 }
296 372
373
374 /**
375 * If the client does not support the Server Name Indication, give the default
376 * certificate for this server.
377 */
378use_default_crt:
379 data_len = MAX_HOST_LEN;
380 rv = gnutls_x509_crt_get_dn_by_oid(ctxt->sc->cert_x509,
381 GNUTLS_OID_X520_COMMON_NAME, 0, 0,
382 crt_name, &data_len);
383
384 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
385 ctxt->c->base_server,
386 "GnuTLS: x509 cn: %s/%d pk: %s", crt_name, rv,
387 gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)));
388
389 ret->cert.x509 = &ctxt->sc->cert_x509;
390 ret->key.x509 = ctxt->sc->privkey_x509;
391#if MOD_GNUTLS_DEBUG
392 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
393 ctxt->c->base_server,
394 "GnuTLS: Using Default Certificate.");
395#endif
297 return 0; 396 return 0;
298} 397}
299 398
@@ -330,12 +429,12 @@ static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c)
330 429
331 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); 430 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs);
332 431
333 gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); 432 gnutls_certificate_server_set_request(ctxt->session, sc->client_verify_mode);
334 433
335 mod_gnutls_cache_session_init(ctxt); 434 mod_gnutls_cache_session_init(ctxt);
336 435
337 /* TODO: Finish Support for Server Name Indication */ 436 /* TODO: Finish Support for Server Name Indication */
338 /* gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn); */ 437 gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn);
339 return ctxt; 438 return ctxt;
340} 439}
341 440
@@ -412,26 +511,101 @@ static int mod_gnutls_hook_fixups(request_rec *r)
412 return OK; 511 return OK;
413} 512}
414 513
514static int load_datum_from_file(apr_pool_t* pool,
515 const char* file,
516 gnutls_datum_t* data)
517{
518 apr_file_t* fp;
519 apr_finfo_t finfo;
520 apr_status_t rv;
521 apr_size_t br = 0;
522
523 rv = apr_file_open(&fp, file, APR_READ|APR_BINARY, APR_OS_DEFAULT,
524 pool);
525 if (rv != APR_SUCCESS) {
526 return rv;
527 }
528
529 rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
530
531 if (rv != APR_SUCCESS) {
532 return rv;
533 }
534
535 data->data = apr_palloc(pool, finfo.size+1);
536 rv = apr_file_read_full(fp, data->data, finfo.size, &br);
537
538 if (rv != APR_SUCCESS) {
539 return rv;
540 }
541 apr_file_close(fp);
542
543 data->data[br] = '\0';
544 data->size = br;
545
546 return 0;
547}
548
415static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy, 549static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy,
416 const char *arg) 550 const char *arg)
417{ 551{
552 int ret;
553 gnutls_datum_t data;
554 const char* file;
555 apr_pool_t* spool;
418 mod_gnutls_srvconf_rec *sc = 556 mod_gnutls_srvconf_rec *sc =
419 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> 557 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server->
420 module_config, 558 module_config,
421 &gnutls_module); 559 &gnutls_module);
422 sc->cert_file = ap_server_root_relative(parms->pool, arg); 560 apr_pool_create(&spool, parms->pool);
561
562 file = ap_server_root_relative(spool, arg);
563
564 if (load_datum_from_file(spool, file, &data) != 0) {
565 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
566 "Certificate '%s'", file);
567 }
568
569 gnutls_x509_crt_init(&sc->cert_x509);
570 ret = gnutls_x509_crt_import(sc->cert_x509, &data, GNUTLS_X509_FMT_PEM);
571 if (ret != 0) {
572 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
573 "Certificate'%s': (%d) %s", file, ret,
574 gnutls_strerror(ret));
575 }
576
577 //apr_pool_destroy(spool);
423 return NULL; 578 return NULL;
424} 579}
425 580
426static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, 581static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy,
427 const char *arg) 582 const char *arg)
428{ 583{
584 int ret;
585 gnutls_datum_t data;
586 const char* file;
587 apr_pool_t* spool;
429 mod_gnutls_srvconf_rec *sc = 588 mod_gnutls_srvconf_rec *sc =
430 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> 589 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server->
431 module_config, 590 module_config,
432 &gnutls_module); 591 &gnutls_module);
592 apr_pool_create(&spool, parms->pool);
433 593
434 sc->key_file = ap_server_root_relative(parms->pool, arg); 594 file = ap_server_root_relative(spool, arg);
595
596 if (load_datum_from_file(spool, file, &data) != 0) {
597 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
598 "Private Key '%s'", file);
599 }
600
601 gnutls_x509_privkey_init(&sc->privkey_x509);
602 ret = gnutls_x509_privkey_import(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM);
603 if (ret != 0) {
604 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
605 "Private Key '%s': (%d) %s", file, ret,
606 gnutls_strerror(ret));
607 }
608 //apr_pool_destroy(spool);
435 return NULL; 609 return NULL;
436} 610}
437 611
@@ -471,6 +645,64 @@ static const char *gnutls_set_cache(cmd_parms * parms, void *dummy,
471 return NULL; 645 return NULL;
472} 646}
473 647
648static const char *gnutls_set_cache_timeout(cmd_parms * parms, void *dummy,
649 const char *arg)
650{
651 int argint;
652 mod_gnutls_srvconf_rec *sc =
653 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server->
654 module_config,
655 &gnutls_module);
656
657 argint = atoi(arg);
658
659 if (argint < 0) {
660 return "GnuTLSCacheTimeout: Invalid argument";
661 }
662 else if (argint == 0) {
663 sc->cache_timeout = 0;
664 }
665 else {
666 sc->cache_timeout = apr_time_from_sec(argint);
667 }
668
669 return NULL;
670}
671
672
673static const char *gnutls_set_client_verify(cmd_parms * parms, void *dummy,
674 const char *arg)
675{
676 gnutls_certificate_request_t mode;
677
678 if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
679 mode = GNUTLS_CERT_IGNORE;
680 }
681 else if (strcasecmp("optional", arg) == 0 || strcasecmp("request", arg) == 0) {
682 mode = GNUTLS_CERT_REQUEST;
683 }
684 else if (strcasecmp("optional", arg) == 0) {
685 mode = GNUTLS_CERT_REQUIRE;
686 }
687 else {
688 return "GnuTLSClientVerify: Invalid argument";
689 }
690
691 /* This was set from a directory context */
692 if (parms->path) {
693 mod_gnutls_dirconf_rec *dc = (mod_gnutls_dirconf_rec *)dummy;
694 dc->client_verify_mode = mode;
695 }
696 else {
697 mod_gnutls_srvconf_rec *sc =
698 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server->
699 module_config,
700 &gnutls_module);
701 sc->client_verify_mode = mode;
702 }
703
704 return NULL;
705}
474static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, 706static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy,
475 const char *arg) 707 const char *arg)
476{ 708{
@@ -492,6 +724,10 @@ static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy,
492} 724}
493 725
494static const command_rec gnutls_cmds[] = { 726static const command_rec gnutls_cmds[] = {
727 AP_INIT_TAKE1("GnuTLSClientVerify", gnutls_set_client_verify,
728 NULL,
729 RSRC_CONF|OR_AUTHCFG,
730 "Set Verification Requirements of the Client Certificate"),
495 AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file, 731 AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file,
496 NULL, 732 NULL,
497 RSRC_CONF, 733 RSRC_CONF,
@@ -500,6 +736,10 @@ static const command_rec gnutls_cmds[] = {
500 NULL, 736 NULL,
501 RSRC_CONF, 737 RSRC_CONF,
502 "SSL Server Certificate file"), 738 "SSL Server Certificate file"),
739 AP_INIT_TAKE1("GnuTLSCacheTimeout", gnutls_set_cache_timeout,
740 NULL,
741 RSRC_CONF,
742 "Cache Timeout"),
503 AP_INIT_TAKE2("GnuTLSCache", gnutls_set_cache, 743 AP_INIT_TAKE2("GnuTLSCache", gnutls_set_cache,
504 NULL, 744 NULL,
505 RSRC_CONF, 745 RSRC_CONF,
@@ -518,6 +758,29 @@ static const command_rec gnutls_cmds[] = {
518 * "CA"), 758 * "CA"),
519 */ 759 */
520 760
761int mod_gnutls_hook_authz(request_rec *r)
762{
763 return OK;
764#if 0
765 mod_gnutls_handle_t *ctxt;
766 mod_gnutls_dirconf_rec *dc = ap_get_module_config(r->per_dir_config,
767 &gnutls_module);
768
769 ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module);
770
771 if (dc->client_verify_mode == -1 ||
772 dc->client_verify_mode == GNUTLS_CERT_IGNORE ||
773 ctxt->sc->client_verify_mode > dc->client_verify_mode) {
774 return DECLINED;
775 }
776
777 gnutls_certificate_server_set_request(ctxt->session, dc->client_verify_mode);
778 if (mod_gnutls_rehandshake(ctxt) != 0) {
779 return HTTP_FORBIDDEN;
780 }
781#endif
782}
783
521static void gnutls_hooks(apr_pool_t * p) 784static void gnutls_hooks(apr_pool_t * p)
522{ 785{
523 ap_hook_pre_connection(mod_gnutls_hook_pre_connection, NULL, NULL, 786 ap_hook_pre_connection(mod_gnutls_hook_pre_connection, NULL, NULL,
@@ -537,8 +800,10 @@ static void gnutls_hooks(apr_pool_t * p)
537 APR_HOOK_MIDDLE); 800 APR_HOOK_MIDDLE);
538 ap_hook_pre_config(mod_gnutls_hook_pre_config, NULL, NULL, 801 ap_hook_pre_config(mod_gnutls_hook_pre_config, NULL, NULL,
539 APR_HOOK_MIDDLE); 802 APR_HOOK_MIDDLE);
540 803
541 ap_hook_fixups(mod_gnutls_hook_fixups, NULL, NULL, APR_HOOK_MIDDLE); 804 ap_hook_auth_checker(mod_gnutls_hook_authz, NULL, NULL, APR_HOOK_MIDDLE);
805
806 ap_hook_fixups(mod_gnutls_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST);
542 807
543 /* TODO: HTTP Upgrade Filter */ 808 /* TODO: HTTP Upgrade Filter */
544 /* ap_register_output_filter ("UPGRADE_FILTER", 809 /* ap_register_output_filter ("UPGRADE_FILTER",
@@ -560,18 +825,21 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s)
560 sc->enabled = GNUTLS_ENABLED_FALSE; 825 sc->enabled = GNUTLS_ENABLED_FALSE;
561 826
562 gnutls_certificate_allocate_credentials(&sc->certs); 827 gnutls_certificate_allocate_credentials(&sc->certs);
563 sc->key_file = NULL; 828 sc->privkey_x509 = NULL;
564 sc->cert_file = NULL; 829 sc->cert_x509 = NULL;
565 sc->cache_timeout = apr_time_from_sec(3600); 830 sc->cache_timeout = apr_time_from_sec(300);
566 sc->cache_type = mod_gnutls_cache_dbm; 831 sc->cache_type = mod_gnutls_cache_dbm;
567 sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); 832 sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache");
568 833
569 /* TODO: Make this Configurable ! */ 834 /* TODO: Make this Configurable. But it isn't configurable in mod_ssl? */
570 sc->dh_params_file = ap_server_root_relative(p, "conf/dhfile"); 835 sc->dh_params_file = ap_server_root_relative(p, "conf/dhfile");
571 sc->rsa_params_file = ap_server_root_relative(p, "conf/rsafile"); 836 sc->rsa_params_file = ap_server_root_relative(p, "conf/rsafile");
572 837
838 /* Finish SSL Client Certificate Support */
839 sc->client_verify_mode = GNUTLS_CERT_IGNORE;
840
573 /* TODO: Make this Configurable ! */ 841 /* TODO: Make this Configurable ! */
574 /* meh. mod_ssl uses a flex based parser for this part.. sigh */ 842 /* mod_ssl uses a flex based parser for this part.. sigh */
575 i = 0; 843 i = 0;
576 sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC; 844 sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC;
577 sc->ciphers[i++] = GNUTLS_CIPHER_AES_128_CBC; 845 sc->ciphers[i++] = GNUTLS_CIPHER_AES_128_CBC;
@@ -616,11 +884,18 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s)
616 return sc; 884 return sc;
617} 885}
618 886
887void *gnutls_config_dir_create(apr_pool_t *p, char *dir)
888{
889 mod_gnutls_dirconf_rec *dc = apr_palloc(p, sizeof(*dc));
619 890
891 dc->client_verify_mode = -1;
892
893 return dc;
894}
620 895
621module AP_MODULE_DECLARE_DATA gnutls_module = { 896module AP_MODULE_DECLARE_DATA gnutls_module = {
622 STANDARD20_MODULE_STUFF, 897 STANDARD20_MODULE_STUFF,
623 NULL, 898 gnutls_config_dir_create,
624 NULL, 899 NULL,
625 gnutls_config_server_create, 900 gnutls_config_server_create,
626 NULL, 901 NULL,