summaryrefslogtreecommitdiffstatsabout
path: root/src/mod_gnutls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_gnutls.c')
-rw-r--r--src/mod_gnutls.c250
1 files changed, 202 insertions, 48 deletions
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