summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
-rw-r--r--src/gnutls_config.c20
-rw-r--r--src/gnutls_hooks.c143
-rw-r--r--src/mod_gnutls.c5
3 files changed, 110 insertions, 58 deletions
diff --git a/src/gnutls_config.c b/src/gnutls_config.c
index 1194448..d3879f1 100644
--- a/src/gnutls_config.c
+++ b/src/gnutls_config.c
@@ -214,19 +214,31 @@ const char *mgs_set_client_ca_file(cmd_parms * parms, void *dummy,
214{ 214{
215 int rv; 215 int rv;
216 const char* file; 216 const char* file;
217 apr_pool_t* spool;
218 gnutls_datum_t data;
219
217 mgs_srvconf_rec *sc = 220 mgs_srvconf_rec *sc =
218 (mgs_srvconf_rec *) ap_get_module_config(parms->server-> 221 (mgs_srvconf_rec *) ap_get_module_config(parms->server->
219 module_config, 222 module_config,
220 &gnutls_module); 223 &gnutls_module);
221 file = ap_server_root_relative(parms->pool, arg); 224 apr_pool_create(&spool, parms->pool);
222 rv = gnutls_certificate_set_x509_trust_file(sc->certs, 225
223 file, GNUTLS_X509_FMT_PEM); 226 file = ap_server_root_relative(spool, arg);
224 227
228 sc->ca_list_size = 16;
229
230 load_datum_from_file(spool, file, &data);
231
232 rv = gnutls_x509_crt_list_import(sc->ca_list, &sc->ca_list_size,
233 &data, GNUTLS_X509_FMT_PEM,
234 GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
225 if (rv < 0) { 235 if (rv < 0) {
226 return apr_psprintf(parms->pool, "GnuTLS: Failed to load " 236 return apr_psprintf(parms->pool, "GnuTLS: Failed to load "
227 "Client CA File '%s': (%d) %s", file, rv, 237 "Client CA File '%s': (%d) %s", file, rv,
228 gnutls_strerror(rv)); 238 gnutls_strerror(rv));
229 } 239 }
240
241 apr_pool_destroy(spool);
230 return NULL; 242 return NULL;
231} 243}
232 244
diff --git a/src/gnutls_hooks.c b/src/gnutls_hooks.c
index 3862c9d..8452d36 100644
--- a/src/gnutls_hooks.c
+++ b/src/gnutls_hooks.c
@@ -586,41 +586,66 @@ int mgs_hook_authz(request_rec *r)
586 if (!ctxt) { 586 if (!ctxt) {
587 return DECLINED; 587 return DECLINED;
588 } 588 }
589 ap_add_common_vars(r); 589
590 mgs_hook_fixups(r);
591 status = mgs_authz_lua(r);
592 if (status != 0) {
593 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
594 "GnuTLS: FAILED Lua Authorization Test");
595 return HTTP_FORBIDDEN;
596 }
597 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) { 590 if (dc->client_verify_mode == GNUTLS_CERT_IGNORE) {
598 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 591 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
599 "GnuTLS: Directory set to Ignore Client Certificate!"); 592 "GnuTLS: Directory set to Ignore Client Certificate!");
600 return DECLINED;
601 } 593 }
602 594 else {
603 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) { 595 if (ctxt->sc->client_verify_mode < dc->client_verify_mode) {
604 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, 596 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
605 "GnuTLS: Attempting to rehandshake with peer. %d %d", 597 "GnuTLS: Attempting to rehandshake with peer. %d %d",
606 ctxt->sc->client_verify_mode, dc->client_verify_mode); 598 ctxt->sc->client_verify_mode, dc->client_verify_mode);
607 599
608 gnutls_certificate_server_set_request(ctxt->session, 600 gnutls_certificate_server_set_request(ctxt->session,
609 dc->client_verify_mode); 601 dc->client_verify_mode);
610 602
611 if (mgs_rehandshake(ctxt) != 0) { 603 if (mgs_rehandshake(ctxt) != 0) {
612 return HTTP_FORBIDDEN; 604 return HTTP_FORBIDDEN;
605 }
613 } 606 }
614 } 607 else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) {
615 else if (ctxt->sc->client_verify_mode == GNUTLS_CERT_IGNORE) {
616#if MOD_GNUTLS_DEBUG 608#if MOD_GNUTLS_DEBUG
617 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 609 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
618 "GnuTLS: Peer is set to IGNORE"); 610 "GnuTLS: Peer is set to IGNORE");
619#endif 611#endif
620 return DECLINED; 612 }
613 else {
614 rv = mgs_cert_verify(r, ctxt);
615 if (rv != DECLINED) {
616 return rv;
617 }
618 }
619
620
621static int mgs_cert_verify(request_rec *r, mgs_handle_t *ctxt)
622{
623 const gnutls_datum_t* cert_list;
624 int cert_list_size;
625 gnutls_x509_crt_t cert;
626
627
628 cert_list = gnutls_certificate_get_peers(ctxt->session, &cert_list_size);
629
630 if (cert_list == NULL || cert_list_size == 0) {
631 /* no certificate provided by the client, but one was required. */
632 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
633 "GnuTLS: Failed to Verify Peer: "
634 "Client did not submit a certificate");
635 return HTTP_FORBIDDEN;
621 } 636 }
622 637
623 rv = gnutls_certificate_verify_peers2(ctxt->session, &status); 638 if (cert_list_size > 1) {
639 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
640 "GnuTLS: Failed to Verify Peer: "
641 "Chained Client Certificates are not supported.");
642 return HTTP_FORBIDDEN;
643 }
644
645 gnutls_x509_crt_init(&cert);
646 gnutls_x509_crt_import(cert, &cert_chain[0], GNUTLS_X509_FMT_DER);
647
648 rv = gnutls_x509_crt_verify(cert, ctxt->sc->ca_list, ctxt->sc->ca_list_size, 0, &status);
624 649
625 if (rv < 0) { 650 if (rv < 0) {
626 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 651 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
@@ -629,42 +654,56 @@ int mgs_hook_authz(request_rec *r)
629 return HTTP_FORBIDDEN; 654 return HTTP_FORBIDDEN;
630 } 655 }
631 656
632 if (status < 0) { 657 if (status < 0) {
633 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 658 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
634 "GnuTLS: Peer Status is invalid."); 659 "GnuTLS: Peer Status is invalid.");
635 return HTTP_FORBIDDEN; 660 return HTTP_FORBIDDEN;
636 } 661 }
637 662
638 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) { 663 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
639 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 664 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
640 "GnuTLS: Could not find Signer for Peer Certificate"); 665 "GnuTLS: Could not find Signer for Peer Certificate");
641 } 666 }
642 667
643 if (status & GNUTLS_CERT_SIGNER_NOT_CA) { 668 if (status & GNUTLS_CERT_SIGNER_NOT_CA) {
644 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 669 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
645 "GnuTLS: Could not find CA for Peer Certificate"); 670 "GnuTLS: Could not find CA for Peer Certificate");
646 } 671 }
647 672
648 if (status & GNUTLS_CERT_INVALID) { 673 if (status & GNUTLS_CERT_INVALID) {
649 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 674 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
650 "GnuTLS: Peer Certificate is invalid."); 675 "GnuTLS: Peer Certificate is invalid.");
651 return HTTP_FORBIDDEN; 676 return HTTP_FORBIDDEN;
652 } 677 }
653 else if (status & GNUTLS_CERT_REVOKED) { 678 else if (status & GNUTLS_CERT_REVOKED) {
654 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, 679 ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
655 "GnuTLS: Peer Certificate is revoked."); 680 "GnuTLS: Peer Certificate is revoked.");
656 return HTTP_FORBIDDEN; 681 return HTTP_FORBIDDEN;
657 } 682 }
658 683
659 /* TODO: OpenPGP Certificates */ 684 /* TODO: OpenPGP Certificates */
660 if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) { 685 if (gnutls_certificate_type_get(ctxt->session) != GNUTLS_CRT_X509) {
686 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
687 "GnuTLS: Only x509 is supported for client certificates");
688 return HTTP_FORBIDDEN;
689 }
690 /* TODO: Further Verification. */
691// gnutls_x509_crt_get_expiration_time() < time
692// gnutls_x509_crt_get_activation_time() > time
693/// ret = gnutls_x509_crt_check_revocation(crt, crl_list, crl_list_size);
661 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r, 694 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
662 "GnuTLS: Only x509 is supported for client certificates"); 695 "GnuTLS: Verified Peer.");
696 }
697
698 ap_add_common_vars(r);
699 mgs_hook_fixups(r);
700 status = mgs_authz_lua(r);
701
702 if (status != 0) {
703 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
704 "GnuTLS: FAILED Authorization Test");
663 return HTTP_FORBIDDEN; 705 return HTTP_FORBIDDEN;
664 } 706 }
665 /* TODO: Further Verification. */ 707
666 ap_log_rerror(APLOG_MARK, APLOG_CRIT, 0, r,
667 "GnuTLS: Verified Peer.");
668 return OK;
669} 708}
670 709
diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c
index 84440d0..5ca198d 100644
--- a/src/mod_gnutls.c
+++ b/src/mod_gnutls.c
@@ -44,8 +44,9 @@ static void gnutls_hooks(apr_pool_t * p)
44 44
45 /* TODO: HTTP Upgrade Filter */ 45 /* TODO: HTTP Upgrade Filter */
46 /* ap_register_output_filter ("UPGRADE_FILTER", 46 /* ap_register_output_filter ("UPGRADE_FILTER",
47 * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); 47 * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);
48*/ 48 */
49
49 ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, 50 ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME,
50 mgs_filter_input, NULL, 51 mgs_filter_input, NULL,
51 AP_FTYPE_CONNECTION + 5); 52 AP_FTYPE_CONNECTION + 5);