aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nokis Mavrogiannopoulos 2008-02-20 18:50:41 +0000
committerGravatar Nokis Mavrogiannopoulos 2008-02-20 18:50:41 +0000
commit586e3bef5d34d090d9480e146783c33313f9dc34 (patch)
tree928d7bc1a0141b95828e62e29aacf4aebab338c8 /src
parent8e33f2d4c149fe8b6d2f1f3bdb06c52da53952f1 (diff)
added tags0.4.1
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am3
-rw-r--r--src/gnutls_cache.c97
-rw-r--r--src/gnutls_config.c603
-rw-r--r--src/gnutls_hooks.c1248
-rw-r--r--src/gnutls_io.c7
-rw-r--r--src/mod_gnutls.c56
6 files changed, 1378 insertions, 636 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 59c8909..93b217d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,7 @@
1CLEANFILES = .libs/libmod_gnutls *~ 1CLEANFILES = .libs/libmod_gnutls *~
2 2
3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c gnutls_lua.c 3libmod_gnutls_la_SOURCES = mod_gnutls.c gnutls_io.c gnutls_cache.c gnutls_config.c gnutls_hooks.c
4#gnutls_lua.c
4libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} ${LUA_CFLAGS} 5libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} ${LUA_CFLAGS}
5libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} ${LUA_LIBS} 6libmod_gnutls_la_LDFLAGS = -rpath ${AP_LIBEXECDIR} -module -avoid-version ${MODULE_LIBS} ${LUA_LIBS}
6 7
diff --git a/src/gnutls_cache.c b/src/gnutls_cache.c
index 4c094fa..83e7bb5 100644
--- a/src/gnutls_cache.c
+++ b/src/gnutls_cache.c
@@ -34,17 +34,16 @@
34 34
35 35
36#define MC_TAG "mod_gnutls:" 36#define MC_TAG "mod_gnutls:"
37#define MC_TAG_LEN \ 37#define MC_TAG_LEN sizeof(MC_TAG)
38 (sizeof(MC_TAG))
39#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN) 38#define STR_SESSION_LEN (GNUTLS_SESSION_ID_STRING_LEN + MC_TAG_LEN)
40 39
41static char *gnutls_session_id2sz(unsigned char *id, int idlen, 40char *mgs_session_id2sz(unsigned char *id, int idlen,
42 char *str, int strsize) 41 char *str, int strsize)
43{ 42{
44 char *cp; 43 char *cp;
45 int n; 44 int n;
46 45
47 cp = apr_cpystrn(str, MC_TAG, MC_TAG_LEN); 46 cp = str;
48 for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { 47 for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) {
49 apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); 48 apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]);
50 cp += 2; 49 cp += 2;
@@ -53,23 +52,58 @@ static char *gnutls_session_id2sz(unsigned char *id, int idlen,
53 return str; 52 return str;
54} 53}
55 54
56char *mgs_session_id2sz(unsigned char *id, int idlen, 55
57 char *str, int strsize) 56/* Name the Session ID as:
57 * server:port.SessionID
58 * to disallow resuming sessions on different servers
59 */
60static int mgs_session_id2dbm(conn_rec* c, unsigned char *id, int idlen,
61 apr_datum_t* dbmkey)
58{ 62{
59 char *cp; 63char buf[STR_SESSION_LEN];
60 int n; 64char *sz;
61 65
62 cp = str; 66 sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf));
63 for (n = 0; n < idlen && n < GNUTLS_MAX_SESSION_ID; n++) { 67 if (sz == NULL)
64 apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]); 68 return -1;
65 cp += 2; 69
66 } 70 dbmkey->dptr = apr_psprintf(c->pool, "%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz);
67 *cp = '\0'; 71 dbmkey->dsize = strlen( dbmkey->dptr);
68 return str; 72
73 return 0;
69} 74}
70 75
76#define CTIME "%b %d %k:%M:%S %Y %Z"
77char *mgs_time2sz(time_t in_time, char *str, int strsize)
78{
79 apr_time_exp_t vtm;
80 apr_size_t ret_size;
81 apr_time_t t;
82
83
84 apr_time_ansi_put (&t, in_time);
85 apr_time_exp_gmt (&vtm, t);
86 apr_strftime(str, &ret_size, strsize-1, CTIME, &vtm);
87
88 return str;
89}
71 90
72#if HAVE_APR_MEMCACHE 91#if HAVE_APR_MEMCACHE
92/* Name the Session ID as:
93 * server:port.SessionID
94 * to disallow resuming sessions on different servers
95 */
96static char* mgs_session_id2mc(conn_rec* c, unsigned char *id, int idlen)
97{
98char buf[STR_SESSION_LEN];
99char *sz;
100
101 sz = mgs_session_id2sz(id, idlen, buf, sizeof(buf));
102 if (sz == NULL)
103 return NULL;
104
105 return apr_psprintf(c->pool, MC_TAG"%s:%d.%s", c->base_server->server_hostname, c->base_server->port, sz);
106}
73 107
74/** 108/**
75 * GnuTLS Session Cache using libmemcached 109 * GnuTLS Session Cache using libmemcached
@@ -167,11 +201,10 @@ static int mc_cache_store(void* baton, gnutls_datum_t key,
167{ 201{
168 apr_status_t rv = APR_SUCCESS; 202 apr_status_t rv = APR_SUCCESS;
169 mgs_handle_t *ctxt = baton; 203 mgs_handle_t *ctxt = baton;
170 char buf[STR_SESSION_LEN];
171 char* strkey = NULL; 204 char* strkey = NULL;
172 apr_uint32_t timeout; 205 apr_uint32_t timeout;
173 206
174 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 207 strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
175 if(!strkey) 208 if(!strkey)
176 return -1; 209 return -1;
177 210
@@ -194,13 +227,12 @@ static gnutls_datum_t mc_cache_fetch(void* baton, gnutls_datum_t key)
194{ 227{
195 apr_status_t rv = APR_SUCCESS; 228 apr_status_t rv = APR_SUCCESS;
196 mgs_handle_t *ctxt = baton; 229 mgs_handle_t *ctxt = baton;
197 char buf[STR_SESSION_LEN];
198 char* strkey = NULL; 230 char* strkey = NULL;
199 char* value; 231 char* value;
200 apr_size_t value_len; 232 apr_size_t value_len;
201 gnutls_datum_t data = { NULL, 0 }; 233 gnutls_datum_t data = { NULL, 0 };
202 234
203 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 235 strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
204 if (!strkey) { 236 if (!strkey) {
205 return data; 237 return data;
206 } 238 }
@@ -235,10 +267,9 @@ static int mc_cache_delete(void* baton, gnutls_datum_t key)
235{ 267{
236 apr_status_t rv = APR_SUCCESS; 268 apr_status_t rv = APR_SUCCESS;
237 mgs_handle_t *ctxt = baton; 269 mgs_handle_t *ctxt = baton;
238 char buf[STR_SESSION_LEN];
239 char* strkey = NULL; 270 char* strkey = NULL;
240 271
241 strkey = gnutls_session_id2sz(key.data, key.size, buf, sizeof(buf)); 272 strkey = mgs_session_id2mc(ctxt->c, key.data, key.size);
242 if(!strkey) 273 if(!strkey)
243 return -1; 274 return -1;
244 275
@@ -349,10 +380,8 @@ static gnutls_datum_t dbm_cache_fetch(void* baton, gnutls_datum_t key)
349 mgs_handle_t *ctxt = baton; 380 mgs_handle_t *ctxt = baton;
350 apr_status_t rv; 381 apr_status_t rv;
351 382
352 dbmkey.dptr = key.data; 383 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
353 dbmkey.dsize = key.size; 384 return data;
354
355 dbm_cache_expire(ctxt);
356 385
357 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 386 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
358 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); 387 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool);
@@ -398,9 +427,9 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key,
398 mgs_handle_t *ctxt = baton; 427 mgs_handle_t *ctxt = baton;
399 apr_status_t rv; 428 apr_status_t rv;
400 apr_time_t expiry; 429 apr_time_t expiry;
401 430
402 dbmkey.dptr = (char *)key.data; 431 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
403 dbmkey.dsize = key.size; 432 return -1;
404 433
405 /* create DBM value */ 434 /* create DBM value */
406 dbmval.dsize = data.size + sizeof(apr_time_t); 435 dbmval.dsize = data.size + sizeof(apr_time_t);
@@ -412,6 +441,8 @@ static int dbm_cache_store(void* baton, gnutls_datum_t key,
412 memcpy((char *)dbmval.dptr+sizeof(apr_time_t), 441 memcpy((char *)dbmval.dptr+sizeof(apr_time_t),
413 data.data, data.size); 442 data.data, data.size);
414 443
444 /* we expire dbm only on every store
445 */
415 dbm_cache_expire(ctxt); 446 dbm_cache_expire(ctxt);
416 447
417 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 448 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
@@ -450,12 +481,10 @@ static int dbm_cache_delete(void* baton, gnutls_datum_t key)
450 apr_datum_t dbmkey; 481 apr_datum_t dbmkey;
451 mgs_handle_t *ctxt = baton; 482 mgs_handle_t *ctxt = baton;
452 apr_status_t rv; 483 apr_status_t rv;
453
454 dbmkey.dptr = (char *)key.data;
455 dbmkey.dsize = key.size;
456 484
457 dbm_cache_expire(ctxt); 485 if (mgs_session_id2dbm(ctxt->c, key.data, key.size, &dbmkey) < 0)
458 486 return -1;
487
459 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config, 488 rv = apr_dbm_open(&dbm, ctxt->sc->cache_config,
460 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool); 489 APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctxt->c->pool);
461 if (rv != APR_SUCCESS) { 490 if (rv != APR_SUCCESS) {
diff --git a/src/gnutls_config.c b/src/gnutls_config.c
index d3879f1..f08512e 100644
--- a/src/gnutls_config.c
+++ b/src/gnutls_config.c
@@ -1,5 +1,6 @@
1/** 1/**
2 * Copyright 2004-2005 Paul Querna 2 * Copyright 2004-2005 Paul Querna
3 * Copyright 2007 Nikos Mavrogiannopoulos
3 * 4 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 6 * you may not use this file except in compliance with the License.
@@ -17,225 +18,449 @@
17 18
18#include "mod_gnutls.h" 19#include "mod_gnutls.h"
19 20
20static int load_datum_from_file(apr_pool_t* pool, 21static int load_datum_from_file(apr_pool_t * pool,
21 const char* file, 22 const char *file, gnutls_datum_t * data)
22 gnutls_datum_t* data)
23{ 23{
24 apr_file_t* fp; 24 apr_file_t *fp;
25 apr_finfo_t finfo; 25 apr_finfo_t finfo;
26 apr_status_t rv; 26 apr_status_t rv;
27 apr_size_t br = 0; 27 apr_size_t br = 0;
28 28
29 rv = apr_file_open(&fp, file, APR_READ|APR_BINARY, APR_OS_DEFAULT, 29 rv = apr_file_open(&fp, file, APR_READ | APR_BINARY, APR_OS_DEFAULT,
30 pool); 30 pool);
31 if (rv != APR_SUCCESS) { 31 if (rv != APR_SUCCESS) {
32 return rv; 32 return rv;
33 } 33 }
34 34
35 rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); 35 rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp);
36 36
37 if (rv != APR_SUCCESS) { 37 if (rv != APR_SUCCESS) {
38 return rv; 38 return rv;
39 } 39 }
40 40
41 data->data = apr_palloc(pool, finfo.size+1); 41 data->data = apr_palloc(pool, finfo.size + 1);
42 rv = apr_file_read_full(fp, data->data, finfo.size, &br); 42 rv = apr_file_read_full(fp, data->data, finfo.size, &br);
43 43
44 if (rv != APR_SUCCESS) { 44 if (rv != APR_SUCCESS) {
45 return rv; 45 return rv;
46 } 46 }
47 apr_file_close(fp); 47 apr_file_close(fp);
48 48
49 data->data[br] = '\0'; 49 data->data[br] = '\0';
50 data->size = br; 50 data->size = br;
51 51
52 return 0; 52 return 0;
53} 53}
54 54
55const char *mgs_set_cert_file(cmd_parms * parms, void *dummy, 55const char *mgs_set_dh_file(cmd_parms * parms, void *dummy,
56 const char *arg) 56 const char *arg)
57{ 57{
58 int ret; 58 int ret;
59 gnutls_datum_t data; 59 gnutls_datum_t data;
60 const char* file; 60 const char *file;
61 apr_pool_t* spool; 61 apr_pool_t *spool;
62 mgs_srvconf_rec *sc = 62 mgs_srvconf_rec *sc =
63 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 63 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
64 module_config, 64 module_config,
65 &gnutls_module); 65 &gnutls_module);
66
66 apr_pool_create(&spool, parms->pool); 67 apr_pool_create(&spool, parms->pool);
67 68
68 file = ap_server_root_relative(spool, arg); 69 file = ap_server_root_relative(spool, arg);
69 70
70 if (load_datum_from_file(spool, file, &data) != 0) { 71 if (load_datum_from_file(spool, file, &data) != 0) {
71 return apr_psprintf(parms->pool, "GnuTLS: Error Reading " 72 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
72 "Certificate '%s'", file); 73 "DH params '%s'", file);
73 } 74 }
74 75
75 gnutls_x509_crt_init(&sc->cert_x509); 76 ret = gnutls_dh_params_init(&sc->dh_params);
76 ret = gnutls_x509_crt_import(sc->cert_x509, &data, GNUTLS_X509_FMT_PEM); 77 if (ret < 0) {
78 return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
79 ": (%d) %s", ret, gnutls_strerror(ret));
80 }
81
82 ret =
83 gnutls_dh_params_import_pkcs3(sc->dh_params, &data, GNUTLS_X509_FMT_PEM);
84 if (ret < 0) {
85 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
86 "DH params '%s': (%d) %s", file, ret,
87 gnutls_strerror(ret));
88 }
89
90 apr_pool_destroy(spool);
91
92 return NULL;
93}
94
95const char *mgs_set_rsa_export_file(cmd_parms * parms, void *dummy,
96 const char *arg)
97{
98 int ret;
99 gnutls_datum_t data;
100 const char *file;
101 apr_pool_t *spool;
102 mgs_srvconf_rec *sc =
103 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
104 module_config,
105 &gnutls_module);
106
107 apr_pool_create(&spool, parms->pool);
108
109 file = ap_server_root_relative(spool, arg);
110
111 if (load_datum_from_file(spool, file, &data) != 0) {
112 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
113 "RSA params '%s'", file);
114 }
115
116 ret = gnutls_rsa_params_init(&sc->rsa_params);
117 if (ret < 0) {
118 return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
119 ": (%d) %s", ret, gnutls_strerror(ret));
120 }
121
122 ret =
123 gnutls_rsa_params_import_pkcs1(sc->rsa_params, &data, GNUTLS_X509_FMT_PEM);
77 if (ret != 0) { 124 if (ret != 0) {
78 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " 125 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
79 "Certificate'%s': (%d) %s", file, ret, 126 "RSA params '%s': (%d) %s", file, ret,
80 gnutls_strerror(ret)); 127 gnutls_strerror(ret));
81 } 128 }
82 129
130 apr_pool_destroy(spool);
131 return NULL;
132}
133
134
135const char *mgs_set_cert_file(cmd_parms * parms, void *dummy,
136 const char *arg)
137{
138 int ret;
139 gnutls_datum_t data;
140 const char *file;
141 apr_pool_t *spool;
142 mgs_srvconf_rec *sc =
143 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
144 module_config,
145 &gnutls_module);
146 apr_pool_create(&spool, parms->pool);
147
148 file = ap_server_root_relative(spool, arg);
149
150 if (load_datum_from_file(spool, file, &data) != 0) {
151 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
152 "Certificate '%s'", file);
153 }
154
155 sc->certs_x509_num = MAX_CHAIN_SIZE;
156 ret =
157 gnutls_x509_crt_list_import(sc->certs_x509, &sc->certs_x509_num, &data, GNUTLS_X509_FMT_PEM, 0);
158 if (ret < 0) {
159 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
160 "Certificate '%s': (%d) %s", file, ret,
161 gnutls_strerror(ret));
162 }
163
83 apr_pool_destroy(spool); 164 apr_pool_destroy(spool);
84 return NULL; 165 return NULL;
85} 166}
86 167
87const char *mgs_set_key_file(cmd_parms * parms, void *dummy, 168const char *mgs_set_key_file(cmd_parms * parms, void *dummy,
88 const char *arg) 169 const char *arg)
89{ 170{
90 int ret; 171 int ret;
91 gnutls_datum_t data; 172 gnutls_datum_t data;
92 const char* file; 173 const char *file;
93 apr_pool_t* spool; 174 apr_pool_t *spool;
94 mgs_srvconf_rec *sc = 175 mgs_srvconf_rec *sc =
95 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 176 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
96 module_config, 177 module_config,
97 &gnutls_module); 178 &gnutls_module);
98 apr_pool_create(&spool, parms->pool); 179 apr_pool_create(&spool, parms->pool);
99 180
100 file = ap_server_root_relative(spool, arg); 181 file = ap_server_root_relative(spool, arg);
101 182
102 if (load_datum_from_file(spool, file, &data) != 0) { 183 if (load_datum_from_file(spool, file, &data) != 0) {
103 return apr_psprintf(parms->pool, "GnuTLS: Error Reading " 184 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
104 "Private Key '%s'", file); 185 "Private Key '%s'", file);
105 } 186 }
106 187
107 gnutls_x509_privkey_init(&sc->privkey_x509); 188 ret = gnutls_x509_privkey_init(&sc->privkey_x509);
108 ret = gnutls_x509_privkey_import(sc->privkey_x509, &data, GNUTLS_X509_FMT_PEM); 189 if (ret < 0) {
190 return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
191 ": (%d) %s", ret, gnutls_strerror(ret));
192 }
193
194 ret =
195 gnutls_x509_privkey_import(sc->privkey_x509, &data,
196 GNUTLS_X509_FMT_PEM);
109 if (ret != 0) { 197 if (ret != 0) {
110 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import " 198 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
111 "Private Key '%s': (%d) %s", file, ret, 199 "Private Key '%s': (%d) %s", file, ret,
112 gnutls_strerror(ret)); 200 gnutls_strerror(ret));
113 } 201 }
114 apr_pool_destroy(spool); 202 apr_pool_destroy(spool);
115 return NULL; 203 return NULL;
116} 204}
117 205
206const char *mgs_set_pgpcert_file(cmd_parms * parms, void *dummy,
207 const char *arg)
208{
209 int ret;
210 gnutls_datum_t data;
211 const char *file;
212 apr_pool_t *spool;
213 mgs_srvconf_rec *sc =
214 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
215 module_config,
216 &gnutls_module);
217 apr_pool_create(&spool, parms->pool);
218
219 file = ap_server_root_relative(spool, arg);
220
221 if (load_datum_from_file(spool, file, &data) != 0) {
222 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
223 "Certificate '%s'", file);
224 }
225
226 ret = gnutls_openpgp_crt_init( &sc->cert_pgp);
227 if (ret < 0) {
228 return apr_psprintf(parms->pool, "GnuTLS: Failed to Init "
229 "PGP Certificate: (%d) %s", ret,
230 gnutls_strerror(ret));
231 }
232
233 ret =
234 gnutls_openpgp_crt_import(sc->cert_pgp, &data, GNUTLS_OPENPGP_FMT_BASE64);
235 if (ret < 0) {
236 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
237 "PGP Certificate '%s': (%d) %s", file, ret,
238 gnutls_strerror(ret));
239 }
240
241 apr_pool_destroy(spool);
242 return NULL;
243}
244
245const char *mgs_set_pgpkey_file(cmd_parms * parms, void *dummy,
246 const char *arg)
247{
248 int ret;
249 gnutls_datum_t data;
250 const char *file;
251 apr_pool_t *spool;
252 mgs_srvconf_rec *sc =
253 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
254 module_config,
255 &gnutls_module);
256 apr_pool_create(&spool, parms->pool);
257
258 file = ap_server_root_relative(spool, arg);
259
260 if (load_datum_from_file(spool, file, &data) != 0) {
261 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
262 "Private Key '%s'", file);
263 }
264
265 ret = gnutls_openpgp_privkey_init(&sc->privkey_pgp);
266 if (ret < 0) {
267 return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
268 ": (%d) %s", ret, gnutls_strerror(ret));
269 }
270
271 ret =
272 gnutls_openpgp_privkey_import(sc->privkey_pgp, &data,
273 GNUTLS_OPENPGP_FMT_BASE64, NULL, 0);
274 if (ret != 0) {
275 return apr_psprintf(parms->pool, "GnuTLS: Failed to Import "
276 "PGP Private Key '%s': (%d) %s", file, ret,
277 gnutls_strerror(ret));
278 }
279 apr_pool_destroy(spool);
280 return NULL;
281}
282
283
284const char *mgs_set_srp_tpasswd_file(cmd_parms * parms, void *dummy,
285 const char *arg)
286{
287 mgs_srvconf_rec *sc =
288 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
289 module_config,
290 &gnutls_module);
291
292 sc->srp_tpasswd_file = ap_server_root_relative(parms->pool, arg);
293
294 return NULL;
295}
296
297const char *mgs_set_srp_tpasswd_conf_file(cmd_parms * parms, void *dummy,
298 const char *arg)
299{
300 mgs_srvconf_rec *sc =
301 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
302 module_config,
303 &gnutls_module);
304
305 sc->srp_tpasswd_conf_file = ap_server_root_relative(parms->pool, arg);
306
307 return NULL;
308}
309
118const char *mgs_set_cache(cmd_parms * parms, void *dummy, 310const char *mgs_set_cache(cmd_parms * parms, void *dummy,
119 const char *type, const char* arg) 311 const char *type, const char *arg)
120{ 312{
121 const char* err; 313 const char *err;
122 mgs_srvconf_rec *sc = ap_get_module_config(parms->server-> 314 mgs_srvconf_rec *sc = ap_get_module_config(parms->server->
123 module_config, 315 module_config,
124 &gnutls_module); 316 &gnutls_module);
125 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) { 317 if ((err = ap_check_cmd_context(parms, GLOBAL_ONLY))) {
126 return err; 318 return err;
127 } 319 }
128 320
129 if (strcasecmp("none", type) == 0) { 321 if (strcasecmp("none", type) == 0) {
130 sc->cache_type = mgs_cache_none; 322 sc->cache_type = mgs_cache_none;
131 } 323 } else if (strcasecmp("dbm", type) == 0) {
132 else if (strcasecmp("dbm", type) == 0) { 324 sc->cache_type = mgs_cache_dbm;
133 sc->cache_type = mgs_cache_dbm;
134 } 325 }
135#if HAVE_APR_MEMCACHE 326#if HAVE_APR_MEMCACHE
136 else if (strcasecmp("memcache", type) == 0) { 327 else if (strcasecmp("memcache", type) == 0) {
137 sc->cache_type = mgs_cache_memcache; 328 sc->cache_type = mgs_cache_memcache;
138 } 329 }
139#endif 330#endif
140 else { 331 else {
141 return "Invalid Type for GnuTLSCache!"; 332 return "Invalid Type for GnuTLSCache!";
142 } 333 }
143 334
144 if (sc->cache_type == mgs_cache_dbm) { 335 if (sc->cache_type == mgs_cache_dbm) {
145 sc->cache_config = ap_server_root_relative(parms->pool, arg); 336 sc->cache_config = ap_server_root_relative(parms->pool, arg);
146 } 337 } else {
147 else { 338 sc->cache_config = apr_pstrdup(parms->pool, arg);
148 sc->cache_config = apr_pstrdup(parms->pool, arg);
149 } 339 }
150 340
151 return NULL; 341 return NULL;
152} 342}
153 343
154const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy, 344const char *mgs_set_cache_timeout(cmd_parms * parms, void *dummy,
155 const char *arg) 345 const char *arg)
156{ 346{
157 int argint; 347 int argint;
158 mgs_srvconf_rec *sc = 348 mgs_srvconf_rec *sc =
159 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 349 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
160 module_config, 350 module_config,
161 &gnutls_module); 351 &gnutls_module);
162 352
163 argint = atoi(arg); 353 argint = atoi(arg);
164 354
165 if (argint < 0) { 355 if (argint < 0) {
166 return "GnuTLSCacheTimeout: Invalid argument"; 356 return "GnuTLSCacheTimeout: Invalid argument";
167 } 357 } else if (argint == 0) {
168 else if (argint == 0) { 358 sc->cache_timeout = 0;
169 sc->cache_timeout = 0; 359 } else {
360 sc->cache_timeout = apr_time_from_sec(argint);
170 } 361 }
171 else { 362
172 sc->cache_timeout = apr_time_from_sec(argint);
173 }
174
175 return NULL; 363 return NULL;
176} 364}
177 365
178const char *mgs_set_client_verify(cmd_parms * parms, void *dummy, 366const char *mgs_set_client_verify(cmd_parms * parms, void *dummy,
179 const char *arg) 367 const char *arg)
180{ 368{
181 int mode; 369 int mode;
182 370
183 if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { 371 if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) {
184 mode = GNUTLS_CERT_IGNORE; 372 mode = GNUTLS_CERT_IGNORE;
185 } 373 } else if (strcasecmp("optional", arg) == 0
186 else if (strcasecmp("optional", arg) == 0 || strcasecmp("request", arg) == 0) { 374 || strcasecmp("request", arg) == 0) {
187 mode = GNUTLS_CERT_REQUEST; 375 mode = GNUTLS_CERT_REQUEST;
188 } 376 } else if (strcasecmp("require", arg) == 0) {
189 else if (strcasecmp("require", arg) == 0) { 377 mode = GNUTLS_CERT_REQUIRE;
190 mode = GNUTLS_CERT_REQUIRE; 378 } else {
191 } 379 return "GnuTLSClientVerify: Invalid argument";
192 else {
193 return "GnuTLSClientVerify: Invalid argument";
194 } 380 }
195 381
196 /* This was set from a directory context */ 382 /* This was set from a directory context */
197 if (parms->path) { 383 if (parms->path) {
198 mgs_dirconf_rec *dc = (mgs_dirconf_rec *)dummy; 384 mgs_dirconf_rec *dc = (mgs_dirconf_rec *) dummy;
199 dc->client_verify_mode = mode; 385 dc->client_verify_mode = mode;
200 } 386 } else {
201 else { 387 mgs_srvconf_rec *sc =
202 mgs_srvconf_rec *sc = 388 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
203 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 389 module_config,
204 module_config, 390 &gnutls_module);
205 &gnutls_module); 391 sc->client_verify_mode = mode;
206 sc->client_verify_mode = mode;
207 } 392 }
208 393
209 return NULL; 394 return NULL;
210} 395}
211 396
212const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy, 397const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
213 const char *arg) 398 const char *arg)
214{ 399{
215 int rv; 400 int rv;
216 const char* file; 401 const char *file;
217 apr_pool_t* spool; 402 apr_pool_t *spool;
218 gnutls_datum_t data; 403 gnutls_datum_t data;
219 404
220 mgs_srvconf_rec *sc = 405 mgs_srvconf_rec *sc =
221 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 406 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
222 module_config, 407 module_config,
223 &gnutls_module); 408 &gnutls_module);
224 apr_pool_create(&spool, parms->pool); 409 apr_pool_create(&spool, parms->pool);
225 410
226 file = ap_server_root_relative(spool, arg); 411 file = ap_server_root_relative(spool, arg);
227 412
228 sc->ca_list_size = 16; 413 if (load_datum_from_file(spool, file, &data) != 0) {
414 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
415 "Client CA File '%s'", file);
416 }
417
418 sc->ca_list_size = MAX_CA_CRTS;
419 rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
420 &data, GNUTLS_X509_FMT_PEM,
421 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
422 if (rv < 0) {
423 return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
424 "Client CA File '%s': (%d) %s", file, rv,
425 gnutls_strerror(rv));
426 }
229 427
230 load_datum_from_file(spool, file, &data); 428 apr_pool_destroy(spool);
429 return NULL;
430}
231 431
232 rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size, 432const char *mgs_set_keyring_file(cmd_parms * parms, void *dummy,
233 &data, GNUTLS_X509_FMT_PEM, 433 const char *arg)
234 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED); 434{
435 int rv;
436 const char *file;
437 apr_pool_t *spool;
438 gnutls_datum_t data;
439
440 mgs_srvconf_rec *sc =
441 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
442 module_config,
443 &gnutls_module);
444 apr_pool_create(&spool, parms->pool);
445
446 file = ap_server_root_relative(spool, arg);
447
448 if (load_datum_from_file(spool, file, &data) != 0) {
449 return apr_psprintf(parms->pool, "GnuTLS: Error Reading "
450 "Keyring File '%s'", file);
451 }
452
453 rv = gnutls_openpgp_keyring_init(&sc->pgp_list);
235 if (rv < 0) { 454 if (rv < 0) {
236 return apr_psprintf(parms->pool, "GnuTLS: Failed to load " 455 return apr_psprintf(parms->pool, "GnuTLS: Failed to initialize"
237 "Client CA File '%s': (%d) %s", file, rv, 456 "keyring: (%d) %s", rv, gnutls_strerror(rv));
238 gnutls_strerror(rv)); 457 }
458
459 rv = gnutls_openpgp_keyring_import(sc->pgp_list, &data, GNUTLS_OPENPGP_FMT_BASE64);
460 if (rv < 0) {
461 return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
462 "Keyring File '%s': (%d) %s", file, rv,
463 gnutls_strerror(rv));
239 } 464 }
240 465
241 apr_pool_destroy(spool); 466 apr_pool_destroy(spool);
@@ -243,20 +468,57 @@ const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
243} 468}
244 469
245const char *mgs_set_enabled(cmd_parms * parms, void *dummy, 470const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
246 const char *arg) 471 const char *arg)
247{ 472{
248 mgs_srvconf_rec *sc = 473 mgs_srvconf_rec *sc =
249 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 474 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
250 module_config, 475 module_config,
251 &gnutls_module); 476 &gnutls_module);
252 if (!strcasecmp(arg, "On")) { 477 if (!strcasecmp(arg, "On")) {
253 sc->enabled = GNUTLS_ENABLED_TRUE; 478 sc->enabled = GNUTLS_ENABLED_TRUE;
479 } else if (!strcasecmp(arg, "Off")) {
480 sc->enabled = GNUTLS_ENABLED_FALSE;
481 } else {
482 return "GnuTLSEnable must be set to 'On' or 'Off'";
254 } 483 }
255 else if (!strcasecmp(arg, "Off")) { 484
256 sc->enabled = GNUTLS_ENABLED_FALSE; 485 return NULL;
486}
487
488const char *mgs_set_export_certificates_enabled(cmd_parms * parms, void *dummy,
489 const char *arg)
490{
491 mgs_srvconf_rec *sc =
492 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
493 module_config,
494 &gnutls_module);
495 if (!strcasecmp(arg, "On")) {
496 sc->export_certificates_enabled = GNUTLS_ENABLED_TRUE;
497 } else if (!strcasecmp(arg, "Off")) {
498 sc->export_certificates_enabled = GNUTLS_ENABLED_FALSE;
499 } else {
500 return "GnuTLSExportCertificates must be set to 'On' or 'Off'";
257 } 501 }
258 else { 502
259 return "GnuTLSEnable must be set to 'On' or 'Off'"; 503 return NULL;
504}
505
506
507const char *mgs_set_priorities(cmd_parms * parms, void *dummy, const char *arg)
508{
509 int ret;
510 const char *err;
511 mgs_srvconf_rec *sc =
512 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
513 module_config,
514 &gnutls_module);
515
516
517 ret = gnutls_priority_init( &sc->priorities, arg, &err);
518 if (ret < 0) {
519 if (ret == GNUTLS_E_INVALID_REQUEST)
520 return apr_psprintf(parms->pool, "GnuTLS: Syntax error parsing priorities string at: %s", err);
521 return "Error setting priorities";
260 } 522 }
261 523
262 return NULL; 524 return NULL;
@@ -264,92 +526,63 @@ const char *mgs_set_enabled(cmd_parms * parms, void *dummy,
264 526
265void *mgs_config_server_create(apr_pool_t * p, server_rec * s) 527void *mgs_config_server_create(apr_pool_t * p, server_rec * s)
266{ 528{
267 int i;
268 mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); 529 mgs_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc));
530 int ret;
269 531
270 sc->enabled = GNUTLS_ENABLED_FALSE; 532 sc->enabled = GNUTLS_ENABLED_FALSE;
271 533
272 gnutls_certificate_allocate_credentials(&sc->certs); 534 ret = gnutls_certificate_allocate_credentials(&sc->certs);
535 if (ret < 0) {
536 return apr_psprintf(p, "GnuTLS: Failed to initialize"
537 ": (%d) %s", ret, gnutls_strerror(ret));
538 }
539
540 ret = gnutls_anon_allocate_server_credentials(&sc->anon_creds);
541 if (ret < 0) {
542 return apr_psprintf(p, "GnuTLS: Failed to initialize"
543 ": (%d) %s", ret, gnutls_strerror(ret));
544 }
545
546 ret = gnutls_srp_allocate_server_credentials(&sc->srp_creds);
547 if (ret < 0) {
548 return apr_psprintf(p, "GnuTLS: Failed to initialize"
549 ": (%d) %s", ret, gnutls_strerror(ret));
550 }
551
552 sc->srp_tpasswd_conf_file = NULL;
553 sc->srp_tpasswd_file = NULL;
273 sc->privkey_x509 = NULL; 554 sc->privkey_x509 = NULL;
274 sc->cert_x509 = NULL; 555 memset( sc->certs_x509, 0, sizeof(sc->certs_x509));
556 sc->certs_x509_num = 0;
275 sc->cache_timeout = apr_time_from_sec(300); 557 sc->cache_timeout = apr_time_from_sec(300);
276 sc->cache_type = mgs_cache_dbm; 558 sc->cache_type = mgs_cache_dbm;
277 sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache"); 559 sc->cache_config = ap_server_root_relative(p, "conf/gnutls_cache");
278 560
279 /* TODO: Make this Configurable. But it isn't configurable in mod_ssl? */
280 sc->dh_params_file = ap_server_root_relative(p, "conf/dhfile");
281 sc->rsa_params_file = ap_server_root_relative(p, "conf/rsafile");
282
283 /* Finish SSL Client Certificate Support */
284 sc->client_verify_mode = GNUTLS_CERT_IGNORE; 561 sc->client_verify_mode = GNUTLS_CERT_IGNORE;
285 562
286 /* TODO: Make this Configurable ! */
287 /* mod_ssl uses a flex based parser for this part.. sigh */
288 i = 0;
289 sc->ciphers[i++] = GNUTLS_CIPHER_AES_256_CBC;
290 sc->ciphers[i++] = GNUTLS_CIPHER_AES_128_CBC;
291 sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_128;
292 sc->ciphers[i++] = GNUTLS_CIPHER_3DES_CBC;
293 sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_40;
294 sc->ciphers[i] = 0;
295
296 i = 0;
297 sc->key_exchange[i++] = GNUTLS_KX_RSA;
298 sc->key_exchange[i++] = GNUTLS_KX_RSA_EXPORT;
299 sc->key_exchange[i++] = GNUTLS_KX_DHE_DSS;
300 sc->key_exchange[i++] = GNUTLS_KX_DHE_RSA;
301 sc->key_exchange[i++] = GNUTLS_KX_ANON_DH;
302 sc->key_exchange[i++] = GNUTLS_KX_SRP;
303 sc->key_exchange[i++] = GNUTLS_KX_SRP_RSA;
304 sc->key_exchange[i++] = GNUTLS_KX_SRP_DSS;
305 sc->key_exchange[i] = 0;
306
307 i = 0;
308 sc->macs[i++] = GNUTLS_MAC_SHA;
309 sc->macs[i++] = GNUTLS_MAC_MD5;
310 sc->macs[i++] = GNUTLS_MAC_RMD160;
311 sc->macs[i] = 0;
312
313 i = 0;
314 sc->protocol[i++] = GNUTLS_TLS1_1;
315 sc->protocol[i++] = GNUTLS_TLS1;
316 sc->protocol[i++] = GNUTLS_SSL3;
317 sc->protocol[i] = 0;
318
319 i = 0;
320 sc->compression[i++] = GNUTLS_COMP_NULL;
321 sc->compression[i++] = GNUTLS_COMP_ZLIB;
322 sc->compression[i++] = GNUTLS_COMP_LZO;
323 sc->compression[i] = 0;
324
325 i = 0;
326 sc->cert_types[i++] = GNUTLS_CRT_X509;
327 sc->cert_types[i] = 0;
328
329 return sc; 563 return sc;
330} 564}
331 565
332void *mgs_config_dir_merge(apr_pool_t *p, void *basev, void *addv) 566void *mgs_config_dir_merge(apr_pool_t * p, void *basev, void *addv)
333{ 567{
334 mgs_dirconf_rec *new; 568 mgs_dirconf_rec *new;
335 mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; 569/* mgs_dirconf_rec *base = (mgs_dirconf_rec *) basev; */
336 mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv; 570 mgs_dirconf_rec *add = (mgs_dirconf_rec *) addv;
337 571
338 new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec)); 572 new = (mgs_dirconf_rec *) apr_pcalloc(p, sizeof(mgs_dirconf_rec));
339 new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode, 573 new->lua_bytecode = apr_pstrmemdup(p, add->lua_bytecode,
340 add->lua_bytecode_len); 574 add->lua_bytecode_len);
341 new->lua_bytecode_len = add->lua_bytecode_len; 575 new->lua_bytecode_len = add->lua_bytecode_len;
342 new->client_verify_mode = add->client_verify_mode; 576 new->client_verify_mode = add->client_verify_mode;
343 return new; 577 return new;
344} 578}
345 579
346void *mgs_config_dir_create(apr_pool_t *p, char *dir) 580void *mgs_config_dir_create(apr_pool_t * p, char *dir)
347{ 581{
348 mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc)); 582 mgs_dirconf_rec *dc = apr_palloc(p, sizeof(*dc));
349 583
350 dc->client_verify_mode = -1; 584 dc->client_verify_mode = -1;
351 dc->lua_bytecode = NULL; 585 dc->lua_bytecode = NULL;
352 dc->lua_bytecode_len = 0; 586 dc->lua_bytecode_len = 0;
353 return dc; 587 return dc;
354} 588}
355
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c
index 8452d36..26917b8 100644
--- a/src/gnutls_hooks.c
+++ b/src/gnutls_hooks.c
@@ -1,5 +1,6 @@
1/** 1/**
2 * Copyright 2004-2005 Paul Querna 2 * Copyright 2004-2005 Paul Querna
3 * Copyright 2007 Nikos Mavrogiannopoulos
3 * 4 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License. 6 * you may not use this file except in compliance with the License.
@@ -28,11 +29,20 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL;
28#endif 29#endif
29 30
30#if MOD_GNUTLS_DEBUG 31#if MOD_GNUTLS_DEBUG
31static apr_file_t* debug_log_fp; 32static apr_file_t *debug_log_fp;
32#endif 33#endif
33 34
34static int mpm_is_threaded; 35static int mpm_is_threaded;
35 36
37static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt);
38/* use side==0 for server and side==1 for client */
39static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert,
40 int side,
41 int export_certificates_enabled);
42static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert,
43 int side,
44 int export_certificates_enabled);
45
36static apr_status_t mgs_cleanup_pre_config(void *data) 46static apr_status_t mgs_cleanup_pre_config(void *data)
37{ 47{
38 gnutls_global_deinit(); 48 gnutls_global_deinit();
@@ -40,208 +50,384 @@ static apr_status_t mgs_cleanup_pre_config(void *data)
40} 50}
41 51
42#if MOD_GNUTLS_DEBUG 52#if MOD_GNUTLS_DEBUG
43static void gnutls_debug_log_all( int level, const char* str) 53static void gnutls_debug_log_all(int level, const char *str)
44{ 54{
45 apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); 55 apr_file_printf(debug_log_fp, "<%d> %s\n", level, str);
46} 56}
47#endif 57#endif
48 58
49int mgs_hook_pre_config(apr_pool_t * pconf, 59int
50 apr_pool_t * plog, apr_pool_t * ptemp) 60mgs_hook_pre_config(apr_pool_t * pconf,
61 apr_pool_t * plog, apr_pool_t * ptemp)
51{ 62{
63int ret;
52 64
53#if APR_HAS_THREADS 65#if APR_HAS_THREADS
54 ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); 66 ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded);
55 if (mpm_is_threaded) { 67 if (mpm_is_threaded) {
56 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 68 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
57 } 69 }
58#else 70#else
59 mpm_is_threaded = 0; 71 mpm_is_threaded = 0;
60#endif 72#endif
61 73
62 gnutls_global_init(); 74 if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) {
75 fprintf(stderr, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n",
76 LIBGNUTLS_VERSION, gnutls_check_version(NULL));
77 return -3;
78 }
79
80 ret = gnutls_global_init();
81 if (ret < 0) {
82 fprintf(stderr, "gnutls_global_init: %s\n", gnutls_strerror(ret));
83 return -3;
84 }
63 85
86 ret = gnutls_global_init_extra();
87 if (ret < 0) {
88 fprintf(stderr, "gnutls_global_init_extra: %s\n", gnutls_strerror(ret));
89 return -3;
90 }
91
64 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, 92 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config,
65 apr_pool_cleanup_null); 93 apr_pool_cleanup_null);
66 94
67#if MOD_GNUTLS_DEBUG 95#if MOD_GNUTLS_DEBUG
68 apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", 96 apr_file_open(&debug_log_fp, "/tmp/gnutls_debug",
69 APR_APPEND|APR_WRITE|APR_CREATE, APR_OS_DEFAULT, pconf); 97 APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
98 pconf);
70 99
71 gnutls_global_set_log_level(9); 100 gnutls_global_set_log_level(9);
72 gnutls_global_set_log_function(gnutls_debug_log_all); 101 gnutls_global_set_log_function(gnutls_debug_log_all);
102 apr_file_printf(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL));
73#endif 103#endif
74 104
75 return OK; 105 return OK;
76} 106}
77 107
108static int mgs_select_virtual_server_cb(gnutls_session_t session)
109{
110 mgs_handle_t *ctxt;
111 mgs_srvconf_rec *tsc;
112 int ret;
113 int cprio[2];
114
115 ctxt = gnutls_transport_get_ptr(session);
116
117 /* find the virtual server */
118 tsc = mgs_find_sni_server(session);
119
120 if (tsc != NULL)
121 ctxt->sc = tsc;
122
123 gnutls_certificate_server_set_request(session,
124 ctxt->sc->client_verify_mode);
125
126 /* set the new server credentials
127 */
128
129 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
130 ctxt->sc->certs);
131
132 gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds);
133
134 if (ctxt->sc->srp_tpasswd_conf_file != NULL
135 && ctxt->sc->srp_tpasswd_file != NULL) {
136 gnutls_credentials_set(session, GNUTLS_CRD_SRP,
137 ctxt->sc->srp_creds);
138 }
139
140 /* update the priorities - to avoid negotiating a ciphersuite that is not
141 * enabled on this virtual server. Note that here we ignore the version
142 * negotiation.
143 */
144 ret = gnutls_priority_set(session, ctxt->sc->priorities);
145 /* actually it shouldn't fail since we have checked at startup */
146 if (ret < 0)
147 return ret;
148
149 /* If both certificate types are not present disallow them from
150 * being negotiated.
151 */
152 if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) {
153 cprio[0] = GNUTLS_CRT_X509;
154 cprio[1] = 0;
155 gnutls_certificate_type_set_priority( session, cprio);
156 } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) {
157 cprio[0] = GNUTLS_CRT_OPENPGP;
158 cprio[1] = 0;
159 gnutls_certificate_type_set_priority( session, cprio);
160 }
161
162 return 0;
163}
78 164
79static gnutls_datum load_params(const char* file, server_rec* s, 165static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret)
80 apr_pool_t* pool)
81{ 166{
82 gnutls_datum ret = { NULL, 0 }; 167 mgs_handle_t *ctxt;
83 apr_file_t* fp; 168
84 apr_finfo_t finfo; 169 ctxt = gnutls_transport_get_ptr(session);
85 apr_status_t rv; 170
86 apr_size_t br = 0; 171 if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) {
172 ret->type = GNUTLS_CRT_X509;
173 ret->ncerts = ctxt->sc->certs_x509_num;
174 ret->deinit_all = 0;
87 175
88 rv = apr_file_open(&fp, file, APR_READ|APR_BINARY, APR_OS_DEFAULT, 176 ret->cert.x509 = ctxt->sc->certs_x509;
89 pool); 177 ret->key.x509 = ctxt->sc->privkey_x509;
90 if (rv != APR_SUCCESS) { 178
91 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 179 return 0;
92 "GnuTLS failed to load params file at: %s", file); 180 } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) {
93 return ret; 181 ret->type = GNUTLS_CRT_OPENPGP;
182 ret->ncerts = 1;
183 ret->deinit_all = 0;
184
185 ret->cert.pgp = ctxt->sc->cert_pgp;
186 ret->key.pgp = ctxt->sc->privkey_pgp;
187
188 return 0;
189
94 } 190 }
95 191
96 rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, fp); 192 return GNUTLS_E_INTERNAL_ERROR;
193}
97 194
98 if (rv != APR_SUCCESS) { 195/* 2048-bit group parameters from SRP specification */
99 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 196const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
100 "GnuTLS failed to stat params file at: %s", file); 197 "MIIBBwKCAQCsa9tBMkqam/Fm3l4TiVgvr3K2ZRmH7gf8MZKUPbVgUKNzKcu0oJnt\n"
101 return ret; 198 "gZPgdXdnoT3VIxKrSwMxDc1/SKnaBP1Q6Ag5ae23Z7DPYJUXmhY6s2YaBfvV+qro\n"
199 "KRipli8Lk7hV+XmT7Jde6qgNdArb9P90c1nQQdXDPqcdKB5EaxR3O8qXtDoj+4AW\n"
200 "dr0gekNsZIHx0rkHhxdGGludMuaI+HdIVEUjtSSw1X1ep3onddLs+gMs+9v1L7N4\n"
201 "YWAnkATleuavh05zA85TKZzMBBx7wwjYKlaY86jQw4JxrjX46dv7tpS1yAPYn3rk\n"
202 "Nd4jbVJfVHWbZeNy/NaO8g+nER+eSv9zAgEC\n"
203 "-----END DH PARAMETERS-----\n";
204
205/* Read the common name or the alternative name of the certificate.
206 * We only support a single name per certificate.
207 *
208 * Returns negative on error.
209 */
210static int read_crt_cn(server_rec * s, apr_pool_t * p,
211 gnutls_x509_crt_t cert, char **cert_cn)
212{
213 int rv = 0, i;
214 size_t data_len;
215
216
217 *cert_cn = NULL;
218
219 data_len = 0;
220 rv = gnutls_x509_crt_get_dn_by_oid(cert,
221 GNUTLS_OID_X520_COMMON_NAME,
222 0, 0, NULL, &data_len);
223
224 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
225 *cert_cn = apr_palloc(p, data_len);
226 rv = gnutls_x509_crt_get_dn_by_oid(cert,
227 GNUTLS_OID_X520_COMMON_NAME, 0,
228 0, *cert_cn, &data_len);
229 } else { /* No CN return subject alternative name */
230 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
231 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...",
232 s->server_hostname, s->port);
233 rv = 0;
234 /* read subject alternative name */
235 for (i = 0; !(rv < 0); i++) {
236 data_len = 0;
237 rv = gnutls_x509_crt_get_subject_alt_name(cert, i,
238 NULL, &data_len,
239 NULL);
240
241 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
242 /* FIXME: not very efficient. What if we have several alt names
243 * before DNSName?
244 */
245 *cert_cn = apr_palloc(p, data_len + 1);
246
247 rv = gnutls_x509_crt_get_subject_alt_name(cert, i,
248 *cert_cn,
249 &data_len, NULL);
250 (*cert_cn)[data_len] = 0;
251
252 if (rv == GNUTLS_SAN_DNSNAME)
253 break;
254 }
255 }
102 } 256 }
103 257
104 ret.data = apr_palloc(pool, finfo.size+1); 258 return rv;
105 rv = apr_file_read_full(fp, ret.data, finfo.size, &br); 259}
260
261static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p,
262 gnutls_openpgp_crt_t cert, char **cert_cn)
263{
264 int rv = 0;
265 size_t data_len;
266
106 267
107 if (rv != APR_SUCCESS) { 268 *cert_cn = NULL;
108 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 269
109 "GnuTLS failed to read params file at: %s", file); 270 data_len = 0;
110 return ret; 271 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len);
272
273 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
274 *cert_cn = apr_palloc(p, data_len);
275 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len);
276 } else { /* No CN return subject alternative name */
277 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
278 "No name found in PGP certificate for '%s:%d'.",
279 s->server_hostname, s->port);
111 } 280 }
112 apr_file_close(fp);
113 ret.data[br] = '\0';
114 ret.size = br;
115 281
116 return ret; 282 return rv;
117} 283}
118 284
119int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 285
120 apr_pool_t * ptemp, 286int
121 server_rec * base_server) 287mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
288 apr_pool_t * ptemp, server_rec * base_server)
122{ 289{
123 int rv; 290 int rv;
124 int data_len;
125 server_rec *s; 291 server_rec *s;
126 gnutls_dh_params_t dh_params; 292 gnutls_dh_params_t dh_params = NULL;
127 gnutls_rsa_params_t rsa_params; 293 gnutls_rsa_params_t rsa_params = NULL;
128 mgs_srvconf_rec *sc; 294 mgs_srvconf_rec *sc;
129 mgs_srvconf_rec *sc_base; 295 mgs_srvconf_rec *sc_base;
130 void *data = NULL; 296 void *data = NULL;
131 int first_run = 0; 297 int first_run = 0;
132 const char *userdata_key = "mgs_init"; 298 const char *userdata_key = "mgs_init";
133 299
134 apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); 300 apr_pool_userdata_get(&data, userdata_key, base_server->process->pool);
135 if (data == NULL) { 301 if (data == NULL) {
136 first_run = 1; 302 first_run = 1;
137 apr_pool_userdata_set((const void *)1, userdata_key, 303 apr_pool_userdata_set((const void *) 1, userdata_key,
138 apr_pool_cleanup_null, 304 apr_pool_cleanup_null,
139 base_server->process->pool); 305 base_server->process->pool);
140 } 306 }
141 307
142 308
143 { 309 {
144 gnutls_datum pdata; 310 s = base_server;
145 apr_pool_t* tpool; 311 sc_base =
146 s = base_server; 312 (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
147 sc_base = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 313 &gnutls_module);
148 &gnutls_module); 314
149 315 gnutls_dh_params_init(&dh_params);
150 apr_pool_create(&tpool, p); 316
151 317 if (sc_base->dh_params == NULL) {
152 gnutls_dh_params_init(&dh_params); 318 gnutls_datum pdata = { (void *) static_dh_params, sizeof(static_dh_params) };
153 319 /* loading defaults */
154 pdata = load_params(sc_base->dh_params_file, s, tpool); 320 rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata,
155 321 GNUTLS_X509_FMT_PEM);
156 if (pdata.size != 0) { 322
157 rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, 323 if (rv < 0) {
158 GNUTLS_X509_FMT_PEM); 324 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
159 if (rv != 0) { 325 "GnuTLS: Unable to load DH Params: (%d) %s",
160 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 326 rv, gnutls_strerror(rv));
161 "GnuTLS: Unable to load DH Params: (%d) %s",
162 rv, gnutls_strerror(rv));
163 exit(rv); 327 exit(rv);
164 } 328 }
165 } 329 } else dh_params = sc_base->dh_params;
166 else { 330
167 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 331 if (sc_base->rsa_params != NULL)
168 "GnuTLS: Unable to load DH Params." 332 rsa_params = sc_base->rsa_params;
169 " Shutting Down."); 333
170 exit(-1); 334 /* else not an error but RSA-EXPORT ciphersuites are not available
171 } 335 */
172 apr_pool_clear(tpool); 336
173 337 rv = mgs_cache_post_config(p, s, sc_base);
174 gnutls_rsa_params_init(&rsa_params); 338 if (rv != 0) {
175 339 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s,
176 pdata = load_params(sc_base->rsa_params_file, s, tpool); 340 "GnuTLS: Post Config for GnuTLSCache Failed."
177 341 " Shutting Down.");
178 if (pdata.size != 0) { 342 exit(-1);
179 rv = gnutls_rsa_params_import_pkcs1(rsa_params, &pdata, 343 }
180 GNUTLS_X509_FMT_PEM); 344
181 if (rv != 0) { 345 for (s = base_server; s; s = s->next) {
182 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 346 void *load = NULL;
183 "GnuTLS: Unable to load RSA Params: (%d) %s", 347 sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
184 rv, gnutls_strerror(rv)); 348 &gnutls_module);
185 exit(rv); 349 sc->cache_type = sc_base->cache_type;
186 } 350 sc->cache_config = sc_base->cache_config;
187 } 351
188 else { 352 /* Check if the priorities have been set */
189 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 353 if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
190 "GnuTLS: Unable to load RSA Params." 354 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
191 " Shutting Down."); 355 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!",
192 exit(-1); 356 s->server_hostname, s->port);
193 } 357 exit(-1);
194
195 apr_pool_destroy(tpool);
196 rv = mgs_cache_post_config(p, s, sc_base);
197 if (rv != 0) {
198 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s,
199 "GnuTLS: Post Config for GnuTLSCache Failed."
200 " Shutting Down.");
201 exit(-1);
202 }
203
204 for (s = base_server; s; s = s->next) {
205 sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
206 &gnutls_module);
207 sc->cache_type = sc_base->cache_type;
208 sc->cache_config = sc_base->cache_config;
209
210 gnutls_certificate_set_rsa_export_params(sc->certs,
211 rsa_params);
212 gnutls_certificate_set_dh_params(sc->certs, dh_params);
213
214 if (sc->cert_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) {
215 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
216 "[GnuTLS] - Host '%s:%d' is missing a "
217 "Certificate File!",
218 s->server_hostname, s->port);
219 exit(-1);
220 } 358 }
221 359
222 if (sc->privkey_x509 == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { 360 /* Check if DH or RSA params have been set per host */
223 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, 361 if (sc->rsa_params != NULL)
224 "[GnuTLS] - Host '%s:%d' is missing a " 362 load = sc->rsa_params;
225 "Private Key File!", 363 else if (rsa_params) load = rsa_params;
226 s->server_hostname, s->port);
227 exit(-1);
228 }
229 364
230 rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, 365 if (load != NULL)
231 GNUTLS_OID_X520_COMMON_NAME, 0, 0, 366 gnutls_certificate_set_rsa_export_params(sc->certs, load);
232 NULL, &data_len); 367
368
369 load = NULL;
370 if (sc->dh_params != NULL)
371 load = sc->dh_params;
372 else if (dh_params) load = dh_params;
233 373
234 if (data_len < 1) { 374 if (load != NULL) { /* not needed but anyway */
235 sc->enabled = GNUTLS_ENABLED_FALSE; 375 gnutls_certificate_set_dh_params(sc->certs, load);
236 sc->cert_cn = NULL; 376 gnutls_anon_set_server_dh_params(sc->anon_creds, load);
237 continue;
238 } 377 }
239 378
240 sc->cert_cn = apr_palloc(p, data_len); 379 gnutls_certificate_server_set_retrieve_function(sc->certs,
241 rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, 380 cert_retrieve_fn);
242 GNUTLS_OID_X520_COMMON_NAME, 0, 0, 381
243 sc->cert_cn, &data_len); 382 if (sc->srp_tpasswd_conf_file != NULL
244 } 383 && sc->srp_tpasswd_file != NULL) {
384 rv = gnutls_srp_set_server_credentials_file(sc->srp_creds,
385 sc->
386 srp_tpasswd_file,
387 sc->
388 srp_tpasswd_conf_file);
389
390 if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
391 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
392 "[GnuTLS] - Host '%s:%d' is missing a "
393 "SRP password or conf File!",
394 s->server_hostname, s->port);
395 exit(-1);
396 }
397 }
398
399 if (sc->certs_x509[0] == NULL
400 && sc->enabled == GNUTLS_ENABLED_TRUE) {
401 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
402 "[GnuTLS] - Host '%s:%d' is missing a "
403 "Certificate File!", s->server_hostname,
404 s->port);
405 exit(-1);
406 }
407
408 if (sc->privkey_x509 == NULL
409 && sc->enabled == GNUTLS_ENABLED_TRUE) {
410 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
411 "[GnuTLS] - Host '%s:%d' is missing a "
412 "Private Key File!",
413 s->server_hostname, s->port);
414 exit(-1);
415 }
416
417 if (sc->enabled == GNUTLS_ENABLED_TRUE) {
418 rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn);
419 if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */
420 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn);
421
422 if (rv < 0) {
423 ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
424 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!",
425 s->server_hostname, s->port);
426 sc->cert_cn = NULL;
427 continue;
428 }
429 }
430 }
245 } 431 }
246 432
247 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION); 433 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION);
@@ -249,34 +435,32 @@ int mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
249 return OK; 435 return OK;
250} 436}
251 437
252void mgs_hook_child_init(apr_pool_t *p, server_rec *s) 438void mgs_hook_child_init(apr_pool_t * p, server_rec * s)
253{ 439{
254 apr_status_t rv = APR_SUCCESS; 440 apr_status_t rv = APR_SUCCESS;
255 mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, 441 mgs_srvconf_rec *sc = ap_get_module_config(s->module_config,
256 &gnutls_module); 442 &gnutls_module);
257 443
258 if (sc->cache_type != mgs_cache_none) { 444 if (sc->cache_type != mgs_cache_none) {
259 rv = mgs_cache_child_init(p, s, sc); 445 rv = mgs_cache_child_init(p, s, sc);
260 if(rv != APR_SUCCESS) { 446 if (rv != APR_SUCCESS) {
261 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 447 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
262 "[GnuTLS] - Failed to run Cache Init"); 448 "[GnuTLS] - Failed to run Cache Init");
263 } 449 }
264 } 450 } else {
265 else { 451 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s,
266 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s, 452 "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache");
267 "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache");
268 } 453 }
269} 454}
270 455
271const char *mgs_hook_http_scheme(const request_rec * r) 456const char *mgs_hook_http_scheme(const request_rec * r)
272{ 457{
273 mgs_srvconf_rec *sc = 458 mgs_srvconf_rec *sc =
274 (mgs_srvconf_rec *) ap_get_module_config(r->server-> 459 (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,
275 module_config, 460 &gnutls_module);
276 &gnutls_module);
277 461
278 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 462 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
279 return NULL; 463 return NULL;
280 } 464 }
281 465
282 return "https"; 466 return "https";
@@ -285,12 +469,11 @@ const char *mgs_hook_http_scheme(const request_rec * r)
285apr_port_t mgs_hook_default_port(const request_rec * r) 469apr_port_t mgs_hook_default_port(const request_rec * r)
286{ 470{
287 mgs_srvconf_rec *sc = 471 mgs_srvconf_rec *sc =
288 (mgs_srvconf_rec *) ap_get_module_config(r->server-> 472 (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,
289 module_config, 473 &gnutls_module);
290 &gnutls_module);
291 474
292 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 475 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
293 return 0; 476 return 0;
294 } 477 }
295 478
296 return 443; 479 return 443;
@@ -299,88 +482,86 @@ apr_port_t mgs_hook_default_port(const request_rec * r)
299#define MAX_HOST_LEN 255 482#define MAX_HOST_LEN 255
300 483
301#if USING_2_1_RECENT 484#if USING_2_1_RECENT
302typedef struct 485typedef struct {
303{
304 mgs_handle_t *ctxt; 486 mgs_handle_t *ctxt;
305 mgs_srvconf_rec *sc; 487 mgs_srvconf_rec *sc;
306 const char* sni_name; 488 const char *sni_name;
307} vhost_cb_rec; 489} vhost_cb_rec;
308 490
309static int vhost_cb (void* baton, conn_rec* conn, server_rec* s) 491static int vhost_cb(void *baton, conn_rec * conn, server_rec * s)
310{ 492{
311 mgs_srvconf_rec *tsc; 493 mgs_srvconf_rec *tsc;
312 vhost_cb_rec* x = baton; 494 vhost_cb_rec *x = baton;
313 495
314 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 496 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
315 &gnutls_module); 497 &gnutls_module);
316 498
317 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { 499 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) {
318 return 0; 500 return 0;
319 } 501 }
320 502
321 /* The CN can contain a * -- this will match those too. */ 503 /* The CN can contain a * -- this will match those too. */
322 if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { 504 if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) {
323 /* found a match */ 505 /* found a match */
324#if MOD_GNUTLS_DEBUG 506#if MOD_GNUTLS_DEBUG
325 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 507 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
326 x->ctxt->c->base_server, 508 x->ctxt->c->base_server,
327 "GnuTLS: Virtual Host CB: " 509 "GnuTLS: Virtual Host CB: "
328 "'%s' == '%s'", tsc->cert_cn, x->sni_name); 510 "'%s' == '%s'", tsc->cert_cn, x->sni_name);
329#endif 511#endif
330 /* Because we actually change the server used here, we need to reset 512 /* Because we actually change the server used here, we need to reset
331 * things like ClientVerify. 513 * things like ClientVerify.
332 */ 514 */
333 x->sc = tsc; 515 x->sc = tsc;
334 /* Shit. Crap. Dammit. We *really* should rehandshake here, as our 516 /* Shit. Crap. Dammit. We *really* should rehandshake here, as our
335 * certificate structure *should* change when the server changes. 517 * certificate structure *should* change when the server changes.
336 * acccckkkkkk. 518 * acccckkkkkk.
337 */ 519 */
338 return 1; 520 return 1;
521 } else {
522#if MOD_GNUTLS_DEBUG
523 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
524 x->ctxt->c->base_server,
525 "GnuTLS: Virtual Host CB: "
526 "'%s' != '%s'", tsc->cert_cn, x->sni_name);
527#endif
528
339 } 529 }
340 return 0; 530 return 0;
341} 531}
342#endif 532#endif
343 533
344mgs_srvconf_rec* mgs_find_sni_server(gnutls_session_t session) 534mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
345{ 535{
346 int rv; 536 int rv;
347 int sni_type; 537 unsigned int sni_type;
348 int data_len = MAX_HOST_LEN; 538 size_t data_len = MAX_HOST_LEN;
349 char sni_name[MAX_HOST_LEN]; 539 char sni_name[MAX_HOST_LEN];
350 mgs_handle_t *ctxt; 540 mgs_handle_t *ctxt;
351#if USING_2_1_RECENT 541#if USING_2_1_RECENT
352 vhost_cb_rec cbx; 542 vhost_cb_rec cbx;
353#else 543#else
354 server_rec* s; 544 server_rec *s;
355 mgs_srvconf_rec *tsc; 545 mgs_srvconf_rec *tsc;
356#endif 546#endif
357 547
358 ctxt = gnutls_transport_get_ptr(session); 548 ctxt = gnutls_transport_get_ptr(session);
359 549
360 sni_type = gnutls_certificate_type_get(session); 550 rv = gnutls_server_name_get(ctxt->session, sni_name,
361 if (sni_type != GNUTLS_CRT_X509) { 551 &data_len, &sni_type, 0);
362 /* In theory, we could support OpenPGP Certificates. Theory != code. */ 552
363 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
364 ctxt->c->base_server,
365 "GnuTLS: Only x509 Certificates are currently supported.");
366 return NULL;
367 }
368
369 rv = gnutls_server_name_get(ctxt->session, sni_name,
370 &data_len, &sni_type, 0);
371
372 if (rv != 0) { 553 if (rv != 0) {
373 return NULL; 554 return NULL;
374 } 555 }
375 556
376 if (sni_type != GNUTLS_NAME_DNS) { 557 if (sni_type != GNUTLS_NAME_DNS) {
377 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 558 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
378 ctxt->c->base_server, 559 ctxt->c->base_server,
379 "GnuTLS: Unknown type '%d' for SNI: " 560 "GnuTLS: Unknown type '%d' for SNI: "
380 "'%s'", sni_type, sni_name); 561 "'%s'", sni_type, sni_name);
381 return NULL; 562 return NULL;
382 } 563 }
383 564
384 /** 565 /**
385 * Code in the Core already sets up the c->base_server as the base 566 * Code in the Core already sets up the c->base_server as the base
386 * for this IP/Port combo. Trust that the core did the 'right' thing. 567 * for this IP/Port combo. Trust that the core did the 'right' thing.
@@ -389,72 +570,57 @@ mgs_srvconf_rec* mgs_find_sni_server(gnutls_session_t session)
389 cbx.ctxt = ctxt; 570 cbx.ctxt = ctxt;
390 cbx.sc = NULL; 571 cbx.sc = NULL;
391 cbx.sni_name = sni_name; 572 cbx.sni_name = sni_name;
392 573
393 rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); 574 rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx);
394 if (rv == 1) { 575 if (rv == 1) {
395 return cbx.sc; 576 return cbx.sc;
396 } 577 }
397#else 578#else
398 for (s = ap_server_conf; s; s = s->next) { 579 for (s = ap_server_conf; s; s = s->next) {
399 580
400 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 581 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
401 &gnutls_module); 582 &gnutls_module);
402 if (tsc->enabled != GNUTLS_ENABLED_TRUE) { 583 if (tsc->enabled != GNUTLS_ENABLED_TRUE) {
403 continue; 584 continue;
404 } 585 }
405#if MOD_GNUTLS_DEBUG 586#if MOD_GNUTLS_DEBUG
406 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 587 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
407 ctxt->c->base_server, 588 ctxt->c->base_server,
408 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", tsc->cert_cn, rv, 589 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X",
409 gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)), 590 tsc->cert_cn, rv,
410 (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc); 591 gnutls_pk_algorithm_get_name
411#endif 592 (gnutls_x509_privkey_get_pk_algorithm
412 /* The CN can contain a * -- this will match those too. */ 593 (ctxt->sc->privkey_x509)), (unsigned int) s,
413 if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { 594 (unsigned int) s->next, (unsigned int) tsc);
595#endif
596 /* The CN can contain a * -- this will match those too. */
597 if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) {
414#if MOD_GNUTLS_DEBUG 598#if MOD_GNUTLS_DEBUG
415 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 599 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
416 ctxt->c->base_server, 600 ctxt->c->base_server,
417 "GnuTLS: Virtual Host: " 601 "GnuTLS: Virtual Host: "
418 "'%s' == '%s'", tsc->cert_cn, sni_name); 602 "'%s' == '%s'", tsc->cert_cn, sni_name);
419#endif 603#endif
420 return tsc; 604 return tsc;
421 } 605 }
422 } 606 }
423#endif 607#endif
424 return NULL; 608 return NULL;
425} 609}
426 610
427 611
428static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) 612static const int protocol_priority[] = {
429{ 613 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
430 mgs_handle_t *ctxt; 614};
431 mgs_srvconf_rec *tsc;
432
433 ctxt = gnutls_transport_get_ptr(session);
434 615
435 ret->type = GNUTLS_CRT_X509;
436 ret->ncerts = 1;
437 ret->deinit_all = 0;
438 616
439 tsc = mgs_find_sni_server(session); 617static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c)
440
441 if (tsc != NULL) {
442 ctxt->sc = tsc;
443 gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode);
444 }
445
446 ret->cert.x509 = &ctxt->sc->cert_x509;
447 ret->key.x509 = ctxt->sc->privkey_x509;
448 return 0;
449}
450
451static mgs_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c)
452{ 618{
453 mgs_handle_t *ctxt; 619 mgs_handle_t *ctxt;
454 mgs_srvconf_rec *sc = 620 mgs_srvconf_rec *sc =
455 (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 621 (mgs_srvconf_rec *) ap_get_module_config(c->base_server->
456 module_config, 622 module_config,
457 &gnutls_module); 623 &gnutls_module);
458 624
459 ctxt = apr_pcalloc(pool, sizeof(*ctxt)); 625 ctxt = apr_pcalloc(pool, sizeof(*ctxt));
460 ctxt->c = c; 626 ctxt->c = c;
@@ -472,19 +638,17 @@ static mgs_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c)
472 638
473 gnutls_init(&ctxt->session, GNUTLS_SERVER); 639 gnutls_init(&ctxt->session, GNUTLS_SERVER);
474 640
475 gnutls_protocol_set_priority(ctxt->session, sc->protocol); 641 /* because we don't set any default priorities here (we set later at
476 gnutls_cipher_set_priority(ctxt->session, sc->ciphers); 642 * the user hello callback) we need to at least set this in order for
477 gnutls_compression_set_priority(ctxt->session, sc->compression); 643 * gnutls to be able to read packets.
478 gnutls_kx_set_priority(ctxt->session, sc->key_exchange); 644 */
479 gnutls_mac_set_priority(ctxt->session, sc->macs); 645 gnutls_protocol_set_priority(ctxt->session, protocol_priority);
480 gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types); 646
647 gnutls_handshake_set_post_client_hello_function(ctxt->session,
648 mgs_select_virtual_server_cb);
481 649
482 mgs_cache_session_init(ctxt); 650 mgs_cache_session_init(ctxt);
483
484 gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs);
485 651
486 gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn);
487 gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode);
488 return ctxt; 652 return ctxt;
489} 653}
490 654
@@ -492,218 +656,484 @@ int mgs_hook_pre_connection(conn_rec * c, void *csd)
492{ 656{
493 mgs_handle_t *ctxt; 657 mgs_handle_t *ctxt;
494 mgs_srvconf_rec *sc = 658 mgs_srvconf_rec *sc =
495 (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 659 (mgs_srvconf_rec *) ap_get_module_config(c->base_server->
496 module_config, 660 module_config,
497 &gnutls_module); 661 &gnutls_module);
498 662
499 if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) { 663 if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) {
500 return DECLINED; 664 return DECLINED;
501 } 665 }
502 666
503 ctxt = create_gnutls_handle(c->pool, c); 667 ctxt = create_gnutls_handle(c->pool, c);
504 668
505 ap_set_module_config(c->conn_config, &gnutls_module, ctxt); 669 ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
506 670
507 gnutls_transport_set_pull_function(ctxt->session, 671 gnutls_transport_set_pull_function(ctxt->session, mgs_transport_read);
508 mgs_transport_read); 672 gnutls_transport_set_push_function(ctxt->session, mgs_transport_write);
509 gnutls_transport_set_push_function(ctxt->session,
510 mgs_transport_write);
511 gnutls_transport_set_ptr(ctxt->session, ctxt); 673 gnutls_transport_set_ptr(ctxt->session, ctxt);
512 674
513 ctxt->input_filter = ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, 675 ctxt->input_filter =
514 NULL, c); 676 ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c);
515 ctxt->output_filter = ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, 677 ctxt->output_filter =
516 NULL, c); 678 ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c);
517 679
518 return OK; 680 return OK;
519} 681}
520 682
521int mgs_hook_fixups(request_rec *r) 683int mgs_hook_fixups(request_rec * r)
522{ 684{
523 unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; 685 unsigned char sbuf[GNUTLS_MAX_SESSION_ID];
524 char buf[AP_IOBUFSIZE]; 686 char buf[AP_IOBUFSIZE];
525 const char* tmp; 687 const char *tmp;
526 int len; 688 size_t len;
527 mgs_handle_t *ctxt; 689 mgs_handle_t *ctxt;
528 int rv = OK; 690 int rv = OK;
529 691
530 apr_table_t *env = r->subprocess_env; 692 apr_table_t *env = r->subprocess_env;
531 693
532 ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); 694 ctxt =
695 ap_get_module_config(r->connection->conn_config, &gnutls_module);
533 696
534 if(!ctxt) { 697 if (!ctxt) {
535 return DECLINED; 698 return DECLINED;
536 } 699 }
537 700
538 apr_table_setn(env, "HTTPS", "on"); 701 apr_table_setn(env, "HTTPS", "on");
539 702
540 apr_table_setn(env, "GNUTLS_VERSION_INTERFACE", MOD_GNUTLS_VERSION); 703 apr_table_setn(env, "SSL_VERSION_LIBRARY",
541 apr_table_setn(env, "GNUTLS_VERSION_LIBRARY", LIBGNUTLS_VERSION); 704 "GnuTLS/" LIBGNUTLS_VERSION);
705 apr_table_setn(env, "SSL_VERSION_INTERFACE",
706 "mod_gnutls/" MOD_GNUTLS_VERSION);
542 707
543 apr_table_setn(env, "SSL_PROTOCOL", 708 apr_table_setn(env, "SSL_PROTOCOL",
544 gnutls_protocol_get_name(gnutls_protocol_get_version(ctxt->session))); 709 gnutls_protocol_get_name(gnutls_protocol_get_version
710 (ctxt->session)));
545 711
712 /* should have been called SSL_CIPHERSUITE instead */
546 apr_table_setn(env, "SSL_CIPHER", 713 apr_table_setn(env, "SSL_CIPHER",
547 gnutls_cipher_get_name(gnutls_cipher_get(ctxt->session))); 714 gnutls_cipher_suite_get_name(gnutls_kx_get
715 (ctxt->session),
716 gnutls_cipher_get(ctxt->
717 session),
718 gnutls_mac_get(ctxt->
719 session)));
720
721 apr_table_setn(env, "SSL_COMPRESS_METHOD",
722 gnutls_compression_get_name(gnutls_compression_get
723 (ctxt->session)));
548 724
549 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); 725 apr_table_setn(env, "SSL_SRP_USER",
726 gnutls_srp_server_get_username(ctxt->session));
550 727
551 tmp = apr_psprintf(r->pool, "%d", 728 if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL)
552 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session))); 729 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE");
730
731 unsigned int key_size =
732 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session));
733 tmp = apr_psprintf(r->pool, "%u", key_size);
553 734
554 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); 735 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp);
555 736
556 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); 737 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp);
557 738
739 apr_table_setn(env, "SSL_CIPHER_EXPORT",
740 (key_size <= 40) ? "true" : "false");
741
558 len = sizeof(sbuf); 742 len = sizeof(sbuf);
559 gnutls_session_get_id(ctxt->session, sbuf, &len); 743 gnutls_session_get_id(ctxt->session, sbuf, &len);
560 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 744 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
561 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); 745 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));
562 746
563 /* TODO: There are many other env vars that we need to add */ 747 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
564 { 748 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0,
565 len = sizeof(buf); 749 ctxt->sc->export_certificates_enabled);
566 gnutls_x509_crt_get_dn(ctxt->sc->cert_x509, buf, &len); 750 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
567 apr_table_setn(env, "SSL_SERVER_S_DN", apr_pstrmemdup(r->pool, buf, len)); 751 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0,
568 752 ctxt->sc->export_certificates_enabled);
569 len = sizeof(buf); 753
570 gnutls_x509_crt_get_issuer_dn(ctxt->sc->cert_x509, buf, &len);
571 apr_table_setn(env, "SSL_SERVER_I_DN", apr_pstrmemdup(r->pool, buf, len));
572 }
573 return rv; 754 return rv;
574} 755}
575 756
576int mgs_hook_authz(request_rec *r) 757int mgs_hook_authz(request_rec * r)
577{ 758{
578 int rv; 759 int rv;
579 int status;
580 mgs_handle_t *ctxt; 760 mgs_handle_t *ctxt;
581 mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, 761 mgs_dirconf_rec *dc = ap_get_module_config(r->per_dir_config,
582 &gnutls_module); 762 &gnutls_module);
583 763
584 ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); 764 ctxt =
585 765 ap_get_module_config(r->connection->conn_config, &gnutls_module);
766
586 if (!ctxt) { 767 if (!ctxt) {
587 return DECLINED; 768 return DECLINED;
588 } 769 }
589 770
590 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { 771 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {
591 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 772 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
592 "GnuTLS: Directory set to Ignore Client Certificate!"); 773 "GnuTLS: Directory set to Ignore Client Certificate!");
593 } 774 } else {
594 else { 775 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) {
595 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { 776 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
596 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 777 "GnuTLS: Attempting to rehandshake with peer. %d %d",
597 "GnuTLS: Attempting to rehandshake with peer. %d %d", 778 ctxt->sc->client_verify_mode,
598 ctxt->sc->client_verify_mode, dc->client_verify_mode); 779 dc->client_verify_mode);
599 780
600 gnutls_certificate_server_set_request(ctxt->session, 781 gnutls_certificate_server_set_request(ctxt->session,
601 dc->client_verify_mode); 782 dc->client_verify_mode);
602 783
603 if (mgs_rehandshake(ctxt) != 0) { 784 if (mgs_rehandshake(ctxt) != 0) {
604 return HTTP_FORBIDDEN; 785 return HTTP_FORBIDDEN;
605 } 786 }
606 } 787 } else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) {
607 else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) {
608#if MOD_GNUTLS_DEBUG 788#if MOD_GNUTLS_DEBUG
609 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 789 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
610 "GnuTLS: Peer is set to IGNORE"); 790 "GnuTLS: Peer is set to IGNORE");
611#endif 791#endif
612 } 792 } else {
613 else { 793 rv = mgs_cert_verify(r, ctxt);
614 rv = mgs_cert_verify(r, ctxt); 794 if (rv != DECLINED) {
615 if (rv != DECLINED) { 795 return rv;
616 return rv; 796 }
617 } 797 }
618 } 798 }
799
800 return DECLINED;
801}
802
803/* variables that are not sent by default:
804 *
805 * SSL_CLIENT_CERT string PEM-encoded client certificate
806 * SSL_SERVER_CERT string PEM-encoded client certificate
807 */
808
809/* side is either 0 for SERVER or 1 for CLIENT
810 */
811#define MGS_SIDE ((side==0)?"SSL_SERVER":"SSL_CLIENT")
812static void
813mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side,
814 int export_certificates_enabled)
815{
816 unsigned char sbuf[64]; /* buffer to hold serials */
817 char buf[AP_IOBUFSIZE];
818 const char *tmp;
819 char *tmp2;
820 size_t len;
821 int ret, i;
822
823 apr_table_t *env = r->subprocess_env;
824
825 if (export_certificates_enabled != 0) {
826 char cert_buf[10 * 1024];
827 len = sizeof(cert_buf);
828
829 if (gnutls_x509_crt_export
830 (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0)
831 apr_table_setn(env,
832 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
833 apr_pstrmemdup(r->pool, cert_buf, len));
834
835 }
836
837 len = sizeof(buf);
838 gnutls_x509_crt_get_dn(cert, buf, &len);
839 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL),
840 apr_pstrmemdup(r->pool, buf, len));
841
842 len = sizeof(buf);
843 gnutls_x509_crt_get_issuer_dn(cert, buf, &len);
844 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL),
845 apr_pstrmemdup(r->pool, buf, len));
846
847 len = sizeof(sbuf);
848 gnutls_x509_crt_get_serial(cert, sbuf, &len);
849 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
850 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL),
851 apr_pstrdup(r->pool, tmp));
852
853 ret = gnutls_x509_crt_get_version(cert);
854 if (ret > 0)
855 apr_table_setn(env,
856 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL),
857 apr_psprintf(r->pool, "%u", ret));
858
859 apr_table_setn(env,
860 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509");
861
862 tmp =
863 mgs_time2sz(gnutls_x509_crt_get_expiration_time
864 (cert), buf, sizeof(buf));
865 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
866 apr_pstrdup(r->pool, tmp));
867
868 tmp =
869 mgs_time2sz(gnutls_x509_crt_get_activation_time
870 (cert), buf, sizeof(buf));
871 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
872 apr_pstrdup(r->pool, tmp));
873
874 ret = gnutls_x509_crt_get_signature_algorithm(cert);
875 if (ret >= 0) {
876 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", NULL),
877 gnutls_sign_algorithm_get_name(ret));
878 }
879
880 ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL);
881 if (ret >= 0) {
882 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL),
883 gnutls_pk_algorithm_get_name(ret));
884 }
619 885
886 /* export all the alternative names (DNS, RFC822 and URI) */
887 for (i = 0; !(ret < 0); i++) {
888 len = 0;
889 ret = gnutls_x509_crt_get_subject_alt_name(cert, i,
890 NULL, &len, NULL);
891
892 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) {
893 tmp2 = apr_palloc(r->pool, len + 1);
894
895 ret =
896 gnutls_x509_crt_get_subject_alt_name(cert, i, tmp2, &len,
897 NULL);
898 tmp2[len] = 0;
899
900 if (ret == GNUTLS_SAN_DNSNAME) {
901 apr_table_setn(env,
902 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i),
903 apr_psprintf(r->pool, "DNSNAME:%s", tmp2));
904 } else if (ret == GNUTLS_SAN_RFC822NAME) {
905 apr_table_setn(env,
906 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i),
907 apr_psprintf(r->pool, "RFC822NAME:%s", tmp2));
908 } else if (ret == GNUTLS_SAN_URI) {
909 apr_table_setn(env,
910 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i),
911 apr_psprintf(r->pool, "URI:%s", tmp2));
912 } else {
913 apr_table_setn(env,
914 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i),
915 "UNSUPPORTED");
916 }
917 }
918 }
919}
620 920
621static int mgs_cert_verify(request_rec *r, mgs_handle_t *ctxt) 921static void
922mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side,
923 int export_certificates_enabled)
622{ 924{
623 const gnutls_datum_t* cert_list; 925 unsigned char sbuf[64]; /* buffer to hold serials */
624 int cert_list_size; 926 char buf[AP_IOBUFSIZE];
625 gnutls_x509_crt_t cert; 927 const char *tmp;
928 size_t len;
929 int ret;
930
931 apr_table_t *env = r->subprocess_env;
626 932
933 if (export_certificates_enabled != 0) {
934 char cert_buf[10 * 1024];
935 len = sizeof(cert_buf);
936
937 if (gnutls_openpgp_crt_export
938 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0)
939 apr_table_setn(env,
940 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL),
941 apr_pstrmemdup(r->pool, cert_buf, len));
942
943 }
627 944
628 cert_list = gnutls_certificate_get_peers(ctxt->session, &cert_list_size); 945 len = sizeof(buf);
946 gnutls_openpgp_crt_get_name(cert, 0, buf, &len);
947 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL),
948 apr_pstrmemdup(r->pool, buf, len));
949
950 len = sizeof(sbuf);
951 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len);
952 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
953 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL),
954 apr_pstrdup(r->pool, tmp));
955
956 ret = gnutls_openpgp_crt_get_version(cert);
957 if (ret > 0)
958 apr_table_setn(env,
959 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL),
960 apr_psprintf(r->pool, "%u", ret));
961
962 apr_table_setn(env,
963 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP");
964
965 tmp =
966 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time
967 (cert), buf, sizeof(buf));
968 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
969 apr_pstrdup(r->pool, tmp));
970
971 tmp =
972 mgs_time2sz(gnutls_openpgp_crt_get_creation_time
973 (cert), buf, sizeof(buf));
974 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
975 apr_pstrdup(r->pool, tmp));
976
977 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL);
978 if (ret >= 0) {
979 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL),
980 gnutls_pk_algorithm_get_name(ret));
981 }
982
983}
984
985/* TODO: Allow client sending a X.509 certificate chain */
986static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
987{
988 const gnutls_datum_t *cert_list;
989 unsigned int cert_list_size, status, expired;
990 int rv, ret;
991 union {
992 gnutls_x509_crt_t x509;
993 gnutls_openpgp_crt_t pgp;
994 } cert;
995 apr_time_t activation_time, expiration_time, cur_time;
996
997 cert_list =
998 gnutls_certificate_get_peers(ctxt->session, &cert_list_size);
629 999
630 if (cert_list == NULL || cert_list_size == 0) { 1000 if (cert_list == NULL || cert_list_size == 0) {
631 /* no certificate provided by the client, but one was required. */ 1001 /* It is perfectly OK for a client not to send a certificate if on REQUEST mode
632 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1002 */
633 "GnuTLS: Failed to Verify Peer: " 1003 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST)
634 "Client did not submit a certificate"); 1004 return OK;
635 return HTTP_FORBIDDEN; 1005
1006 /* no certificate provided by the client, but one was required. */
1007 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1008 "GnuTLS: Failed to Verify Peer: "
1009 "Client did not submit a certificate");
1010 return HTTP_FORBIDDEN;
636 } 1011 }
637 1012
638 if (cert_list_size > 1) { 1013 if (cert_list_size > 1) {
639 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1014 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
640 "GnuTLS: Failed to Verify Peer: " 1015 "GnuTLS: Failed to Verify Peer: "
641 "Chained Client Certificates are not supported."); 1016 "Chained Client Certificates are not supported.");
642 return HTTP_FORBIDDEN; 1017 return HTTP_FORBIDDEN;
643 } 1018 }
644 1019
645 gnutls_x509_crt_init(&cert); 1020 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
646 gnutls_x509_crt_import(cert, &cert_chain[0], GNUTLS_X509_FMT_DER); 1021 gnutls_x509_crt_init(&cert.x509);
1022 rv = gnutls_x509_crt_import(cert.x509, &cert_list[0], GNUTLS_X509_FMT_DER);
1023 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) {
1024 gnutls_openpgp_crt_init(&cert.pgp);
1025 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW);
1026 } else return HTTP_FORBIDDEN;
1027
1028 if (rv < 0) {
1029 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1030 "GnuTLS: Failed to Verify Peer: "
1031 "Failed to import peer certificates.");
1032 ret = HTTP_FORBIDDEN;
1033 goto exit;
1034 }
647 1035
648 rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list, ctxt->sc->ca_list_size, 0, &status); 1036 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
1037 apr_time_ansi_put(&expiration_time,
1038 gnutls_x509_crt_get_expiration_time(cert.x509));
1039 apr_time_ansi_put(&activation_time,
1040 gnutls_x509_crt_get_activation_time(cert.x509));
1041
1042 rv = gnutls_x509_crt_verify(cert.x509, ctxt->sc->ca_list,
1043 ctxt->sc->ca_list_size, 0, &status);
1044 } else {
1045 apr_time_ansi_put(&expiration_time,
1046 gnutls_openpgp_crt_get_expiration_time(cert.pgp));
1047 apr_time_ansi_put(&activation_time,
1048 gnutls_openpgp_crt_get_creation_time(cert.pgp));
1049
1050 rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list,
1051 0, &status);
1052 }
649 1053
650 if (rv < 0) { 1054 if (rv < 0) {
651 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1055 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
652 "GnuTLS: Failed to Verify Peer: (%d) %s", 1056 "GnuTLS: Failed to Verify Peer certificate: (%d) %s",
653 rv, gnutls_strerror(rv)); 1057 rv, gnutls_strerror(rv));
654 return HTTP_FORBIDDEN; 1058 if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND)
1059 ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r,
1060 "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?");
1061 ret = HTTP_FORBIDDEN;
1062 goto exit;
655 } 1063 }
656 1064
657 if (status < 0) { 1065 /* TODO: X509 CRL Verification. */
658 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1066 /* May add later if anyone needs it.
659 "GnuTLS: Peer Status is invalid."); 1067 */
660 return HTTP_FORBIDDEN; 1068 /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */
661 } 1069
662 1070 expired = 0;
663 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 1071 cur_time = apr_time_now();
664 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1072 if (activation_time > cur_time) {
665 "GnuTLS: Could not find Signer for Peer Certificate"); 1073 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
666 } 1074 "GnuTLS: Failed to Verify Peer: "
667 1075 "Peer Certificate is not yet activated.");
668 if (status & GNUTLS_CERT_SIGNER_NOT_CA) { 1076 expired = 1;
669 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
670 "GnuTLS: Could not find CA for Peer Certificate");
671 }
672
673 if (status & GNUTLS_CERT_INVALID) {
674 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
675 "GnuTLS: Peer Certificate is invalid.");
676 return HTTP_FORBIDDEN;
677 }
678 else if (status & GNUTLS_CERT_REVOKED) {
679 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
680 "GnuTLS: Peer Certificate is revoked.");
681 return HTTP_FORBIDDEN;
682 }
683
684 /* TODO: OpenPGP Certificates */
685 if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) {
686 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
687 "GnuTLS: Only x509 is supported for client certificates");
688 return HTTP_FORBIDDEN;
689 }
690 /* TODO: Further Verification. */
691// gnutls_x509_crt_get_expiration_time() < time
692// gnutls_x509_crt_get_activation_time() > time
693/// ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size);
694 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
695 "GnuTLS: Verified Peer.");
696 }
697
698 ap_add_common_vars(r);
699 mgs_hook_fixups(r);
700 status = mgs_authz_lua(r);
701
702 if (status != 0) {
703 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
704 "GnuTLS: FAILED Authorization Test");
705 return HTTP_FORBIDDEN;
706 } 1077 }
707 1078
708} 1079 if (expiration_time < cur_time) {
1080 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1081 "GnuTLS: Failed to Verify Peer: "
1082 "Peer Certificate is expired.");
1083 expired = 1;
1084 }
1085
1086 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1087 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1088 "GnuTLS: Could not find Signer for Peer Certificate");
1089 }
1090
1091 if (status & GNUTLS_CERT_SIGNER_NOT_CA) {
1092 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1093 "GnuTLS: Peer's Certificate signer is not a CA");
1094 }
709 1095
1096 if (status & GNUTLS_CERT_INVALID) {
1097 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1098 "GnuTLS: Peer Certificate is invalid.");
1099 } else if (status & GNUTLS_CERT_REVOKED) {
1100 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1101 "GnuTLS: Peer Certificate is revoked.");
1102 }
1103
1104 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
1105 mgs_add_common_cert_vars(r, cert.x509, 1,
1106 ctxt->sc->export_certificates_enabled);
1107 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
1108 mgs_add_common_pgpcert_vars(r, cert.pgp, 1,
1109 ctxt->sc->export_certificates_enabled);
1110
1111 {
1112 /* days remaining */
1113 unsigned long remain =
1114 (apr_time_sec(expiration_time) -
1115 apr_time_sec(cur_time)) / 86400;
1116 apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN",
1117 apr_psprintf(r->pool, "%lu", remain));
1118 }
1119
1120 if (status == 0 && expired == 0) {
1121 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "SUCCESS");
1122 ret = OK;
1123 } else {
1124 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "FAILED");
1125 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST)
1126 ret = OK;
1127 else
1128 ret = HTTP_FORBIDDEN;
1129 }
1130
1131 exit:
1132 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
1133 gnutls_x509_crt_deinit(cert.x509);
1134 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
1135 gnutls_openpgp_crt_deinit(cert.pgp);
1136 return ret;
1137
1138
1139}
diff --git a/src/gnutls_io.c b/src/gnutls_io.c
index 14e7cf6..753c87b 100644
--- a/src/gnutls_io.c
+++ b/src/gnutls_io.c
@@ -543,8 +543,7 @@ apr_status_t mgs_filter_output(ap_filter_t * f,
543 apr_bucket *bucket = APR_BRIGADE_FIRST(bb); 543 apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
544 if (AP_BUCKET_IS_EOC(bucket)) { 544 if (AP_BUCKET_IS_EOC(bucket)) {
545 do { 545 do {
546 ret = gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, 546 ret = gnutls_bye( ctxt->session, GNUTLS_SHUT_WR);
547 GNUTLS_A_CLOSE_NOTIFY);
548 } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); 547 } while(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
549 548
550 apr_bucket_copy(bucket, &e); 549 apr_bucket_copy(bucket, &e);
@@ -556,7 +555,6 @@ apr_status_t mgs_filter_output(ap_filter_t * f,
556 } 555 }
557 556
558 apr_brigade_cleanup(ctxt->output_bb); 557 apr_brigade_cleanup(ctxt->output_bb);
559 gnutls_bye(ctxt->session, GNUTLS_SHUT_WR);
560 gnutls_deinit(ctxt->session); 558 gnutls_deinit(ctxt->session);
561 continue; 559 continue;
562 560
@@ -568,6 +566,7 @@ apr_status_t mgs_filter_output(ap_filter_t * f,
568 apr_brigade_cleanup(ctxt->output_bb); 566 apr_brigade_cleanup(ctxt->output_bb);
569 return status; 567 return status;
570 } 568 }
569
571 apr_brigade_cleanup(ctxt->output_bb); 570 apr_brigade_cleanup(ctxt->output_bb);
572 continue; 571 continue;
573 } 572 }
@@ -599,7 +598,7 @@ apr_status_t mgs_filter_output(ap_filter_t * f,
599 ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->output_rc, 598 ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->output_rc,
600 ctxt->c->base_server, 599 ctxt->c->base_server,
601 "GnuTLS: Error writing data." 600 "GnuTLS: Error writing data."
602 " (%d) '%s'", ret, gnutls_strerror(ret)); 601 " (%d) '%s'", (int)ret, gnutls_strerror(ret));
603 if (ctxt->output_rc == APR_SUCCESS) { 602 if (ctxt->output_rc == APR_SUCCESS) {
604 ctxt->output_rc = APR_EGENERAL; 603 ctxt->output_rc = APR_EGENERAL;
605 } 604 }
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index 5ca198d..014bfc8 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -63,15 +63,55 @@ static const command_rec mgs_config_cmds[] = {
63 AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file, 63 AP_INIT_TAKE1("GnuTLSClientCAFile", mgs_set_client_ca_file,
64 NULL, 64 NULL,
65 RSRC_CONF, 65 RSRC_CONF,
66 "Set the CA File for Client Certificates"), 66 "Set the CA File to verify Client Certificates"),
67 AP_INIT_TAKE1("GnuTLSX509CAFile", mgs_set_client_ca_file,
68 NULL,
69 RSRC_CONF,
70 "Set the CA File to verify Client Certificates"),
71 AP_INIT_TAKE1("GnuTLSPGPKeyringFile", mgs_set_keyring_file,
72 NULL,
73 RSRC_CONF,
74 "Set the Keyring File to verify Client Certificates"),
75 AP_INIT_TAKE1("GnuTLSDHFile", mgs_set_dh_file,
76 NULL,
77 RSRC_CONF,
78 "Set the file to read Diffie Hellman parameters from"),
79 AP_INIT_TAKE1("GnuTLSRSAFile", mgs_set_rsa_export_file,
80 NULL,
81 RSRC_CONF,
82 "Set the file to read RSA-EXPORT parameters from"),
67 AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file, 83 AP_INIT_TAKE1("GnuTLSCertificateFile", mgs_set_cert_file,
68 NULL, 84 NULL,
69 RSRC_CONF, 85 RSRC_CONF,
70 "SSL Server Key file"), 86 "SSL Server X509 Certificate file"),
71 AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file, 87 AP_INIT_TAKE1("GnuTLSKeyFile", mgs_set_key_file,
72 NULL, 88 NULL,
73 RSRC_CONF, 89 RSRC_CONF,
74 "SSL Server Certificate file"), 90 "SSL Server X509 Private Key file"),
91 AP_INIT_TAKE1("GnuTLSX509CertificateFile", mgs_set_cert_file,
92 NULL,
93 RSRC_CONF,
94 "SSL Server X509 Certificate file"),
95 AP_INIT_TAKE1("GnuTLSX509KeyFile", mgs_set_key_file,
96 NULL,
97 RSRC_CONF,
98 "SSL Server X509 Private Key file"),
99 AP_INIT_TAKE1("GnuTLSPGPCertificateFile", mgs_set_pgpcert_file,
100 NULL,
101 RSRC_CONF,
102 "SSL Server PGP Certificate file"),
103 AP_INIT_TAKE1("GnuTLSPGPKeyFile", mgs_set_pgpkey_file,
104 NULL,
105 RSRC_CONF,
106 "SSL Server PGP Private key file"),
107 AP_INIT_TAKE1("GnuTLSSRPPasswdFile", mgs_set_srp_tpasswd_file,
108 NULL,
109 RSRC_CONF,
110 "SSL Server SRP Password Conf file"),
111 AP_INIT_TAKE1("GnuTLSSRPPasswdConfFile", mgs_set_srp_tpasswd_conf_file,
112 NULL,
113 RSRC_CONF,
114 "SSL Server SRP Parameters file"),
75 AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout, 115 AP_INIT_TAKE1("GnuTLSCacheTimeout", mgs_set_cache_timeout,
76 NULL, 116 NULL,
77 RSRC_CONF, 117 RSRC_CONF,
@@ -80,10 +120,19 @@ static const command_rec mgs_config_cmds[] = {
80 NULL, 120 NULL,
81 RSRC_CONF, 121 RSRC_CONF,
82 "Cache Configuration"), 122 "Cache Configuration"),
123 AP_INIT_RAW_ARGS("GnuTLSPriorities", mgs_set_priorities,
124 NULL,
125 RSRC_CONF,
126 "The priorities to enable (ciphers, Key exchange, macs, compression)."),
83 AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled, 127 AP_INIT_TAKE1("GnuTLSEnable", mgs_set_enabled,
84 NULL, 128 NULL,
85 RSRC_CONF, 129 RSRC_CONF,
86 "Whether this server has GnuTLS Enabled. Default: Off"), 130 "Whether this server has GnuTLS Enabled. Default: Off"),
131 AP_INIT_TAKE1("GnuTLSExportCertificates", mgs_set_export_certificates_enabled,
132 NULL,
133 RSRC_CONF,
134 "Whether to export PEM encoded certificates to CGIs. Default: Off"),
135#if 0
87 AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section, 136 AP_INIT_RAW_ARGS("<GnuTLSRequire", mgs_set_require_section,
88 NULL, 137 NULL,
89 EXEC_ON_READ|OR_ALL, 138 EXEC_ON_READ|OR_ALL,
@@ -92,6 +141,7 @@ static const command_rec mgs_config_cmds[] = {
92 NULL, 141 NULL,
93 OR_ALL, 142 OR_ALL,
94 "Internal Command for reading Lua Bytecode."), 143 "Internal Command for reading Lua Bytecode."),
144#endif
95 {NULL} 145 {NULL}
96}; 146};
97 147