]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Treat non-leaf certificates present in SSLProxyMachineCertificateFile
authorJoe Orton <jorton@apache.org>
Thu, 17 Dec 2020 12:44:41 +0000 (12:44 +0000)
committerJoe Orton <jorton@apache.org>
Thu, 17 Dec 2020 12:44:41 +0000 (12:44 +0000)
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 [new file with mode: 0644]
docs/log-message-tags/next-number
docs/manual/mod/mod_ssl.xml
modules/ssl/ssl_engine_init.c

diff --git a/changes-entries/ssl-proxy-chain-certs.txt b/changes-entries/ssl-proxy-chain-certs.txt
new file mode 100644 (file)
index 0000000..244a24c
--- /dev/null
@@ -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]
+
index 60f8c40814b82c54cf6de3da587e3e721ec6d562..685949ac36d0b3bdb914de838431d963aeb81486 100644 (file)
@@ -1 +1 @@
-10261
+10262
index 6cee399b4fe2912357f52dd930c5063c8b560d53..8168c1738e799113aaaa5974b5219dac2918a0dc 100644 (file)
@@ -1872,7 +1872,8 @@ SSLProxyMachineCertificatePath "/usr/local/apache2/conf/proxy.crt/"
 <syntax>SSLProxyMachineCertificateFile <em>filename</em></syntax>
 <contextlist><context>server config</context> <context>virtual host</context>
 <context>proxy section</context></contextlist>
-<compatibility>The proxy section context is allowed in httpd 2.4.30 and later</compatibility>
+<compatibility>The proxy section context is allowed in httpd 2.4.30 and later<br/>
+Inclusion of non-leaf (CA) certificates is permitted only in httpd 2.5.1 and later.</compatibility>
 
 <usage>
 <p>
@@ -1884,7 +1885,9 @@ This referenced file is simply the concatenation of the various
 PEM-encoded certificate files. Use this directive alternatively or
 additionally to <code>SSLProxyMachineCertificatePath</code>.  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.</p>
+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  <directive
+module="mod_ssl">SSLProxyMachineCertificateChainFile</directive>.</p>
 
 <p>When challenged to provide a client certificate by a remote server,
 the server should provide a list of <em>acceptable certificate
@@ -1895,7 +1898,7 @@ client cert/key.  If a list of CA names <em>is</em> 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 <directive
+included in the file, or configured with <directive
 module="mod_ssl">SSLProxyMachineCertificateChainFile</directive>.  The
 first configured matching certificate will then be supplied in
 response to the challenge.</p>
index bcb8c8aca1598fe7a849183a6fd15e10023c2e1e..bec4d7b2550bf5adf59a6a4d8510db2cd189234d 100644 (file)
@@ -1715,6 +1715,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 && !defined(LIBRESSL_VERSION_NUMBER)
     /* For OpenSSL >=1.1.1, turn on client cert support which is
@@ -1740,20 +1744,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 "
@@ -1770,13 +1782,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;
     }