Blame SOURCES/mod_nss-ocsp-tuning-knobs.patch

49b7d4
From 8d6121731175f3a9a1fa1fbe3752763b0b48a67d Mon Sep 17 00:00:00 2001
49b7d4
From: Rob Crittenden <rcritten@redhat.com>
49b7d4
Date: Mon, 31 Oct 2016 15:06:36 -0400
49b7d4
Subject: [PATCH] Add OCSP cache and timeout tuning knobs
49b7d4
49b7d4
NSS provides functions to control the timeout for connecting to
49b7d4
an OCSP server and for caching the results. This includes the
49b7d4
number of responses to cache and the duration to cache them.
49b7d4
49b7d4
Based on a patch by Jack Magne
49b7d4
---
49b7d4
 docs/mod_nss.html   | 42 ++++++++++++++++++++++++++
49b7d4
 mod_nss.c           | 12 ++++++++
49b7d4
 mod_nss.h           |  8 +++++
49b7d4
 nss_engine_config.c | 86 +++++++++++++++++++++++++++++++++++++++++++----------
49b7d4
 nss_engine_init.c   | 47 +++++++++++++++++++++++++++++
49b7d4
 5 files changed, 179 insertions(+), 16 deletions(-)
49b7d4
49b7d4
diff --git a/docs/mod_nss.html b/docs/mod_nss.html
49b7d4
index 65d0bd8..655d2f2 100644
49b7d4
--- a/docs/mod_nss.html
49b7d4
+++ b/docs/mod_nss.html
49b7d4
@@ -544,6 +544,48 @@ Example
49b7d4
 
49b7d4
 NSSOCSP on
49b7d4
 
49b7d4
+<big><big>NSSOCSPTimeout</big></big>
49b7d4
+
49b7d4
+Configure the maximum time to wait for an OCSP response in seconds.
49b7d4
+There are no constraints or special meanings for this value. The default
49b7d4
+is 60 seconds.
49b7d4
+
49b7d4
+
49b7d4
+Example
49b7d4
+
49b7d4
+NSSOCSPTimeout 30
49b7d4
+
49b7d4
+<big><big>NSSOCSPCacheSize</big></big>
49b7d4
+
49b7d4
+Configures the maximum number of entries in the OCSP cache. A value of
49b7d4
+-1 will disable the cache completely. A value of 0 configures an unlimited
49b7d4
+number of cache entries. The default is 1000.
49b7d4
+
49b7d4
+
49b7d4
+Example
49b7d4
+
49b7d4
+NSSOCSPCacheSize 300
49b7d4
+
49b7d4
+<big><big>NSSOCSPMinCacheEntryDuration</big></big>
49b7d4
+
49b7d4
+Configure the minimum amount of time an OCSP response is cached in seconds.
49b7d4
+The default is 3600 seconds (1 hour).
49b7d4
+
49b7d4
+
49b7d4
+Example
49b7d4
+
49b7d4
+NSSOCSPMinCacheEntryDuration 30
49b7d4
+
49b7d4
+<big><big>NSSOCSPMaxCacheEntryDuration</big></big>
49b7d4
+
49b7d4
+Configure the maximum amount of time an OCSP response is cached in seconds
49b7d4
+before being updated. The default is 86400 seconds (24 hours).
49b7d4
+
49b7d4
+
49b7d4
+Example
49b7d4
+
49b7d4
+NSSOCSPMaxCacheEntryDuration 300
49b7d4
+
49b7d4
 <big><big>NSSCipherSuite
49b7d4
 </big></big>
49b7d4
 There are two options for configuring the available ciphers. mod_nss
