aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/mod_gnutls.c204
2 files changed, 156 insertions, 50 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7a4903a..00ef272 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,7 +2,7 @@ CLEANFILES = .libs/libmod_gnutls *~
2 2
3libmod_gnutls_la_SOURCES = mod_gnutls.c 3libmod_gnutls_la_SOURCES = mod_gnutls.c
4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} 4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS}
5libmod_gnutls_la_LDFLAGS = 5libmod_gnutls_la_LDFLAGS = ${MODULE_LIBS}
6 6
7lib_LTLIBRARIES = libmod_gnutls.la 7lib_LTLIBRARIES = libmod_gnutls.la
8 8
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index bf0d9c3..e9ad89c 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -34,32 +34,42 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL;
34 34
35module AP_MODULE_DECLARE_DATA gnutls_module; 35module AP_MODULE_DECLARE_DATA gnutls_module;
36 36
37#ifdef GNUTLS_AS_FILTER
37#define GNUTLS_OUTPUT_FILTER_NAME "GnuTLS Output Filter" 38#define GNUTLS_OUTPUT_FILTER_NAME "GnuTLS Output Filter"
38#define GNUTLS_INPUT_FILTER_NAME "GnuTLS Input Filter" 39#define GNUTLS_INPUT_FILTER_NAME "GnuTLS Input Filter"
40#endif
39 41
40#define GNUTLS_ENABLED_FALSE 0 42#define GNUTLS_ENABLED_FALSE 0
41#define GNUTLS_ENABLED_TRUE 1 43#define GNUTLS_ENABLED_TRUE 1
42 44
43 45
44typedef struct gnutls_srvconf_t gnutls_srvconf_t; 46typedef struct {
45struct gnutls_srvconf_t
46{
47 gnutls_certificate_credentials_t certs; 47 gnutls_certificate_credentials_t certs;
48 gnutls_anon_server_credentials_t anoncred;
48 char *key_file; 49 char *key_file;
49 char *cert_file; 50 char *cert_file;
50 int enabled; 51 int enabled;
51}; 52 int non_https;
53 int ciphers[16];
54 int key_exchange[16];
55 int macs[16];
56 int protocol[16];
57 int compression[16];
58} gnutls_srvconf_rec;
52 59
53typedef struct gnutls_handle_t gnutls_handle_t; 60typedef struct gnutls_handle_t gnutls_handle_t;
54struct gnutls_handle_t 61struct gnutls_handle_t
55{ 62{
56 gnutls_srvconf_t *sc; 63 gnutls_srvconf_rec *sc;
57 gnutls_session_t session; 64 gnutls_session_t session;
65#ifdef GNUTLS_AS_FILTER
58 ap_filter_t *input_filter; 66 ap_filter_t *input_filter;
59 apr_bucket_brigade *input_bb; 67 apr_bucket_brigade *input_bb;
60 apr_read_type_e input_block; 68 apr_read_type_e input_block;
69#endif
61}; 70};
62 71
72#ifdef GNUTLS_AS_FILTER
63static apr_status_t gnutls_filter_input(ap_filter_t * f, 73static apr_status_t gnutls_filter_input(ap_filter_t * f,
64 apr_bucket_brigade * bb, 74 apr_bucket_brigade * bb,
65 ap_input_mode_t mode, 75 ap_input_mode_t mode,
@@ -105,6 +115,8 @@ static apr_status_t gnutls_filter_output(ap_filter_t * f,
105 return status; 115 return status;
106} 116}
107 117
118#endif /* GNUTLS_AS_FILTER */
119
108static apr_status_t gnutls_cleanup_pre_config(void *data) 120static apr_status_t gnutls_cleanup_pre_config(void *data)
109{ 121{
110 gnutls_global_deinit(); 122 gnutls_global_deinit();
@@ -134,48 +146,44 @@ static int gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
134 apr_pool_t * ptemp, 146 apr_pool_t * ptemp,
135 server_rec * base_server) 147 server_rec * base_server)
136{ 148{
137 gnutls_srvconf_t *sc; 149 gnutls_srvconf_rec *sc;
138 server_rec *s; 150 server_rec *s;
139 gnutls_dh_params_t dh_params; 151 gnutls_dh_params_t dh_params;
140 gnutls_rsa_params_t rsa_params; 152 gnutls_rsa_params_t rsa_params;
141 153
142 154
143 /* TODO: Should we regenerate these after X requests / X time ? */ 155 /* TODO: Should we regenerate these after X requests / X time ? */
144 gnutls_dh_params_init(&dh_params); 156// gnutls_dh_params_init(&dh_params);
145 gnutls_dh_params_generate2(dh_params, DH_BITS); 157// gnutls_dh_params_generate2(dh_params, DH_BITS);
146 gnutls_rsa_params_init(&rsa_params); 158// gnutls_rsa_params_init(&rsa_params);
147 gnutls_rsa_params_generate2(rsa_params, RSA_BITS); 159// gnutls_rsa_params_generate2(rsa_params, RSA_BITS);
148 160
149 for (s = base_server; s; s = s->next) { 161 for (s = base_server; s; s = s->next) {
150 sc = (gnutls_srvconf_t *) ap_get_module_config(s->module_config, 162 sc = (gnutls_srvconf_rec *) ap_get_module_config(s->module_config,
151 &gnutls_module); 163 &gnutls_module);
152 if (sc->cert_file != NULL && sc->key_file != NULL) { 164 if (sc->cert_file != NULL && sc->key_file != NULL) {
153 gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, 165 gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file,
154 sc->key_file, 166 sc->key_file,
155 GNUTLS_X509_FMT_PEM); 167 GNUTLS_X509_FMT_PEM);
168// gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params);
169// gnutls_certificate_set_dh_params(sc->certs, dh_params);
156 } 170 }
157 else { 171 else if(sc->enabled == GNUTLS_ENABLED_TRUE ){
158 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, 172 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
159 "[GnuTLS] - Host '%s' is missing a Cert and Key File!", 173 "[GnuTLS] - Host '%s:%d' is missing a Cert and Key File!",
160 s->server_hostname); 174 s->server_hostname, s->port);
161 } 175 }
162
163 /**
164 * TODO: Is it okay for all virtual hosts to
165 * share the same DH/RSAparams?
166 */
167 gnutls_certificate_set_dh_params(sc->certs, dh_params);
168 gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params);
169 } 176 }
170 177
178
171 ap_add_version_component(p, "GnuTLS/" LIBGNUTLS_VERSION); 179 ap_add_version_component(p, "GnuTLS/" LIBGNUTLS_VERSION);
172 return OK; 180 return OK;
173} 181}
174 182
175static const char *gnutls_hook_http_method(const request_rec * r) 183static const char *gnutls_hook_http_method(const request_rec * r)
176{ 184{
177 gnutls_srvconf_t *sc = 185 gnutls_srvconf_rec *sc =
178 (gnutls_srvconf_t *) ap_get_module_config(r->server->module_config, 186 (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config,
179 &gnutls_module); 187 &gnutls_module);
180 188
181 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 189 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
@@ -187,8 +195,8 @@ static const char *gnutls_hook_http_method(const request_rec * r)
187 195
188static apr_port_t gnutls_hook_default_port(const request_rec * r) 196static apr_port_t gnutls_hook_default_port(const request_rec * r)
189{ 197{
190 gnutls_srvconf_t *sc = 198 gnutls_srvconf_rec *sc =
191 (gnutls_srvconf_t *) ap_get_module_config(r->server->module_config, 199 (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config,
192 &gnutls_module); 200 &gnutls_module);
193 201
194 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 202 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
@@ -198,6 +206,7 @@ static apr_port_t gnutls_hook_default_port(const request_rec * r)
198 return 443; 206 return 443;
199} 207}
200 208
209#ifdef GNUTLS_AS_FILTER
201/** 210/**
202 * From mod_ssl / ssl_engine_io.c 211 * From mod_ssl / ssl_engine_io.c
203 * This function will read from a brigade and discard the read buckets as it 212 * This function will read from a brigade and discard the read buckets as it
@@ -336,15 +345,17 @@ static ssize_t gnutls_transport_write(gnutls_transport_ptr_t ptr,
336 //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); 345 //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket);
337 return 0; 346 return 0;
338} 347}
348#endif /* GNUTLS_AS_FILTER */
339 349
340static int gnutls_hook_pre_connection(conn_rec * c, void *csd) 350static int gnutls_hook_pre_connection(conn_rec * c, void *csd)
341{ 351{
342#ifndef GNUTLS_AS_FILTER 352#ifndef GNUTLS_AS_FILTER
343 int cfd; 353 int cfd;
354 int ret;
344#endif 355#endif
345 gnutls_handle_t *ctxt; 356 gnutls_handle_t *ctxt;
346 gnutls_srvconf_t *sc = 357 gnutls_srvconf_rec *sc =
347 (gnutls_srvconf_t *) ap_get_module_config(c->base_server-> 358 (gnutls_srvconf_rec *) ap_get_module_config(c->base_server->
348 module_config, 359 module_config,
349 &gnutls_module); 360 &gnutls_module);
350 361
@@ -357,13 +368,17 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd)
357 ctxt->sc = sc; 368 ctxt->sc = sc;
358 gnutls_init(&ctxt->session, GNUTLS_SERVER); 369 gnutls_init(&ctxt->session, GNUTLS_SERVER);
359 370
360 gnutls_set_default_priority(ctxt->session); 371 gnutls_cipher_set_priority(ctxt->session, sc->ciphers);
372 gnutls_compression_set_priority(ctxt->session, sc->compression);
373 gnutls_kx_set_priority(ctxt->session, sc->key_exchange);
374 gnutls_protocol_set_priority(ctxt->session, sc->protocol);
375 gnutls_mac_set_priority(ctxt->session, sc->macs);
361 376
362 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); 377 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs);
378 gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE);
363 379
364 gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_REQUEST); 380// gnutls_dh_set_prime_bits(ctxt->session, DH_BITS);
365 381
366 gnutls_dh_set_prime_bits(ctxt->session, DH_BITS);
367 382
368 ap_set_module_config(c->conn_config, &gnutls_module, ctxt); 383 ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
369 384
@@ -377,41 +392,97 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd)
377#else 392#else
378 apr_os_sock_get(&cfd, csd); 393 apr_os_sock_get(&cfd, csd);
379 gnutls_transport_set_ptr(ctxt->session, (gnutls_transport_ptr)cfd); 394 gnutls_transport_set_ptr(ctxt->session, (gnutls_transport_ptr)cfd);
395 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred);
396
397 do{
398 ret = gnutls_handshake(ctxt->session);
399
400 if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN){
401 continue;
402 }
403
404 if (ret < 0) {
405 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
406 ret = gnutls_alert_get(ctxt->session);
407 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
408 "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, gnutls_alert_get_name(ret));
409 }
410
411 if (gnutls_error_is_fatal(ret) != 0) {
412 gnutls_deinit(ctxt->session);
413 ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server,
414 "GnuTLS: Handshake Failed (%d) '%s'",ret, gnutls_strerror(ret));
415 sc->non_https = 1;
416 break;
417 }
418 }
419 break; /* all done with the handshake */
420 } while(1);
380#endif 421#endif
381 return OK; 422 return OK;
382} 423}
383 424
384static const char *gnutls_set_ca_file(cmd_parms * parms, void *dummy, 425static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy,
385 const char *arg) 426 const char *arg)
386{ 427{
387 gnutls_srvconf_t *sc = 428 gnutls_srvconf_rec *sc =
388 (gnutls_srvconf_t *) ap_get_module_config(parms->server-> 429 (gnutls_srvconf_rec *) ap_get_module_config(parms->server->
389 module_config, 430 module_config,
390 &gnutls_module); 431 &gnutls_module);
391/* TODO: CRL, CAFile */ 432 sc->cert_file = apr_pstrdup(parms->pool, arg);
392// gnutls_certificate_set_x509_trust_file(sc->certs, CAFILE, 433 return NULL;
393// GNUTLS_X509_FMT_PEM); 434}
435
436static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy,
437 const char *arg)
438{
439 gnutls_srvconf_rec *sc =
440 (gnutls_srvconf_rec *) ap_get_module_config(parms->server->
441 module_config,
442 &gnutls_module);
443 sc->key_file = apr_pstrdup(parms->pool, arg);
444 return NULL;
445}
446
447static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy,
448 const char *arg)
449{
450 gnutls_srvconf_rec *sc =
451 (gnutls_srvconf_rec *) ap_get_module_config(parms->server->
452 module_config,
453 &gnutls_module);
454 if (!strcasecmp(arg, "On")) {
455 sc->enabled = GNUTLS_ENABLED_TRUE;
456 }
457 else if (!strcasecmp(arg, "Off")) {
458 sc->enabled = GNUTLS_ENABLED_FALSE;
459 }
460 else {
461 return "GnuTLSEnable must be set to 'On' or 'Off'";
462 }
463
394 return NULL; 464 return NULL;
395} 465}
396 466
397static const command_rec gnutls_cmds[] = { 467static const command_rec gnutls_cmds[] = {
398 AP_INIT_FLAG("GnuTLSEnable", ap_set_flag_slot, 468 AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file,
399 (void *) APR_OFFSETOF(gnutls_srvconf_t, enabled), RSRC_CONF, 469 NULL,
400 "Whether this server has GnuTLS Enabled. Default: Off"),
401 AP_INIT_TAKE1("GnuTLSCertificateFile", ap_set_string_slot,
402 (void *) APR_OFFSETOF(gnutls_srvconf_t, cert_file),
403 RSRC_CONF, 470 RSRC_CONF,
404 "SSL Server Key file"), 471 "SSL Server Key file"),
405 AP_INIT_TAKE1("GnuTLSKeyFile", ap_set_string_slot, 472 AP_INIT_TAKE1("GnuTLSKeyFile", gnutls_set_key_file,
406 (void *) APR_OFFSETOF(gnutls_srvconf_t, key_file), 473 NULL,
407 RSRC_CONF, 474 RSRC_CONF,
408 "SSL Server Certificate file"), 475 "SSL Server Certificate file"),
476 AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled,
477 NULL, RSRC_CONF,
478 "Whether this server has GnuTLS Enabled. Default: Off"),
479
409 {NULL} 480 {NULL}
410}; 481};
411 482
412/* TODO: CACertificateFile & Client Authentication 483/* TODO: CACertificateFile & Client Authentication
413 * AP_INIT_TAKE1("GnuTLSCACertificateFile", ap_set_server_string_slot, 484 * AP_INIT_TAKE1("GnuTLSCACertificateFile", ap_set_server_string_slot,
414 * (void *) APR_OFFSETOF(gnutls_srvconf_t, key_file), NULL, 485 * (void *) APR_OFFSETOF(gnutls_srvconf_rec, key_file), NULL,
415 * RSRC_CONF, 486 * RSRC_CONF,
416 * "CA"), 487 * "CA"),
417 */ 488 */
@@ -430,24 +501,59 @@ static void gnutls_hooks(apr_pool_t * p)
430 /* ap_register_output_filter ("UPGRADE_FILTER", 501 /* ap_register_output_filter ("UPGRADE_FILTER",
431 * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); 502 * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
432 */ 503 */
433 504#ifdef GNUTLS_AS_FILTER
434 ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input, 505 ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input,
435 NULL, AP_FTYPE_CONNECTION + 5); 506 NULL, AP_FTYPE_CONNECTION + 5);
436 ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output, 507 ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output,
437 NULL, AP_FTYPE_CONNECTION + 5); 508 NULL, AP_FTYPE_CONNECTION + 5);
438 509#endif
439} 510}
440 511
441static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) 512static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s)
442{ 513{
443 gnutls_srvconf_t *sc = apr_pcalloc(p, sizeof *sc); 514 int i;
515 gnutls_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc));
444 516
445 sc->enabled = GNUTLS_ENABLED_FALSE; 517 sc->enabled = GNUTLS_ENABLED_FALSE;
518 sc->non_https = 0;
446 519
447 gnutls_certificate_allocate_credentials(&sc->certs); 520 gnutls_certificate_allocate_credentials(&sc->certs);
448 521 gnutls_anon_allocate_server_credentials(&sc->anoncred);
449 sc->key_file = NULL; 522 sc->key_file = NULL;
450 sc->cert_file = NULL; 523 sc->cert_file = NULL;
524
525 i = 0;
526 sc->ciphers[i++] = GNUTLS_CIPHER_RIJNDAEL_128_CBC;
527 sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_128;
528 sc->ciphers[i++] = GNUTLS_CIPHER_3DES_CBC;
529 sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_40;
530 sc->ciphers[i] = 0;
531
532 i = 0;
533 sc->key_exchange[i++] = GNUTLS_KX_RSA;
534 sc->key_exchange[i++] = GNUTLS_KX_RSA_EXPORT;
535 sc->key_exchange[i++] = GNUTLS_KX_DHE_RSA;
536 sc->key_exchange[i++] = GNUTLS_KX_DHE_DSS;
537 sc->key_exchange[i] = 0;
538
539 i = 0;
540 sc->macs[i++] = GNUTLS_MAC_MD5;
541 sc->macs[i++] = GNUTLS_MAC_SHA;
542 sc->macs[i++] = GNUTLS_MAC_RMD160;
543 sc->macs[i] = 0;
544
545 i = 0;
546 sc->protocol[i++] = GNUTLS_TLS1_1;
547 sc->protocol[i++] = GNUTLS_TLS1;
548 sc->protocol[i++] = GNUTLS_SSL3;
549 sc->protocol[i] = 0;
550
551 i = 0;
552 sc->compression[i++] = GNUTLS_COMP_NULL;
553 sc->compression[i++] = GNUTLS_COMP_ZLIB;
554 sc->compression[i++] = GNUTLS_COMP_LZO;
555 sc->compression[i] = 0;
556
451 return sc; 557 return sc;
452} 558}
453 559