|
|
00df7d |
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
|
|
|
00df7d |
index 4580f1c..fb8202e 100644
|
|
|
00df7d |
--- a/docs/manual/mod/mod_ssl.html.en
|
|
|
00df7d |
+++ b/docs/manual/mod/mod_ssl.html.en
|
|
|
00df7d |
@@ -991,7 +991,8 @@ the certificate being verified.
|
|
|
00df7d |
This option enables OCSP validation of the client certificate
|
|
|
00df7d |
chain. If this option is enabled, certificates in the client's
|
|
|
00df7d |
certificate chain will be validated against an OCSP responder after
|
|
|
00df7d |
-normal verification (including CRL checks) have taken place.
|
|
|
00df7d |
+normal verification (including CRL checks) have taken place. In
|
|
|
00df7d |
+mode 'leaf', only the client certificate itself will be validated.
|
|
|
00df7d |
|
|
|
00df7d |
The OCSP responder used is either extracted from the certificate
|
|
|
00df7d |
itself, or derived by configuration; see the
|
|
|
00df7d |
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
|
|
|
00df7d |
index 4a8b661..e637a9d 100644
|
|
|
00df7d |
--- a/modules/ssl/mod_ssl.c
|
|
|
00df7d |
+++ b/modules/ssl/mod_ssl.c
|
|
|
00df7d |
@@ -227,8 +227,8 @@ static const command_rec ssl_config_cmds[] = {
|
|
|
00df7d |
"request body if a per-location SSL renegotiation is required due to "
|
|
|
00df7d |
"changed access control requirements")
|
|
|
00df7d |
|
|
|
00df7d |
- SSL_CMD_SRV(OCSPEnable, FLAG,
|
|
|
00df7d |
- "Enable use of OCSP to verify certificate revocation ('on', 'off')")
|
|
|
00df7d |
+ SSL_CMD_SRV(OCSPEnable, RAW_ARGS,
|
|
|
00df7d |
+ "Enable use of OCSP to verify certificate revocation mode ('on', 'leaf', 'off')")
|
|
|
00df7d |
SSL_CMD_SRV(OCSPDefaultResponder, TAKE1,
|
|
|
00df7d |
"URL of the default OCSP Responder")
|
|
|
00df7d |
SSL_CMD_SRV(OCSPOverrideResponder, FLAG,
|
|
|
00df7d |
diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c
|
|
|
00df7d |
index 86a7f0f..714aee9 100644
|
|
|
00df7d |
--- a/modules/ssl/ssl_engine_config.c
|
|
|
00df7d |
+++ b/modules/ssl/ssl_engine_config.c
|
|
|
00df7d |
@@ -130,7 +130,7 @@ static void modssl_ctx_init(modssl_ctx_t *mctx)
|
|
|
00df7d |
mctx->auth.verify_depth = UNSET;
|
|
|
00df7d |
mctx->auth.verify_mode = SSL_CVERIFY_UNSET;
|
|
|
00df7d |
|
|
|
00df7d |
- mctx->ocsp_enabled = FALSE;
|
|
|
00df7d |
+ mctx->ocsp_mask = UNSET;
|
|
|
00df7d |
mctx->ocsp_force_default = FALSE;
|
|
|
00df7d |
mctx->ocsp_responder = NULL;
|
|
|
00df7d |
mctx->ocsp_resptime_skew = UNSET;
|
|
|
00df7d |
@@ -264,7 +264,7 @@ static void modssl_ctx_cfg_merge(modssl_ctx_t *base,
|
|
|
00df7d |
cfgMergeInt(auth.verify_depth);
|
|
|
00df7d |
cfgMerge(auth.verify_mode, SSL_CVERIFY_UNSET);
|
|
|
00df7d |
|
|
|
00df7d |
- cfgMergeBool(ocsp_enabled);
|
|
|
00df7d |
+ cfgMergeInt(ocsp_mask);
|
|
|
00df7d |
cfgMergeBool(ocsp_force_default);
|
|
|
00df7d |
cfgMerge(ocsp_responder, NULL);
|
|
|
00df7d |
cfgMergeInt(ocsp_resptime_skew);
|
|
|
00df7d |
@@ -1575,11 +1575,46 @@ const char *ssl_cmd_SSLUserName(cmd_parms *cmd, void *dcfg,
|
|
|
00df7d |
return NULL;
|
|
|
00df7d |
}
|
|
|
00df7d |
|
|
|
00df7d |
-const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag)
|
|
|
00df7d |
+static const char *ssl_cmd_ocspcheck_parse(cmd_parms *parms,
|
|
|
00df7d |
+ const char *arg,
|
|
|
00df7d |
+ int *mask)
|
|
|
00df7d |
{
|
|
|
00df7d |
- SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
|
|
00df7d |
+ const char *w;
|
|
|
00df7d |
+
|
|
|
00df7d |
+ w = ap_getword_conf(parms->temp_pool, &arg;;
|
|
|
00df7d |
+ if (strcEQ(w, "off")) {
|
|
|
00df7d |
+ *mask = SSL_OCSPCHECK_NONE;
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+ else if (strcEQ(w, "leaf")) {
|
|
|
00df7d |
+ *mask = SSL_OCSPCHECK_LEAF;
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+ else if (strcEQ(w, "on")) {
|
|
|
00df7d |
+ *mask = SSL_OCSPCHECK_CHAIN;
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+ else {
|
|
|
00df7d |
+ return apr_pstrcat(parms->temp_pool, parms->cmd->name,
|
|
|
00df7d |
+ ": Invalid argument '", w, "'",
|
|
|
00df7d |
+ NULL);
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+
|
|
|
00df7d |
+ while (*arg) {
|
|
|
00df7d |
+ w = ap_getword_conf(parms->temp_pool, &arg;;
|
|
|
00df7d |
+ if (strcEQ(w, "no_ocsp_for_cert_ok")) {
|
|
|
00df7d |
+ *mask |= SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK;
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+ else {
|
|
|
00df7d |
+ return apr_pstrcat(parms->temp_pool, parms->cmd->name,
|
|
|
00df7d |
+ ": Invalid argument '", w, "'",
|
|
|
00df7d |
+ NULL);
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+ }
|
|
|
00df7d |
|
|
|
00df7d |
- sc->server->ocsp_enabled = flag ? TRUE : FALSE;
|
|
|
00df7d |
+ return NULL;
|
|
|
00df7d |
+}
|
|
|
00df7d |
+
|
|
|
00df7d |
+const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *arg)
|
|
|
00df7d |
+{
|
|
|
00df7d |
+ SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
|
|
|
00df7d |
|
|
|
00df7d |
#ifdef OPENSSL_NO_OCSP
|
|
|
00df7d |
if (flag) {
|
|
|
00df7d |
@@ -1588,7 +1623,7 @@ const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag)
|
|
|
00df7d |
}
|
|
|
00df7d |
#endif
|
|
|
00df7d |
|
|
|
00df7d |
- return NULL;
|
|
|
00df7d |
+ return ssl_cmd_ocspcheck_parse(cmd, arg, &sc->server->ocsp_mask);
|
|
|
00df7d |
}
|
|
|
00df7d |
|
|
|
00df7d |
const char *ssl_cmd_SSLOCSPOverrideResponder(cmd_parms *cmd, void *dcfg, int flag)
|
|
|
00df7d |
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
|
|
00df7d |
index 672760c..57b76c0 100644
|
|
|
00df7d |
--- a/modules/ssl/ssl_engine_init.c
|
|
|
00df7d |
+++ b/modules/ssl/ssl_engine_init.c
|
|
|
00df7d |
@@ -762,6 +762,10 @@ static void ssl_init_ctx_crl(server_rec *s,
|
|
|
00df7d |
unsigned long crlflags = 0;
|
|
|
00df7d |
char *cfgp = mctx->pkp ? "SSLProxy" : "SSL";
|
|
|
00df7d |
|
|
|
00df7d |
+ if (mctx->ocsp_mask == UNSET) {
|
|
|
00df7d |
+ mctx->ocsp_mask = SSL_OCSPCHECK_NONE;
|
|
|
00df7d |
+ }
|
|
|
00df7d |
+
|
|
|
00df7d |
/*
|
|
|
00df7d |
* Configure Certificate Revocation List (CRL) Details
|
|
|
00df7d |
*/
|
|
|
00df7d |
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
|
|
00df7d |
index 5ff35f5..9dc236c 100644
|
|
|
00df7d |
--- a/modules/ssl/ssl_engine_kernel.c
|
|
|
00df7d |
+++ b/modules/ssl/ssl_engine_kernel.c
|
|
|
00df7d |
@@ -1416,7 +1416,8 @@ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx)
|
|
|
00df7d |
/*
|
|
|
00df7d |
* Perform OCSP-based revocation checks
|
|
|
00df7d |
*/
|
|
|
00df7d |
- if (ok && sc->server->ocsp_enabled) {
|
|
|
ceb09b |
+ if (ok && ((mctx->ocsp_mask & SSL_OCSPCHECK_CHAIN) ||
|
|
|
ceb09b |
+ (errdepth == 0 && (mctx->ocsp_mask & SSL_OCSPCHECK_LEAF)))) {
|
|
|
00df7d |
/* If there was an optional verification error, it's not
|
|
|
00df7d |
* possible to perform OCSP validation since the issuer may be
|
|
|
00df7d |
* missing/untrusted. Fail in that case. */
|
|
|
00df7d |
diff --git a/modules/ssl/ssl_engine_ocsp.c b/modules/ssl/ssl_engine_ocsp.c
|
|
|
00df7d |
index 90da5c2..58d267b 100644
|
|
|
00df7d |
--- a/modules/ssl/ssl_engine_ocsp.c
|
|
|
00df7d |
+++ b/modules/ssl/ssl_engine_ocsp.c
|
|
|
00df7d |
@@ -136,7 +136,14 @@ static int verify_ocsp_status(X509 *cert, X509_STORE_CTX *ctx, conn_rec *c,
|
|
|
00df7d |
|
|
|
00df7d |
ruri = determine_responder_uri(sc, cert, c, pool);
|
|
|
00df7d |
if (!ruri) {
|
|
|
00df7d |
- return V_OCSP_CERTSTATUS_UNKNOWN;
|
|
|
00df7d |
+ if (sc->server->ocsp_mask & SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK) {
|
|
|
00df7d |
+ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
|
|
|
00df7d |
+ "Skipping OCSP check for certificate cos no OCSP URL"
|
|
|
00df7d |
+ " found and no_ocsp_for_cert_ok is set");
|
|
|
00df7d |
+ return V_OCSP_CERTSTATUS_GOOD;
|
|
|
00df7d |
+ } else {
|
|
|
00df7d |
+ return V_OCSP_CERTSTATUS_UNKNOWN;
|
|
|
00df7d |
+ }
|
|
|
00df7d |
}
|
|
|
00df7d |
|
|
|
00df7d |
request = create_request(ctx, cert, &certID, s, pool);
|
|
|
00df7d |
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
|
|
|
00df7d |
index b601316..2d505f9 100644
|
|
|
00df7d |
--- a/modules/ssl/ssl_private.h
|
|
|
00df7d |
+++ b/modules/ssl/ssl_private.h
|
|
|
00df7d |
@@ -379,6 +379,16 @@ typedef enum {
|
|
|
00df7d |
} ssl_crlcheck_t;
|
|
|
00df7d |
|
|
|
00df7d |
/**
|
|
|
00df7d |
+ * OCSP checking mask (mode | flags)
|
|
|
00df7d |
+ */
|
|
|
00df7d |
+typedef enum {
|
|
|
00df7d |
+ SSL_OCSPCHECK_NONE = (0),
|
|
|
00df7d |
+ SSL_OCSPCHECK_LEAF = (1 << 0),
|
|
|
00df7d |
+ SSL_OCSPCHECK_CHAIN = (1 << 1),
|
|
|
00df7d |
+ SSL_OCSPCHECK_NO_OCSP_FOR_CERT_OK = (1 << 2)
|
|
|
00df7d |
+} ssl_ocspcheck_t;
|
|
|
00df7d |
+
|
|
|
00df7d |
+/**
|
|
|
00df7d |
* Define the SSL pass phrase dialog types
|
|
|
00df7d |
*/
|
|
|
00df7d |
typedef enum {
|
|
|
00df7d |
@@ -668,7 +678,7 @@ typedef struct {
|
|
|
00df7d |
|
|
|
00df7d |
modssl_auth_ctx_t auth;
|
|
|
00df7d |
|
|
|
00df7d |
- BOOL ocsp_enabled; /* true if OCSP verification enabled */
|
|
|
00df7d |
+ int ocsp_mask;
|
|
|
00df7d |
BOOL ocsp_force_default; /* true if the default responder URL is
|
|
|
00df7d |
* used regardless of per-cert URL */
|
|
|
00df7d |
const char *ocsp_responder; /* default responder URL */
|
|
|
00df7d |
@@ -796,7 +806,7 @@ const char *ssl_cmd_SSLOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, const ch
|
|
|
00df7d |
const char *ssl_cmd_SSLOCSPResponseTimeSkew(cmd_parms *cmd, void *dcfg, const char *arg);
|
|
|
00df7d |
const char *ssl_cmd_SSLOCSPResponseMaxAge(cmd_parms *cmd, void *dcfg, const char *arg);
|
|
|
00df7d |
const char *ssl_cmd_SSLOCSPResponderTimeout(cmd_parms *cmd, void *dcfg, const char *arg);
|
|
|
00df7d |
-const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, int flag);
|
|
|
00df7d |
+const char *ssl_cmd_SSLOCSPEnable(cmd_parms *cmd, void *dcfg, const char *flag);
|
|
|
00df7d |
|
|
|
00df7d |
#ifndef OPENSSL_NO_SRP
|
|
|
00df7d |
const char *ssl_cmd_SSLSRPVerifierFile(cmd_parms *cmd, void *dcfg, const char *arg);
|