]> granicus.if.org Git - apache/commitdiff
*) mod_ssl/mod_md:
authorStefan Eissing <icing@apache.org>
Mon, 1 Jul 2019 14:22:04 +0000 (14:22 +0000)
committerStefan Eissing <icing@apache.org>
Mon, 1 Jul 2019 14:22:04 +0000 (14:22 +0000)
     Adding 2 new hooks for init/get of OCSP stapling status information when
     other modules want to provide those. Falls back to own implementation with
     same behaviour as before.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1862384 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/ssl/mod_ssl.h
modules/ssl/ssl_engine_init.c
modules/ssl/ssl_util_stapling.c

diff --git a/CHANGES b/CHANGES
index a77b77e204b9c56aabf72c20b241af0c1ef204b8..2134b3472df1e4a93302627dbb8f6cfc01d1337f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,9 @@ Changes with Apache 2.5.1
   *) mod_ssl/mod_md: reversing dependency by letting mod_ssl offer hooks for
      adding certificates and keys to a virtual host. An additional hook allows
      answering special TLS connections as used in ACME challenges.
+     Adding 2 new hooks for init/get of OCSP stapling status information when
+     other modules want to provide those. Falls back to own implementation with
+     same behaviour as before.
      [Stefan Eissing]
   
   *) mod_md: bringing over v2.0.6 from github.
index 5ae7ba6a7199023f4efdf202f958c3a6a09ea5e0..5856680870bda3bf61dd50dc4df31d1b8bc597de 100644 (file)
@@ -121,10 +121,41 @@ APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, add_fallback_cert_files,
 /** On TLS connections that do not relate to a configured virtual host,
  * allow other modules to provide a X509 certificate and EVP_PKEY to
  * be used on the connection. This first hook which does not
- * return DECLINDED will determine the outcome. */
+ * return DECLINED will determine the outcome. */
 APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, answer_challenge,
                           (conn_rec *c, const char *server_name, 
                           void **pX509, void **pEVP_PKEY))
+
+/** During post_config phase, ask around if someone wants to provide
+ * OCSP stapling status information for the given cert (with the also
+ * provided issuer certificate). The first hook which does not
+ * return DECLINED promises to take responsibility (and respond
+ * in later calls via hook ssl_get_stapling_status).
+ * If no hook takes over, mod_ssl's own stapling implementation will
+ * be applied (if configured).
+ */
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, init_stapling_status,
+                          (server_rec *s, apr_pool_t *p, 
+                          void *x509cert, void *x509issuer))
+
+/** Anyone answering positive to ssl_init_stapling_status for a 
+ * certificate, needs to register here and supply the actual OCSP stapling
+ * status data (OCSP_RESP) for a new connection.
+ * The data is returned in DER encoded bytes via pder and pderlen. The
+ * returned pointer may be NULL, which indicates that data is (currently)
+ * unavailable.
+ * If DER data is returned, it MUST come from a response with
+ * status OCSP_RESPONSE_STATUS_SUCCESSFUL and V_OCSP_CERTSTATUS_GOOD
+ * or V_OCSP_CERTSTATUS_REVOKED, not V_OCSP_CERTSTATUS_UNKNOWN. This means
+ * errors in OCSP retrieval are to be handled/logged by the hook and
+ * are not done by mod_ssl.
+ * Any DER bytes returned MUST be allocated via malloc() and ownership
+ * passes to mod_ssl. Meaning, the hook must return a malloced copy of
+ * the data it has. mod_ssl (or OpenSSL) will free it. 
+ */
+APR_DECLARE_EXTERNAL_HOOK(ssl, SSL, int, get_stapling_status,
+                          (unsigned char **pder, int *pderlen, 
+                          conn_rec *c, server_rec *s, void *x509cert))
                           
 #endif /* SSL_CERT_HOOKS */
 
index bb9b4ab385188974288676aa8589878cd9e05319..eb9d2dc38c787aea6bb72b10ddf905481e7731f9 100644 (file)
@@ -59,7 +59,6 @@ APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, answer_challenge,
                                     DECLINED, DECLINED)
 
 
