From: Yann Ylavic Date: Fri, 22 Jun 2018 09:45:39 +0000 (+0000) Subject: Merge r1826995, r1827001 from trunk: X-Git-Tag: 2.4.34~82 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dab6bb637385bbb9506e5503f583aecbc23ebdf6;p=apache Merge r1826995, r1827001 from trunk: Extend SSLOCSPEnable with mode 'leaf' that only checks the leaf of a certificate chain. PR62112 [Ricardo Martin Camarero ] Fixed OCSPEnable to keep accepting "off", not "none". Submitted by: icing Reviewedby: icing, ylavic, rpluem git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1834089 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index cc74c69465..352d44cc50 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.4.34 + *) mod_ssl: Extend SSLOCSPEnable with mode 'leaf' that only checks the leaf + of a certificate chain. PR62112. + [Ricardo Martin Camarero ] + *) http: Fix small memory leak per request when handling persistent connections. [Ruediger Pluem, Joe Orton] diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index cae5ae69e4..5f7282760e 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -2298,16 +2298,18 @@ SSLCryptoDevice ubsec SSLOCSPEnable Enable OCSP validation of the client certificate chain -SSLOCSPEnable on|off +SSLOCSPEnable on|leaf|off SSLOCSPEnable off server config virtual host +Mode leaf available in httpd 2.4.34 and later

This option enables OCSP validation of the client certificate chain. If this option is enabled, certificates in the client's certificate chain will be validated against an OCSP responder after -normal verification (including CRL checks) have taken place.

+normal verification (including CRL checks) have taken place. In +mode 'leaf', only the client certificate itself will be validated.

