From 6a8a8396ceed9fb87a6586ebcb144b5f4b62a39a Mon Sep 17 00:00:00 2001 From: Paul Querna Date: Mon, 27 Sep 2004 06:54:58 +0000 Subject: updated --- src/Makefile.am | 2 +- src/mod_gnutls.c | 204 ++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 156 insertions(+), 50 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 7a4903a..00ef272 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,7 +2,7 @@ CLEANFILES = .libs/libmod_gnutls *~ libmod_gnutls_la_SOURCES = mod_gnutls.c libmod_gnutls_la_CFLAGS = -Wall ${MODULE_CFLAGS} -libmod_gnutls_la_LDFLAGS = +libmod_gnutls_la_LDFLAGS = ${MODULE_LIBS} lib_LTLIBRARIES = libmod_gnutls.la diff --git a/src/mod_gnutls.c b/src/mod_gnutls.c index bf0d9c3..e9ad89c 100644 --- a/src/mod_gnutls.c +++ b/src/mod_gnutls.c @@ -34,32 +34,42 @@ GCRY_THREAD_OPTION_PTHREAD_IMPL; module AP_MODULE_DECLARE_DATA gnutls_module; +#ifdef GNUTLS_AS_FILTER #define GNUTLS_OUTPUT_FILTER_NAME "GnuTLS Output Filter" #define GNUTLS_INPUT_FILTER_NAME "GnuTLS Input Filter" +#endif #define GNUTLS_ENABLED_FALSE 0 #define GNUTLS_ENABLED_TRUE 1 -typedef struct gnutls_srvconf_t gnutls_srvconf_t; -struct gnutls_srvconf_t -{ +typedef struct { gnutls_certificate_credentials_t certs; + gnutls_anon_server_credentials_t anoncred; char *key_file; char *cert_file; int enabled; -}; + int non_https; + int ciphers[16]; + int key_exchange[16]; + int macs[16]; + int protocol[16]; + int compression[16]; +} gnutls_srvconf_rec; typedef struct gnutls_handle_t gnutls_handle_t; struct gnutls_handle_t { - gnutls_srvconf_t *sc; + gnutls_srvconf_rec *sc; gnutls_session_t session; +#ifdef GNUTLS_AS_FILTER ap_filter_t *input_filter; apr_bucket_brigade *input_bb; apr_read_type_e input_block; +#endif }; +#ifdef GNUTLS_AS_FILTER static apr_status_t gnutls_filter_input(ap_filter_t * f, apr_bucket_brigade * bb, ap_input_mode_t mode, @@ -105,6 +115,8 @@ static apr_status_t gnutls_filter_output(ap_filter_t * f, return status; } +#endif /* GNUTLS_AS_FILTER */ + static apr_status_t gnutls_cleanup_pre_config(void *data) { gnutls_global_deinit(); @@ -134,48 +146,44 @@ static int gnutls_hook_post_config(apr_pool_t * p, apr_pool_t * plog, apr_pool_t * ptemp, server_rec * base_server) { - gnutls_srvconf_t *sc; + gnutls_srvconf_rec *sc; server_rec *s; gnutls_dh_params_t dh_params; gnutls_rsa_params_t rsa_params; /* TODO: Should we regenerate these after X requests / X time ? */ - gnutls_dh_params_init(&dh_params); - gnutls_dh_params_generate2(dh_params, DH_BITS); - gnutls_rsa_params_init(&rsa_params); - gnutls_rsa_params_generate2(rsa_params, RSA_BITS); +// gnutls_dh_params_init(&dh_params); +// gnutls_dh_params_generate2(dh_params, DH_BITS); +// gnutls_rsa_params_init(&rsa_params); +// gnutls_rsa_params_generate2(rsa_params, RSA_BITS); for (s = base_server; s; s = s->next) { - sc = (gnutls_srvconf_t *) ap_get_module_config(s->module_config, + sc = (gnutls_srvconf_rec *) ap_get_module_config(s->module_config, &gnutls_module); if (sc->cert_file != NULL && sc->key_file != NULL) { gnutls_certificate_set_x509_key_file(sc->certs, sc->cert_file, sc->key_file, GNUTLS_X509_FMT_PEM); +// gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params); +// gnutls_certificate_set_dh_params(sc->certs, dh_params); } - else { + else if(sc->enabled == GNUTLS_ENABLED_TRUE ){ ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s, - "[GnuTLS] - Host '%s' is missing a Cert and Key File!", - s->server_hostname); + "[GnuTLS] - Host '%s:%d' is missing a Cert and Key File!", + s->server_hostname, s->port); } - - /** - * TODO: Is it okay for all virtual hosts to - * share the same DH/RSAparams? - */ - gnutls_certificate_set_dh_params(sc->certs, dh_params); - gnutls_certificate_set_rsa_export_params(sc->certs, rsa_params); } + ap_add_version_component(p, "GnuTLS/" LIBGNUTLS_VERSION); return OK; } static const char *gnutls_hook_http_method(const request_rec * r) { - gnutls_srvconf_t *sc = - (gnutls_srvconf_t *) ap_get_module_config(r->server->module_config, + gnutls_srvconf_rec *sc = + (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config, &gnutls_module); if (sc->enabled == GNUTLS_ENABLED_FALSE) { @@ -187,8 +195,8 @@ static const char *gnutls_hook_http_method(const request_rec * r) static apr_port_t gnutls_hook_default_port(const request_rec * r) { - gnutls_srvconf_t *sc = - (gnutls_srvconf_t *) ap_get_module_config(r->server->module_config, + gnutls_srvconf_rec *sc = + (gnutls_srvconf_rec *) ap_get_module_config(r->server->module_config, &gnutls_module); if (sc->enabled == GNUTLS_ENABLED_FALSE) { @@ -198,6 +206,7 @@ static apr_port_t gnutls_hook_default_port(const request_rec * r) return 443; } +#ifdef GNUTLS_AS_FILTER /** * From mod_ssl / ssl_engine_io.c * This function will read from a brigade and discard the read buckets as it @@ -336,15 +345,17 @@ static ssize_t gnutls_transport_write(gnutls_transport_ptr_t ptr, //APR_BRIGADE_INSERT_TAIL(outctx->bb, bucket); return 0; } +#endif /* GNUTLS_AS_FILTER */ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) { #ifndef GNUTLS_AS_FILTER int cfd; + int ret; #endif gnutls_handle_t *ctxt; - gnutls_srvconf_t *sc = - (gnutls_srvconf_t *) ap_get_module_config(c->base_server-> + gnutls_srvconf_rec *sc = + (gnutls_srvconf_rec *) ap_get_module_config(c->base_server-> module_config, &gnutls_module); @@ -357,13 +368,17 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) ctxt->sc = sc; gnutls_init(&ctxt->session, GNUTLS_SERVER); - gnutls_set_default_priority(ctxt->session); + gnutls_cipher_set_priority(ctxt->session, sc->ciphers); + gnutls_compression_set_priority(ctxt->session, sc->compression); + gnutls_kx_set_priority(ctxt->session, sc->key_exchange); + gnutls_protocol_set_priority(ctxt->session, sc->protocol); + gnutls_mac_set_priority(ctxt->session, sc->macs); gnutls_credentials_set(ctxt->session, GNUTLS_CRD_CERTIFICATE, sc->certs); + gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_IGNORE); - gnutls_certificate_server_set_request(ctxt->session, GNUTLS_CERT_REQUEST); - - gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); +// gnutls_dh_set_prime_bits(ctxt->session, DH_BITS); + ap_set_module_config(c->conn_config, &gnutls_module, ctxt); @@ -377,41 +392,97 @@ static int gnutls_hook_pre_connection(conn_rec * c, void *csd) #else apr_os_sock_get(&cfd, csd); gnutls_transport_set_ptr(ctxt->session, (gnutls_transport_ptr)cfd); + gnutls_credentials_set(ctxt->session, GNUTLS_CRD_ANON, sc->anoncred); + + do{ + ret = gnutls_handshake(ctxt->session); + + if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN){ + continue; + } + + if (ret < 0) { + if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { + ret = gnutls_alert_get(ctxt->session); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, + "GnuTLS: Hanshake Alert (%d) '%s'.\n", ret, gnutls_alert_get_name(ret)); + } + + if (gnutls_error_is_fatal(ret) != 0) { + gnutls_deinit(ctxt->session); + ap_log_error(APLOG_MARK, APLOG_ERR, 0, c->base_server, + "GnuTLS: Handshake Failed (%d) '%s'",ret, gnutls_strerror(ret)); + sc->non_https = 1; + break; + } + } + break; /* all done with the handshake */ + } while(1); #endif return OK; } -static const char *gnutls_set_ca_file(cmd_parms * parms, void *dummy, +static const char *gnutls_set_cert_file(cmd_parms * parms, void *dummy, const char *arg) { - gnutls_srvconf_t *sc = - (gnutls_srvconf_t *) ap_get_module_config(parms->server-> + gnutls_srvconf_rec *sc = + (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> module_config, &gnutls_module); -/* TODO: CRL, CAFile */ -// gnutls_certificate_set_x509_trust_file(sc->certs, CAFILE, -// GNUTLS_X509_FMT_PEM); + sc->cert_file = apr_pstrdup(parms->pool, arg); + return NULL; +} + +static const char *gnutls_set_key_file(cmd_parms * parms, void *dummy, + const char *arg) +{ + gnutls_srvconf_rec *sc = + (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + sc->key_file = apr_pstrdup(parms->pool, arg); + return NULL; +} + +static const char *gnutls_set_enabled(cmd_parms * parms, void *dummy, + const char *arg) +{ + gnutls_srvconf_rec *sc = + (gnutls_srvconf_rec *) ap_get_module_config(parms->server-> + module_config, + &gnutls_module); + if (!strcasecmp(arg, "On")) { + sc->enabled = GNUTLS_ENABLED_TRUE; + } + else if (!strcasecmp(arg, "Off")) { + sc->enabled = GNUTLS_ENABLED_FALSE; + } + else { + return "GnuTLSEnable must be set to 'On' or 'Off'"; + } + return NULL; } static const command_rec gnutls_cmds[] = { - AP_INIT_FLAG("GnuTLSEnable", ap_set_flag_slot, - (void *) APR_OFFSETOF(gnutls_srvconf_t, enabled), RSRC_CONF, - "Whether this server has GnuTLS Enabled. Default: Off"), - AP_INIT_TAKE1("GnuTLSCertificateFile", ap_set_string_slot, - (void *) APR_OFFSETOF(gnutls_srvconf_t, cert_file), + AP_INIT_TAKE1("GnuTLSCertificateFile", gnutls_set_cert_file, + NULL, RSRC_CONF, "SSL Server Key file"), - AP_INIT_TAKE1("GnuTLSKeyFile", ap_set_string_slot, - (void *) APR_OFFSETOF(gnutls_srvconf_t, key_file), + AP_INIT_TAKE1("GnuTLSKeyFile", gnutls_set_key_file, + NULL, RSRC_CONF, "SSL Server Certificate file"), + AP_INIT_TAKE1("GnuTLSEnable", gnutls_set_enabled, + NULL, RSRC_CONF, + "Whether this server has GnuTLS Enabled. Default: Off"), + {NULL} }; /* TODO: CACertificateFile & Client Authentication * AP_INIT_TAKE1("GnuTLSCACertificateFile", ap_set_server_string_slot, - * (void *) APR_OFFSETOF(gnutls_srvconf_t, key_file), NULL, + * (void *) APR_OFFSETOF(gnutls_srvconf_rec, key_file), NULL, * RSRC_CONF, * "CA"), */ @@ -430,24 +501,59 @@ static void gnutls_hooks(apr_pool_t * p) /* ap_register_output_filter ("UPGRADE_FILTER", * ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5); */ - +#ifdef GNUTLS_AS_FILTER ap_register_input_filter(GNUTLS_INPUT_FILTER_NAME, gnutls_filter_input, NULL, AP_FTYPE_CONNECTION + 5); ap_register_output_filter(GNUTLS_OUTPUT_FILTER_NAME, gnutls_filter_output, NULL, AP_FTYPE_CONNECTION + 5); - +#endif } static void *gnutls_config_server_create(apr_pool_t * p, server_rec * s) { - gnutls_srvconf_t *sc = apr_pcalloc(p, sizeof *sc); + int i; + gnutls_srvconf_rec *sc = apr_pcalloc(p, sizeof(*sc)); sc->enabled = GNUTLS_ENABLED_FALSE; + sc->non_https = 0; gnutls_certificate_allocate_credentials(&sc->certs); - + gnutls_anon_allocate_server_credentials(&sc->anoncred); sc->key_file = NULL; sc->cert_file = NULL; + + i = 0; + sc->ciphers[i++] = GNUTLS_CIPHER_RIJNDAEL_128_CBC; + sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_128; + sc->ciphers[i++] = GNUTLS_CIPHER_3DES_CBC; + sc->ciphers[i++] = GNUTLS_CIPHER_ARCFOUR_40; + sc->ciphers[i] = 0; + + i = 0; + sc->key_exchange[i++] = GNUTLS_KX_RSA; + sc->key_exchange[i++] = GNUTLS_KX_RSA_EXPORT; + sc->key_exchange[i++] = GNUTLS_KX_DHE_RSA; + sc->key_exchange[i++] = GNUTLS_KX_DHE_DSS; + sc->key_exchange[i] = 0; + + i = 0; + sc->macs[i++] = GNUTLS_MAC_MD5; + sc->macs[i++] = GNUTLS_MAC_SHA; + sc->macs[i++] = GNUTLS_MAC_RMD160; + sc->macs[i] = 0; + + i = 0; + sc->protocol[i++] = GNUTLS_TLS1_1; + sc->protocol[i++] = GNUTLS_TLS1; + sc->protocol[i++] = GNUTLS_SSL3; + sc->protocol[i] = 0; + + i = 0; + sc->compression[i++] = GNUTLS_COMP_NULL; + sc->compression[i++] = GNUTLS_COMP_ZLIB; + sc->compression[i++] = GNUTLS_COMP_LZO; + sc->compression[i] = 0; + return sc; } -- cgit