]> granicus.if.org Git - apache/commitdiff
mod_ssl: Add no_crl_for_cert_ok flag to SSLCARevocationCheck directive
authorYann Ylavic <ylavic@apache.org>
Fri, 11 Mar 2016 13:51:17 +0000 (13:51 +0000)
committerYann Ylavic <ylavic@apache.org>
Fri, 11 Mar 2016 13:51:17 +0000 (13:51 +0000)
to opt-in previous behaviour (2.2) with CRLs verification when checking
certificate(s) with no corresponding CRL.

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

CHANGES
docs/manual/mod/mod_ssl.xml
modules/ssl/mod_ssl.c
modules/ssl/ssl_engine_config.c
modules/ssl/ssl_engine_init.c
modules/ssl/ssl_engine_kernel.c
modules/ssl/ssl_private.h

diff --git a/CHANGES b/CHANGES
index 0871f4851c8d3c666fa1c5964fcc88f92121be14..0c00524d05218ee4c69b3f7eee95179d4ff47c36 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) mod_ssl: Add "no_crl_for_cert_ok" flag to SSLCARevocationCheck directive
+     to opt-in previous behaviour (2.2) with CRLs verification when checking
+     certificate(s) with no corresponding CRL.  [Yann Ylavic]
+
   *) mod_proxy_http2: rescheduling of requests that have not been processed
      by the backend when receiving a GOAWAY frame before done.
      [Stefan Eissing]
index 9bac1ebca06724bc7fe2ea7c8762747304623f2e..8b22b35e039e9988ae665d12b4784d9a6007fbcf 100644 (file)
@@ -1205,10 +1205,12 @@ SSLCARevocationFile /usr/local/apache2/conf/ssl.crl/ca-bundle-client.crl
 <directivesynopsis>
 <name>SSLCARevocationCheck</name>
 <description>Enable CRL-based revocation checking</description>
-<syntax>SSLCARevocationCheck chain|leaf|none</syntax>
+<syntax>SSLCARevocationCheck chain|leaf|none <em>flag</em>s</syntax>
 <default>SSLCARevocationCheck none</default>
 <contextlist><context>server config</context>
 <context>virtual host</context></contextlist>
+<compatibility>Optional <em>flag</em>s available in httpd 2.5-dev or
+later</compatibility>
 
 <usage>
 <p>
@@ -1219,25 +1221,38 @@ configured. When set to <code>chain</code> (recommended setting),
 CRL checks are applied to all certificates in the chain, while setting it to
 <code>leaf</code> limits the checks to the end-entity cert.
 </p>
-<note>
-<title>When set to <code>chain</code> or <code>leaf</code>,
-CRLs <em>must</em> be available for successful validation</title>
-<p>
-Prior to version 2.3.15, CRL checking in mod_ssl also succeeded when
-no CRL(s) were found in any of the locations configured with
-<directive module="mod_ssl">SSLCARevocationFile</directive>
-or <directive module="mod_ssl">SSLCARevocationPath</directive>.
-With the introduction of this directive, the behavior has been changed:
-when checking is enabled, CRLs <em>must</em> be present for the validation
-to succeed - otherwise it will fail with an
-<code>"unable to get certificate CRL"</code> error.
-</p>
-</note>
+The available <em>flag</em>s are:</p>
+<ul>
+<li><code>no_crl_for_cert_ok</code>
+    <p>
+    Prior to version 2.3.15, CRL checking in mod_ssl also succeeded when
+    no CRL(s) for the checked certificate(s) were found in any of the locations
+    configured with <directive module="mod_ssl">SSLCARevocationFile</directive>
+    or <directive module="mod_ssl">SSLCARevocationPath</directive>.
+    </p>
+    <p>
+    With the introduction of <directive>SSLCARevocationFile</directive>,
+    the behavior has been changed: by default with <code>chain</code> or
+    <code>leaf</code>, CRLs <strong>must</strong> be present for the
+    validation to succeed - otherwise it will fail with an
+    <code>"unable to get certificate CRL"</code> error.
+    </p>
+    <p>
+    The <em>flag</em> <code>no_crl_for_cert_ok</code> allows to restore
+    previous behaviour.
+    </p>
+</li>
+</ul>
 <example><title>Example</title>
 <highlight language="config">
 SSLCARevocationCheck chain
 </highlight>
 </example>
