From 4438d4797585905f2fad85b85ecda2bce9087287 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 17 Dec 2020 12:44:41 +0000 Subject: [PATCH] Treat non-leaf certificates present in SSLProxyMachineCertificateFile the same was as non-leaf certs are in SSLCertificateFile - use them to build the trusted cert chain for the end-entity (client) cert. * modules/ssl/ssl_engine_init.c (ssl_init_proxy_certs): For any non-leaf certificate present in the configured, trust as if used in SSLProxyMachineCertificateChainFile. Github: closes #151 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1884552 13f79535-47bb-0310-9956-ffa450edef68 --- changes-entries/ssl-proxy-chain-certs.txt | 4 ++ docs/manual/mod/mod_ssl.xml | 17 ++++----- modules/ssl/ssl_engine_init.c | 46 ++++++++++++++++------- 3 files changed, 45 insertions(+), 22 deletions(-) create mode 100644 changes-entries/ssl-proxy-chain-certs.txt diff --git a/changes-entries/ssl-proxy-chain-certs.txt b/changes-entries/ssl-proxy-chain-certs.txt new file mode 100644 index 00000000000..244a24c5d0c --- /dev/null +++ b/changes-entries/ssl-proxy-chain-certs.txt @@ -0,0 +1,4 @@ + *) mod_ssl: SSLProxyMachineCertificateFile/Path may reference files + which include CA certificates; those CA certs are treated as if + configured with SSLProxyMachineCertificateChainFile. [Joe Orton] + diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index 7e2f8d509de..4d8ad133ade 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -1859,7 +1859,8 @@ SSLProxyMachineCertificatePath "/usr/local/apache2/conf/proxy.crt/" SSLProxyMachineCertificateFile filename server config virtual host proxy section -The proxy section context is allowed in httpd 2.4.30 and later +The proxy section context is allowed in httpd 2.4.30 and later
+Inclusion of non-leaf (CA) certificates is permitted only in httpd 2.5.1 and later.

@@ -1869,13 +1870,11 @@ keys used for authentication of the proxy server to remote servers.

This referenced file is simply the concatenation of the various PEM-encoded certificate files. Use this directive alternatively or -additionally to SSLProxyMachineCertificatePath. The -referenced file can contain any number of pairs of client certificate -and associated private key. Each pair can be specified in either -(certificate, key) or (key, certificate) order. If the file includes -any non-leaf certificate, or any unmatched key and certificate pair, a -configuration error will be issued at startup. -

+additionally to SSLProxyMachineCertificatePath. The referenced file can contain any number of pairs of client +certificate and associated private key. Each pair can be specified in +either (certificate, key) or (key, certificate) order. Non-leaf (CA) certificates can +also be included in the file, and are treated as if configured with SSLProxyMachineCertificateChainFile.

When challenged to provide a client certificate by a remote server, the server should provide a list of acceptable certificate @@ -1886,7 +1885,7 @@ client cert/key. If a list of CA names is provided, to find a configured client cert which was issued either directly by that CA, or indirectly via any number of intermediary CA certificates. The chain of intermediate CA certificates can be built from those -configured with SSLProxyMachineCertificateChainFile. The first configured matching certificate will then be supplied in response to the challenge.

diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index bbac34dba8b..0888ae637b8 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -1711,6 +1711,10 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s, STACK_OF(X509) *chain; X509_STORE_CTX *sctx; X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx); + int addl_chain = 0; /* non-zero if additional chain certs were + * added to store */ + + ap_assert(store != NULL); /* safe to assume always non-NULL? */ #if OPENSSL_VERSION_NUMBER >= 0x1010100fL /* For OpenSSL >=1.1.1, turn on client cert support which is @@ -1736,20 +1740,28 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s, ssl_init_ca_cert_path(s, ptemp, pkp->cert_path, NULL, sk); } - if ((ncerts = sk_X509_INFO_num(sk)) <= 0) { - sk_X509_INFO_free(sk); - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206) - "no client certs found for SSL proxy"); - return APR_SUCCESS; - } - /* Check that all client certs have got certificates and private - * keys. */ - for (n = 0; n < ncerts; n++) { + * keys. Note the number of certs in the stack may decrease + * during the loop. */ + for (n = 0; n < sk_X509_INFO_num(sk); n++) { X509_INFO *inf = sk_X509_INFO_value(sk, n); + int has_privkey = inf->x_pkey && inf->x_pkey->dec_pkey; - if (!inf->x509 || !inf->x_pkey || !inf->x_pkey->dec_pkey || - inf->enc_data) { + /* For a lone certificate in the file, trust it as a + * CA/intermediate certificate. */ + if (inf->x509 && !has_privkey && !inf->enc_data) { + ssl_log_xerror(SSLLOG_MARK, APLOG_DEBUG, 0, ptemp, s, inf->x509, + APLOGNO(10261) "Trusting non-leaf certificate"); + X509_STORE_add_cert(store, inf->x509); /* increments inf->x509 */ + /* Delete from the stack and iterate again. */ + X509_INFO_free(inf); + sk_X509_INFO_delete(sk, n); + n--; + addl_chain = 1; + continue; + } + + if (!has_privkey || inf->enc_data) { sk_X509_INFO_free(sk); ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, s, APLOGNO(02252) "incomplete client cert configured for SSL proxy " @@ -1766,13 +1778,21 @@ static apr_status_t ssl_init_proxy_certs(server_rec *s, } } + if ((ncerts = sk_X509_INFO_num(sk)) <= 0) { + sk_X509_INFO_free(sk); + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02206) + "no client certs found for SSL proxy"); + return APR_SUCCESS; + } + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02207) "loaded %d client certs for SSL proxy", ncerts); pkp->certs = sk; - - if (!pkp->ca_cert_file || !store) { + /* If any chain certs are configured, build the ->ca_certs chains + * corresponding to the loaded keypairs. */ + if (!pkp->ca_cert_file && !addl_chain) { return APR_SUCCESS; }