diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gnutls_io.c | 21 | ||||
-rw-r--r-- | src/mod_gnutls.c | 259 |
2 files changed, 202 insertions, 78 deletions
diff --git a/src/gnutls_io.c b/src/gnutls_io.c index f081284..5e0c4ef 100644 --- a/src/gnutls_io.c +++ b/src/gnutls_io.c | |||
@@ -358,12 +358,14 @@ static int gnutls_do_handshake(mod_gnutls_handle_t * ctxt) | |||
358 | int ret; | 358 | int ret; |
359 | int errcode; | 359 | int errcode; |
360 | if (ctxt->status != 0) { | 360 | if (ctxt->status != 0) { |
361 | return 0; | 361 | return -1; |
362 | } | 362 | } |
363 | 363 | ||
364 | tryagain: | 364 | tryagain: |
365 | 365 | do { | |
366 | ret = gnutls_handshake(ctxt->session); | 366 | ret = gnutls_handshake(ctxt->session); |
367 | } while (ret == GNUTLS_E_AGAIN); | ||
368 | |||
367 | if (ret < 0) { | 369 | if (ret < 0) { |
368 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED | 370 | if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED |
369 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { | 371 | || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { |
@@ -392,7 +394,7 @@ tryagain: | |||
392 | else { | 394 | else { |
393 | /* all done with the handshake */ | 395 | /* all done with the handshake */ |
394 | ctxt->status = 1; | 396 | ctxt->status = 1; |
395 | return ret; | 397 | return 0; |
396 | } | 398 | } |
397 | } | 399 | } |
398 | 400 | ||
@@ -411,14 +413,9 @@ int mod_gnutls_rehandshake(mod_gnutls_handle_t * ctxt) | |||
411 | 413 | ||
412 | ctxt->status = 0; | 414 | ctxt->status = 0; |
413 | 415 | ||
414 | gnutls_do_handshake(ctxt); | 416 | rv = gnutls_do_handshake(ctxt); |
415 | 417 | ||
416 | if (ctxt->status == 1) { | 418 | return rv; |
417 | return 0; | ||
418 | } | ||
419 | else { | ||
420 | return -1; | ||
421 | } | ||
422 | } | 419 | } |
423 | 420 | ||
424 | 421 | ||
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index be150a9..cb81a26 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include "mod_gnutls.h" | 18 | #include "mod_gnutls.h" |
19 | #include "http_vhost.h" | ||
19 | 20 | ||
20 | extern server_rec *ap_server_conf; | 21 | extern server_rec *ap_server_conf; |
21 | 22 | ||
@@ -111,6 +112,7 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
111 | server_rec * base_server) | 112 | server_rec * base_server) |
112 | { | 113 | { |
113 | int rv; | 114 | int rv; |
115 | int data_len; | ||
114 | server_rec *s; | 116 | server_rec *s; |
115 | gnutls_dh_params_t dh_params; | 117 | gnutls_dh_params_t dh_params; |
116 | gnutls_rsa_params_t rsa_params; | 118 | gnutls_rsa_params_t rsa_params; |
@@ -215,23 +217,26 @@ static int mod_gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, | |||
215 | s->server_hostname, s->port); | 217 | s->server_hostname, s->port); |
216 | exit(-1); | 218 | exit(-1); |
217 | } | 219 | } |
218 | { | 220 | |
219 | int rv; | 221 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, |
220 | int data_len = 255; | 222 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, |
221 | char crt_name[255]; | 223 | NULL, &data_len); |
222 | for (rv = 0; rv < data_len; rv++) { | 224 | |
223 | crt_name[rv] = '\0'; | 225 | if (data_len < 1) { |
224 | } | 226 | sc->enabled = GNUTLS_ENABLED_FALSE; |
225 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, | 227 | sc->cert_cn = NULL; |
226 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | 228 | continue; |
227 | crt_name, &data_len); | 229 | } |
228 | 230 | ||
231 | sc->cert_cn = apr_palloc(p, data_len); | ||
232 | rv = gnutls_x509_crt_get_dn_by_oid(sc->cert_x509, | ||
233 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
234 | sc->cert_cn, &data_len); | ||
229 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 235 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
230 | s, | 236 | s, |
231 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", crt_name, rv, | 237 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X sc: 0x%08X", sc->cert_cn, rv, |
232 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)), | 238 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(sc->privkey_x509)), |
233 | (unsigned int)s, (unsigned int)sc); | 239 | (unsigned int)s, (unsigned int)sc); |
234 | } | ||
235 | } | 240 | } |
236 | } | 241 | } |
237 | 242 | ||
@@ -287,17 +292,69 @@ static apr_port_t mod_gnutls_hook_default_port(const request_rec * r) | |||
287 | return 443; | 292 | return 443; |
288 | } | 293 | } |
289 | 294 | ||
295 | static void mod_gnutls_changed_servers(mod_gnutls_handle_t *ctxt) | ||
296 | { | ||
297 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, ctxt->sc->certs); | ||
298 | gnutls_certificate_server_set_request(ctxt->session, ctxt->sc->client_verify_mode); | ||
299 | } | ||
300 | |||
290 | #define MAX_HOST_LEN 255 | 301 | #define MAX_HOST_LEN 255 |
302 | |||
303 | #if USING_2_1_RECENT | ||
304 | typedef struct | ||
305 | { | ||
306 | mod_gnutls_handle_t *ctxt; | ||
307 | gnutls_retr_st* ret; | ||
308 | const char* sni_name; | ||
309 | } vhost_cb_rec; | ||
310 | |||
311 | int vhost_cb (void* baton, conn_rec* conn, server_rec* s) | ||
312 | { | ||
313 | mod_gnutls_srvconf_rec *tsc; | ||
314 | vhost_cb_rec* x = baton; | ||
315 | |||
316 | tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | ||
317 | &gnutls_module); | ||
318 | |||
319 | if (tsc->enabled != GNUTLS_ENABLED_TRUE || tsc->cert_cn == NULL) { | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | /* The CN can contain a * -- this will match those too. */ | ||
324 | if (ap_strcasecmp_match(x->sni_name, tsc->cert_cn) == 0) { | ||
325 | /* found a match */ | ||
326 | x->ret->cert.x509 = &tsc->cert_x509; | ||
327 | x->ret->key.x509 = tsc->privkey_x509; | ||
328 | #if MOD_GNUTLS_DEBUG | ||
329 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
330 | x->ctxt->c->base_server, | ||
331 | "GnuTLS: Virtual Host CB: " | ||
332 | "'%s' == '%s'", tsc->cert_cn, x->sni_name); | ||
333 | #endif | ||
334 | /* Because we actually change the server used here, we need to reset | ||
335 | * things like ClientVerify. | ||
336 | */ | ||
337 | x->ctxt->sc = tsc; | ||
338 | mod_gnutls_changed_servers(x->ctxt); | ||
339 | return 1; | ||
340 | } | ||
341 | return 0; | ||
342 | } | ||
343 | #endif | ||
344 | |||
291 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) | 345 | static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) |
292 | { | 346 | { |
293 | int rv; | 347 | int rv; |
294 | int sni_type; | 348 | int sni_type; |
295 | int data_len = MAX_HOST_LEN; | 349 | int data_len = MAX_HOST_LEN; |
296 | char sni_name[MAX_HOST_LEN]; | 350 | char sni_name[MAX_HOST_LEN]; |
297 | char crt_name[MAX_HOST_LEN]; | ||
298 | mod_gnutls_handle_t *ctxt; | 351 | mod_gnutls_handle_t *ctxt; |
299 | mod_gnutls_srvconf_rec *tsc; | 352 | #if USING_2_1_RECENT |
353 | vhost_cb_rec cbx; | ||
354 | #else | ||
300 | server_rec* s; | 355 | server_rec* s; |
356 | mod_gnutls_srvconf_rec *tsc; | ||
357 | #endif | ||
301 | 358 | ||
302 | ctxt = gnutls_transport_get_ptr(session); | 359 | ctxt = gnutls_transport_get_ptr(session); |
303 | 360 | ||
@@ -333,6 +390,16 @@ static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) | |||
333 | * Code in the Core already sets up the c->base_server as the base | 390 | * Code in the Core already sets up the c->base_server as the base |
334 | * for this IP/Port combo. Trust that the core did the 'right' thing. | 391 | * for this IP/Port combo. Trust that the core did the 'right' thing. |
335 | */ | 392 | */ |
393 | #if USING_2_1_RECENT | ||
394 | cbx.ctxt = ctxt; | ||
395 | cbx.ret = ret; | ||
396 | cbx.sni_name = sni_name; | ||
397 | |||
398 | rv = ap_vhost_iterate_given_conn(ctxt->c, vhost_cb, &cbx); | ||
399 | if (rv == 1) { | ||
400 | return 0; | ||
401 | } | ||
402 | #else | ||
336 | for (s = ap_server_conf; s; s = s->next) { | 403 | for (s = ap_server_conf; s; s = s->next) { |
337 | 404 | ||
338 | tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, | 405 | tsc = (mod_gnutls_srvconf_rec *) ap_get_module_config(s->module_config, |
@@ -340,23 +407,15 @@ static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) | |||
340 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { | 407 | if (tsc->enabled != GNUTLS_ENABLED_TRUE) { |
341 | continue; | 408 | continue; |
342 | } | 409 | } |
343 | 410 | #if MOD_GNUTLS_DEBUG | |
344 | data_len = MAX_HOST_LEN; | ||
345 | rv = gnutls_x509_crt_get_dn_by_oid(tsc->cert_x509, | ||
346 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
347 | crt_name, &data_len); | ||
348 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 411 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
349 | ctxt->c->base_server, | 412 | ctxt->c->base_server, |
350 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", crt_name, rv, | 413 | "GnuTLS: sni-x509 cn: %s/%d pk: %s s: 0x%08X s->n: 0x%08X sc: 0x%08X", tsc->cert_cn, rv, |
351 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)), | 414 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509)), |
352 | (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc); | 415 | (unsigned int)s, (unsigned int)s->next, (unsigned int)tsc); |
353 | 416 | #endif | |
354 | if (rv != 0) { | ||
355 | continue; | ||
356 | } | ||
357 | |||
358 | /* The CN can contain a * -- this will match those too. */ | 417 | /* The CN can contain a * -- this will match those too. */ |
359 | if (ap_strcasecmp_match(sni_name, crt_name) == 0) { | 418 | if (ap_strcasecmp_match(sni_name, tsc->cert_cn) == 0) { |
360 | /* found a match */ | 419 | /* found a match */ |
361 | ret->cert.x509 = &tsc->cert_x509; | 420 | ret->cert.x509 = &tsc->cert_x509; |
362 | ret->key.x509 = tsc->privkey_x509; | 421 | ret->key.x509 = tsc->privkey_x509; |
@@ -364,28 +423,20 @@ static int cert_retrieve_fn(gnutls_session_t session, gnutls_retr_st* ret) | |||
364 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | 423 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, |
365 | ctxt->c->base_server, | 424 | ctxt->c->base_server, |
366 | "GnuTLS: Virtual Host: " | 425 | "GnuTLS: Virtual Host: " |
367 | "'%s' == '%s'", crt_name, sni_name); | 426 | "'%s' == '%s'", tsc->cert_cn, sni_name); |
368 | #endif | 427 | #endif |
428 | ctxt->sc = tsc; | ||
429 | mod_gnutls_changed_servers(ctxt); | ||
369 | return 0; | 430 | return 0; |
370 | } | 431 | } |
371 | } | 432 | } |
372 | 433 | #endif | |
373 | 434 | ||
374 | /** | 435 | /** |
375 | * If the client does not support the Server Name Indication, give the default | 436 | * If the client does not support the Server Name Indication, give the default |
376 | * certificate for this server. | 437 | * certificate for this server. |
377 | */ | 438 | */ |
378 | use_default_crt: | 439 | use_default_crt: |
379 | data_len = MAX_HOST_LEN; | ||
380 | rv = gnutls_x509_crt_get_dn_by_oid(ctxt->sc->cert_x509, | ||
381 | GNUTLS_OID_X520_COMMON_NAME, 0, 0, | ||
382 | crt_name, &data_len); | ||
383 | |||
384 | ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, | ||
385 | ctxt->c->base_server, | ||
386 | "GnuTLS: x509 cn: %s/%d pk: %s", crt_name, rv, | ||
387 | gnutls_pk_algorithm_get_name(gnutls_x509_privkey_get_pk_algorithm(ctxt->sc->privkey_x509))); | ||
388 | |||
389 | ret->cert.x509 = &ctxt->sc->cert_x509; | 440 | ret->cert.x509 = &ctxt->sc->cert_x509; |
390 | ret->key.x509 = ctxt->sc->privkey_x509; | 441 | ret->key.x509 = ctxt->sc->privkey_x509; |
391 | #if MOD_GNUTLS_DEBUG | 442 | #if MOD_GNUTLS_DEBUG |
@@ -427,14 +478,11 @@ static mod_gnutls_handle_t* create_gnutls_handle(apr_pool_t* pool, conn_rec * c) | |||
427 | gnutls_mac_set_priority(ctxt->session, sc->macs); | 478 | gnutls_mac_set_priority(ctxt->session, sc->macs); |
428 | gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types); | 479 | gnutls_certificate_type_set_priority(ctxt->session, sc->cert_types); |
429 | 480 | ||
430 | gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); | ||
431 | |||
432 | gnutls_certificate_server_set_request(ctxt->session, sc->client_verify_mode); | ||
433 | |||
434 | mod_gnutls_cache_session_init(ctxt); | 481 | mod_gnutls_cache_session_init(ctxt); |
435 | 482 | ||
436 | /* TODO: Finish Support for Server Name Indication */ | ||
437 | gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn); | 483 | gnutls_certificate_server_set_retrieve_function(sc->certs, cert_retrieve_fn); |
484 | |||
485 | mod_gnutls_changed_servers(ctxt); | ||
438 | return ctxt; | 486 | return ctxt; |
439 | } | 487 | } |
440 | 488 | ||
@@ -574,7 +622,7 @@ static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy, | |||
574 | gnutls_strerror(ret)); | 622 | gnutls_strerror(ret)); |
575 | } | 623 | } |
576 | 624 | ||
577 | //apr_pool_destroy(spool); | 625 | apr_pool_destroy(spool); |
578 | return NULL; | 626 | return NULL; |
579 | } | 627 | } |
580 | 628 | ||
@@ -605,7 +653,7 @@ static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, | |||
605 | "Private Key '%s': (%d) %s", file, ret, | 653 | "Private Key '%s': (%d) %s", file, ret, |
606 | gnutls_strerror(ret)); | 654 | gnutls_strerror(ret)); |
607 | } | 655 | } |
608 | //apr_pool_destroy(spool); | 656 | apr_pool_destroy(spool); |
609 | return NULL; | 657 | return NULL; |
610 | } | 658 | } |
611 | 659 | ||
@@ -673,15 +721,15 @@ static const char *gnutls_set_cache_timeout(cmd_parms * parms, void *dummy, | |||
673 | static const char *gnutls_set_client_verify(cmd_parms * parms, void *dummy, | 721 | static const char *gnutls_set_client_verify(cmd_parms * parms, void *dummy, |
674 | const char *arg) | 722 | const char *arg) |
675 | { | 723 | { |
676 | gnutls_certificate_request_t mode; | 724 | int mode; |
677 | 725 | ||
678 | if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { | 726 | if (strcasecmp("none", arg) == 0 || strcasecmp("ignore", arg) == 0) { |
679 | mode = GNUTLS_CERT_IGNORE; | 727 | mode = GNUTLS_CERT_IGNORE; |
680 | } | 728 | } |
681 | else if (strcasecmp("optional", arg) == 0 || strcasecmp("request", arg) == 0) { | 729 | else if (strcasecmp("optional", arg) == 0 || strcasecmp("request", arg) == 0) { |
682 | mode = GNUTLS_CERT_REQUEST; | 730 | mode = GNUTLS_CERT_REQUEST; |
683 | } | 731 | } |
684 | else if (strcasecmp("optional", arg) == 0) { | 732 | else if (strcasecmp("require", arg) == 0) { |
685 | mode = GNUTLS_CERT_REQUIRE; | 733 | mode = GNUTLS_CERT_REQUIRE; |
686 | } | 734 | } |
687 | else { | 735 | else { |
@@ -703,6 +751,29 @@ static const char *gnutls_set_client_verify(cmd_parms * parms, void *dummy, | |||
703 | 751 | ||
704 | return NULL; | 752 | return NULL; |
705 | } | 753 | } |
754 | |||
755 | static const char *gnutls_set_client_ca_file(cmd_parms * parms, void *dummy, | ||
756 | const char *arg) | ||
757 | { | ||
758 | int rv; | ||
759 | const char* file; | ||
760 | mod_gnutls_srvconf_rec *sc = | ||
761 | (mod_gnutls_srvconf_rec *) ap_get_module_config(parms->server-> | ||
762 | module_config, | ||
763 | &gnutls_module); | ||
764 | file = ap_server_root_relative(parms->pool, arg); | ||
765 | rv = gnutls_certificate_set_x509_trust_file(sc->certs, | ||
766 | file, GNUTLS_X509_FMT_PEM); | ||
767 | |||
768 | if (rv < 0) { | ||
769 | return apr_psprintf(parms->pool, "GnuTLS: Failed to load " | ||
770 | "Client CA File '%s': (%d) %s", file, rv, | ||
771 | gnutls_strerror(rv)); | ||
772 | } | ||
773 | return NULL; | ||
774 | } | ||
775 | |||
776 | |||
706 | static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, | 777 | static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, |
707 | const char *arg) | 778 | const char *arg) |
708 | { | 779 | { |
@@ -728,6 +799,10 @@ static const command_rec gnutls_cmds[] = { | |||
728 | NULL, | 799 | NULL, |
729 | RSRC_CONF|OR_AUTHCFG, | 800 | RSRC_CONF|OR_AUTHCFG, |
730 | "Set Verification Requirements of the Client Certificate"), | 801 | "Set Verification Requirements of the Client Certificate"), |
802 | AP_INIT_TAKE1("GnuTLSClientCAFile", gnutls_set_client_ca_file, | ||
803 | NULL, | ||
804 | RSRC_CONF, | ||
805 | "Set the CA File for Client Certificates"), | ||
731 | AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file, | 806 | AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file, |
732 | NULL, | 807 | NULL, |
733 | RSRC_CONF, | 808 | RSRC_CONF, |
@@ -751,34 +826,86 @@ static const command_rec gnutls_cmds[] = { | |||
751 | {NULL} | 826 | {NULL} |
752 | }; | 827 | }; |
753 | 828 | ||
754 | /* TODO: CACertificateFile & Client Authentication | ||
755 | * AP_INIT_TAKE1("GnuTLSCACertificateFile", ap_set_server_string_slot, | ||
756 | * (void *) APR_OFFSETOF(gnutls_srvconf_rec, key_file), NULL, | ||
757 | * RSRC_CONF, | ||
758 | * "CA"), | ||
759 | */ | ||
760 | |||
761 | int mod_gnutls_hook_authz(request_rec *r) | 829 | int mod_gnutls_hook_authz(request_rec *r) |
762 | { | 830 | { |
763 | return OK; | 831 | int rv; |
764 | #if 0 | 832 | int status; |
765 | mod_gnutls_handle_t *ctxt; | 833 | mod_gnutls_handle_t *ctxt; |
766 | mod_gnutls_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, | 834 | mod_gnutls_dirconf_rec *dc = ap_get_module_config(r->per_dir_config, |
767 | &gnutls_module); | 835 | &gnutls_module); |
768 | 836 | ||
769 | ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); | 837 | ctxt = ap_get_module_config(r->connection->conn_config, &gnutls_module); |
770 | 838 | ||
771 | if (dc->client_verify_mode == -1 || | 839 | if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { |
772 | dc->client_verify_mode == GNUTLS_CERT_IGNORE || | 840 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
773 | ctxt->sc->client_verify_mode > dc->client_verify_mode) { | 841 | "GnuTLS: Ignoring Client Certificate!"); |
774 | return DECLINED; | 842 | return DECLINED; |
775 | } | 843 | } |
776 | 844 | ||
777 | gnutls_certificate_server_set_request(ctxt->session, dc->client_verify_mode); | 845 | if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { |
778 | if (mod_gnutls_rehandshake(ctxt) != 0) { | 846 | ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, |
847 | "GnuTLS: Attempting to rehandshake with peer. %d %d", | ||
848 | ctxt->sc->client_verify_mode, dc->client_verify_mode); | ||
849 | |||
850 | gnutls_certificate_server_set_request(ctxt->session, | ||
851 | dc->client_verify_mode); | ||
852 | |||
853 | if (mod_gnutls_rehandshake(ctxt) != 0) { | ||
854 | return HTTP_FORBIDDEN; | ||
855 | } | ||
856 | } | ||
857 | else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) { | ||
858 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
859 | "GnuTLS: Peer is set to IGNORE"); | ||
860 | return DECLINED; | ||
861 | } | ||
862 | |||
863 | rv = gnutls_certificate_verify_peers2(ctxt->session, &status); | ||
864 | |||
865 | if (rv < 0) { | ||
866 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
867 | "GnuTLS: Failed to Verify Peer: (%d) %s", | ||
868 | rv, gnutls_strerror(rv)); | ||
869 | return HTTP_FORBIDDEN; | ||
870 | } | ||
871 | |||
872 | if (status < 0) { | ||
873 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
874 | "GnuTLS: Peer Status is invalid."); | ||
875 | return HTTP_FORBIDDEN; | ||
876 | } | ||
877 | |||
878 | if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { | ||
879 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
880 | "GnuTLS: Could not find Signer for Peer Certificate"); | ||
881 | } | ||
882 | |||
883 | if (status & GNUTLS_CERT_SIGNER_NOT_CA) { | ||
884 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
885 | "GnuTLS: Could not find CA for Peer Certificate"); | ||
886 | } | ||
887 | |||
888 | if (status & GNUTLS_CERT_INVALID) { | ||
889 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
890 | "GnuTLS: Peer Certificate is invalid."); | ||
891 | return HTTP_FORBIDDEN; | ||
892 | } | ||
893 | else if (status & GNUTLS_CERT_REVOKED) { | ||
894 | ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, | ||
895 | "GnuTLS: Peer Certificate is revoked."); | ||
779 | return HTTP_FORBIDDEN; | 896 | return HTTP_FORBIDDEN; |
780 | } | 897 | } |
781 | #endif | 898 | |
899 | /* TODO: OpenPGP Certificates */ | ||
900 | if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) { | ||
901 | ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, | ||
902 | "GnuTLS: Only x509 is supported for client certificates"); | ||
903 | return HTTP_FORBIDDEN; | ||
904 | } | ||
905 | /* TODO: Further Verification. */ | ||
906 | ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, | ||
907 | "GnuTLS: Verified Peer."); | ||
908 | return OK; | ||
782 | } | 909 | } |
783 | 910 | ||
784 | static void gnutls_hooks(apr_pool_t * p) | 911 | static void gnutls_hooks(apr_pool_t * p) |
@@ -801,8 +928,8 @@ static void gnutls_hooks(apr_pool_t * p) | |||
801 | ap_hook_pre_config(mod_gnutls_hook_pre_config, NULL, NULL, | 928 | ap_hook_pre_config(mod_gnutls_hook_pre_config, NULL, NULL, |
802 | APR_HOOK_MIDDLE); | 929 | APR_HOOK_MIDDLE); |
803 | 930 | ||
804 | ap_hook_auth_checker(mod_gnutls_hook_authz, NULL, NULL, APR_HOOK_MIDDLE); | 931 | ap_hook_access_checker(mod_gnutls_hook_authz, NULL, NULL, APR_HOOK_REALLY_FIRST); |
805 | 932 | ||
806 | ap_hook_fixups(mod_gnutls_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); | 933 | ap_hook_fixups(mod_gnutls_hook_fixups, NULL, NULL, APR_HOOK_REALLY_FIRST); |
807 | 934 | ||
808 | /* TODO: HTTP Upgrade Filter */ | 935 | /* TODO: HTTP Upgrade Filter */ |