49b7d4
diff --git a/mod_nss.c b/mod_nss.c
49b7d4
index 38098c8..dca5a73 100644
49b7d4
--- a/mod_nss.c
49b7d4
+++ b/mod_nss.c
49b7d4
@@ -66,6 +66,18 @@ static const command_rec nss_config_cmds[] = {
49b7d4
     SSL_CMD_SRV(OCSP, FLAG,
49b7d4
                 "OCSP (Online Certificate Status Protocol)"
49b7d4
                 "(`on', `off')")
49b7d4
+    SSL_CMD_SRV(OCSPTimeout, TAKE1,
49b7d4
+                "OCSP Timeout"
49b7d4
+                "(`N' - Max number of seconds to wait for an OCSP response.)")
49b7d4
+    SSL_CMD_SRV(OCSPCacheSize, TAKE1,
49b7d4
+                "OCSP Cache size"
49b7d4
+                "(`N' - number of entries -1 for no cache)")
49b7d4
+    SSL_CMD_SRV(OCSPMinCacheEntryDuration, TAKE1,
49b7d4
+                "OCSP Minimum time until next fetch attempt"
49b7d4
+                "(`N' - Time in seconds)")
49b7d4
+    SSL_CMD_SRV(OCSPMaxCacheEntryDuration, TAKE1,
49b7d4
+                "OCSP Maximum time until next fetch attempt"
49b7d4
+                "(`N' - Time in seconds)")
49b7d4
     SSL_CMD_SRV(OCSPDefaultResponder, FLAG,
49b7d4
                 "Use a default OCSP Responder"
49b7d4
                 "(`on', `off')")
49b7d4
diff --git a/mod_nss.h b/mod_nss.h
49b7d4
index 226f7a8..8643e88 100644
49b7d4
--- a/mod_nss.h
49b7d4
+++ b/mod_nss.h
49b7d4
@@ -325,6 +325,10 @@ struct SSLSrvConfigRec {
49b7d4
     const char      *ocsp_url;
49b7d4
     const char      *ocsp_name;
49b7d4
     BOOL             ocsp;
49b7d4
+    int              ocsp_timeout;
49b7d4
+    int              ocsp_cache_size;
49b7d4
+    int              ocsp_min_cache_entry_duration;
49b7d4
+    int              ocsp_max_cache_entry_duration;
49b7d4
     BOOL             enabled;
49b7d4
     BOOL             sni;
49b7d4
     BOOL             strict_sni_vhost_check;
49b7d4
@@ -398,6 +402,10 @@ const char *nss_cmd_NSSSNI(cmd_parms *, void *, int);
49b7d4
 const char *nss_cmd_NSSStrictSNIVHostCheck(cmd_parms *, void *, int);
49b7d4
 const char *nss_cmd_NSSEngine(cmd_parms *, void *, int);
49b7d4
 const char *nss_cmd_NSSOCSP(cmd_parms *, void *, int);
49b7d4
+const char *nss_cmd_NSSOCSPTimeout(cmd_parms *, void *, const char *arg);
49b7d4
+const char *nss_cmd_NSSOCSPCacheSize(cmd_parms *, void *, const char *arg);
49b7d4
+const char *nss_cmd_NSSOCSPMinCacheEntryDuration(cmd_parms *, void *, const char *arg);
49b7d4
+const char *nss_cmd_NSSOCSPMaxCacheEntryDuration(cmd_parms *, void *, const char *arg);
49b7d4
 const char *nss_cmd_NSSOCSPDefaultResponder(cmd_parms *, void *, int);
49b7d4
 const char *nss_cmd_NSSOCSPDefaultURL(cmd_parms *, void *dcfg, const char *arg);
49b7d4
 const char *nss_cmd_NSSOCSPDefaultName(cmd_parms *, void *, const char *arg);
49b7d4
diff --git a/nss_engine_config.c b/nss_engine_config.c
49b7d4
index e1fbe41..597d56d 100644
49b7d4
--- a/nss_engine_config.c
49b7d4
+++ b/nss_engine_config.c
49b7d4
@@ -129,22 +129,26 @@ static SSLSrvConfigRec *nss_config_server_new(apr_pool_t *p)
49b7d4
 {
49b7d4
     SSLSrvConfigRec *sc = apr_palloc(p, sizeof(*sc));
49b7d4
 
49b7d4
-    sc->mc                          = NULL;
49b7d4
-    sc->ocsp                        = UNSET;
49b7d4
-    sc->ocsp_default                = UNSET;
49b7d4
-    sc->ocsp_url                    = NULL;
49b7d4
-    sc->ocsp_name                   = NULL;
49b7d4
-    sc->fips                        = UNSET;
49b7d4
-    sc->enabled                     = UNSET;
49b7d4
-    sc->sni                         = TRUE;
49b7d4
-    sc->strict_sni_vhost_check      = TRUE;
49b7d4
-    sc->proxy_enabled               = UNSET;
49b7d4
-    sc->vhost_id                    = NULL;  /* set during module init */
49b7d4
-    sc->vhost_id_len                = 0;     /* set during module init */
49b7d4
-    sc->proxy                       = NULL;
49b7d4
-    sc->server                      = NULL;
49b7d4
-    sc->proxy_ssl_check_peer_cn     = TRUE;
49b7d4
-    sc->session_tickets             = FALSE;
49b7d4
+    sc->mc                            = NULL;
49b7d4
+    sc->ocsp                          = UNSET;
49b7d4
+    sc->ocsp_timeout                  = 60;
49b7d4
+    sc->ocsp_cache_size               = 1000;
49b7d4
+    sc->ocsp_min_cache_entry_duration = 1*60*60L;
49b7d4
+    sc->ocsp_max_cache_entry_duration = 24*60*60L;
49b7d4
+    sc->ocsp_default                  = UNSET;
49b7d4
+    sc->ocsp_url                      = NULL;
49b7d4
+    sc->ocsp_name                     = NULL;
49b7d4
+    sc->fips                          = UNSET;
49b7d4
+    sc->enabled                       = UNSET;
49b7d4
+    sc->sni                           = TRUE;
49b7d4
+    sc->strict_sni_vhost_check        = TRUE;
49b7d4
+    sc->proxy_enabled                 = UNSET;
49b7d4
+    sc->vhost_id                      = NULL;  /* set during module init */
49b7d4
+    sc->vhost_id_len                  = 0;     /* set during module init */
49b7d4
+    sc->proxy                         = NULL;
49b7d4
+    sc->server                        = NULL;
49b7d4
+    sc->proxy_ssl_check_peer_cn       = TRUE;
49b7d4
+    sc->session_tickets               = FALSE;
49b7d4
 
49b7d4
     modnss_ctx_init_proxy(sc, p);
49b7d4
 
49b7d4
@@ -213,6 +217,10 @@ void *nss_config_server_merge(apr_pool_t *p, void *basev, void *addv) {
49b7d4
 
49b7d4
     cfgMerge(mc, NULL);
49b7d4
     cfgMergeBool(ocsp);
49b7d4
+    cfgMergeInt(ocsp_timeout);
49b7d4
+    cfgMergeInt(ocsp_cache_size);
49b7d4
+    cfgMergeInt(ocsp_min_cache_entry_duration);
49b7d4
+    cfgMergeInt(ocsp_max_cache_entry_duration);
49b7d4
     cfgMergeBool(ocsp_default);
49b7d4
     cfgMerge(ocsp_url, NULL);
49b7d4
     cfgMerge(ocsp_name, NULL);
49b7d4
@@ -376,6 +384,52 @@ const char *nss_cmd_NSSOCSP(cmd_parms *cmd, void *dcfg, int flag)
49b7d4
     return NULL;
49b7d4
 }
49b7d4
 
49b7d4
+const char *nss_cmd_NSSOCSPTimeout(cmd_parms *cmd, void *dcfg, const char *arg)
49b7d4
+{
49b7d4
+
49b7d4
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
49b7d4
+
49b7d4
+    sc->ocsp_timeout = atoi(arg);
49b7d4
+
49b7d4
+    return NULL;
49b7d4
+}
49b7d4
+
49b7d4
+const char *nss_cmd_NSSOCSPCacheSize(cmd_parms *cmd, void *dcfg, const char *arg)
49b7d4
+{
49b7d4
+
49b7d4
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
49b7d4
+
49b7d4
+    sc->ocsp_cache_size = atoi(arg);
49b7d4
+
49b7d4
+    if (sc->ocsp_cache_size < -1) {
49b7d4
+        return "NSSOCSPCacheSize: must be >= -1";
49b7d4
+    }
49b7d4
+
49b7d4
+    return NULL;
49b7d4
+}
49b7d4
+
49b7d4
+const char *nss_cmd_NSSOCSPMinCacheEntryDuration(cmd_parms *cmd, void *dcfg,
49b7d4
+                                                 const char *arg)
49b7d4
+{
49b7d4
+
49b7d4
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
49b7d4
+
49b7d4
+    sc->ocsp_min_cache_entry_duration = atoi(arg);
49b7d4
+
49b7d4
+    return NULL;
49b7d4
+}
49b7d4
+
49b7d4
+const char *nss_cmd_NSSOCSPMaxCacheEntryDuration(cmd_parms *cmd, void *dcfg,
49b7d4
+                                                 const char *arg)
49b7d4
+{
49b7d4
+
49b7d4
+    SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
49b7d4
+
49b7d4
+    sc->ocsp_max_cache_entry_duration = atoi(arg);
49b7d4
+
49b7d4
+    return NULL;
49b7d4
+}
49b7d4
+
49b7d4
 const char *nss_cmd_NSSOCSPDefaultResponder(cmd_parms *cmd, void *dcfg, int flag)
49b7d4
 {
49b7d4
     SSLSrvConfigRec *sc = mySrvConfig(cmd->server);
49b7d4
diff --git a/nss_engine_init.c b/nss_engine_init.c
49b7d4
index 14f86d8..2571591 100644
49b7d4
--- a/nss_engine_init.c
49b7d4
+++ b/nss_engine_init.c
49b7d4
@@ -174,6 +174,18 @@ static void nss_init_SSLLibrary(server_rec *base_server, apr_pool_t *p)
49b7d4
         }
49b7d4
     }
49b7d4
 
49b7d4
+    if (ocspenabled) {
49b7d4
+        if (sc->ocsp_min_cache_entry_duration > sc->ocsp_max_cache_entry_duration)  {
49b7d4
+            ap_log_error(APLOG_MARK,APLOG_ERR, 0, base_server,
49b7d4
+                "OCSP minimum cache duration must be less than the maximum.");
49b7d4
+
49b7d4
+            if (mc->nInitCount == 1)
49b7d4
+                nss_die();
49b7d4
+            else
49b7d4
+                return;
49b7d4
+        }
49b7d4
+    }
49b7d4
+
49b7d4
     if (strncasecmp(mc->pCertificateDatabase, "sql:", 4) == 0)
49b7d4
         dbdir = (char *)mc->pCertificateDatabase + 4;
49b7d4
     else
49b7d4
@@ -343,10 +355,45 @@ static void nss_init_SSLLibrary(server_rec *base_server, apr_pool_t *p)
49b7d4
     }
49b7d4
 
49b7d4
     if (ocspenabled) {
49b7d4
+        SECStatus rv;
49b7d4
+
49b7d4
         CERT_EnableOCSPChecking(CERT_GetDefaultCertDB());
49b7d4
         ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
49b7d4
             "OCSP is enabled.");
49b7d4
 
49b7d4
+        /* Set desired OCSP Cache Settings, values already checked. */
49b7d4
+        rv = CERT_OCSPCacheSettings((PRInt32)sc->ocsp_cache_size,
49b7d4
+                                    (PRUint32)sc->ocsp_min_cache_entry_duration,
49b7d4
+                                    (PRUint32)sc->ocsp_max_cache_entry_duration);
49b7d4
+
49b7d4
+        if (rv == SECFailure) {
49b7d4
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
49b7d4
+                        "Unable to set the OCSP cache settings.");
49b7d4
+            nss_log_nss_error(APLOG_MARK, APLOG_ERR, base_server);
49b7d4
+            if (mc->nInitCount == 1)
49b7d4
+                nss_die();
49b7d4
+            else
49b7d4
+                return;
49b7d4
+        } else {
49b7d4
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
49b7d4
+                         "OCSP cache size %d, duration %d - %d seconds.", sc->ocsp_cache_size, sc->ocsp_min_cache_entry_duration, sc->ocsp_max_cache_entry_duration);
49b7d4
+        }
49b7d4
+
49b7d4
+        /* Set OCSP timeout. */
49b7d4
+        rv = CERT_SetOCSPTimeout((PRUint32) sc->ocsp_timeout);
49b7d4
+        if (rv == SECFailure) {
49b7d4
+            ap_log_error(APLOG_MARK, APLOG_ERR, 0, base_server,
49b7d4
+                         "Unable to set the OCSP timeout. (this shouldn't happen.");
49b7d4
+            nss_log_nss_error(APLOG_MARK, APLOG_ERR, base_server);
49b7d4
+            if (mc->nInitCount == 1)
49b7d4
+                nss_die();
49b7d4
+            else
49b7d4
+                return;
49b7d4
+        } else {
49b7d4
+            ap_log_error(APLOG_MARK, APLOG_INFO, 0, base_server,
49b7d4
+                         "OCSP timeout set to %d.", sc->ocsp_timeout);
49b7d4
+        }
49b7d4
+
49b7d4
         /* We ensure that ocspname and ocspurl are not NULL above. */
49b7d4
         if (ocspdefault) {
49b7d4
             SECStatus sv;
49b7d4
-- 
49b7d4
2.9.3
49b7d4