summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorPaul Querna <chip@outoforder.cc>2005-04-06 04:52:25 (GMT)
committer Paul Querna <chip@outoforder.cc>2005-04-06 04:52:25 (GMT)
commit42307a9120b12fa5eb6fe1b316ef521ae46dbeb9 (patch)
tree3f3da6cbf06c91cbca72f9f6f552a0a26afe62f2
parentfcb122d264414b86ca89dddffba5f839963fc7fa (diff)
- remove anno creds
- initial attempt at Server Name Extension - change to adding 'mod_gnutls' to the server sig instead of GnuTLS/ - fix for EOF/EOC/EOS buckets - 'general' code cleanups
-rw-r--r--configure.ac8
-rw-r--r--include/mod_gnutls.h.in16
-rw-r--r--mod_gnutls.xcode/project.pbxproj20
-rw-r--r--src/gnutls_cache.c153
-rw-r--r--src/gnutls_io.c99
-rw-r--r--src/mod_gnutls.c52
6 files changed, 277 insertions, 71 deletions
diff --git a/configure.ac b/configure.ac
index 086b9f5..772177c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
1
2AC_INIT(mod_gnutls, 0.1.0) 1AC_INIT(mod_gnutls, 0.1.0)
3OOO_CONFIG_NICE(config.nice) 2OOO_CONFIG_NICE(config.nice)
3MOD_GNUTLS_VERSION=AC_PACKAGE_VERSION
4AC_PREREQ(2.53) 4AC_PREREQ(2.53)
5AC_CONFIG_SRCDIR([src/mod_gnutls.c]) 5AC_CONFIG_SRCDIR([src/mod_gnutls.c])
6AC_CONFIG_AUX_DIR(config) 6AC_CONFIG_AUX_DIR(config)
@@ -9,6 +9,7 @@ AC_CANONICAL_TARGET
9AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) 9AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
10AM_CONFIG_HEADER(include/mod_gnutls_config.h:config.in) 10AM_CONFIG_HEADER(include/mod_gnutls_config.h:config.in)
11 11
12AC_SUBST(MOD_GNUTLS_VERSION)
12 13
13AC_PROG_CC 14AC_PROG_CC
14AC_PROG_LD 15AC_PROG_LD
@@ -41,9 +42,10 @@ AC_CONFIG_FILES([Makefile src/Makefile include/mod_gnutls.h])
41AC_OUTPUT 42AC_OUTPUT
42 43
43echo "---" 44echo "---"
44echo "Configuration summary for mod_gnutls" 45echo "Configuration summary for mod_gnutls:"
45echo "" 46echo ""
47echo " * mod_gnutls version: ${MOD_GNUTLS_VERSION}"
46echo " * Apache Modules directory: ${AP_LIBEXECDIR}" 48echo " * Apache Modules directory: ${AP_LIBEXECDIR}"
47echo " * GnuTLS Library Version: ${LIBGNUTLS_VERSION}" 49echo " * GnuTLS Library version: ${LIBGNUTLS_VERSION}"
48echo "" 50echo ""
49echo "---" 51echo "---"
diff --git a/include/mod_gnutls.h.in b/include/mod_gnutls.h.in
index f9ff32b..58fc928 100644
--- a/include/mod_gnutls.h.in
+++ b/include/mod_gnutls.h.in
@@ -42,6 +42,8 @@ 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#define MOD_GNUTLS_VERSION "@MOD_GNUTLS_VERSION@"
46
45typedef enum 47typedef enum
46{ 48{
47 mod_gnutls_cache_none, 49 mod_gnutls_cache_none,
@@ -54,7 +56,6 @@ typedef enum
54typedef struct 56typedef struct
55{ 57{
56 gnutls_certificate_credentials_t certs; 58 gnutls_certificate_credentials_t certs;
57 gnutls_anon_server_credentials_t anoncred;
58 char *key_file; 59 char *key_file;
59 char *cert_file; 60 char *cert_file;
60 int enabled; 61 int enabled;
@@ -171,4 +172,17 @@ int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s,
171 */ 172 */
172int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt); 173int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt);
173 174
175#define GNUTLS_SESSION_ID_STRING_LEN \
176 ((GNUTLS_MAX_SESSION_ID + 1) * 2)
177
178/**
179 * Convert a SSL Session ID into a Null Terminated Hex Encoded String
180 * @param id raw SSL Session ID
181 * @param idlen Length of the raw Session ID
182 * @param str Location to store the Hex Encoded String
183 * @param strsize The Maximum Length that can be stored in str
184 */
185char *mod_gnutls_session_id2sz(unsigned char *id, int idlen,
186 char *str, int strsize);
187
174#endif /* __mod_gnutls_h_inc */ 188#endif /* __mod_gnutls_h_inc */
diff --git a/mod_gnutls.xcode/project.pbxproj b/mod_gnutls.xcode/project.pbxproj
index 6d79e40..7b9c1e0 100644
--- a/mod_gnutls.xcode/project.pbxproj
+++ b/mod_gnutls.xcode/project.pbxproj
@@ -8,6 +8,8 @@
8 45B624630802F1E200CBFD9A = { 8 45B624630802F1E200CBFD9A = {
9 children = ( 9 children = (
10 45B6246D0802F20D00CBFD9A, 10 45B6246D0802F20D00CBFD9A,
11 45B6247D0802F85B00CBFD9A,
12 45B6247A0802F84500CBFD9A,
11 45B6246E0802F20D00CBFD9A, 13 45B6246E0802F20D00CBFD9A,
12 45B6246F0802F20D00CBFD9A, 14 45B6246F0802F20D00CBFD9A,
13 ); 15 );
@@ -70,6 +72,24 @@
70 refType = 2; 72 refType = 2;
71 sourceTree = SOURCE_ROOT; 73 sourceTree = SOURCE_ROOT;
72 }; 74 };
75 45B6247A0802F84500CBFD9A = {
76 fileEncoding = 4;
77 isa = PBXFileReference;
78 lastKnownFileType = sourcecode.c.h;
79 name = mod_gnutls.h;
80 path = include/mod_gnutls.h;
81 refType = 2;
82 sourceTree = SOURCE_ROOT;
83 };
84 45B6247D0802F85B00CBFD9A = {
85 fileEncoding = 4;
86 isa = PBXFileReference;
87 lastKnownFileType = text;
88 name = mod_gnutls.h.in;
89 path = include/mod_gnutls.h.in;
90 refType = 2;
91 sourceTree = SOURCE_ROOT;
92 };
73 }; 93 };
74 rootObject = 45B624670802F1E200CBFD9A; 94 rootObject = 45B624670802F1E200CBFD9A;
75} 95}
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c
index 868568b..91e6ec9 100644
--- a/src/gnutls_cache.c
+++ b/src/gnutls_cache.c
@@ -32,15 +32,14 @@
32#include "unixd.h" 32#include "unixd.h"
33#endif 33#endif
34 34
35#define GNUTLS_SESSION_ID_STRING_LEN \ 35
36 ((GNUTLS_MAX_SESSION_ID + 1) * 2)
37#define MC_TAG "mod_gnutls:" 36#define MC_TAG "mod_gnutls:"
38#define MC_TAG_LEN \ 37#define MC_TAG_LEN \
39 (sizeof(MC_TAG)) 38 (sizeof(MC_TAG))
40#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) 39#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN)
41 40
42static char *gnutls_session_id2sz(unsigned char *id, int idlen, 41static char *gnutls_session_id2sz(unsigned char *id, int idlen,
43 char *str, int strsize) 42 char *str, int strsize)
44{ 43{
45 char *cp; 44 char *cp;
46 int n; 45 int n;
@@ -54,6 +53,21 @@ static char *gnutls_session_id2sz(unsigned char *id, int idlen,
54 return str; 53 return str;
55} 54}
56 55
56char *mod_gnutls_session_id2sz(unsigned char *id, int idlen,
57 char *str, int strsize)
58{
59 char *cp;
60 int n;
61
62 cp = str;
63 for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) {
64 apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]);
65 cp += 2;
66 }
67 *cp = '\0';
68 return str;
69}
70
57 71
58#if HAVE_APR_MEMCACHE 72#if HAVE_APR_MEMCACHE
59 73
@@ -103,13 +117,13 @@ int mc_cache_child_init(apr_pool_t *p, server_rec *s,
103 apr_port_t port; 117 apr_port_t port;
104 118
105 rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p); 119 rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
106 if(rv != APR_SUCCESS) { 120 if (rv != APR_SUCCESS) {
107 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 121 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
108 "[gnutls_cache] Failed to Parse Server: '%s'", split); 122 "[gnutls_cache] Failed to Parse Server: '%s'", split);
109 return rv; 123 return rv;
110 } 124 }
111 125
112 if(host_str == NULL) { 126 if (host_str == NULL) {
113 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 127 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
114 "[gnutls_cache] Failed to Parse Server, " 128 "[gnutls_cache] Failed to Parse Server, "
115 "no hostname specified: '%s'", split); 129 "no hostname specified: '%s'", split);
@@ -128,7 +142,7 @@ int mc_cache_child_init(apr_pool_t *p, server_rec *s,
128 thread_limit, 142 thread_limit,
129 600, 143 600,
130 &st); 144 &st);
131 if(rv != APR_SUCCESS) { 145 if (rv != APR_SUCCESS) {
132 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 146 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
133 "[gnutls_cache] Failed to Create Server: %s:%d", 147 "[gnutls_cache] Failed to Create Server: %s:%d",
134 host_str, port); 148 host_str, port);
@@ -136,7 +150,7 @@ int mc_cache_child_init(apr_pool_t *p, server_rec *s,
136 } 150 }
137 151
138 rv = apr_memcache_add_server(mc, st); 152 rv = apr_memcache_add_server(mc, st);
139 if(rv != APR_SUCCESS) { 153 if (rv != APR_SUCCESS) {
140 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s, 154 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
141 "[gnutls_cache] Failed to Add Server: %s:%d", 155 "[gnutls_cache] Failed to Add Server: %s:%d",
142 host_str, port); 156 host_str, port);
@@ -161,11 +175,11 @@ static int mc_cache_store(void* baton, gnutls_datum_t key,
161 if(!strkey) 175 if(!strkey)
162 return -1; 176 return -1;
163 177
164 timeout = ctxt->sc->cache_timeout; 178 timeout = apr_time_sec(ctxt->sc->cache_timeout);
165 179
166 rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0); 180 rv = apr_memcache_set(mc, strkey, data.data, data.size, timeout, 0);
167 181
168 if(rv != APR_SUCCESS) { 182 if (rv != APR_SUCCESS) {
169 ap_log_error(APLOG_MARK, APLOG_CRIT, rv, 183 ap_log_error(APLOG_MARK, APLOG_CRIT, rv,
170 ctxt->c->base_server, 184 ctxt->c->base_server,
171 "[gnutls_cache] error setting key '%s' " 185 "[gnutls_cache] error setting key '%s' "
@@ -187,14 +201,14 @@ static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key)
187 gnutls_datum_t data = { NULL, 0 }; 201 gnutls_datum_t data = { NULL, 0 };
188 202
189 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 203 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf));
190 if(!strkey) { 204 if (!strkey) {
191 return data; 205 return data;
192 } 206 }
193 207
194 rv = apr_memcache_getp(mc, ctxt->c->pool, strkey, 208 rv = apr_memcache_getp(mc, ctxt->c->pool, strkey,
195 &value, &value_len, NULL); 209 &value, &value_len, NULL);
196 210
197 if(rv != APR_SUCCESS) { 211 if (rv != APR_SUCCESS) {
198 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 212 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
199 ctxt->c->base_server, 213 ctxt->c->base_server,
200 "[gnutls_cache] error fetching key '%s' ", 214 "[gnutls_cache] error fetching key '%s' ",
@@ -229,7 +243,7 @@ static int mc_cache_delete(void* baton, gnutls_datum_t key)
229 243
230 rv = apr_memcache_delete(mc, strkey, 0); 244 rv = apr_memcache_delete(mc, strkey, 0);
231 245
232 if(rv != APR_SUCCESS) { 246 if (rv != APR_SUCCESS) {
233 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, 247 ap_log_error(APLOG_MARK, APLOG_DEBUG, rv,
234 ctxt->c->base_server, 248 ctxt->c->base_server,
235 "[gnutls_cache] error deleting key '%s' ", 249 "[gnutls_cache] error deleting key '%s' ",
@@ -248,18 +262,80 @@ static int dbm_cache_expire(mod_gnutls_handle_t *ctxt)
248{ 262{
249 apr_status_t rv; 263 apr_status_t rv;
250 apr_dbm_t *dbm; 264 apr_dbm_t *dbm;
251 265 apr_datum_t *keylist;
252 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 266 apr_datum_t dbmkey;
253 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); 267 apr_datum_t dbmval;
268 apr_time_t ex;
269 apr_time_t dtime;
270 apr_pool_t* spool;
271 int i = 0;
272 int keyidx = 0;
273 int should_delete = 0;
274
275 apr_pool_create(&spool, ctxt->c->pool);
276 ex = apr_time_now();
277
278 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, APR_DBM_READONLY,
279 SSL_DBM_FILE_MODE, spool);
254 if (rv != APR_SUCCESS) { 280 if (rv != APR_SUCCESS) {
255 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 281 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
256 ctxt->c->base_server, 282 ctxt->c->base_server,
257 "[gnutls_cache] error opening cache '%s'", 283 "[gnutls_cache] error opening cache searcher '%s'",
258 ctxt->sc->cache_config); 284 ctxt->sc->cache_config);
259 return -1; 285 return -1;
260 } 286 }
287
288#define KEYMAX 128
289
290 keylist = apr_palloc(spool, sizeof(dbmkey)*KEYMAX);
291
292 apr_dbm_firstkey(dbm, &dbmkey);
293 while (dbmkey.dptr != NULL) {
294 apr_dbm_fetch(dbm, dbmkey, &dbmval);
295 if (dbmval.dptr != NULL) {
296 if (dbmval.dsize >= sizeof(apr_time_t)) {
297 memcpy(&dtime, dbmval.dptr, sizeof(apr_time_t));
298 if (dtime < ex) {
299 should_delete = 1;
300 }
301 }
302 else {
303 should_delete = 1;
304 }
305
306 if (should_delete == 1) {
307 should_delete = 0;
308 keylist[keyidx].dptr = apr_palloc(spool, dbmkey.dsize) ;
309 memcpy(keylist[keyidx].dptr, dbmkey.dptr, dbmkey.dsize);
310 keylist[keyidx].dsize = dbmkey.dsize;
311 keyidx++;
312 if (keyidx == KEYMAX) {
313 break;
314 }
315 }
316
317 }
318 apr_dbm_nextkey(dbm, &dbmkey);
319 }
261 apr_dbm_close(dbm); 320 apr_dbm_close(dbm);
262 321
322 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
323 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, spool);
324 if (rv != APR_SUCCESS) {
325 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
326 ctxt->c->base_server,
327 "[gnutls_cache] error opening cache writer '%s'",
328 ctxt->sc->cache_config);
329 return -1;
330 }
331
332 for (i = 0; i < keyidx; i++) {
333 apr_dbm_delete(dbm, keylist[i]);
334 }
335
336 apr_dbm_close(dbm);
337 apr_pool_destroy(spool);
338
263 return 0; 339 return 0;
264} 340}
265 341
@@ -275,6 +351,8 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key)
275 dbmkey.dptr = key.data; 351 dbmkey.dptr = key.data;
276 dbmkey.dsize = key.size; 352 dbmkey.dsize = key.size;
277 353
354 dbm_cache_expire(ctxt);
355
278 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 356 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
279 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); 357 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool);
280 if (rv != APR_SUCCESS) { 358 if (rv != APR_SUCCESS) {
@@ -286,7 +364,7 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key)
286 } 364 }
287 365
288 rv = apr_dbm_fetch(dbm, dbmkey, &dbmval); 366 rv = apr_dbm_fetch(dbm, dbmkey, &dbmval);
289 367
290 if (rv != APR_SUCCESS) { 368 if (rv != APR_SUCCESS) {
291 apr_dbm_close(dbm); 369 apr_dbm_close(dbm);
292 return data; 370 return data;
@@ -296,15 +374,17 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key)
296 apr_dbm_close(dbm); 374 apr_dbm_close(dbm);
297 return data; 375 return data;
298 } 376 }
299 377 apr_dbm_close(dbm);
300 data.data = gnutls_malloc(dbmval.dsize - sizeof(apr_time_t));
301 if (data.data == NULL)
302 return data;
303 378
304 data.size = dbmval.dsize - sizeof(apr_time_t); 379 data.size = dbmval.dsize - sizeof(apr_time_t);
380
381 data.data = gnutls_malloc(data.size);
382 if (data.data == NULL) {
383 return data;
384 }
385
305 memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size); 386 memcpy(data.data, dbmval.dptr+sizeof(apr_time_t), data.size);
306 387
307 apr_dbm_close(dbm);
308 return data; 388 return data;
309} 389}
310 390
@@ -316,18 +396,23 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key,
316 apr_datum_t dbmval; 396 apr_datum_t dbmval;
317 mod_gnutls_handle_t *ctxt = baton; 397 mod_gnutls_handle_t *ctxt = baton;
318 apr_status_t rv; 398 apr_status_t rv;
319 apr_time_t timeout; 399 apr_time_t expiry;
320 400
321 dbmkey.dptr = (char *)key.data; 401 dbmkey.dptr = (char *)key.data;
322 dbmkey.dsize = key.size; 402 dbmkey.dsize = key.size;
323 403
324 /* create DBM value */ 404 /* create DBM value */
325 dbmval.dsize = data.size; 405 dbmval.dsize = data.size + sizeof(apr_time_t);
326 dbmval.dptr = (char *)malloc(dbmval.dsize+sizeof(apr_time_t)); 406 dbmval.dptr = (char *)malloc(dbmval.dsize);
407
408 expiry = apr_time_now() + ctxt->sc->cache_timeout;
327 409
410 memcpy((char *)dbmval.dptr, &expiry, sizeof(apr_time_t));
328 memcpy((char *)dbmval.dptr+sizeof(apr_time_t), 411 memcpy((char *)dbmval.dptr+sizeof(apr_time_t),
329 data.data, data.size); 412 data.data, data.size);
330 413
414 dbm_cache_expire(ctxt);
415
331 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 416 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
332 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); 417 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool);
333 if (rv != APR_SUCCESS) { 418 if (rv != APR_SUCCESS) {
@@ -340,7 +425,7 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key,
340 } 425 }
341 426
342 rv = apr_dbm_store(dbm, dbmkey, dbmval); 427 rv = apr_dbm_store(dbm, dbmkey, dbmval);
343 428
344 if (rv != APR_SUCCESS) { 429 if (rv != APR_SUCCESS) {
345 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 430 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
346 ctxt->c->base_server, 431 ctxt->c->base_server,
@@ -368,6 +453,8 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key)
368 dbmkey.dptr = (char *)key.data; 453 dbmkey.dptr = (char *)key.data;
369 dbmkey.dsize = key.size; 454 dbmkey.dsize = key.size;
370 455
456 dbm_cache_expire(ctxt);
457
371 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 458 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
372 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); 459 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool);
373 if (rv != APR_SUCCESS) { 460 if (rv != APR_SUCCESS) {
@@ -383,7 +470,7 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key)
383 if (rv != APR_SUCCESS) { 470 if (rv != APR_SUCCESS) {
384 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv, 471 ap_log_error(APLOG_MARK, APLOG_NOTICE, rv,
385 ctxt->c->base_server, 472 ctxt->c->base_server,
386 "[gnutls_cache] error storing in cache '%s'", 473 "[gnutls_cache] error deleting from cache '%s'",
387 ctxt->sc->cache_config); 474 ctxt->sc->cache_config);
388 apr_dbm_close(dbm); 475 apr_dbm_close(dbm);
389 return -1; 476 return -1;
@@ -394,7 +481,7 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key)
394 return 0; 481 return 0;
395} 482}
396 483
397static int dbm_cache_child_init(apr_pool_t *p, server_rec *s, 484static int dbm_cache_post_config(apr_pool_t *p, server_rec *s,
398 mod_gnutls_srvconf_rec *sc) 485 mod_gnutls_srvconf_rec *sc)
399{ 486{
400 apr_status_t rv; 487 apr_status_t rv;
@@ -434,7 +521,7 @@ int mod_gnutls_cache_post_config(apr_pool_t *p, server_rec *s,
434 mod_gnutls_srvconf_rec *sc) 521 mod_gnutls_srvconf_rec *sc)
435{ 522{
436 if (sc->cache_type == mod_gnutls_cache_dbm) { 523 if (sc->cache_type == mod_gnutls_cache_dbm) {
437 return dbm_cache_child_init(p, s, sc); 524 return dbm_cache_post_config(p, s, sc);
438 } 525 }
439 return 0; 526 return 0;
440} 527}
@@ -457,7 +544,6 @@ int mod_gnutls_cache_child_init(apr_pool_t *p, server_rec *s,
457 544
458int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt) 545int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt)
459{ 546{
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) { 547 if (ctxt->sc->cache_type == mod_gnutls_cache_dbm) {
462 gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch); 548 gnutls_db_set_retrieve_function(ctxt->session, dbm_cache_fetch);
463 gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete); 549 gnutls_db_set_remove_function(ctxt->session, dbm_cache_delete);
@@ -472,9 +558,6 @@ int mod_gnutls_cache_session_init(mod_gnutls_handle_t *ctxt)
472 gnutls_db_set_ptr(ctxt->session, ctxt); 558 gnutls_db_set_ptr(ctxt->session, ctxt);
473 } 559 }
474#endif 560#endif
475 else { 561
476 assert(1);
477 /* No Session Cache is Available. Opps. */
478 }
479 return 0; 562 return 0;
480} 563}
diff --git a/src/gnutls_io.c b/src/gnutls_io.c
index a44ba9c..f761f96 100644
--- a/src/gnutls_io.c
+++ b/src/gnutls_io.c
@@ -271,6 +271,22 @@ static apr_status_t gnutls_io_input_read(mod_gnutls_handle_t * ctxt,
271 "GnuTLS: Error reading data. Client Requested a New Handshake." 271 "GnuTLS: Error reading data. Client Requested a New Handshake."
272 " (%d) '%s'", rc, gnutls_strerror(rc)); 272 " (%d) '%s'", rc, gnutls_strerror(rc));
273 } 273 }
274 else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) {
275 rc = gnutls_alert_get(ctxt->session);
276 ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc,
277 ctxt->c->base_server,
278 "GnuTLS: Warning Alert From Client: "
279 " (%d) '%s'", rc, gnutls_alert_get_name(rc));
280 }
281 else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) {
282 rc = gnutls_alert_get(ctxt->session);
283 ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc,
284 ctxt->c->base_server,
285 "GnuTLS: Fatal Alert From Client: "
286 "(%d) '%s'", rc, gnutls_alert_get_name(rc));
287 ctxt->input_rc = APR_EGENERAL;
288 break;
289 }
274 else { 290 else {
275 /* Some Other Error. Report it. Die. */ 291 /* Some Other Error. Report it. Die. */
276 if(gnutls_error_is_fatal(rc)) { 292 if(gnutls_error_is_fatal(rc)) {
@@ -341,7 +357,7 @@ static apr_status_t gnutls_io_input_getline(mod_gnutls_handle_t * ctxt,
341static void gnutls_do_handshake(mod_gnutls_handle_t * ctxt) 357static void gnutls_do_handshake(mod_gnutls_handle_t * ctxt)
342{ 358{
343 int ret; 359 int ret;
344 360 int errcode;
345 if (ctxt->status != 0) { 361 if (ctxt->status != 0) {
346 return; 362 return;
347 } 363 }
@@ -352,10 +368,10 @@ tryagain:
352 if (ret < 0) { 368 if (ret < 0) {
353 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED 369 if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED
354 || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { 370 || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
355 ret = gnutls_alert_get(ctxt->session); 371 errcode = gnutls_alert_get(ctxt->session);
356 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, 372 ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server,
357 "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, 373 "GnuTLS: Hanshake Alert (%d) '%s'.", errcode,
358 gnutls_alert_get_name(ret)); 374 gnutls_alert_get_name(errcode));
359 } 375 }
360 376
361 if (!gnutls_error_is_fatal(ret)) { 377 if (!gnutls_error_is_fatal(ret)) {
@@ -398,7 +414,26 @@ apr_status_t mod_gnutls_filter_input(ap_filter_t* f,
398 } 414 }
399 415
400 if (ctxt->status == 0) { 416 if (ctxt->status == 0) {
417 char* server_name;
418 int server_type;
419 int data_len = 256;
420
401 gnutls_do_handshake(ctxt); 421 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 }
402 } 437 }
403 438
404 if (ctxt->status < 0) { 439 if (ctxt->status < 0) {
@@ -449,6 +484,7 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f,
449 apr_bucket_brigade * bb) 484 apr_bucket_brigade * bb)
450{ 485{
451 apr_size_t ret; 486 apr_size_t ret;
487 apr_bucket* e;
452 mod_gnutls_handle_t *ctxt = (mod_gnutls_handle_t *) f->ctx; 488 mod_gnutls_handle_t *ctxt = (mod_gnutls_handle_t *) f->ctx;
453 apr_status_t status = APR_SUCCESS; 489 apr_status_t status = APR_SUCCESS;
454 apr_read_type_e rblock = APR_NONBLOCK_READ; 490 apr_read_type_e rblock = APR_NONBLOCK_READ;
@@ -469,21 +505,34 @@ apr_status_t mod_gnutls_filter_output(ap_filter_t * f,
469 while (!APR_BRIGADE_EMPTY(bb)) { 505 while (!APR_BRIGADE_EMPTY(bb)) {
470 apr_bucket *bucket = APR_BRIGADE_FIRST(bb); 506 apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
471 if (AP_BUCKET_IS_EOC(bucket)) { 507 if (AP_BUCKET_IS_EOC(bucket)) {
508 do {
509 ret = gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL,
510 GNUTLS_A_CLOSE_NOTIFY);
511 } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
512
513 apr_bucket_copy(bucket, &e);
514 APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e);
515
516 if ((status = ap_pass_brigade(f->next, ctxt->output_bb)) != APR_SUCCESS) {
517 apr_brigade_cleanup(ctxt->output_bb);
518 return status;
519 }
472 520
521 apr_brigade_cleanup(ctxt->output_bb);
473 gnutls_bye(ctxt->session, GNUTLS_SHUT_WR); 522 gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
474 gnutls_deinit(ctxt->session); 523 gnutls_deinit(ctxt->session);
475 524 continue;
476 if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
477 return status;
478 }
479 break;
480 525
481 } else if (APR_BUCKET_IS_FLUSH(bucket) || APR_BUCKET_IS_EOS(bucket)) { 526 } else if (APR_BUCKET_IS_FLUSH(bucket) || APR_BUCKET_IS_EOS(bucket)) {
482 527
528 apr_bucket_copy(bucket, &e);
529 APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, e);
483 if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) { 530 if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
531 apr_brigade_cleanup(ctxt->output_bb);
484 return status; 532 return status;
485 } 533 }
486 break; 534 apr_brigade_cleanup(ctxt->output_bb);
535 continue;
487 } 536 }
488 else { 537 else {
489 /* filter output */ 538 /* filter output */
@@ -628,9 +677,9 @@ static ssize_t write_flush(mod_gnutls_handle_t * ctxt)
628 677
629 ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next, 678 ctxt->output_rc = ap_pass_brigade(ctxt->output_filter->next,
630 ctxt->output_bb); 679 ctxt->output_bb);
631 /* create new brigade ready for next time through */ 680 /* clear the brigade to be ready for next time */
632 ctxt->output_bb = 681 apr_brigade_cleanup(ctxt->output_bb);
633 apr_brigade_create(ctxt->c->pool, ctxt->c->bucket_alloc); 682
634 return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1; 683 return (ctxt->output_rc == APR_SUCCESS) ? 1 : -1;
635} 684}
636 685
@@ -639,19 +688,17 @@ ssize_t mod_gnutls_transport_write(gnutls_transport_ptr_t ptr,
639{ 688{
640 mod_gnutls_handle_t *ctxt = ptr; 689 mod_gnutls_handle_t *ctxt = ptr;
641 690
642 /* pass along the encrypted data 691 /* pass along the encrypted data
643 * need to flush since we're using SSL's malloc-ed buffer 692 * need to flush since we're using SSL's malloc-ed buffer
644 * which will be overwritten once we leave here 693 * which will be overwritten once we leave here
645 */ 694 */
646 apr_bucket *bucket = apr_bucket_transient_create(buffer, len, 695 apr_bucket *bucket = apr_bucket_transient_create(buffer, len,
647 ctxt->output_bb-> 696 ctxt->output_bb->bucket_alloc);
648 bucket_alloc); 697 ctxt->output_length += len;
649 698 APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket);
650 ctxt->output_length += len;
651 APR_BRIGADE_INSERT_TAIL(ctxt->output_bb, bucket);
652 699
653 if (write_flush(ctxt) < 0) { 700 if (write_flush(ctxt) < 0) {
654 return -1; 701 return -1;
655 } 702 }
656 return len; 703 return len;
657} 704}
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index edf7068..b803ce7 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -189,6 +189,7 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
189 sc->cache_config = sc_base->cache_config; 189 sc->cache_config = sc_base->cache_config;
190 190
191 if (sc->cert_file != NULL && sc->key_file != NULL) { 191 if (sc->cert_file != NULL && sc->key_file != NULL) {
192
192 rv = gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, 193 rv = gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file,
193 sc->key_file, 194 sc->key_file,
194 GNUTLS_X509_FMT_PEM); 195 GNUTLS_X509_FMT_PEM);
@@ -214,7 +215,7 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
214 } 215 }
215 } /* first_run */ 216 } /* first_run */
216 217
217 ap_add_version_component(p, "GnuTLS/" LIBGNUTLS_VERSION); 218 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION);
218 219
219 return OK; 220 return OK;
220} 221}
@@ -266,6 +267,30 @@ static apr_port_t mod_gnutls_hook_default_port(const request_rec * r)
266 return 443; 267 return 443;
267} 268}
268 269
270/* TODO: Complete support for Server Name Indication */
271static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret)
272{
273 char* server_name;
274 int server_type;
275 int data_len = 256;
276 mod_gnutls_handle_t *ctxt;
277 ctxt = gnutls_transport_get_ptr(session);
278
279 ret->type = GNUTLS_CRT_X509;
280 ret->ncerts = 1;
281 server_name = apr_palloc(ctxt->c->pool, data_len);
282 if (gnutls_server_name_get(ctxt->session, server_name, &data_len, &server_type, 0) == 0) {
283 if (server_type == GNUTLS_NAME_DNS) {
284 ap_log_error(APLOG_MARK, APLOG_INFO, 0,
285 ctxt->c->base_server,
286 "GnuTLS: Virtual Host: "
287 "%s", server_name);
288 }
289 }
290
291 return 0;
292}
293
269static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c) 294static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c)
270{ 295{
271 mod_gnutls_handle_t *ctxt; 296 mod_gnutls_handle_t *ctxt;
@@ -299,13 +324,12 @@ static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c)
299 324
300 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); 325 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs);
301 326
302// if(anon) {
303// gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred);
304// }
305
306 gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); 327 gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE);
307 328
308 mod_gnutls_cache_session_init(ctxt); 329 mod_gnutls_cache_session_init(ctxt);
330
331 /* TODO: Finish Support for Server Name Indication */
332 /* gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn); */
309 return ctxt; 333 return ctxt;
310} 334}
311 335
@@ -341,7 +365,10 @@ static int mod_gnutls_hook_pre_connection(conn_rec * c, void *csd)
341 365
342static int mod_gnutls_hook_fixups(request_rec *r) 366static int mod_gnutls_hook_fixups(request_rec *r)
343{ 367{
368 unsigned char sbuf[GNUTLS_MAX_SESSION_ID];
369 char buf[GNUTLS_SESSION_ID_STRING_LEN];
344 const char* tmp; 370 const char* tmp;
371 int len;
345 mod_gnutls_handle_t *ctxt; 372 mod_gnutls_handle_t *ctxt;
346 apr_table_t *env = r->subprocess_env; 373 apr_table_t *env = r->subprocess_env;
347 374
@@ -352,17 +379,30 @@ static int mod_gnutls_hook_fixups(request_rec *r)
352 } 379 }
353 380
354 apr_table_setn(env, "HTTPS", "on"); 381 apr_table_setn(env, "HTTPS", "on");
382
383 apr_table_setn(env, "GNUTLS_VERSION_INTERFACE", MOD_GNUTLS_VERSION);
384 apr_table_setn(env, "GNUTLS_VERSION_LIBRARY", LIBGNUTLS_VERSION);
385
355 apr_table_setn(env, "SSL_PROTOCOL", 386 apr_table_setn(env, "SSL_PROTOCOL",
356 gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session))); 387 gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session)));
388
357 apr_table_setn(env, "SSL_CIPHER", 389 apr_table_setn(env, "SSL_CIPHER",
358 gnutls_cipher_get_name(gnutls_cipher_get(ctxt->session))); 390 gnutls_cipher_get_name(gnutls_cipher_get(ctxt->session)));
359 391
392 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE");
393
360 tmp = apr_psprintf(r->pool, "%d", 394 tmp = apr_psprintf(r->pool, "%d",
361 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session))); 395 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)));
362 396
363 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); 397 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp);
398
364 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); 399 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp);
365 400
401 len = sizeof(sbuf);
402 gnutls_session_get_id(ctxt->session, sbuf, &len);
403 tmp = mod_gnutls_session_id2sz(sbuf, len, buf, sizeof(buf));
404 apr_table_setn(env, "SSL_SESSION_ID", tmp);
405
366 return OK; 406 return OK;
367} 407}
368 408
@@ -384,6 +424,7 @@ static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy,
384 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> 424 (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server->
385 module_config, 425 module_config,
386 &gnutls_module); 426 &gnutls_module);
427
387 sc->key_file = ap_server_root_relative(parms->pool, arg); 428 sc->key_file = ap_server_root_relative(parms->pool, arg);
388 return NULL; 429 return NULL;
389} 430}
@@ -508,7 +549,6 @@ static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s)
508 sc->enabled = GNUTLS_ENABLED_FALSE; 549 sc->enabled = GNUTLS_ENABLED_FALSE;
509 550
510 gnutls_certificate_allocate_credentials(&sc->certs); 551 gnutls_certificate_allocate_credentials(&sc->certs);
511 gnutls_anon_allocate_server_credentials(&sc->anoncred);
512 sc->key_file = NULL; 552 sc->key_file = NULL;
513 sc->cert_file = NULL; 553 sc->cert_file = NULL;
514 sc->cache_timeout = apr_time_from_sec(3600); 554 sc->cache_timeout = apr_time_from_sec(3600);