-
 /*  _________________________________________________________________
 **
 **  Module Initialization
@@ -1423,8 +1422,7 @@ static apr_status_t ssl_init_server_certs(server_rec *s,
          * loaded via SSLOpenSSLConfCmd Certificate), so for 1.0.2 and
          * later, we defer to the code in ssl_init_server_ctx.
          */
-        if ((mctx->stapling_enabled == TRUE) &&
-            !ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
+        if (!ssl_stapling_init_cert(s, p, ptemp, mctx, cert)) {
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02567)
                          "Unable to configure certificate %s for stapling",
                          key_id);
@@ -1833,8 +1831,8 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
         
         pks->service_unavailable = 1;
         ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(10085)
-                     "Init: %s will respond with '503 Service Unavailable' for now. This "
-                     "has no SSL certificate configured and no other module contributed any.",
+                     "Init: %s will respond with '503 Service Unavailable' for now. There "
+                     "are no SSL certificates configured and no other module contributed any.",
                      ssl_util_vhostid(p, s));
     }
     
@@ -1887,7 +1885,7 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
      * (late) point makes sure that we catch both certificates loaded
      * via SSLCertificateFile and SSLOpenSSLConfCmd Certificate.
      */
-    if (sc->server->stapling_enabled == TRUE) {
+    do {
         X509 *cert;
         int i = 0;
         int ret = SSL_CTX_set_current_cert(sc->server->ssl_ctx,
@@ -1904,7 +1902,7 @@ static apr_status_t ssl_init_server_ctx(server_rec *s,
                                            SSL_CERT_SET_NEXT);
             i++;
         }
-    }
+    } while(0);
 #endif
 
 #ifdef HAVE_TLS_SESSION_TICKETS
index aecf5d324c3f15b8f56a6d2d5f34afc5b6ad40bf..4105c80157b1ce83daf572276d82aca847972ea9 100644 (file)
 #include "ssl_private.h"
 #include "ap_mpm.h"
 #include "apr_thread_mutex.h"
+#include "mod_ssl.h"
+
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, init_stapling_status,
+                                    (server_rec *s, apr_pool_t *p, 
+                                     void *x509cert, void *x509issuer),
+                                     (s, p, x509cert, x509issuer),
+                                    DECLINED, DECLINED)
+
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, get_stapling_status,
+                                    (unsigned char **pder, int *pderlen, 
+                                     conn_rec *c, server_rec *s, void *x509cert),
+                                     (pder, pderlen, c, s, x509cert), 
+                                    DECLINED, DECLINED)
+                         
 
 #ifdef HAVE_OCSP_STAPLING
 
 static int stapling_cache_mutex_on(server_rec *s);
 static int stapling_cache_mutex_off(server_rec *s);
 
+static int stapling_cb(SSL *ssl, void *arg);
+
 /**
  * Maxiumum OCSP stapling response size. This should be the response for a
  * single certificate and will typically include the responder certificate chain
@@ -119,7 +135,38 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
     OCSP_CERTID *cid = NULL;
     STACK_OF(OPENSSL_STRING) *aia = NULL;
 
-    if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
+    if (x == NULL)
+        return 0;
+
+    if (!(issuer = stapling_get_issuer(mctx, x))) {
+        /* In Apache pre 2.4.40, we use to come here only when mod_ssl stapling
+         * was enabled. With the new hooks, we give other modules the chance
+         * to provide stapling status. However, we do not want to log ssl errors
+         * where we did not do so in the past. */
+        if (mctx->stapling_enabled == TRUE) {
+            ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02217)
+                           "ssl_stapling_init_cert: can't retrieve issuer "
+                           "certificate!");
+            return 0;
+        }
+        return 1;
+    }
+
+    if (ssl_run_init_stapling_status(s, p, x, issuer) == APR_SUCCESS) {
+        /* Someone's taken over or mod_ssl's own implementation is not enabled */
+        if (mctx->stapling_enabled != TRUE) {
+            SSL_CTX_set_tlsext_status_cb(mctx->ssl_ctx, stapling_cb);
+            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO() "OCSP stapling added via hook");
+        }
+        return 1;
+    }
+    
+    if (mctx->stapling_enabled != TRUE) {
+        /* mod_ssl's own implementation is not enabled */
+        return 1;
+    }
+    
+    if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
         return 0;
 
     cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