The OCSP responder used is either extracted from the certificate itself, or derived by configuration; see the diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 48d64cb624..b716a7b371 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -243,8 +243,8 @@ static const command_rec ssl_config_cmds[] = { "request body if a per-location SSL renegotiation is required due to " "changed access control requirements") - SSL_CMD_SRV(OCSPEnable, FLAG, - "Enable use of OCSP to verify certificate revocation ('on', 'off')") + SSL_CMD_SRV(OCSPEnable, RAW_ARGS, + "Enable use of OCSP to verify certificate revocation mode ('on', 'leaf', 'off')") SSL_CMD_SRV(OCSPDefaultResponder, TAKE1, "URL of the default OCSP Responder") SSL_CMD_SRV(OCSPOverrideResponder, FLAG, diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index e5fd901658..195380e2f3 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -137,8 +137,8 @@ static void modssl_ctx_init(modssl_ctx_t *mctx, apr_pool_t *p) mctx->auth.verify_depth = UNSET; mctx->auth.verify_mode = SSL_CVERIFY_UNSET; - mctx->ocsp_enabled = FALSE; - mctx->ocsp_force_default = FALSE; + mctx->ocsp_mask = UNSET; + mctx->ocsp_force_default = UNSET; mctx->ocsp_responder = NULL; mctx->ocsp_resptime_skew = UNSET; mctx->ocsp_resp_maxage = UNSET; @@ -281,7 +281,7 @@ static void modssl_ctx_cfg_merge(apr_pool_t *p, cfgMergeInt(auth.verify_depth); cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET); - cfgMergeBool(ocsp_enabled); + cfgMergeInt(ocsp_mask); cfgMergeBool(ocsp_force_default); cfgMerge(ocsp_responder, NULL); cfgMergeInt(ocsp_resptime_skew); @@ -1681,11 +1681,46 @@ const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg, return NULL; } -const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) +static const char *ssl_cmd_ocspcheck_parse(cmd_parms *parms, + const char *arg, + int *mask) { - SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *w; + + w = ap_getword_conf(parms->temp_pool, &arg); + if (strcEQ(w, "off")) { + *mask = SSL_OCSPCHECK_NONE; + } + else if (strcEQ(w, "leaf")) { + *mask = SSL_OCSPCHECK_LEAF; + } + else if (strcEQ(w, "on")) { + *mask = SSL_OCSPCHECK_CHAIN; + } + else { + return apr_pstrcat(parms->temp_pool, parms->cmd->name, + ": Invalid argument '", w, "'", + NULL); + } + + while (*arg) { + w = ap_getword_conf(parms->temp_pool, &arg); + if (strcEQ(w, "no_ocsp_for_cert_ok")) { + *mask |= SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK; + } + else { + return apr_pstrcat(parms->temp_pool, parms->cmd->name, + ": Invalid argument '", w, "'", + NULL); + } + } - sc->server->ocsp_enabled = flag ? TRUE : FALSE; + return NULL; +} + +const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); #ifdef OPENSSL_NO_OCSP if (flag) { @@ -1694,7 +1729,7 @@ const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag) } #endif - return NULL; + return ssl_cmd_ocspcheck_parse(cmd, arg, &sc->server->ocsp_mask); } const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag) @@ -2073,3 +2108,4 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s) } } + diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index c75e51ebdd..4f4daab052 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -902,6 +902,10 @@ static apr_status_t ssl_init_ctx_crl(server_rec *s, char *cfgp = mctx->pkp ? "SSLProxy" : "SSL"; int crl_check_mode; + if (mctx->ocsp_mask == UNSET) { + mctx->ocsp_mask = SSL_OCSPCHECK_NONE; + } + if (mctx->crl_check_mask == UNSET) { mctx->crl_check_mask = SSL_CRLCHECK_NONE; } diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index b1591edc5f..e34fc55fa2 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -1578,7 +1578,6 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) int errdepth = X509_STORE_CTX_get_error_depth(ctx); int depth, verify; - /* * Log verification information */ @@ -1652,7 +1651,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) /* * Perform OCSP-based revocation checks */ - if (ok && sc->server->ocsp_enabled) { + if (ok && ((sc->server->ocsp_mask & SSL_OCSPCHECK_CHAIN) || + (errdepth == 0 && (sc->server->ocsp_mask & SSL_OCSPCHECK_LEAF)))) { /* If there was an optional verification error, it's not * possible to perform OCSP validation since the issuer may be * missing/untrusted. Fail in that case. */ diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c index ae0f84253c..bfb8952bf4 100644 --- a/modules/ssl/ssl_engine_ocsp.c +++ b/modules/ssl/ssl_engine_ocsp.c @@ -139,7 +139,14 @@ static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c, ruri = determine_responder_uri(sc, cert, c, pool); if (!ruri) { - return V_OCSP_CERTSTATUS_UNKNOWN; + if (sc->server->ocsp_mask & SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK) { + ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, + "Skipping OCSP check for certificate cos no OCSP URL" + " found and no_ocsp_for_cert_ok is set"); + return V_OCSP_CERTSTATUS_GOOD; + } else { + return V_OCSP_CERTSTATUS_UNKNOWN; + } } request = create_request(ctx, cert, &certID, s, pool, sc); diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index a39569cbf7..9683a1ae89 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -417,6 +417,16 @@ typedef enum { SSL_CRLCHECK_NO_CRL_FOR_CERT_OK = (1 << 2) } ssl_crlcheck_t; +/** + * OCSP checking mask (mode | flags) + */ +typedef enum { + SSL_OCSPCHECK_NONE = (0), + SSL_OCSPCHECK_LEAF = (1 << 0), + SSL_OCSPCHECK_CHAIN = (1 << 1), + SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK = (1 << 2) +} ssl_ocspcheck_t; + /** * Define the SSL pass phrase dialog types */ @@ -701,7 +711,7 @@ typedef struct { modssl_auth_ctx_t auth; - BOOL ocsp_enabled; /* true if OCSP verification enabled */ + int ocsp_mask; BOOL ocsp_force_default; /* true if the default responder URL is * used regardless of per-cert URL */ const char *ocsp_responder; /* default responder URL */ @@ -844,7 +854,7 @@ const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const ch const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg); const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg); const char *ssl_cmd_SSLOCSPUseRequestNonce(cmd_parms *cmd, void *dcfg, int flag); -const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag); +const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *arg); const char *ssl_cmd_SSLOCSPProxyURL(cmd_parms *cmd, void *dcfg, const char *arg); /* Declare OCSP Responder Certificate Verification Directive */