aboutsummaryrefslogtreecommitdiffstats
path: root/src/gnutls_hooks.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gnutls_hooks.c')
-rw-r--r--src/gnutls_hooks.c1944
1 files changed, 1018 insertions, 926 deletions
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c
index 7c638fb..34c3585 100644
--- a/src/gnutls_hooks.c
+++ b/src/gnutls_hooks.c
@@ -40,179 +40,191 @@ static gnutls_datum session_ticket_key = { NULL, 0 };
40 40
41static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt); 41static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt);
42/* use side==0 for server and side==1 for client */ 42/* use side==0 for server and side==1 for client */
43static void mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, 43static void mgs_add_common_cert_vars(request_rec * r,
44 int side, 44 gnutls_x509_crt_t cert, int side,
45 int export_certificates_enabled);
46static void mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert,
47 int side,
48 int export_certificates_enabled); 45 int export_certificates_enabled);
46static void mgs_add_common_pgpcert_vars(request_rec * r,
47 gnutls_openpgp_crt_t cert,
48 int side,
49 int export_certificates_enabled);
49 50
50static apr_status_t mgs_cleanup_pre_config(void *data) 51static apr_status_t mgs_cleanup_pre_config(void *data)
51{ 52{
52 gnutls_free(session_ticket_key.data); 53 gnutls_free(session_ticket_key.data);
53 session_ticket_key.data = NULL; 54 session_ticket_key.data = NULL;
54 session_ticket_key.size = 0; 55 session_ticket_key.size = 0;
55 gnutls_global_deinit(); 56 gnutls_global_deinit();
56 return APR_SUCCESS; 57 return APR_SUCCESS;
57} 58}
58 59
59#if MOD_GNUTLS_DEBUG 60#if MOD_GNUTLS_DEBUG
60static void gnutls_debug_log_all(int level, const char *str) 61static void gnutls_debug_log_all(int level, const char *str)
61{ 62{
62 apr_file_printf(debug_log_fp, "<%d> %s\n", level, str); 63 apr_file_printf(debug_log_fp, "<%d> %s\n", level, str);
63} 64}
65
64#define _gnutls_log apr_file_printf 66#define _gnutls_log apr_file_printf
65#else 67#else
66# define _gnutls_log(...) 68# define _gnutls_log(...)
67#endif 69#endif
68 70
69int 71int
70mgs_hook_pre_config(apr_pool_t * pconf, 72mgs_hook_pre_config(apr_pool_t * pconf,
71 apr_pool_t * plog, apr_pool_t * ptemp) 73 apr_pool_t * plog, apr_pool_t * ptemp)
72{ 74{
73int ret; 75 int ret;
74 76
75#if MOD_GNUTLS_DEBUG 77#if MOD_GNUTLS_DEBUG
76 apr_file_open(&debug_log_fp, "/tmp/gnutls_debug", 78 apr_file_open(&debug_log_fp, "/tmp/gnutls_debug",
77 APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, 79 APR_APPEND | APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
78 pconf); 80 pconf);
79 81
80 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 82 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
81 83
82 gnutls_global_set_log_level(9); 84 gnutls_global_set_log_level(9);
83 gnutls_global_set_log_function(gnutls_debug_log_all); 85 gnutls_global_set_log_function(gnutls_debug_log_all);
84 _gnutls_log(debug_log_fp, "gnutls: %s\n", gnutls_check_version(NULL)); 86 _gnutls_log(debug_log_fp, "gnutls: %s\n",
87 gnutls_check_version(NULL));
85#endif 88#endif
86 89
87#if APR_HAS_THREADS 90#if APR_HAS_THREADS
88 ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded); 91 ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_is_threaded);
89#if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2 92#if (GNUTLS_VERSION_MAJOR == 2 && GNUTLS_VERSION_MINOR < 11) || GNUTLS_VERSION_MAJOR < 2
90 if (mpm_is_threaded) { 93 if (mpm_is_threaded) {
91 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 94 gcry_control(GCRYCTL_SET_THREAD_CBS,
92 } 95 &gcry_threads_pthread);
96 }
93#endif 97#endif
94#else 98#else
95 mpm_is_threaded = 0; 99 mpm_is_threaded = 0;
96#endif 100#endif
97 101
98 102
99 if (gnutls_check_version(LIBGNUTLS_VERSION)==NULL) { 103 if (gnutls_check_version(LIBGNUTLS_VERSION) == NULL) {
100 _gnutls_log(debug_log_fp, "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n", 104 _gnutls_log(debug_log_fp,
101 LIBGNUTLS_VERSION, gnutls_check_version(NULL)); 105 "gnutls_check_version() failed. Required: gnutls-%s Found: gnutls-%s\n",
102 return -3; 106 LIBGNUTLS_VERSION, gnutls_check_version(NULL));
103 } 107 return -3;
108 }
109
110 ret = gnutls_global_init();
111 if (ret < 0) {
112 _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n",
113 gnutls_strerror(ret));
114 return -3;
115 }
104 116
105 ret = gnutls_global_init(); 117 ret = gnutls_session_ticket_key_generate(&session_ticket_key);
106 if (ret < 0) { 118 if (ret < 0) {
107 _gnutls_log(debug_log_fp, "gnutls_global_init: %s\n", gnutls_strerror(ret)); 119 _gnutls_log(debug_log_fp,
108 return -3; 120 "gnutls_session_ticket_key_generate: %s\n",
109 } 121 gnutls_strerror(ret));
110 122 }
111 ret = gnutls_session_ticket_key_generate( &session_ticket_key);
112 if (ret < 0) {
113 _gnutls_log(debug_log_fp, "gnutls_session_ticket_key_generate: %s\n", gnutls_strerror(ret));
114 }
115 123
116 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config, 124 apr_pool_cleanup_register(pconf, NULL, mgs_cleanup_pre_config,
117 apr_pool_cleanup_null); 125 apr_pool_cleanup_null);
118 126
119 127
120 return OK; 128 return OK;
121} 129}
122 130
123static int mgs_select_virtual_server_cb(gnutls_session_t session) 131static int mgs_select_virtual_server_cb(gnutls_session_t session)
124{ 132{
125 mgs_handle_t *ctxt; 133 mgs_handle_t *ctxt;
126 mgs_srvconf_rec *tsc; 134 mgs_srvconf_rec *tsc;
127 int ret; 135 int ret;
128 int cprio[2]; 136 int cprio[2];
129 137
130 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 138 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
131 139
132 ctxt = gnutls_transport_get_ptr(session); 140 ctxt = gnutls_transport_get_ptr(session);
133 141
134 /* find the virtual server */ 142 /* find the virtual server */
135 tsc = mgs_find_sni_server(session); 143 tsc = mgs_find_sni_server(session);
136 144
137 if (tsc != NULL) 145 if (tsc != NULL)
138 ctxt->sc = tsc; 146 ctxt->sc = tsc;
139 147
140 gnutls_certificate_server_set_request(session, 148 gnutls_certificate_server_set_request(session,
141 ctxt->sc->client_verify_mode); 149 ctxt->
150 sc->client_verify_mode);
142 151
143 /* set the new server credentials 152 /* set the new server credentials
144 */ 153 */
145 154
146 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, 155 gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE,
147 ctxt->sc->certs); 156 ctxt->sc->certs);
148 157
149 gnutls_credentials_set(session, GNUTLS_CRD_ANON, ctxt->sc->anon_creds); 158 gnutls_credentials_set(session, GNUTLS_CRD_ANON,
159 ctxt->sc->anon_creds);
150 160
151#ifdef ENABLE_SRP 161#ifdef ENABLE_SRP
152 if (ctxt->sc->srp_tpasswd_conf_file != NULL 162 if (ctxt->sc->srp_tpasswd_conf_file != NULL
153 && ctxt->sc->srp_tpasswd_file != NULL) { 163 && ctxt->sc->srp_tpasswd_file != NULL) {
154 gnutls_credentials_set(session, GNUTLS_CRD_SRP, 164 gnutls_credentials_set(session, GNUTLS_CRD_SRP,
155 ctxt->sc->srp_creds); 165 ctxt->sc->srp_creds);
156 } 166 }
157#endif 167#endif
158 168
159 /* update the priorities - to avoid negotiating a ciphersuite that is not 169 /* update the priorities - to avoid negotiating a ciphersuite that is not
160 * enabled on this virtual server. Note that here we ignore the version 170 * enabled on this virtual server. Note that here we ignore the version
161 * negotiation. 171 * negotiation.
162 */ 172 */
163 ret = gnutls_priority_set(session, ctxt->sc->priorities); 173 ret = gnutls_priority_set(session, ctxt->sc->priorities);
164 /* actually it shouldn't fail since we have checked at startup */ 174 /* actually it shouldn't fail since we have checked at startup */
165 if (ret < 0) 175 if (ret < 0)
166 return ret; 176 return ret;
167 177
168 /* If both certificate types are not present disallow them from 178 /* If both certificate types are not present disallow them from
169 * being negotiated. 179 * being negotiated.
170 */ 180 */
171 if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) { 181 if (ctxt->sc->certs_x509[0] != NULL && ctxt->sc->cert_pgp == NULL) {
172 cprio[0] = GNUTLS_CRT_X509; 182 cprio[0] = GNUTLS_CRT_X509;
173 cprio[1] = 0; 183 cprio[1] = 0;
174 gnutls_certificate_type_set_priority( session, cprio); 184 gnutls_certificate_type_set_priority(session, cprio);
175 } else if (ctxt->sc->cert_pgp != NULL && ctxt->sc->certs_x509[0]==NULL) { 185 } else if (ctxt->sc->cert_pgp != NULL
176 cprio[0] = GNUTLS_CRT_OPENPGP; 186 && ctxt->sc->certs_x509[0] == NULL) {
177 cprio[1] = 0; 187 cprio[0] = GNUTLS_CRT_OPENPGP;
178 gnutls_certificate_type_set_priority( session, cprio); 188 cprio[1] = 0;
179 } 189 gnutls_certificate_type_set_priority(session, cprio);
180 190 }
181 return 0; 191
192 return 0;
182} 193}
183 194
184static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret) 195static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st * ret)
185{ 196{
186 mgs_handle_t *ctxt; 197 mgs_handle_t *ctxt;
198
199 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
200 ctxt = gnutls_transport_get_ptr(session);
187 201
188 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 202 if (ctxt == NULL)
189 ctxt = gnutls_transport_get_ptr(session); 203 return GNUTLS_E_INTERNAL_ERROR;
190 204
191 if (ctxt == NULL) 205 if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) {
192 return GNUTLS_E_INTERNAL_ERROR; 206 ret->type = GNUTLS_CRT_X509;
207 ret->ncerts = ctxt->sc->certs_x509_num;
208 ret->deinit_all = 0;
193 209
194 if (gnutls_certificate_type_get( session) == GNUTLS_CRT_X509) { 210 ret->cert.x509 = ctxt->sc->certs_x509;
195 ret->type = GNUTLS_CRT_X509; 211 ret->key.x509 = ctxt->sc->privkey_x509;
196 ret->ncerts = ctxt->sc->certs_x509_num;
197 ret->deinit_all = 0;
198 212
199 ret->cert.x509 = ctxt->sc->certs_x509; 213 return 0;
200 ret->key.x509 = ctxt->sc->privkey_x509; 214 } else if (gnutls_certificate_type_get(session) ==
201 215 GNUTLS_CRT_OPENPGP) {
202 return 0; 216 ret->type = GNUTLS_CRT_OPENPGP;
203 } else if (gnutls_certificate_type_get( session) == GNUTLS_CRT_OPENPGP) { 217 ret->ncerts = 1;
204 ret->type = GNUTLS_CRT_OPENPGP; 218 ret->deinit_all = 0;
205 ret->ncerts = 1;
206 ret->deinit_all = 0;
207 219
208 ret->cert.pgp = ctxt->sc->cert_pgp; 220 ret->cert.pgp = ctxt->sc->cert_pgp;
209 ret->key.pgp = ctxt->sc->privkey_pgp; 221 ret->key.pgp = ctxt->sc->privkey_pgp;
210 222
211 return 0; 223 return 0;
212
213 }
214 224
215 return GNUTLS_E_INTERNAL_ERROR; 225 }
226
227 return GNUTLS_E_INTERNAL_ERROR;
216} 228}
217 229
218/* 2048-bit group parameters from SRP specification */ 230/* 2048-bit group parameters from SRP specification */
@@ -233,78 +245,81 @@ const char static_dh_params[] = "-----BEGIN DH PARAMETERS-----\n"
233static int read_crt_cn(server_rec * s, apr_pool_t * p, 245static int read_crt_cn(server_rec * s, apr_pool_t * p,
234 gnutls_x509_crt_t cert, char **cert_cn) 246 gnutls_x509_crt_t cert, char **cert_cn)
235{ 247{
236 int rv = 0, i; 248 int rv = 0, i;
237 size_t data_len; 249 size_t data_len;
238
239 250
240 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
241 *cert_cn = NULL;
242 251
243 data_len = 0; 252 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
244 rv = gnutls_x509_crt_get_dn_by_oid(cert, 253 *cert_cn = NULL;
245 GNUTLS_OID_X520_COMMON_NAME,
246 0, 0, NULL, &data_len);
247 254
248 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 255 data_len = 0;
249 *cert_cn = apr_palloc(p, data_len);
250 rv = gnutls_x509_crt_get_dn_by_oid(cert, 256 rv = gnutls_x509_crt_get_dn_by_oid(cert,
251 GNUTLS_OID_X520_COMMON_NAME, 0, 257 GNUTLS_OID_X520_COMMON_NAME,
252 0, *cert_cn, &data_len); 258 0, 0, NULL, &data_len);
253 } else { /* No CN return subject alternative name */ 259
254 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, 260 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
255 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...", 261 *cert_cn = apr_palloc(p, data_len);
256 s->server_hostname, s->port); 262 rv = gnutls_x509_crt_get_dn_by_oid(cert,
257 rv = 0; 263 GNUTLS_OID_X520_COMMON_NAME,
258 /* read subject alternative name */ 264 0, 0, *cert_cn,
259 for (i = 0; !(rv < 0); i++) { 265 &data_len);
260 data_len = 0; 266 } else { /* No CN return subject alternative name */
261 rv = gnutls_x509_crt_get_subject_alt_name(cert, i, 267 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
262 NULL, &data_len, 268 "No common name found in certificate for '%s:%d'. Looking for subject alternative name...",
263 NULL); 269 s->server_hostname, s->port);
264 270 rv = 0;
265 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 271 /* read subject alternative name */
266 /* FIXME: not very efficient. What if we have several alt names 272 for (i = 0; !(rv < 0); i++) {
267 * before DNSName? 273 data_len = 0;
268 */ 274 rv = gnutls_x509_crt_get_subject_alt_name(cert, i,
269 *cert_cn = apr_palloc(p, data_len + 1); 275 NULL,
270 276 &data_len,
271 rv = gnutls_x509_crt_get_subject_alt_name(cert, i, 277 NULL);
272 *cert_cn, 278
273 &data_len, NULL); 279 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER
274 (*cert_cn)[data_len] = 0; 280 && data_len > 1) {
275 281 /* FIXME: not very efficient. What if we have several alt names
276 if (rv == GNUTLS_SAN_DNSNAME) 282 * before DNSName?
277 break; 283 */
278 } 284 *cert_cn = apr_palloc(p, data_len + 1);
285
286 rv = gnutls_x509_crt_get_subject_alt_name
287 (cert, i, *cert_cn, &data_len, NULL);
288 (*cert_cn)[data_len] = 0;
289
290 if (rv == GNUTLS_SAN_DNSNAME)
291 break;
292 }
293 }
279 } 294 }
280 }
281 295
282 return rv; 296 return rv;
283} 297}
284 298
285static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p, 299static int read_pgpcrt_cn(server_rec * s, apr_pool_t * p,
286 gnutls_openpgp_crt_t cert, char **cert_cn) 300 gnutls_openpgp_crt_t cert, char **cert_cn)
287{ 301{
288 int rv = 0; 302 int rv = 0;
289 size_t data_len; 303 size_t data_len;
290 304
291 305
292 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 306 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
293 *cert_cn = NULL; 307 *cert_cn = NULL;
294 308
295 data_len = 0; 309 data_len = 0;
296 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len); 310 rv = gnutls_openpgp_crt_get_name(cert, 0, NULL, &data_len);
297 311
298 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) { 312 if (rv == GNUTLS_E_SHORT_MEMORY_BUFFER && data_len > 1) {
299 *cert_cn = apr_palloc(p, data_len); 313 *cert_cn = apr_palloc(p, data_len);
300 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn, &data_len); 314 rv = gnutls_openpgp_crt_get_name(cert, 0, *cert_cn,
301 } else { /* No CN return subject alternative name */ 315 &data_len);
302 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, 316 } else { /* No CN return subject alternative name */
303 "No name found in PGP certificate for '%s:%d'.", 317 ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
304 s->server_hostname, s->port); 318 "No name found in PGP certificate for '%s:%d'.",
305 } 319 s->server_hostname, s->port);
320 }
306 321
307 return rv; 322 return rv;
308} 323}
309 324
310 325
@@ -312,27 +327,27 @@ int
312mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog, 327mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
313 apr_pool_t * ptemp, server_rec * base_server) 328 apr_pool_t * ptemp, server_rec * base_server)
314{ 329{
315 int rv; 330 int rv;
316 server_rec *s; 331 server_rec *s;
317 gnutls_dh_params_t dh_params = NULL; 332 gnutls_dh_params_t dh_params = NULL;
318 gnutls_rsa_params_t rsa_params = NULL; 333 gnutls_rsa_params_t rsa_params = NULL;
319 mgs_srvconf_rec *sc; 334 mgs_srvconf_rec *sc;
320 mgs_srvconf_rec *sc_base; 335 mgs_srvconf_rec *sc_base;
321 void *data = NULL; 336 void *data = NULL;
322 int first_run = 0; 337 int first_run = 0;
323 const char *userdata_key = "mgs_init"; 338 const char *userdata_key = "mgs_init";
324 339
325 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 340 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
326 apr_pool_userdata_get(&data, userdata_key, base_server->process->pool); 341 apr_pool_userdata_get(&data, userdata_key,
327 if (data == NULL) {
328 first_run = 1;
329 apr_pool_userdata_set((const void *) 1, userdata_key,
330 apr_pool_cleanup_null,
331 base_server->process->pool); 342 base_server->process->pool);
332 } 343 if (data == NULL) {
344 first_run = 1;
345 apr_pool_userdata_set((const void *) 1, userdata_key,
346 apr_pool_cleanup_null,
347 base_server->process->pool);
348 }
333 349
334 350
335 {
336 s = base_server; 351 s = base_server;
337 sc_base = 352 sc_base =
338 (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 353 (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
@@ -341,545 +356,568 @@ mgs_hook_post_config(apr_pool_t * p, apr_pool_t * plog,
341 gnutls_dh_params_init(&dh_params); 356 gnutls_dh_params_init(&dh_params);
342 357
343 if (sc_base->dh_params == NULL) { 358 if (sc_base->dh_params == NULL) {
344 gnutls_datum pdata = { (void *) static_dh_params, sizeof(static_dh_params) }; 359 gnutls_datum pdata = {
345 /* loading defaults */ 360 (void *) static_dh_params,
346 rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata, 361 sizeof(static_dh_params)
347 GNUTLS_X509_FMT_PEM); 362 };
348 363 /* loading defaults */
349 if (rv < 0) { 364 rv = gnutls_dh_params_import_pkcs3(dh_params, &pdata,
350 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 365 GNUTLS_X509_FMT_PEM);
351 "GnuTLS: Unable to load DH Params: (%d) %s", 366
352 rv, gnutls_strerror(rv)); 367 if (rv < 0) {
353 exit(rv); 368 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
354 } 369 "GnuTLS: Unable to load DH Params: (%d) %s",
355 } else dh_params = sc_base->dh_params; 370 rv, gnutls_strerror(rv));
356 371 exit(rv);
357 if (sc_base->rsa_params != NULL) 372 }
358 rsa_params = sc_base->rsa_params; 373 } else
374 dh_params = sc_base->dh_params;
375
376 if (sc_base->rsa_params != NULL)
377 rsa_params = sc_base->rsa_params;
359 378
360 /* else not an error but RSA-EXPORT ciphersuites are not available 379 /* else not an error but RSA-EXPORT ciphersuites are not available
361 */ 380 */
362 381
363 rv = mgs_cache_post_config(p, s, sc_base); 382 rv = mgs_cache_post_config(p, s, sc_base);
364 if (rv != 0) { 383 if (rv != 0) {
365 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s, 384 ap_log_error(APLOG_MARK, APLOG_STARTUP, rv, s,
366 "GnuTLS: Post Config for GnuTLSCache Failed." 385 "GnuTLS: Post Config for GnuTLSCache Failed."
367 " Shutting Down."); 386 " Shutting Down.");
368 exit(-1); 387 exit(-1);
369 } 388 }
370 389
371 for (s = base_server; s; s = s->next) { 390 for (s = base_server; s; s = s->next) {
372 void *load = NULL; 391 void *load = NULL;
373 sc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 392 sc = (mgs_srvconf_rec *)
374 &gnutls_module); 393 ap_get_module_config(s->module_config, &gnutls_module);
375 sc->cache_type = sc_base->cache_type; 394 sc->cache_type = sc_base->cache_type;
376 sc->cache_config = sc_base->cache_config; 395 sc->cache_config = sc_base->cache_config;
377 396
378 /* Check if the priorities have been set */ 397 /* Check if the priorities have been set */
379 if (sc->priorities == NULL && sc->enabled == GNUTLS_ENABLED_TRUE) { 398 if (sc->priorities == NULL
380 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 399 && sc->enabled == GNUTLS_ENABLED_TRUE) {
381 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!", 400 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
382 s->server_hostname, s->port); 401 "GnuTLS: Host '%s:%d' is missing the GnuTLSPriorities directive!",
383 exit(-1); 402 s->server_hostname, s->port);
384 } 403 exit(-1);
385 404 }
386 /* Check if DH or RSA params have been set per host */ 405
387 if (sc->rsa_params != NULL) 406 /* Check if DH or RSA params have been set per host */
388 load = sc->rsa_params; 407 if (sc->rsa_params != NULL)
389 else if (rsa_params) load = rsa_params; 408 load = sc->rsa_params;
390 409 else if (rsa_params)
391 if (load != NULL) 410 load = rsa_params;
392 gnutls_certificate_set_rsa_export_params(sc->certs, load); 411
393 412 if (load != NULL)
394 413 gnutls_certificate_set_rsa_export_params(sc->certs,
395 load = NULL; 414 load);
396 if (sc->dh_params != NULL) 415
397 load = sc->dh_params; 416
398 else if (dh_params) load = dh_params; 417 load = NULL;
399 418 if (sc->dh_params != NULL)
400 if (load != NULL) { /* not needed but anyway */ 419 load = sc->dh_params;
401 gnutls_certificate_set_dh_params(sc->certs, load); 420 else if (dh_params)
402 gnutls_anon_set_server_dh_params(sc->anon_creds, load); 421 load = dh_params;
403 } 422
404 423 if (load != NULL) { /* not needed but anyway */
405 gnutls_certificate_server_set_retrieve_function(sc->certs, 424 gnutls_certificate_set_dh_params(sc->certs, load);
406 cert_retrieve_fn); 425 gnutls_anon_set_server_dh_params(sc->anon_creds,
426 load);
427 }
428
429 gnutls_certificate_server_set_retrieve_function(sc->certs,
430 cert_retrieve_fn);
407 431
408#ifdef ENABLE_SRP 432#ifdef ENABLE_SRP
409 if (sc->srp_tpasswd_conf_file != NULL 433 if (sc->srp_tpasswd_conf_file != NULL
410 && sc->srp_tpasswd_file != NULL) { 434 && sc->srp_tpasswd_file != NULL) {
411 rv = gnutls_srp_set_server_credentials_file(sc->srp_creds, 435 rv = gnutls_srp_set_server_credentials_file
412 sc-> 436 (sc->srp_creds, sc->srp_tpasswd_file,
413 srp_tpasswd_file, 437 sc->srp_tpasswd_conf_file);
414 sc-> 438
415 srp_tpasswd_conf_file); 439 if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) {
416 440 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0,
417 if (rv < 0 && sc->enabled == GNUTLS_ENABLED_TRUE) { 441 s,
418 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 442 "[GnuTLS] - Host '%s:%d' is missing a "
419 "[GnuTLS] - Host '%s:%d' is missing a " 443 "SRP password or conf File!",
420 "SRP password or conf File!", 444 s->server_hostname, s->port);
421 s->server_hostname, s->port); 445 exit(-1);
422 exit(-1); 446 }
423 } 447 }
424 }
425#endif 448#endif
426 449
427 if (sc->certs_x509[0] == NULL && 450 if (sc->certs_x509[0] == NULL &&
428 sc->cert_pgp == NULL && 451 sc->cert_pgp == NULL &&
429 sc->enabled == GNUTLS_ENABLED_TRUE) { 452 sc->enabled == GNUTLS_ENABLED_TRUE) {
430 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 453 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
431 "[GnuTLS] - Host '%s:%d' is missing a " 454 "[GnuTLS] - Host '%s:%d' is missing a "
432 "Certificate File!", s->server_hostname, 455 "Certificate File!",
433 s->port); 456 s->server_hostname, s->port);
434 exit(-1); 457 exit(-1);
435 } 458 }
436
437 if (sc->enabled == GNUTLS_ENABLED_TRUE &&
438 ((sc->certs_x509[0] != NULL && sc->privkey_x509 == NULL) ||
439 (sc->cert_pgp != NULL && sc->privkey_pgp == NULL))) {
440 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
441 "[GnuTLS] - Host '%s:%d' is missing a "
442 "Private Key File!",
443 s->server_hostname, s->port);
444 exit(-1);
445 }
446 459
447 if (sc->enabled == GNUTLS_ENABLED_TRUE) { 460 if (sc->enabled == GNUTLS_ENABLED_TRUE &&
448 rv = read_crt_cn(s, p, sc->certs_x509[0], &sc->cert_cn); 461 ((sc->certs_x509[0] != NULL
449 if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */ 462 && sc->privkey_x509 == NULL) || (sc->cert_pgp != NULL
450 rv = read_pgpcrt_cn(s, p, sc->cert_pgp, &sc->cert_cn); 463 && sc->privkey_pgp
464 == NULL))) {
465 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s,
466 "[GnuTLS] - Host '%s:%d' is missing a "
467 "Private Key File!",
468 s->server_hostname, s->port);
469 exit(-1);
470 }
451 471
452 if (rv < 0) { 472 if (sc->enabled == GNUTLS_ENABLED_TRUE) {
453 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, 473 rv = read_crt_cn(s, p, sc->certs_x509[0],
454 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!", 474 &sc->cert_cn);
455 s->server_hostname, s->port); 475 if (rv < 0 && sc->cert_pgp != NULL) /* try openpgp certificate */
456 sc->cert_cn = NULL; 476 rv = read_pgpcrt_cn(s, p, sc->cert_pgp,
457 continue; 477 &sc->cert_cn);
478
479 if (rv < 0) {
480 ap_log_error(APLOG_MARK, APLOG_STARTUP, 0,
481 s,
482 "[GnuTLS] - Cannot find a certificate for host '%s:%d'!",
483 s->server_hostname, s->port);
484 sc->cert_cn = NULL;
485 continue;
486 }
458 } 487 }
459 }
460 } 488 }
461 }
462 489
463 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION);
464 490
465 return OK; 491 ap_add_version_component(p, "mod_gnutls/" MOD_GNUTLS_VERSION);
492
493 return OK;
466} 494}
467 495
468void mgs_hook_child_init(apr_pool_t * p, server_rec * s) 496void mgs_hook_child_init(apr_pool_t * p, server_rec * s)
469{ 497{
470 apr_status_t rv = APR_SUCCESS; 498 apr_status_t rv = APR_SUCCESS;
471 mgs_srvconf_rec *sc = ap_get_module_config(s->module_config, 499 mgs_srvconf_rec *sc = ap_get_module_config(s->module_config,
472 &gnutls_module); 500 &gnutls_module);
473 501
474 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 502 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
475 if (sc->cache_type != mgs_cache_none) { 503 if (sc->cache_type != mgs_cache_none) {
476 rv = mgs_cache_child_init(p, s, sc); 504 rv = mgs_cache_child_init(p, s, sc);
477 if (rv != APR_SUCCESS) { 505 if (rv != APR_SUCCESS) {
478 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, 506 ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
479 "[GnuTLS] - Failed to run Cache Init"); 507 "[GnuTLS] - Failed to run Cache Init");
508 }
509 } else {
510 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s,
511 "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache");
480 } 512 }
481 } else {
482 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, s,
483 "[GnuTLS] - No Cache Configured. Hint: GnuTLSCache");
484 }
485} 513}
486 514
487const char *mgs_hook_http_scheme(const request_rec * r) 515const char *mgs_hook_http_scheme(const request_rec * r)
488{ 516{
489 mgs_srvconf_rec *sc; 517 mgs_srvconf_rec *sc;
490
491 if (r == NULL)
492 return NULL;
493
494 sc =
495 (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config,
496 &gnutls_module);
497
498 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
499 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
500 return NULL;
501 }
502 518
503 return "https"; 519 if (r == NULL)
520 return NULL;
521
522 sc = (mgs_srvconf_rec *) ap_get_module_config(r->
523 server->module_config,
524 &gnutls_module);
525
526 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
527 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
528 return NULL;
529 }
530
531 return "https";
504} 532}
505 533
506apr_port_t mgs_hook_default_port(const request_rec * r) 534apr_port_t mgs_hook_default_port(const request_rec * r)
507{ 535{
508 mgs_srvconf_rec *sc; 536 mgs_srvconf_rec *sc;
509 537
510 if (r == NULL) 538 if (r == NULL)
511 return 0; 539 return 0;
512 540
513 sc = 541 sc = (mgs_srvconf_rec *) ap_get_module_config(r->
514 (mgs_srvconf_rec *) ap_get_module_config(r->server->module_config, 542 server->module_config,
515 &gnutls_module); 543 &gnutls_module);
516 544
517 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 545 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
518 if (sc->enabled == GNUTLS_ENABLED_FALSE) { 546 if (sc->enabled == GNUTLS_ENABLED_FALSE) {
519 return 0; 547 return 0;
520 } 548 }
521 549
522 return 443; 550 return 443;
523} 551}
524 552
525#define MAX_HOST_LEN 255 553#define MAX_HOST_LEN 255
526 554
527#if USING_2_1_RECENT 555#if USING_2_1_RECENT
528typedef struct { 556typedef struct {
529 mgs_handle_t *ctxt; 557 mgs_handle_t *ctxt;
530 mgs_srvconf_rec *sc; 558 mgs_srvconf_rec *sc;
531 const char *sni_name; 559 const char *sni_name;
532} vhost_cb_rec; 560} vhost_cb_rec;
533 561
534static int vhost_cb(void *baton, conn_rec * conn, server_rec * s) 562static int vhost_cb(void *baton, conn_rec * conn, server_rec * s)
535{ 563{
536 mgs_srvconf_rec *tsc; 564 mgs_srvconf_rec *tsc;
537 vhost_cb_rec *x = baton; 565 vhost_cb_rec *x = baton;
538 566
539 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 567 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
540 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 568 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config,
541 &gnutls_module); 569 &gnutls_module);
542 570
543 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { 571 if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) {
544 return 0; 572 return 0;
545 } 573 }
546 574
547 /* The CN can contain a * -- this will match those too. */ 575 /* The CN can contain a * -- this will match those too. */
548 if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { 576 if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) {
549 /* found a match */ 577 /* found a match */
550#if MOD_GNUTLS_DEBUG 578#if MOD_GNUTLS_DEBUG
551 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 579 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
552 x->ctxt->c->base_server, 580 x->ctxt->c->base_server,
553 "GnuTLS: Virtual Host CB: " 581 "GnuTLS: Virtual Host CB: "
554 "'%s' == '%s'", tsc->cert_cn, x->sni_name); 582 "'%s' == '%s'", tsc->cert_cn, x->sni_name);
555#endif 583#endif
556 /* Because we actually change the server used here, we need to reset 584 /* Because we actually change the server used here, we need to reset
557 * things like ClientVerify. 585 * things like ClientVerify.
558 */ 586 */
559 x->sc = tsc; 587 x->sc = tsc;
560 /* Shit. Crap. Dammit. We *really* should rehandshake here, as our 588 /* Shit. Crap. Dammit. We *really* should rehandshake here, as our
561 * certificate structure *should* change when the server changes. 589 * certificate structure *should* change when the server changes.
562 * acccckkkkkk. 590 * acccckkkkkk.
563 */ 591 */
564 return 1; 592 return 1;
565 } else { 593 } else {
566#if MOD_GNUTLS_DEBUG 594#if MOD_GNUTLS_DEBUG
567 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 595 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
568 x->ctxt->c->base_server, 596 x->ctxt->c->base_server,
569 "GnuTLS: Virtual Host CB: " 597 "GnuTLS: Virtual Host CB: "
570 "'%s' != '%s'", tsc->cert_cn, x->sni_name); 598 "'%s' != '%s'", tsc->cert_cn, x->sni_name);
571#endif 599#endif
572 600
573 } 601 }
574 return 0; 602 return 0;
575} 603}
576#endif 604#endif
577 605
578mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session) 606mgs_srvconf_rec *mgs_find_sni_server(gnutls_session_t session)
579{ 607{
580 int rv; 608 int rv;
581 unsigned int sni_type; 609 unsigned int sni_type;
582 size_t data_len = MAX_HOST_LEN; 610 size_t data_len = MAX_HOST_LEN;
583 char sni_name[MAX_HOST_LEN]; 611 char sni_name[MAX_HOST_LEN];
584 mgs_handle_t *ctxt; 612 mgs_handle_t *ctxt;
585#if USING_2_1_RECENT 613#if USING_2_1_RECENT
586 vhost_cb_rec cbx; 614 vhost_cb_rec cbx;
587#else 615#else
588 server_rec *s; 616 server_rec *s;
589 mgs_srvconf_rec *tsc; 617 mgs_srvconf_rec *tsc;
590#endif 618#endif
591 619
592 if (session == NULL) 620 if (session == NULL)
593 return NULL; 621 return NULL;
594 622
595 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 623 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
596 ctxt = gnutls_transport_get_ptr(session); 624 ctxt = gnutls_transport_get_ptr(session);
597 625
598 rv = gnutls_server_name_get(ctxt->session, sni_name, 626 rv = gnutls_server_name_get(ctxt->session, sni_name,
599 &data_len, &sni_type, 0); 627 &data_len, &sni_type, 0);
600 628
601 if (rv != 0) { 629 if (rv != 0) {
602 return NULL; 630 return NULL;
603 } 631 }
604 632
605 if (sni_type != GNUTLS_NAME_DNS) { 633 if (sni_type != GNUTLS_NAME_DNS) {
606 ap_log_error(APLOG_MARK, APLOG_CRIT, 0, 634 ap_log_error(APLOG_MARK, APLOG_CRIT, 0,
607 ctxt->c->base_server, 635 ctxt->c->base_server,
608 "GnuTLS: Unknown type '%d' for SNI: " 636 "GnuTLS: Unknown type '%d' for SNI: "
609 "'%s'", sni_type, sni_name); 637 "'%s'", sni_type, sni_name);
610 return NULL; 638 return NULL;
611 } 639 }
612 640
613 /** 641 /**
614 * Code in the Core already sets up the c->base_server as the base 642 * Code in the Core already sets up the c->base_server as the base
615 * for this IP/Port combo. Trust that the core did the 'right' thing. 643 * for this IP/Port combo. Trust that the core did the 'right' thing.
616 */ 644 */
617#if USING_2_1_RECENT 645#if USING_2_1_RECENT
618 cbx.ctxt = ctxt; 646 cbx.ctxt = ctxt;
619 cbx.sc = NULL; 647 cbx.sc = NULL;
620 cbx.sni_name = sni_name; 648 cbx.sni_name = sni_name;
621
622 rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx);
623 if (rv == 1) {
624 return cbx.sc;
625 }
626#else
627 for (s = ap_server_conf; s; s = s->next) {
628 649
629 tsc = (mgs_srvconf_rec *) ap_get_module_config(s->module_config, 650 rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx);
630 &gnutls_module); 651 if (rv == 1) {
631 if (tsc->enabled != GNUTLS_ENABLED_TRUE) { 652 return cbx.sc;
632 continue;
633 } 653 }
654#else
655 for (s = ap_server_conf; s; s = s->next) {
656
657 tsc =
658 (mgs_srvconf_rec *)
659 ap_get_module_config(s->module_config, &gnutls_module);
660 if (tsc->enabled != GNUTLS_ENABLED_TRUE) {
661 continue;
662 }
634#if MOD_GNUTLS_DEBUG 663#if MOD_GNUTLS_DEBUG
635 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 664 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
636 ctxt->c->base_server, 665 ctxt->c->base_server,
637 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", 666 "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X",
638 tsc->cert_cn, rv, 667 tsc->cert_cn, rv,
639 gnutls_pk_algorithm_get_name 668 gnutls_pk_algorithm_get_name
640 (gnutls_x509_privkey_get_pk_algorithm 669 (gnutls_x509_privkey_get_pk_algorithm
641 (ctxt->sc->privkey_x509)), (unsigned int) s, 670 (ctxt->sc->privkey_x509)), (unsigned int) s,
642 (unsigned int) s->next, (unsigned int) tsc); 671 (unsigned int) s->next, (unsigned int) tsc);
643#endif 672#endif
644 /* The CN can contain a * -- this will match those too. */ 673 /* The CN can contain a * -- this will match those too. */
645 if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { 674 if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) {
646#if MOD_GNUTLS_DEBUG 675#if MOD_GNUTLS_DEBUG
647 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, 676 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,
648 ctxt->c->base_server, 677 ctxt->c->base_server,
649 "GnuTLS: Virtual Host: " 678 "GnuTLS: Virtual Host: "
650 "'%s' == '%s'", tsc->cert_cn, sni_name); 679 "'%s' == '%s'", tsc->cert_cn,
680 sni_name);
651#endif 681#endif
652 return tsc; 682 return tsc;
683 }
653 } 684 }
654 }
655#endif 685#endif
656 return NULL; 686 return NULL;
657} 687}
658 688
659 689
660static const int protocol_priority[] = { 690static const int protocol_priority[] = {
661 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 691 GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0
662}; 692};
663 693
664 694
665static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c) 695static mgs_handle_t *create_gnutls_handle(apr_pool_t * pool, conn_rec * c)
666{ 696{
667 mgs_handle_t *ctxt; 697 mgs_handle_t *ctxt;
668 mgs_srvconf_rec *sc = 698 mgs_srvconf_rec *sc =
669 (mgs_srvconf_rec *) ap_get_module_config(c->base_server-> 699 (mgs_srvconf_rec *) ap_get_module_config(c->base_server->
670 module_config, 700 module_config,
671 &gnutls_module); 701 &gnutls_module);
672 702
673 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 703 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
674 ctxt = apr_pcalloc(pool, sizeof(*ctxt)); 704 ctxt = apr_pcalloc(pool, sizeof(*ctxt));
675 ctxt->c = c; 705 ctxt->c = c;
676 ctxt->sc = sc; 706 ctxt->sc = sc;
677 ctxt->status = 0; 707 ctxt->status = 0;
678 708
679 ctxt->input_rc = APR_SUCCESS; 709 ctxt->input_rc = APR_SUCCESS;
680 ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc); 710 ctxt->input_bb = apr_brigade_create(c->pool, c->bucket_alloc);
681 ctxt->input_cbuf.length = 0; 711 ctxt->input_cbuf.length = 0;
682 712
683 ctxt->output_rc = APR_SUCCESS; 713 ctxt->output_rc = APR_SUCCESS;
684 ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc); 714 ctxt->output_bb = apr_brigade_create(c->pool, c->bucket_alloc);
685 ctxt->output_blen = 0; 715 ctxt->output_blen = 0;
686 ctxt->output_length = 0; 716 ctxt->output_length = 0;
687 717
688 gnutls_init(&ctxt->session, GNUTLS_SERVER); 718 gnutls_init(&ctxt->session, GNUTLS_SERVER);
689 if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0) 719 if (session_ticket_key.data != NULL && ctxt->sc->tickets != 0)
690 gnutls_session_ticket_enable_server(ctxt->session, &session_ticket_key); 720 gnutls_session_ticket_enable_server(ctxt->session,
691 721 &session_ticket_key);
692 /* because we don't set any default priorities here (we set later at 722
693 * the user hello callback) we need to at least set this in order for 723 /* because we don't set any default priorities here (we set later at
694 * gnutls to be able to read packets. 724 * the user hello callback) we need to at least set this in order for
695 */ 725 * gnutls to be able to read packets.
696 gnutls_protocol_set_priority(ctxt->session, protocol_priority); 726 */
727 gnutls_protocol_set_priority(ctxt->session, protocol_priority);
697 728
698 gnutls_handshake_set_post_client_hello_function(ctxt->session, 729 gnutls_handshake_set_post_client_hello_function(ctxt->session,
699 mgs_select_virtual_server_cb); 730 mgs_select_virtual_server_cb);
700 731
701 mgs_cache_session_init(ctxt); 732 mgs_cache_session_init(ctxt);
702 733
703 return ctxt; 734 return ctxt;
704} 735}
705 736
706int mgs_hook_pre_connection(conn_rec * c, void *csd) 737int mgs_hook_pre_connection(conn_rec * c, void *csd)
707{ 738{
708 mgs_handle_t *ctxt; 739 mgs_handle_t *ctxt;
709 mgs_srvconf_rec *sc; 740 mgs_srvconf_rec *sc;
710 741
711 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 742 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
712 743
713 if (c == NULL) 744 if (c == NULL)
714 return DECLINED; 745 return DECLINED;
715
716 sc =
717 (mgs_srvconf_rec *) ap_get_module_config(c->base_server->
718 module_config,
719 &gnutls_module);
720
721 if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) {
722 return DECLINED;
723 }
724 746
725 if(c->remote_addr->hostname) 747 sc = (mgs_srvconf_rec *) ap_get_module_config(c->base_server->
726 /* Connection initiated by Apache (mod_proxy) => ignore */ 748 module_config,
727 return OK; 749 &gnutls_module);
728 750
729 ctxt = create_gnutls_handle(c->pool, c); 751 if (!(sc && (sc->enabled == GNUTLS_ENABLED_TRUE))) {
752 return DECLINED;
753 }
754
755 if (c->remote_addr->hostname)
756 /* Connection initiated by Apache (mod_proxy) => ignore */
757 return OK;
758
759 ctxt = create_gnutls_handle(c->pool, c);
730 760
731 ap_set_module_config(c->conn_config, &gnutls_module, ctxt); 761 ap_set_module_config(c->conn_config, &gnutls_module, ctxt);
732 762
733 gnutls_transport_set_pull_function(ctxt->session, mgs_transport_read); 763 gnutls_transport_set_pull_function(ctxt->session,
734 gnutls_transport_set_push_function(ctxt->session, mgs_transport_write); 764 mgs_transport_read);
735 gnutls_transport_set_ptr(ctxt->session, ctxt); 765 gnutls_transport_set_push_function(ctxt->session,
766 mgs_transport_write);
767 gnutls_transport_set_ptr(ctxt->session, ctxt);
736 768
737 ctxt->input_filter = 769 ctxt->input_filter =
738 ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c); 770 ap_add_input_filter(GNUTLS_INPUT_FILTER_NAME, ctxt, NULL, c);
739 ctxt->output_filter = 771 ctxt->output_filter =
740 ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c); 772 ap_add_output_filter(GNUTLS_OUTPUT_FILTER_NAME, ctxt, NULL, c);
741 773
742 return OK; 774 return OK;
743} 775}
744 776
745int mgs_hook_fixups(request_rec * r) 777int mgs_hook_fixups(request_rec * r)
746{ 778{
747 unsigned char sbuf[GNUTLS_MAX_SESSION_ID]; 779 unsigned char sbuf[GNUTLS_MAX_SESSION_ID];
748 char buf[AP_IOBUFSIZE]; 780 char buf[AP_IOBUFSIZE];
749 const char *tmp; 781 const char *tmp;
750 size_t len; 782 size_t len;
751 mgs_handle_t *ctxt; 783 mgs_handle_t *ctxt;
752 int rv = OK; 784 int rv = OK;
753 785
754 if (r == NULL) 786 if (r == NULL)
755 return DECLINED; 787 return DECLINED;
756 788
757 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 789 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
758 apr_table_t *env = r->subprocess_env; 790 apr_table_t *env = r->subprocess_env;
759 791
760 ctxt = 792 ctxt =
761 ap_get_module_config(r->connection->conn_config, &gnutls_module); 793 ap_get_module_config(r->connection->conn_config,
794 &gnutls_module);
762 795
763 if (!ctxt || ctxt->session == NULL) { 796 if (!ctxt || ctxt->session == NULL) {
764 return DECLINED; 797 return DECLINED;
765 } 798 }
766 799
767 apr_table_setn(env, "HTTPS", "on"); 800 apr_table_setn(env, "HTTPS", "on");
768 801
769 apr_table_setn(env, "SSL_VERSION_LIBRARY", 802 apr_table_setn(env, "SSL_VERSION_LIBRARY",
770 "GnuTLS/" LIBGNUTLS_VERSION); 803 "GnuTLS/" LIBGNUTLS_VERSION);
771 apr_table_setn(env, "SSL_VERSION_INTERFACE", 804 apr_table_setn(env, "SSL_VERSION_INTERFACE",
772 "mod_gnutls/" MOD_GNUTLS_VERSION); 805 "mod_gnutls/" MOD_GNUTLS_VERSION);
773 806
774 apr_table_setn(env, "SSL_PROTOCOL", 807 apr_table_setn(env, "SSL_PROTOCOL",
775 gnutls_protocol_get_name(gnutls_protocol_get_version 808 gnutls_protocol_get_name(gnutls_protocol_get_version
776 (ctxt->session))); 809 (ctxt->session)));
777 810
778 /* should have been called SSL_CIPHERSUITE instead */ 811 /* should have been called SSL_CIPHERSUITE instead */
779 apr_table_setn(env, "SSL_CIPHER", 812 apr_table_setn(env, "SSL_CIPHER",
780 gnutls_cipher_suite_get_name(gnutls_kx_get 813 gnutls_cipher_suite_get_name(gnutls_kx_get
781 (ctxt->session), 814 (ctxt->session),
782 gnutls_cipher_get(ctxt-> 815 gnutls_cipher_get
783 session), 816 (ctxt->session),
784 gnutls_mac_get(ctxt-> 817 gnutls_mac_get
785 session))); 818 (ctxt->session)));
786 819
787 apr_table_setn(env, "SSL_COMPRESS_METHOD", 820 apr_table_setn(env, "SSL_COMPRESS_METHOD",
788 gnutls_compression_get_name(gnutls_compression_get 821 gnutls_compression_get_name(gnutls_compression_get
789 (ctxt->session))); 822 (ctxt->session)));
790 823
791#ifdef ENABLE_SRP 824#ifdef ENABLE_SRP
792 tmp = gnutls_srp_server_get_username(ctxt->session); 825 tmp = gnutls_srp_server_get_username(ctxt->session);
793 apr_table_setn(env, "SSL_SRP_USER", (tmp!=NULL)?tmp:""); 826 apr_table_setn(env, "SSL_SRP_USER", (tmp != NULL) ? tmp : "");
794#endif 827#endif
795 828
796 if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL) 829 if (apr_table_get(env, "SSL_CLIENT_VERIFY") == NULL)
797 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE"); 830 apr_table_setn(env, "SSL_CLIENT_VERIFY", "NONE");
798 831
799 unsigned int key_size = 832 unsigned int key_size =
800 8 * gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session)); 833 8 *
801 tmp = apr_psprintf(r->pool, "%u", key_size); 834 gnutls_cipher_get_key_size(gnutls_cipher_get(ctxt->session));
835 tmp = apr_psprintf(r->pool, "%u", key_size);
802 836
803 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp); 837 apr_table_setn(env, "SSL_CIPHER_USEKEYSIZE", tmp);
804 838
805 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp); 839 apr_table_setn(env, "SSL_CIPHER_ALGKEYSIZE", tmp);
806 840
807 apr_table_setn(env, "SSL_CIPHER_EXPORT", 841 apr_table_setn(env, "SSL_CIPHER_EXPORT",
808 (key_size <= 40) ? "true" : "false"); 842 (key_size <= 40) ? "true" : "false");
809 843
810 len = sizeof(sbuf); 844 len = sizeof(sbuf);
811 gnutls_session_get_id(ctxt->session, sbuf, &len); 845 gnutls_session_get_id(ctxt->session, sbuf, &len);
812 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 846 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
813 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp)); 847 apr_table_setn(env, "SSL_SESSION_ID", apr_pstrdup(r->pool, tmp));
814 848
815 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) 849 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509)
816 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0, 850 mgs_add_common_cert_vars(r, ctxt->sc->certs_x509[0], 0,
817 ctxt->sc->export_certificates_enabled); 851 ctxt->
818 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) 852 sc->export_certificates_enabled);
819 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0, 853 else if (gnutls_certificate_type_get(ctxt->session) ==
820 ctxt->sc->export_certificates_enabled); 854 GNUTLS_CRT_OPENPGP)
855 mgs_add_common_pgpcert_vars(r, ctxt->sc->cert_pgp, 0,
856 ctxt->
857 sc->export_certificates_enabled);
821 858
822 return rv; 859 return rv;
823} 860}
824 861
825int mgs_hook_authz(request_rec * r) 862int mgs_hook_authz(request_rec * r)
826{ 863{
827 int rv; 864 int rv;
828 mgs_handle_t *ctxt; 865 mgs_handle_t *ctxt;
829 mgs_dirconf_rec *dc; 866 mgs_dirconf_rec *dc;
830 867
831 if (r == NULL) 868 if (r == NULL)
832 return DECLINED; 869 return DECLINED;
833 870
834 dc = ap_get_module_config(r->per_dir_config, 871 dc = ap_get_module_config(r->per_dir_config, &gnutls_module);
835 &gnutls_module); 872
836 873 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
837 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 874 ctxt =
838 ctxt = 875 ap_get_module_config(r->connection->conn_config,
839 ap_get_module_config(r->connection->conn_config, &gnutls_module); 876 &gnutls_module);
840 877
841 if (!ctxt || ctxt->session == NULL) { 878 if (!ctxt || ctxt->session == NULL) {
842 return DECLINED; 879 return DECLINED;
843 } 880 }
844 881
845 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { 882 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {
846 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 883 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
847 "GnuTLS: Directory set to Ignore Client Certificate!"); 884 "GnuTLS: Directory set to Ignore Client Certificate!");
848 } else { 885 } else {
849 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { 886 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) {
850 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 887 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
851 "GnuTLS: Attempting to rehandshake with peer. %d %d", 888 "GnuTLS: Attempting to rehandshake with peer. %d %d",
852 ctxt->sc->client_verify_mode, 889 ctxt->sc->client_verify_mode,
853 dc->client_verify_mode); 890 dc->client_verify_mode);
854 891
855 /* If we already have a client certificate, there's no point in 892 /* If we already have a client certificate, there's no point in
856 * re-handshaking... */ 893 * re-handshaking... */
857 rv = mgs_cert_verify(r, ctxt); 894 rv = mgs_cert_verify(r, ctxt);
858 if (rv != DECLINED && rv != HTTP_FORBIDDEN) 895 if (rv != DECLINED && rv != HTTP_FORBIDDEN)
859 return rv; 896 return rv;
860 897
861 gnutls_certificate_server_set_request(ctxt->session, 898 gnutls_certificate_server_set_request
862 dc->client_verify_mode); 899 (ctxt->session, dc->client_verify_mode);
863 900
864 if (mgs_rehandshake(ctxt) != 0) { 901 if (mgs_rehandshake(ctxt) != 0) {
865 return HTTP_FORBIDDEN; 902 return HTTP_FORBIDDEN;
866 } 903 }
867 } else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { 904 } else if (ctxt->sc->client_verify_mode ==
905 GNUTLS_CERT_IGNORE) {
868#if MOD_GNUTLS_DEBUG 906#if MOD_GNUTLS_DEBUG
869 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 907 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
870 "GnuTLS: Peer is set to IGNORE"); 908 "GnuTLS: Peer is set to IGNORE");
871#endif 909#endif
872 return DECLINED; 910 return DECLINED;
873 } 911 }
874 rv = mgs_cert_verify(r, ctxt); 912 rv = mgs_cert_verify(r, ctxt);
875 if (rv != DECLINED && 913 if (rv != DECLINED &&
876 (rv != HTTP_FORBIDDEN || 914 (rv != HTTP_FORBIDDEN ||
877 dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) { 915 dc->client_verify_mode == GNUTLS_CERT_REQUIRE)) {
878 return rv; 916 return rv;
917 }
879 } 918 }
880 }
881 919
882 return DECLINED; 920 return DECLINED;
883} 921}
884 922
885/* variables that are not sent by default: 923/* variables that are not sent by default:
@@ -895,359 +933,413 @@ static void
895mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side, 933mgs_add_common_cert_vars(request_rec * r, gnutls_x509_crt_t cert, int side,
896 int export_certificates_enabled) 934 int export_certificates_enabled)
897{ 935{
898 unsigned char sbuf[64]; /* buffer to hold serials */ 936 unsigned char sbuf[64]; /* buffer to hold serials */
899 char buf[AP_IOBUFSIZE]; 937 char buf[AP_IOBUFSIZE];
900 const char *tmp; 938 const char *tmp;
901 char *tmp2; 939 char *tmp2;
902 size_t len; 940 size_t len;
903 int ret, i; 941 int ret, i;
904 942
905 if (r == NULL) 943 if (r == NULL)
906 return; 944 return;
907 945
908 apr_table_t *env = r->subprocess_env; 946 apr_table_t *env = r->subprocess_env;
909 947
910 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 948 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
911 if (export_certificates_enabled != 0) { 949 if (export_certificates_enabled != 0) {
912 char cert_buf[10 * 1024]; 950 char cert_buf[10 * 1024];
913 len = sizeof(cert_buf); 951 len = sizeof(cert_buf);
914 952
915 if (gnutls_x509_crt_export 953 if (gnutls_x509_crt_export
916 (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0) 954 (cert, GNUTLS_X509_FMT_PEM, cert_buf, &len) >= 0)
917 apr_table_setn(env, 955 apr_table_setn(env,
918 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), 956 apr_pstrcat(r->pool, MGS_SIDE,
919 apr_pstrmemdup(r->pool, cert_buf, len)); 957 "_CERT", NULL),
920 958 apr_pstrmemdup(r->pool, cert_buf,
921 } 959 len));
922 960
923 len = sizeof(buf); 961 }
924 gnutls_x509_crt_get_dn(cert, buf, &len); 962
925 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL), 963 len = sizeof(buf);
926 apr_pstrmemdup(r->pool, buf, len)); 964 gnutls_x509_crt_get_dn(cert, buf, &len);
927 965 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_S_DN", NULL),
928 len = sizeof(buf); 966 apr_pstrmemdup(r->pool, buf, len));
929 gnutls_x509_crt_get_issuer_dn(cert, buf, &len); 967
930 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL), 968 len = sizeof(buf);
931 apr_pstrmemdup(r->pool, buf, len)); 969 gnutls_x509_crt_get_issuer_dn(cert, buf, &len);
932 970 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_I_DN", NULL),
933 len = sizeof(sbuf); 971 apr_pstrmemdup(r->pool, buf, len));
934 gnutls_x509_crt_get_serial(cert, sbuf, &len); 972
935 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 973 len = sizeof(sbuf);
936 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL), 974 gnutls_x509_crt_get_serial(cert, sbuf, &len);
937 apr_pstrdup(r->pool, tmp)); 975 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
938
939 ret = gnutls_x509_crt_get_version(cert);
940 if (ret > 0)
941 apr_table_setn(env, 976 apr_table_setn(env,
942 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), 977 apr_pstrcat(r->pool, MGS_SIDE, "_M_SERIAL", NULL),
943 apr_psprintf(r->pool, "%u", ret)); 978 apr_pstrdup(r->pool, tmp));
944 979
945 apr_table_setn(env, 980 ret = gnutls_x509_crt_get_version(cert);
946 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "X.509"); 981 if (ret > 0)
947
948 tmp =
949 mgs_time2sz(gnutls_x509_crt_get_expiration_time
950 (cert), buf, sizeof(buf));
951 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
952 apr_pstrdup(r->pool, tmp));
953
954 tmp =
955 mgs_time2sz(gnutls_x509_crt_get_activation_time
956 (cert), buf, sizeof(buf));
957 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
958 apr_pstrdup(r->pool, tmp));
959
960 ret = gnutls_x509_crt_get_signature_algorithm(cert);
961 if (ret >= 0) {
962 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG", NULL),
963 gnutls_sign_algorithm_get_name(ret));
964 }
965
966 ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL);
967 if (ret >= 0) {
968 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL),
969 gnutls_pk_algorithm_get_name(ret));
970 }
971
972 /* export all the alternative names (DNS, RFC822 and URI) */
973 for (i = 0; !(ret < 0); i++) {
974 len = 0;
975 ret = gnutls_x509_crt_get_subject_alt_name(cert, i,
976 NULL, &len, NULL);
977
978 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) {
979 tmp2 = apr_palloc(r->pool, len + 1);
980
981 ret =
982 gnutls_x509_crt_get_subject_alt_name(cert, i, tmp2, &len,
983 NULL);
984 tmp2[len] = 0;
985
986 if (ret == GNUTLS_SAN_DNSNAME) {
987 apr_table_setn(env,
988 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i),
989 apr_psprintf(r->pool, "DNSNAME:%s", tmp2));
990 } else if (ret == GNUTLS_SAN_RFC822NAME) {
991 apr_table_setn(env, 982 apr_table_setn(env,
992 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 983 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION",
993 apr_psprintf(r->pool, "RFC822NAME:%s", tmp2)); 984 NULL), apr_psprintf(r->pool,
994 } else if (ret == GNUTLS_SAN_URI) { 985 "%u", ret));
986
987 apr_table_setn(env,
988 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL),
989 "X.509");
990
991 tmp =
992 mgs_time2sz(gnutls_x509_crt_get_expiration_time
993 (cert), buf, sizeof(buf));
994 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
995 apr_pstrdup(r->pool, tmp));
996
997 tmp =
998 mgs_time2sz(gnutls_x509_crt_get_activation_time
999 (cert), buf, sizeof(buf));
1000 apr_table_setn(env,
1001 apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
1002 apr_pstrdup(r->pool, tmp));
1003
1004 ret = gnutls_x509_crt_get_signature_algorithm(cert);
1005 if (ret >= 0) {
995 apr_table_setn(env, 1006 apr_table_setn(env,
996 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 1007 apr_pstrcat(r->pool, MGS_SIDE, "_A_SIG",
997 apr_psprintf(r->pool, "URI:%s", tmp2)); 1008 NULL),
998 } else { 1009 gnutls_sign_algorithm_get_name(ret));
1010 }
1011
1012 ret = gnutls_x509_crt_get_pk_algorithm(cert, NULL);
1013 if (ret >= 0) {
999 apr_table_setn(env, 1014 apr_table_setn(env,
1000 apr_psprintf(r->pool, "%s_S_AN%u", MGS_SIDE, i), 1015 apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY",
1001 "UNSUPPORTED"); 1016 NULL),
1002 } 1017 gnutls_pk_algorithm_get_name(ret));
1018 }
1019
1020 /* export all the alternative names (DNS, RFC822 and URI) */
1021 for (i = 0; !(ret < 0); i++) {
1022 len = 0;
1023 ret = gnutls_x509_crt_get_subject_alt_name(cert, i,
1024 NULL, &len,
1025 NULL);
1026
1027 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER && len > 1) {
1028 tmp2 = apr_palloc(r->pool, len + 1);
1029
1030 ret =
1031 gnutls_x509_crt_get_subject_alt_name(cert, i,
1032 tmp2,
1033 &len,
1034 NULL);
1035 tmp2[len] = 0;
1036
1037 if (ret == GNUTLS_SAN_DNSNAME) {
1038 apr_table_setn(env,
1039 apr_psprintf(r->pool,
1040 "%s_S_AN%u",
1041 MGS_SIDE, i),
1042 apr_psprintf(r->pool,
1043 "DNSNAME:%s",
1044 tmp2));
1045 } else if (ret == GNUTLS_SAN_RFC822NAME) {
1046 apr_table_setn(env,
1047 apr_psprintf(r->pool,
1048 "%s_S_AN%u",
1049 MGS_SIDE, i),
1050 apr_psprintf(r->pool,
1051 "RFC822NAME:%s",
1052 tmp2));
1053 } else if (ret == GNUTLS_SAN_URI) {
1054 apr_table_setn(env,
1055 apr_psprintf(r->pool,
1056 "%s_S_AN%u",
1057 MGS_SIDE, i),
1058 apr_psprintf(r->pool,
1059 "URI:%s",
1060 tmp2));
1061 } else {
1062 apr_table_setn(env,
1063 apr_psprintf(r->pool,
1064 "%s_S_AN%u",
1065 MGS_SIDE, i),
1066 "UNSUPPORTED");
1067 }
1068 }
1003 } 1069 }
1004 }
1005} 1070}
1006 1071
1007static void 1072static void
1008mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert, int side, 1073mgs_add_common_pgpcert_vars(request_rec * r, gnutls_openpgp_crt_t cert,
1009 int export_certificates_enabled) 1074 int side, int export_certificates_enabled)
1010{ 1075{
1011 unsigned char sbuf[64]; /* buffer to hold serials */ 1076 unsigned char sbuf[64]; /* buffer to hold serials */
1012 char buf[AP_IOBUFSIZE]; 1077 char buf[AP_IOBUFSIZE];
1013 const char *tmp; 1078 const char *tmp;
1014 size_t len; 1079 size_t len;
1015 int ret; 1080 int ret;
1016 1081
1017 if (r == NULL) 1082 if (r == NULL)
1018 return; 1083 return;
1019 1084
1020 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 1085 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
1021 apr_table_t *env = r->subprocess_env; 1086 apr_table_t *env = r->subprocess_env;
1022 1087
1023 if (export_certificates_enabled != 0) { 1088 if (export_certificates_enabled != 0) {
1024 char cert_buf[10 * 1024]; 1089 char cert_buf[10 * 1024];
1025 len = sizeof(cert_buf); 1090 len = sizeof(cert_buf);
1026 1091
1027 if (gnutls_openpgp_crt_export 1092 if (gnutls_openpgp_crt_export
1028 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0) 1093 (cert, GNUTLS_OPENPGP_FMT_BASE64, cert_buf, &len) >= 0)
1029 apr_table_setn(env, 1094 apr_table_setn(env,
1030 apr_pstrcat(r->pool, MGS_SIDE, "_CERT", NULL), 1095 apr_pstrcat(r->pool, MGS_SIDE,
1031 apr_pstrmemdup(r->pool, cert_buf, len)); 1096 "_CERT", NULL),
1032 1097 apr_pstrmemdup(r->pool, cert_buf,
1033 } 1098 len));
1034 1099
1035 len = sizeof(buf); 1100 }
1036 gnutls_openpgp_crt_get_name(cert, 0, buf, &len); 1101
1037 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL), 1102 len = sizeof(buf);
1038 apr_pstrmemdup(r->pool, buf, len)); 1103 gnutls_openpgp_crt_get_name(cert, 0, buf, &len);
1039 1104 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_NAME", NULL),
1040 len = sizeof(sbuf); 1105 apr_pstrmemdup(r->pool, buf, len));
1041 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len); 1106
1042 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf)); 1107 len = sizeof(sbuf);
1043 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT", NULL), 1108 gnutls_openpgp_crt_get_fingerprint(cert, sbuf, &len);
1044 apr_pstrdup(r->pool, tmp)); 1109 tmp = mgs_session_id2sz(sbuf, len, buf, sizeof(buf));
1045
1046 ret = gnutls_openpgp_crt_get_version(cert);
1047 if (ret > 0)
1048 apr_table_setn(env, 1110 apr_table_setn(env,
1049 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION", NULL), 1111 apr_pstrcat(r->pool, MGS_SIDE, "_FINGERPRINT",
1050 apr_psprintf(r->pool, "%u", ret)); 1112 NULL), apr_pstrdup(r->pool, tmp));
1051 1113
1052 apr_table_setn(env, 1114 ret = gnutls_openpgp_crt_get_version(cert);
1053 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL), "OPENPGP"); 1115 if (ret > 0)
1054 1116 apr_table_setn(env,
1055 tmp = 1117 apr_pstrcat(r->pool, MGS_SIDE, "_M_VERSION",
1056 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time 1118 NULL), apr_psprintf(r->pool,
1057 (cert), buf, sizeof(buf)); 1119 "%u", ret));
1058 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL), 1120
1059 apr_pstrdup(r->pool, tmp)); 1121 apr_table_setn(env,
1060 1122 apr_pstrcat(r->pool, MGS_SIDE, "_CERT_TYPE", NULL),
1061 tmp = 1123 "OPENPGP");
1062 mgs_time2sz(gnutls_openpgp_crt_get_creation_time 1124
1063 (cert), buf, sizeof(buf)); 1125 tmp =
1064 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL), 1126 mgs_time2sz(gnutls_openpgp_crt_get_expiration_time
1065 apr_pstrdup(r->pool, tmp)); 1127 (cert), buf, sizeof(buf));
1066 1128 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_V_END", NULL),
1067 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL); 1129 apr_pstrdup(r->pool, tmp));
1068 if (ret >= 0) { 1130
1069 apr_table_setn(env, apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY", NULL), 1131 tmp =
1070 gnutls_pk_algorithm_get_name(ret)); 1132 mgs_time2sz(gnutls_openpgp_crt_get_creation_time
1071 } 1133 (cert), buf, sizeof(buf));
1134 apr_table_setn(env,
1135 apr_pstrcat(r->pool, MGS_SIDE, "_V_START", NULL),
1136 apr_pstrdup(r->pool, tmp));
1137
1138 ret = gnutls_openpgp_crt_get_pk_algorithm(cert, NULL);
1139 if (ret >= 0) {
1140 apr_table_setn(env,
1141 apr_pstrcat(r->pool, MGS_SIDE, "_A_KEY",
1142 NULL),
1143 gnutls_pk_algorithm_get_name(ret));
1144 }
1072 1145
1073} 1146}
1074 1147
1075/* TODO: Allow client sending a X.509 certificate chain */ 1148/* TODO: Allow client sending a X.509 certificate chain */
1076static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt) 1149static int mgs_cert_verify(request_rec * r, mgs_handle_t * ctxt)
1077{ 1150{
1078 const gnutls_datum_t *cert_list; 1151 const gnutls_datum_t *cert_list;
1079 unsigned int cert_list_size, status; 1152 unsigned int cert_list_size, status;
1080 int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret; 1153 int rv = GNUTLS_E_NO_CERTIFICATE_FOUND, ret;
1081 unsigned int ch_size = 0; 1154 unsigned int ch_size = 0;
1082 union { 1155 union {
1083 gnutls_x509_crt_t x509[MAX_CHAIN_SIZE]; 1156 gnutls_x509_crt_t x509[MAX_CHAIN_SIZE];
1084 gnutls_openpgp_crt_t pgp; 1157 gnutls_openpgp_crt_t pgp;
1085 } cert; 1158 } cert;
1086 apr_time_t expiration_time, cur_time; 1159 apr_time_t expiration_time, cur_time;
1087 1160
1088 if (r == NULL || ctxt == NULL || ctxt->session == NULL) 1161 if (r == NULL || ctxt == NULL || ctxt->session == NULL)
1089 return HTTP_FORBIDDEN; 1162 return HTTP_FORBIDDEN;
1090 1163
1091 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__); 1164 _gnutls_log(debug_log_fp, "%s: %d\n", __func__, __LINE__);
1092 cert_list = 1165 cert_list =
1093 gnutls_certificate_get_peers(ctxt->session, &cert_list_size); 1166 gnutls_certificate_get_peers(ctxt->session, &cert_list_size);
1094 1167
1095 if (cert_list == NULL || cert_list_size == 0) { 1168 if (cert_list == NULL || cert_list_size == 0) {
1096 /* It is perfectly OK for a client not to send a certificate if on REQUEST mode 1169 /* It is perfectly OK for a client not to send a certificate if on REQUEST mode
1170 */
1171 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST)
1172 return OK;
1173
1174 /* no certificate provided by the client, but one was required. */
1175 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1176 "GnuTLS: Failed to Verify Peer: "
1177 "Client did not submit a certificate");
1178 return HTTP_FORBIDDEN;
1179 }
1180
1181 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
1182 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
1183 "GnuTLS: A Chain of %d certificate(s) was provided for validation",
1184 cert_list_size);
1185
1186 for (ch_size = 0; ch_size < cert_list_size; ch_size++) {
1187 gnutls_x509_crt_init(&cert.x509[ch_size]);
1188 rv = gnutls_x509_crt_import(cert.x509[ch_size],
1189 &cert_list[ch_size],
1190 GNUTLS_X509_FMT_DER);
1191 // When failure to import, leave the loop
1192 if (rv != GNUTLS_E_SUCCESS) {
1193 if (ch_size < 1) {
1194 ap_log_rerror(APLOG_MARK,
1195 APLOG_INFO, 0, r,
1196 "GnuTLS: Failed to Verify Peer: "
1197 "Failed to import peer certificates.");
1198 ret = HTTP_FORBIDDEN;
1199 goto exit;
1200 }
1201 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1202 "GnuTLS: Failed to import some peer certificates. Using %d certificates",
1203 ch_size);
1204 rv = GNUTLS_E_SUCCESS;
1205 break;
1206 }
1207 }
1208 } else if (gnutls_certificate_type_get(ctxt->session) ==
1209 GNUTLS_CRT_OPENPGP) {
1210 if (cert_list_size > 1) {
1211 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1212 "GnuTLS: Failed to Verify Peer: "
1213 "Chained Client Certificates are not supported.");
1214 return HTTP_FORBIDDEN;
1215 }
1216
1217 gnutls_openpgp_crt_init(&cert.pgp);
1218 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0],
1219 GNUTLS_OPENPGP_FMT_RAW);
1220
1221 } else
1222 return HTTP_FORBIDDEN;
1223
1224 if (rv < 0) {
1225 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1226 "GnuTLS: Failed to Verify Peer: "
1227 "Failed to import peer certificates.");
1228 ret = HTTP_FORBIDDEN;
1229 goto exit;
1230 }
1231
1232 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
1233 apr_time_ansi_put(&expiration_time,
1234 gnutls_x509_crt_get_expiration_time
1235 (cert.x509[0]));
1236
1237 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
1238 "GnuTLS: Verifying list of %d certificate(s)",
1239 ch_size);
1240 rv = gnutls_x509_crt_list_verify(cert.x509, ch_size,
1241 ctxt->sc->ca_list,
1242 ctxt->sc->ca_list_size,
1243 NULL, 0, 0, &status);
1244 } else {
1245 apr_time_ansi_put(&expiration_time,
1246 gnutls_openpgp_crt_get_expiration_time
1247 (cert.pgp));
1248
1249 rv = gnutls_openpgp_crt_verify_ring(cert.pgp,
1250 ctxt->sc->pgp_list, 0,
1251 &status);
1252 }
1253
1254 if (rv < 0) {
1255 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1256 "GnuTLS: Failed to Verify Peer certificate: (%d) %s",
1257 rv, gnutls_strerror(rv));
1258 if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND)
1259 ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r,
1260 "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?");
1261 ret = HTTP_FORBIDDEN;
1262 goto exit;
1263 }
1264
1265 /* TODO: X509 CRL Verification. */
1266 /* May add later if anyone needs it.
1097 */ 1267 */
1098 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST) 1268 /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */
1099 return OK; 1269
1100 1270 cur_time = apr_time_now();
1101 /* no certificate provided by the client, but one was required. */ 1271
1102 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1272 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1103 "GnuTLS: Failed to Verify Peer: " 1273 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1104 "Client did not submit a certificate"); 1274 "GnuTLS: Could not find Signer for Peer Certificate");
1105 return HTTP_FORBIDDEN; 1275 }
1106 } 1276
1107 1277 if (status & GNUTLS_CERT_SIGNER_NOT_CA) {
1108 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1278 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1109 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 1279 "GnuTLS: Peer's Certificate signer is not a CA");
1110 "GnuTLS: A Chain of %d certificate(s) was provided for validation", cert_list_size); 1280 }
1111 1281
1112 for (ch_size = 0; ch_size<cert_list_size; ch_size++) { 1282 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1113 gnutls_x509_crt_init(&cert.x509[ch_size]); 1283 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1114 rv = gnutls_x509_crt_import(cert.x509[ch_size], &cert_list[ch_size], GNUTLS_X509_FMT_DER); 1284 "GnuTLS: Peer's Certificate is using insecure algorithms");
1115 // When failure to import, leave the loop 1285 }
1116 if ( rv != GNUTLS_E_SUCCESS ) { 1286
1117 if (ch_size < 1) { 1287 if (status & GNUTLS_CERT_EXPIRED
1118 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1288 || status & GNUTLS_CERT_NOT_ACTIVATED) {
1119 "GnuTLS: Failed to Verify Peer: " 1289 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1120 "Failed to import peer certificates."); 1290 "GnuTLS: Peer's Certificate signer is expired or not yet activated");
1121 ret = HTTP_FORBIDDEN; 1291 }
1122 goto exit; 1292
1123 } 1293 if (status & GNUTLS_CERT_INVALID) {
1124 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1294 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1125 "GnuTLS: Failed to import some peer certificates. Using %d certificates", 1295 "GnuTLS: Peer Certificate is invalid.");
1126 ch_size); 1296 } else if (status & GNUTLS_CERT_REVOKED) {
1127 rv = GNUTLS_E_SUCCESS; 1297 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1128 break; 1298 "GnuTLS: Peer Certificate is revoked.");
1129 } 1299 }
1130 } 1300
1131 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP) { 1301 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509)
1132 if (cert_list_size > 1) { 1302 mgs_add_common_cert_vars(r, cert.x509[0], 1,
1133 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1303 ctxt->
1134 "GnuTLS: Failed to Verify Peer: " 1304 sc->export_certificates_enabled);
1135 "Chained Client Certificates are not supported."); 1305 else if (gnutls_certificate_type_get(ctxt->session) ==
1136 return HTTP_FORBIDDEN; 1306 GNUTLS_CRT_OPENPGP)
1137 } 1307 mgs_add_common_pgpcert_vars(r, cert.pgp, 1,
1138 1308 ctxt->
1139 gnutls_openpgp_crt_init(&cert.pgp); 1309 sc->export_certificates_enabled);
1140 rv = gnutls_openpgp_crt_import(cert.pgp, &cert_list[0], GNUTLS_OPENPGP_FMT_RAW); 1310
1141 1311 {
1142 } else return HTTP_FORBIDDEN; 1312 /* days remaining */
1143 1313 unsigned long remain =
1144 if (rv < 0) { 1314 (apr_time_sec(expiration_time) -
1145 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1315 apr_time_sec(cur_time)) / 86400;
1146 "GnuTLS: Failed to Verify Peer: " 1316 apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN",
1147 "Failed to import peer certificates."); 1317 apr_psprintf(r->pool, "%lu", remain));
1148 ret = HTTP_FORBIDDEN; 1318 }
1149 goto exit; 1319
1150 } 1320 if (status == 0) {
1151 1321 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY",
1152 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) { 1322 "SUCCESS");
1153 apr_time_ansi_put(&expiration_time, 1323 ret = OK;
1154 gnutls_x509_crt_get_expiration_time(cert.x509[0])); 1324 } else {
1155 1325 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY",
1156 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 1326 "FAILED");
1157 "GnuTLS: Verifying list of %d certificate(s)", ch_size); 1327 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST)
1158 rv = gnutls_x509_crt_list_verify(cert.x509, ch_size, 1328 ret = OK;
1159 ctxt->sc->ca_list, ctxt->sc->ca_list_size, 1329 else
1160 NULL, 0, 0, &status); 1330 ret = HTTP_FORBIDDEN;
1161 } else { 1331 }
1162 apr_time_ansi_put(&expiration_time, 1332
1163 gnutls_openpgp_crt_get_expiration_time(cert.pgp)); 1333 exit:
1164 1334 if (gnutls_certificate_type_get(ctxt->session) == GNUTLS_CRT_X509) {
1165 rv = gnutls_openpgp_crt_verify_ring(cert.pgp, ctxt->sc->pgp_list, 1335 int i;
1166 0, &status); 1336 for (i = 0; i < ch_size; i++) {
1167 } 1337 gnutls_x509_crt_deinit(cert.x509[i]);
1168 1338 }
1169 if (rv < 0) { 1339 } else if (gnutls_certificate_type_get(ctxt->session) ==
1170 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 1340 GNUTLS_CRT_OPENPGP)
1171 "GnuTLS: Failed to Verify Peer certificate: (%d) %s", 1341 gnutls_openpgp_crt_deinit(cert.pgp);
1172 rv, gnutls_strerror(rv)); 1342 return ret;
1173 if (rv == GNUTLS_E_NO_CERTIFICATE_FOUND)
1174 ap_log_rerror(APLOG_MARK, APLOG_EMERG, 0, r,
1175 "GnuTLS: No certificate was found for verification. Did you set the GnuTLSX509CAFile or GnuTLSPGPKeyringFile directives?");
1176 ret = HTTP_FORBIDDEN;
1177 goto exit;
1178 }
1179
1180 /* TODO: X509 CRL Verification. */
1181 /* May add later if anyone needs it.
1182 */
1183 /* ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size); */
1184
1185 cur_time = apr_time_now();
1186
1187 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
1188 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1189 "GnuTLS: Could not find Signer for Peer Certificate");
1190 }
1191
1192 if (status & GNUTLS_CERT_SIGNER_NOT_CA) {
1193 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1194 "GnuTLS: Peer's Certificate signer is not a CA");
1195 }
1196
1197 if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
1198 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1199 "GnuTLS: Peer's Certificate is using insecure algorithms");
1200 }
1201
1202 if (status & GNUTLS_CERT_EXPIRED || status & GNUTLS_CERT_NOT_ACTIVATED) {
1203 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1204 "GnuTLS: Peer's Certificate signer is expired or not yet activated");
1205 }
1206
1207 if (status & GNUTLS_CERT_INVALID) {
1208 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1209 "GnuTLS: Peer Certificate is invalid.");
1210 } else if (status & GNUTLS_CERT_REVOKED) {
1211 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
1212 "GnuTLS: Peer Certificate is revoked.");
1213 }
1214
1215 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509)
1216 mgs_add_common_cert_vars(r, cert.x509[0], 1,
1217 ctxt->sc->export_certificates_enabled);
1218 else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
1219 mgs_add_common_pgpcert_vars(r, cert.pgp, 1,
1220 ctxt->sc->export_certificates_enabled);
1221
1222 {
1223 /* days remaining */
1224 unsigned long remain =
1225 (apr_time_sec(expiration_time) -
1226 apr_time_sec(cur_time)) / 86400;
1227 apr_table_setn(r->subprocess_env, "SSL_CLIENT_V_REMAIN",
1228 apr_psprintf(r->pool, "%lu", remain));
1229 }
1230
1231 if (status == 0) {
1232 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "SUCCESS");
1233 ret = OK;
1234 } else {
1235 apr_table_setn(r->subprocess_env, "SSL_CLIENT_VERIFY", "FAILED");
1236 if (ctxt->sc->client_verify_mode == GNUTLS_CERT_REQUEST)
1237 ret = OK;
1238 else
1239 ret = HTTP_FORBIDDEN;
1240 }
1241
1242 exit:
1243 if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_X509) {
1244 int i;
1245 for (i=0; i<ch_size; i++) {
1246 gnutls_x509_crt_deinit(cert.x509[i]);
1247 }
1248 } else if (gnutls_certificate_type_get( ctxt->session) == GNUTLS_CRT_OPENPGP)
1249 gnutls_openpgp_crt_deinit(cert.pgp);
1250 return ret;
1251 1343
1252 1344
1253} 1345}