Commit 9c0582ab authored by Kaspar Brand's avatar Kaspar Brand
Browse files

Revamp CRL checking for client and remote servers:

- completely delegate CRL processing to OpenSSL
- introduce a new [Proxy]CARevocationCheck directive
- drop ssl_callback_SSLVerify_CRL from ssl_engine_kernel.c
- remove X509_STORE from modssl_ctx_t
- drop CRL store helper functions from ssl_util_ssl.c
- avoid sending "certificate_expired" SSL alerts to peers
  when the nextUpdate field of a CRL is in the past


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1165056 13f79535-47bb-0310-9956-ffa450edef68
parent eb74280b
Loading
Loading
Loading
Loading
+5 −0
Changes for CHANGES: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
                                                         -*- coding: utf-8 -*-
Changes with Apache 2.3.15

  *) mod_ssl: revamp CRL-based revocation checking when validating
     certificates of clients or proxied servers. Completely delegate
     CRL processing to OpenSSL, and add a new [Proxy]CARevocationCheck
     directive for controlling the revocation checking mode. [Kaspar Brand]

  *) Fix a regression in the CVE-2011-3192 byterange fix.
     PR 51748. [low_priority <lowprio20 gmail.com>]

+75 −0
Changes for docs/manual/mod/mod_ssl.xml: 75 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1033,6 +1033,43 @@ SSLCARevocationFile /usr/local/apache2/conf/ssl.crl/ca-bundle-client.crl
</usage>
</directivesynopsis>

<directivesynopsis>
<name>SSLCARevocationCheck</name>
<description>Enable CRL-based revocation checking</description>
<syntax>SSLCARevocationCheck chain|leaf|none</syntax>
<default>SSLCARevocationCheck none</default>
<contextlist><context>server config</context>
<context>virtual host</context></contextlist>

<usage>
<p>
Enables certificate revocation list (CRL) checking. At least one of
<directive module="mod_ssl">SSLCARevocationFile</directive>
or <directive module="mod_ssl">SSLCARevocationPath</directive> must be
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>
<example><title>Example</title>
SSLCARevocationCheck chain
</example>
</usage>
</directivesynopsis>

<directivesynopsis>
<name>SSLVerifyClient</name>
<description>Type of Client Certificate verification</description>
@@ -1784,6 +1821,44 @@ SSLProxyCARevocationFile /usr/local/apache2/conf/ssl.crl/ca-bundle-remote-server
</usage>
</directivesynopsis>

<directivesynopsis>
<name>SSLProxyCARevocationCheck</name>
<description>Enable CRL-based revocation checking for Remote Server Auth</description>
<syntax>SSLProxyCARevocationCheck chain|leaf|none</syntax>
<default>SSLProxyCARevocationCheck none</default>
<contextlist><context>server config</context>
<context>virtual host</context></contextlist>

<usage>
<p>
Enables certificate revocation list (CRL) checking for the
<em>remote servers</em> you deal with. At least one of
<directive module="mod_ssl">SSLProxyCARevocationFile</directive>
or <directive module="mod_ssl">SSLProxyCARevocationPath</directive> must be
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">SSLProxyCARevocationFile</directive>
or <directive module="mod_ssl">SSLProxyCARevocationPath</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>
<example><title>Example</title>
SSLProxyCARevocationCheck chain
</example>
</usage>
</directivesynopsis>

<directivesynopsis>
<name>SSLUserName</name>
<description>Variable name to determine user name</description>
+4 −0
Changes for modules/ssl/mod_ssl.c: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -112,6 +112,8 @@ 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 CA Certificate Revocation List (CRL) checking mode")
    SSL_CMD_ALL(VerifyClient, TAKE1,
                "SSL Client verify type "
                "('none', 'optional', 'require', 'optional_no_ca')")
@@ -163,6 +165,8 @@ 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 Proxy: CA Certificate Revocation List (CRL) checking mode")
    SSL_CMD_SRV(ProxyMachineCertificateFile, TAKE1,
               "SSL Proxy: file containing client certificates "
               "('/path/to/file' - PEM encoded certificates)")
+44 −1
Changes for modules/ssl/ssl_engine_config.c: 44 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -119,7 +119,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx)

    mctx->crl_path            = NULL;
    mctx->crl_file            = NULL;
    mctx->crl                 = NULL; /* set during module init */
    mctx->crl_check_mode      = SSL_CRLCHECK_UNSET;

    mctx->auth.ca_cert_path   = NULL;
    mctx->auth.ca_cert_file   = NULL;
@@ -238,6 +238,7 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base,

    cfgMerge(crl_path, NULL);
    cfgMerge(crl_file, NULL);
    cfgMerge(crl_check_mode, SSL_CRLCHECK_UNSET);

    cfgMergeString(auth.ca_cert_path);
    cfgMergeString(auth.ca_cert_file);
