summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eissing <icing@apache.org>2018-01-04 12:15:42 +0000
committerStefan Eissing <icing@apache.org>2018-01-04 12:15:42 +0000
commit2b0f47eda5ba13987677d9eca8492e80fed39406 (patch)
tree6f8bea86ed8d9f718432bc9d4576855f16e1777e
parent2fb118187898608bd1fe38e7998428b3d3084c5c (diff)
downloadhttpd-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--CHANGES2
-rw-r--r--modules/ssl/ssl_engine_init.c91
-rw-r--r--modules/ssl/ssl_engine_kernel.c40
-rw-r--r--modules/ssl/ssl_private.h7
-rw-r--r--modules/ssl/ssl_util_ssl.c27
-rw-r--r--modules/ssl/ssl_util_ssl.h1
6 files changed, 168 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
index d1851c05f5..d99d07bb99 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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);