diff options
author | Stefan Eissing <icing@apache.org> | 2018-01-04 12:15:42 +0000 |
---|---|---|
committer | Stefan Eissing <icing@apache.org> | 2018-01-04 12:15:42 +0000 |
commit | 2b0f47eda5ba13987677d9eca8492e80fed39406 (patch) | |
tree | 6f8bea86ed8d9f718432bc9d4576855f16e1777e | |
parent | 2fb118187898608bd1fe38e7998428b3d3084c5c (diff) | |
download | httpd-2b0f47eda5ba13987677d9eca8492e80fed39406.tar.gz |
On the 2.4.x branch:
merge of 1804530,1804531,1805186,1806939,1807232,1808122 from trunk.
Backport of mod_md support in mod_ssl.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1820075 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_init.c | 91 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_kernel.c | 40 | ||||
-rw-r--r-- | modules/ssl/ssl_private.h | 7 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ssl.c | 27 | ||||
-rw-r--r-- | modules/ssl/ssl_util_ssl.h | 1 |
6 files changed, 168 insertions, 0 deletions
@@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.30 + *) mod_ssl: support for mod_md added. [Stefan Eissing] + *) mod_proxy_html: process parsed comments immediately. Fixes bug (seen in the wild when used with IBM's HTTPD bundle) where parsed comments may be lost. [Nick Kew] diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index e5dee0fc41..f6c51a49b5 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -31,6 +31,22 @@ #include "mod_ssl_openssl.h" #include "mpm_common.h" +/* Use the header, once mod_md is backported. break the dependency loop for now. */ +#define MOD_MD_BACKPORTED 0 +#if MOD_MD_BACKPORTED +#include "mod_md.h" +#else +APR_DECLARE_OPTIONAL_FN(int, + md_is_managed, (struct server_rec *)); +APR_DECLARE_OPTIONAL_FN(apr_status_t, + md_get_certificate, (struct server_rec *, apr_pool_t *, + const char **pkeyfile, + const char **pcertfile)); +APR_DECLARE_OPTIONAL_FN(int, + md_is_challenge, (struct conn_rec *, const char *, + X509 **pcert, EVP_PKEY **pkey)); +#endif + APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, init_server, (server_rec *s,apr_pool_t *p,int is_proxy,SSL_CTX *ctx), (s,p,is_proxy,ctx), OK, DECLINED) @@ -164,6 +180,24 @@ static void ssl_add_version_components(apr_pool_t *p, modver, AP_SERVER_BASEVERSION, incver); } +/**************************************************************************************************/ +/* Managed Domains Interface */ + +static APR_OPTIONAL_FN_TYPE(md_is_managed) *md_is_managed; +static APR_OPTIONAL_FN_TYPE(md_get_certificate) *md_get_certificate; +static APR_OPTIONAL_FN_TYPE(md_is_challenge) *md_is_challenge; + +int ssl_is_challenge(conn_rec *c, const char *servername, + X509 **pcert, EVP_PKEY **pkey) +{ + if (md_is_challenge) { + return md_is_challenge(c, servername, pcert, pkey); + } + *pcert = NULL; + *pkey = NULL; + return 0; +} + /* * Per-module initialization */ @@ -204,6 +238,16 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, ssl_config_global_create(base_server); /* just to avoid problems */ ssl_config_global_fix(mc); + /* Initialize our interface to mod_md, if it is loaded + */ + md_is_managed = APR_RETRIEVE_OPTIONAL_FN(md_is_managed); + md_get_certificate = APR_RETRIEVE_OPTIONAL_FN(md_get_certificate); + md_is_challenge = APR_RETRIEVE_OPTIONAL_FN(md_is_challenge); + if (!md_is_managed || !md_get_certificate) { + md_is_managed = NULL; + md_get_certificate = NULL; + } + /* * try to fix the configuration and open the dedicated SSL * logfile as early as possible @@ -1606,6 +1650,53 @@ static apr_status_t ssl_init_server_ctx(server_rec *s, return APR_EGENERAL; } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(10083) + "Init: (%s) mod_md support is %s.", ssl_util_vhostid(p, s), + md_is_managed? "available" : "unavailable"); + if (md_is_managed && md_is_managed(s)) { + modssl_pk_server_t *const pks = sc->server->pks; + if (pks->cert_files->nelts > 0 || pks->key_files->nelts > 0) { + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10084) + "Init: (%s) You configured certificate/key files on this host, but " + "is is covered by a Managed Domain. You need to remove these directives " + "for the Managed Domain to take over.", ssl_util_vhostid(p, s)); + } + else { + const char *key_file, *cert_file, *chain_file; + + key_file = cert_file = chain_file = NULL; + + if (md_get_certificate) { + /* mod_md >= v0.9.0 */ + rv = md_get_certificate(s, p, &key_file, &cert_file); + } + else { + rv = APR_ENOTIMPL; + } + + if (key_file && cert_file) { + ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, + "%s: installing key=%s, cert=%s, chain=%s", + ssl_util_vhostid(p, s), key_file, cert_file, chain_file); + APR_ARRAY_PUSH(pks->key_files, const char *) = key_file; + APR_ARRAY_PUSH(pks->cert_files, const char *) = cert_file; + sc->server->cert_chain = chain_file; + } + + if (APR_STATUS_IS_EAGAIN(rv)) { + /* Managed Domain not ready yet. This is not a reason to fail the config */ + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085) + "Init: %s will respond with '503 Service Unavailable' for now. This " + "host is part of a Managed Domain, but no SSL certificate is " + "available (yet).", ssl_util_vhostid(p, s)); + pks->service_unavailable = 1; + } + else if (rv != APR_SUCCESS) { + return rv; + } + } + } + if ((rv = ssl_init_ctx(s, p, ptemp, sc->server)) != APR_SUCCESS) { return rv; } diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 7c00123088..b22f8c125a 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -264,6 +264,15 @@ int ssl_hook_ReadReq(request_rec *r) return DECLINED; } + if (sslconn->service_unavailable) { + /* This is set when the SSL properties of this connection are + * incomplete or if this connection was made to challenge a + * particular hostname (ACME). We never serve any request on + * such a connection. */ + /* TODO: a retry-after indicator would be nice here */ + return HTTP_SERVICE_UNAVAILABLE; + } + if (sslconn->non_ssl_request == NON_SSL_SET_ERROR_MSG) { apr_table_setn(r->notes, "error-notes", "Reason: You're speaking plain HTTP to an SSL-enabled " @@ -2110,6 +2119,8 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc) static apr_status_t init_vhost(conn_rec *c, SSL *ssl) { const char *servername; + X509 *cert; + EVP_PKEY *key; if (c) { SSLConnRec *sslcon = myConnConfig(c); @@ -2126,8 +2137,35 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl) ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02043) "SSL virtual host for servername %s found", servername); + return APR_SUCCESS; } + else if (ssl_is_challenge(c, servername, &cert, &key)) { + + sslcon->service_unavailable = 1; + if ((SSL_use_certificate(ssl, cert) < 1)) { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10086) + "Failed to configure challenge certificate %s", + servername); + return APR_EGENERAL; + } + + if (!SSL_use_PrivateKey(ssl, key)) { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10087) + "error '%s' using Challenge key: %s", + ERR_error_string(ERR_peek_last_error(), NULL), + servername); + return APR_EGENERAL; + } + + if (SSL_check_private_key(ssl) < 1) { + ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, c, APLOGNO(10088) + "Challenbge certificate and private key %s " + "do not match", servername); + return APR_EGENERAL; + } + + } else { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044) "No matching SSL virtual host for servername " @@ -2233,6 +2271,8 @@ static int ssl_find_vhost(void *servername, conn_rec *c, server_rec *s) */ sslcon->server = s; sslcon->cipher_suite = sc->server->auth.cipher_suite; + sslcon->service_unavailable = sc->server->pks? + sc->server->pks->service_unavailable : 0; ap_update_child_status_from_server(c->sbh, SERVER_BUSY_READ, c, s); /* diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 0ab60a0dfb..9990f8b41e 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -524,6 +524,7 @@ typedef struct { server_rec *server; const char *cipher_suite; /* cipher suite used in last reneg */ + int service_unavailable; /* thouugh we negotiate SSL, no requests will be served */ } SSLConnRec; /* BIG FAT WARNING: SSLModConfigRec has unusual memory lifetime: it is @@ -600,6 +601,9 @@ typedef struct { * sent in the CertificateRequest message: */ const char *ca_name_path; const char *ca_name_file; + + /* TLS service for this server is suspended */ + int service_unavailable; } modssl_pk_server_t; typedef struct { @@ -1063,6 +1067,9 @@ void ssl_init_ocsp_certificates(server_rec *s, modssl_ctx_t *mctx); * memory. */ DH *modssl_get_dh_params(unsigned keylen); +int ssl_is_challenge(conn_rec *c, const char *servername, + X509 **pcert, EVP_PKEY **pkey); + #endif /* SSL_PRIVATE_H */ /** @} */ diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index 980759210d..e22dd7d694 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -115,6 +115,33 @@ EVP_PKEY *modssl_read_privatekey(const char* filename, EVP_PKEY **key, pem_passw return rc; } +typedef struct { + const char *pass; + int pass_len; +} pass_ctx; + +static int provide_pass(char *buf, int size, int rwflag, void *baton) +{ + pass_ctx *ctx = baton; + if (ctx->pass_len > 0) { + if (ctx->pass_len < size) { + size = (int)ctx->pass_len; + } + memcpy(buf, ctx->pass, size); + } + return ctx->pass_len; +} + +EVP_PKEY *modssl_read_encrypted_pkey(const char *filename, EVP_PKEY **key, + const char *pass, apr_size_t pass_len) +{ + pass_ctx ctx; + + ctx.pass = pass; + ctx.pass_len = pass_len; + return modssl_read_privatekey(filename, key, provide_pass, &ctx); +} + /* _________________________________________________________________ ** ** Smart shutdown diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h index 04b138d2ae..5c6c8b6853 100644 --- a/modules/ssl/ssl_util_ssl.h +++ b/modules/ssl/ssl_util_ssl.h @@ -65,6 +65,7 @@ void modssl_init_app_data2_idx(void); void *modssl_get_app_data2(SSL *); void modssl_set_app_data2(SSL *, void *); EVP_PKEY *modssl_read_privatekey(const char *, EVP_PKEY **, pem_password_cb *, void *); +EVP_PKEY *modssl_read_encrypted_pkey(const char *, EVP_PKEY **, const char *, apr_size_t); int modssl_smart_shutdown(SSL *ssl); BOOL modssl_X509_getBC(X509 *, int *, int *); char *modssl_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne); |