@@ -902,6 +903,39 @@ const char *ssl_cmd_SSLCARevocationFile(cmd_parms *cmd,
    return NULL;
}

static const char *ssl_cmd_crlcheck_parse(cmd_parms *parms,
                                          const char *arg,
                                          ssl_crlcheck_t *mode)
{
    if (strcEQ(arg, "none")) {
        *mode = SSL_CRLCHECK_NONE;
    }
    else if (strcEQ(arg, "leaf")) {
        *mode = SSL_CRLCHECK_LEAF;
    }
    else if (strcEQ(arg, "chain")) {
        *mode = SSL_CRLCHECK_CHAIN;
    }
    else {
        return apr_pstrcat(parms->temp_pool, parms->cmd->name,
                           ": Invalid argument '", arg, "'",
                           NULL);
    }

    return NULL;
}

const char *ssl_cmd_SSLCARevocationCheck(cmd_parms *cmd,
                                         void *dcfg,
                                         const char *arg)
{   
    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);

    const char *err;

    return ssl_cmd_crlcheck_parse(cmd, arg, &sc->server->crl_check_mode);
}
        
static const char *ssl_cmd_verify_parse(cmd_parms *parms,
                                        const char *arg,
                                        ssl_verify_t *id)
@@ -1379,6 +1413,15 @@ const char *ssl_cmd_SSLProxyCARevocationFile(cmd_parms *cmd,
    return NULL;
}

const char *ssl_cmd_SSLProxyCARevocationCheck(cmd_parms *cmd,
                                              void *dcfg,
                                              const char *arg)
{   
    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);

    return ssl_cmd_crlcheck_parse(cmd, arg, &sc->proxy->crl_check_mode);
}
        
const char *ssl_cmd_SSLProxyMachineCertificateFile(cmd_parms *cmd,
                                                   void *dcfg,
                                                   const char *arg)
+34 −9
Changes for modules/ssl/ssl_engine_init.c: 34 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -726,28 +726,55 @@ static void ssl_init_ctx_crl(server_rec *s,
                             apr_pool_t *ptemp,
                             modssl_ctx_t *mctx)
{
    X509_STORE *store = SSL_CTX_get_cert_store(mctx->ssl_ctx);
    unsigned long crlflags = 0;
    char *cfgp = mctx->pkp ? "SSLProxy" : "SSL";

    /*
     * Configure Certificate Revocation List (CRL) Details
     */

    if (!(mctx->crl_file || mctx->crl_path)) {
        if (mctx->crl_check_mode == SSL_CRLCHECK_LEAF ||
            mctx->crl_check_mode == SSL_CRLCHECK_CHAIN) {
            ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
                         "Host %s: CRL checking has been enabled, but "
                         "neither %sCARevocationFile nor %sCARevocationPath "
                         "is configured", mctx->sc->vhost_id, cfgp, cfgp);
            ssl_die();
        }
        return;
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "Configuring certificate revocation facility");

    mctx->crl =
        SSL_X509_STORE_create((char *)mctx->crl_file,
                              (char *)mctx->crl_path);

    if (!mctx->crl) {
    if (!store || !X509_STORE_load_locations(store, mctx->crl_file,
                                             mctx->crl_path)) {
        ap_log_error(APLOG_MARK, APLOG_EMERG, 0, s,
                "Unable to configure X.509 CRL storage "
                "for certificate revocation");
                     "Host %s: unable to configure X.509 CRL storage "
                     "for certificate revocation", mctx->sc->vhost_id);
        ssl_log_ssl_error(SSLLOG_MARK, APLOG_EMERG, s);
        ssl_die();
    }

    switch (mctx->crl_check_mode) {
       case SSL_CRLCHECK_LEAF:
           crlflags = X509_V_FLAG_CRL_CHECK;
           break;
       case SSL_CRLCHECK_CHAIN:
           crlflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
           break;
    }

    if (crlflags) {
        X509_STORE_set_flags(store, crlflags);
    } else {
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s,
                     "Host %s: X.509 CRL storage locations configured, "
                     "but CRL checking (%sCARevocationCheck) is not "
                     "enabled", mctx->sc->vhost_id, cfgp);
    }
}

static void ssl_init_ctx_pkcs7_cert_chain(server_rec *s, modssl_ctx_t *mctx)
@@ -1432,8 +1459,6 @@ void ssl_init_Child(apr_pool_t *p, server_rec *s)

static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx)
{
    MODSSL_CFG_ITEM_FREE(X509_STORE_free, mctx->crl);

    MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx);
}

Loading