]> granicus.if.org Git - apache/commitdiff
mod_ssl: give mod_md the chance to override certificate after ALPN protocol negotiation.
authorStefan Eissing <icing@apache.org>
Fri, 25 Jan 2019 13:33:07 +0000 (13:33 +0000)
committerStefan Eissing <icing@apache.org>
Fri, 25 Jan 2019 13:33:07 +0000 (13:33 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1852128 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/ssl/ssl_engine_kernel.c

diff --git a/CHANGES b/CHANGES
index 5a3824b97832d40ffdd62770e2c07a2ae2c80bdc..c12376fc580e50a0a29174f912d1b5f6465f5349 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.1
 
+  *) mod_ssl: give mod_md the chance to override certificate after ALPN protocol
+     negotiation. [Stefan Eissing]
+
   *) mod_http2: enable re-use of slave connections again. Fixed slave connection
      keepalives counter. [Stefan Eissing]
 
index 1570d8da647b31366f6b756cc69af6f21fe3d5e2..49c46d7e3c7dd37991d27b352ba850767e1c97ea 100644 (file)
@@ -2308,6 +2308,37 @@ void ssl_callback_Info(const SSL *ssl, int where, int rc)
 }
 
 #ifdef HAVE_TLSEXT
+
+static apr_status_t set_challenge_creds(conn_rec *c, const char *servername,
+                                        SSL *ssl, X509 *cert, EVP_PKEY *key)
+{
+    SSLConnRec *sslcon = myConnConfig(c);
+    
+    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)
+                      "Challenge certificate and private key %s "
+                      "do not match", servername);
+        return APR_EGENERAL;
+    }
+    return APR_SUCCESS;
+}
+  
 /*
  * This function sets the virtual host from an extended
  * client hello with a server name indication extension ("SNI", cf. RFC 6066).
@@ -2337,30 +2368,12 @@ static apr_status_t init_vhost(conn_rec *c, SSL *ssl)
                 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);
+                /* With ACMEv1 we can have challenge connections to a unknown domains
+                 * that need to be answered with a special certificate and will
+                 * otherwise not answer any requests. */
+                if (set_challenge_creds(c, servername, ssl, cert, key) != APR_SUCCESS) {
                     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)
-                                  "Challenge certificate and private key %s "
-                                  "do not match", servername);
-                    return APR_EGENERAL;
-                }
-                
             }
             else {
                 ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(02044)
@@ -2653,6 +2666,23 @@ int ssl_callback_alpn_select(SSL *ssl,
                           proposed);
             return SSL_TLSEXT_ERR_ALERT_FATAL;
         }
+        
+        /* protocol was switched, this could be a challenge protocol such as "acme-tls/1".
+         * For that to work, we need to allow overrides to our ssl certificate. 
+         * However, exclude challenge checks on our best known traffic protocol.
+         * (http/1.1 is the default, we never switch to it anyway.)
+         */
+        if (strcmp("h2", proposed)) {
+            const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+            X509 *cert;
+            EVP_PKEY *key;
+            
+            if (ssl_is_challenge(c, servername, &cert, &key)) {
+                if (set_challenge_creds(c, servername, ssl, cert, key) != APR_SUCCESS) {
+                    return SSL_TLSEXT_ERR_ALERT_FATAL;
+                }
+            }
+        }
     }
 
     return SSL_TLSEXT_ERR_OK;