@@ -139,13 +186,6 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
         return 1;
     }
 
-    if (!(issuer = stapling_get_issuer(mctx, x))) {
-        ssl_log_xerror(SSLLOG_MARK, APLOG_ERR, 0, ptemp, s, x, APLOGNO(02217)
-                       "ssl_stapling_init_cert: can't retrieve issuer "
-                       "certificate!");
-        return 0;
-    }
-
     cid = OCSP_cert_to_id(NULL, x, issuer);
     X509_free(issuer);
     if (!cid) {
@@ -182,18 +222,16 @@ int ssl_stapling_init_cert(server_rec *s, apr_pool_t *p, apr_pool_t *ptemp,
                    mctx->sc->vhost_id);
 
     apr_hash_set(stapling_certinfo, cinf->idx, sizeof(cinf->idx), cinf);
-
+    
     return 1;
 }
 
-static certinfo *stapling_get_certinfo(server_rec *s, modssl_ctx_t *mctx,
+static certinfo *stapling_get_certinfo(server_rec *s, X509 *x, modssl_ctx_t *mctx,
                                         SSL *ssl)
 {
     certinfo *cinf;
-    X509 *x;
     UCHAR idx[SHA_DIGEST_LENGTH];
-    x = SSL_get_certificate(ssl);
-    if ((x == NULL) || (X509_digest(x, EVP_sha1(), idx, NULL) != 1))
+    if (X509_digest(x, EVP_sha1(), idx, NULL) != 1)
         return NULL;
     cinf = apr_hash_get(stapling_certinfo, idx, sizeof(idx));
     if (cinf && cinf->cid)
@@ -751,18 +789,34 @@ static int stapling_cb(SSL *ssl, void *arg)
     OCSP_RESPONSE *rsp = NULL;
     int rv;
     BOOL ok = TRUE;
+    X509 *x;
+    unsigned char *rspder = NULL;
+    int rspderlen;
 
+    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
+                 "stapling_cb: OCSP Stapling callback called");
+
+    x = SSL_get_certificate(ssl);
+    if (x == NULL) {
+        return SSL_TLSEXT_ERR_NOACK;
+    }
+
+    if (ssl_run_get_stapling_status(&rspder, &rspderlen, conn, s, x) == APR_SUCCESS) {
+        /* a hook handles stapling for this certicate and determines the response */
+        if (rspder == NULL || rspderlen <= 0) {
+            return SSL_TLSEXT_ERR_NOACK;
+        }
+        SSL_set_tlsext_status_ocsp_resp(ssl, rspder, rspderlen);
+        return SSL_TLSEXT_ERR_OK;
+    }
+    
     if (sc->server->stapling_enabled != TRUE) {
         ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01950)
                      "stapling_cb: OCSP Stapling disabled");
         return SSL_TLSEXT_ERR_NOACK;
     }
 
-    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01951)
-                 "stapling_cb: OCSP Stapling callback called");
-
-    cinf = stapling_get_certinfo(s, mctx, ssl);
-    if (cinf == NULL) {
+    if ((cinf = stapling_get_certinfo(s, x, mctx, ssl)) == NULL) {
         return SSL_TLSEXT_ERR_NOACK;
     }
 
@@ -865,9 +919,10 @@ apr_status_t modssl_init_stapling(server_rec *s, apr_pool_t *p,
     if (mctx->stapling_responder_timeout == UNSET) {
         mctx->stapling_responder_timeout = 10 * APR_USEC_PER_SEC;
     }
+
     SSL_CTX_set_tlsext_status_cb(ctx, stapling_cb);
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01960) "OCSP stapling initialized");
-
+    
     return APR_SUCCESS;
 }