+<example><title>Compatibility with versions 2.2</title>
+<highlight language="config">
+SSLCARevocationCheck chain no_crl_for_cert_ok
+</highlight>
+</example>
 </usage>
 </directivesynopsis>
 
index cff0d0c42039df52bf9fcf0c9d394a47e499e530..a19e24f18f2114be12824b67df81dbb8536e92ca 100644 (file)
@@ -124,7 +124,7 @@ static const command_rec ssl_config_cmds[] = {
     SSL_CMD_SRV(CARevocationFile, TAKE1,
                 "SSL CA Certificate Revocation List (CRL) file "
                 "('/path/to/file' - PEM encoded)")
-    SSL_CMD_SRV(CARevocationCheck, TAKE1,
+    SSL_CMD_SRV(CARevocationCheck, RAW_ARGS,
                 "SSL CA Certificate Revocation List (CRL) checking mode")
     SSL_CMD_ALL(VerifyClient, TAKE1,
                 "SSL Client verify type "
@@ -202,7 +202,7 @@ static const command_rec ssl_config_cmds[] = {
     SSL_CMD_SRV(ProxyCARevocationFile, TAKE1,
                 "SSL Proxy: CA Certificate Revocation List (CRL) file "
                 "('/path/to/file' - PEM encoded)")
-    SSL_CMD_SRV(ProxyCARevocationCheck, TAKE1,
+    SSL_CMD_SRV(ProxyCARevocationCheck, RAW_ARGS,
                 "SSL Proxy: CA Certificate Revocation List (CRL) checking mode")
     SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
                "SSL Proxy: file containing client certificates "
index 1b872629cb899ae92b1ab429af3e157c5ceafbe5..d2c2b30de639e970a34f05c4495b55bd31173042 100644 (file)
@@ -122,6 +122,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p)
     mctx->crl_path            = NULL;
     mctx->crl_file            = NULL;
     mctx->crl_check_mode      = SSL_CRLCHECK_UNSET;
+    mctx->crl_check_flags     = UNSET;
 
     mctx->auth.ca_cert_path   = NULL;
     mctx->auth.ca_cert_file   = NULL;
@@ -272,6 +273,7 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p,
     cfgMerge(crl_path, NULL);
     cfgMerge(crl_file, NULL);
     cfgMerge(crl_check_mode, SSL_CRLCHECK_UNSET);
+    cfgMergeInt(crl_check_flags);
 
     cfgMergeString(auth.ca_cert_path);
     cfgMergeString(auth.ca_cert_file);
@@ -998,8 +1000,29 @@ const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *cmd,
                                          const char *arg)
 {
     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+    const char *err, *w;
 
-    return ssl_cmd_crlcheck_parse(cmd, arg, &sc->server->crl_check_mode);
+    w = ap_getword_conf(cmd->temp_pool, &arg);
+    err = ssl_cmd_crlcheck_parse(cmd, w, &sc->server->crl_check_mode);
+    if (err || sc->server->crl_check_mode == SSL_CRLCHECK_NONE) {
+        return err;
+    }
+
+    if (sc->server->crl_check_flags == UNSET) {
+        sc->server->crl_check_flags = 0;
+    }
+    while (*arg) {
+        w = ap_getword_conf(cmd->temp_pool, &arg);
+        if (strcEQ(w, "no_crl_for_cert_ok")) {
+            sc->server->crl_check_flags |= MODSSL_CCF_NO_CRL_FOR_CERT_OK;
+        }
+        else {
+            return apr_pstrcat(cmd->temp_pool, cmd->cmd->name,
+                               ": Invalid flag '", w, "'",
+                               NULL);
+        }
+    }
+    return NULL;
 }
 
 static const char *ssl_cmd_verify_parse(cmd_parms *parms,
@@ -1512,8 +1535,29 @@ const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *cmd,
                                               const char *arg)
 {
     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
+    const char *err, *w;
 
-    return ssl_cmd_crlcheck_parse(cmd, arg, &sc->proxy->crl_check_mode);
+    w = ap_getword_conf(cmd->temp_pool, &arg);
+    err = ssl_cmd_crlcheck_parse(cmd, w, &sc->proxy->crl_check_mode);
+    if (err || sc->proxy->crl_check_mode == SSL_CRLCHECK_NONE) {
+        return err;
+    }
+
+    if (sc->proxy->crl_check_flags == UNSET) {
+        sc->proxy->crl_check_flags = 0;
+    }
+    while (*arg) {
+        w = ap_getword_conf(cmd->temp_pool, &arg);
+        if (strcEQ(w, "no_crl_for_cert_ok")) {
+            sc->proxy->crl_check_flags |= MODSSL_CCF_NO_CRL_FOR_CERT_OK;
+        }
+        else {
+            return apr_pstrcat(cmd->temp_pool, cmd->cmd->name,
+                               ": Invalid flag '", w, "'",
+                               NULL);
+        }
+    }
+    return NULL;
 }
 
 const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd,
index e8a9487d50cb165b0dfa6456612e3f8ea869cc9a..ad15d89fcdabf050d79586f02bc6a3ecfe2c677b 100644 (file)
@@ -229,6 +229,13 @@ apr_status_t ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
             sc->fips = FALSE;
         }
 #endif
+
+        if (sc->server && sc->server->crl_check_flags == UNSET) {
+            sc->server->crl_check_flags = 0;
+        }
+        if (sc->proxy && sc->proxy->crl_check_flags == UNSET) {
+            sc->proxy->crl_check_flags = 0;
+        }
     }
 
 #if APR_HAS_THREADS
index 8f50785c8843bf6bc69260bccfba4bb3f60d1d9a..952c92e6e0ec1b1f641a9cd857142c0600f2ca0f 100644 (file)
@@ -1581,10 +1581,11 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
     ssl_log_cxerror(SSLLOG_MARK, APLOG_DEBUG, 0, conn,
                     X509_STORE_CTX_get_current_cert(ctx), APLOGNO(02275)
                     "Certificate Verification, depth %d, "
-                    "CRL checking mode: %s", errdepth,
+                    "CRL checking mode: %s (%x)", errdepth,
                     mctx->crl_check_mode == SSL_CRLCHECK_CHAIN ?
                     "chain" : (mctx->crl_check_mode == SSL_CRLCHECK_LEAF ?
-                               "leaf" : "none"));
+                               "leaf" : "none"),
+                    mctx->crl_check_flags);
 
     /*
      * Check for optionally acceptable non-verifiable issuer situation
@@ -1633,6 +1634,12 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
         X509_STORE_CTX_set_error(ctx, -1);
     }
 
+    if (!ok && errnum == X509_V_ERR_UNABLE_TO_GET_CRL
+            && (sc->server->crl_check_flags & MODSSL_CCF_NO_CRL_FOR_CERT_OK)) {
+        errnum = X509_V_OK;
+        ok = TRUE;
+    }
+
 #ifndef OPENSSL_NO_OCSP
     /*
      * Perform OCSP-based revocation checks
index 7ba9903b98bee779a49e1eb2c10323730120348c..690e8476bbbe1f3704613067a9c4c14fae83b3fb 100644 (file)
@@ -338,6 +338,7 @@ typedef enum {
 /**
   * CRL checking modes
   */
+#define MODSSL_CCF_NO_CRL_FOR_CERT_OK (1 << 0)
 typedef enum {
     SSL_CRLCHECK_UNSET = UNSET,
     SSL_CRLCHECK_NONE  = 0,
@@ -601,6 +602,7 @@ typedef struct {
     const char    *crl_path;
     const char    *crl_file;
     ssl_crlcheck_t crl_check_mode;
+    int            crl_check_flags;
 
 #ifdef HAVE_OCSP_STAPLING
     /** OCSP stapling options */