c0c6d9
diff --git a/docs/manual/mod/mod_ssl.html.en b/docs/manual/mod/mod_ssl.html.en
c0c6d9
index 4580f1c..fb8202e 100644
c0c6d9
--- a/docs/manual/mod/mod_ssl.html.en
c0c6d9
+++ b/docs/manual/mod/mod_ssl.html.en
c0c6d9
@@ -991,7 +991,8 @@ the certificate being verified.

c0c6d9
 

This option enables OCSP validation of the client certificate

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

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

c0c6d9
 
c0c6d9
 

The OCSP responder used is either extracted from the certificate

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