[Pkg-fedora-ds-maintainers] [libapache2-mod-nss] 45/156: Add support for seeding the NSS Random Number Generator. This adds a new directive, NSSRandomSeed based on the mod_ssl SSLRandomSeed directive.

Timo Aaltonen tjaalton-guest at moszumanska.debian.org
Wed Jul 2 13:55:26 UTC 2014


This is an automated email from the git hooks/post-receive script.

tjaalton-guest pushed a commit to branch master
in repository libapache2-mod-nss.

commit 252fddba6cd7431db7cbd8a677bb52860ef5ba0a
Author: rcritten <>
Date:   Mon Oct 3 14:59:26 2005 +0000

    Add support for seeding the NSS Random Number Generator. This adds
    a new directive, NSSRandomSeed based on the mod_ssl SSLRandomSeed
    directive.
---
 Makefile.am         |   2 +-
 Makefile.in         |   6 ++-
 docs/mod_nss.html   |  30 ++++++++++-
 mod_nss.c           |   3 ++
 mod_nss.h           |  23 ++++++++
 nss.conf.in         |  14 +++++
 nss_engine_config.c |  89 +++++++++++++++++++++++++++++++
 nss_engine_init.c   |  10 +++-
 nss_engine_rand.c   | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 322 insertions(+), 6 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index cfd6c2b..06486dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,7 +6,7 @@ bin_PROGRAMS = nss_pcache
 nss_pcache_SOURCES = nss_pcache.c
 
 ## Define the source file for the module
-libmodnss_la_SOURCES = mod_nss.c nss_engine_config.c nss_engine_init.c nss_engine_io.c nss_engine_kernel.c nss_engine_log.c nss_engine_pphrase.c nss_engine_vars.c nss_expr.c nss_expr_eval.c nss_expr_parse.y nss_expr_scan.l nss_util.c
+libmodnss_la_SOURCES = mod_nss.c nss_engine_config.c nss_engine_init.c nss_engine_io.c nss_engine_kernel.c nss_engine_log.c nss_engine_pphrase.c nss_engine_vars.c nss_expr.c nss_expr_eval.c nss_expr_parse.y nss_expr_scan.l nss_util.c nss_engine_rand.c
 
 ## Set the includes and libraries needed
 INCLUDES = -I at apache_inc@ @nspr_inc@ @nss_inc@ @apr_inc@
diff --git a/Makefile.in b/Makefile.in
index 9a61632..c57d232 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -107,7 +107,7 @@ bin_PROGRAMS = nss_pcache
 
 nss_pcache_SOURCES = nss_pcache.c
 
-libmodnss_la_SOURCES = mod_nss.c nss_engine_config.c nss_engine_init.c nss_engine_io.c nss_engine_kernel.c nss_engine_log.c nss_engine_pphrase.c nss_engine_vars.c nss_expr.c nss_expr_eval.c nss_expr_parse.y nss_expr_scan.l nss_util.c
+libmodnss_la_SOURCES = mod_nss.c nss_engine_config.c nss_engine_init.c nss_engine_io.c nss_engine_kernel.c nss_engine_log.c nss_engine_pphrase.c nss_engine_vars.c nss_expr.c nss_expr_eval.c nss_expr_parse.y nss_expr_scan.l nss_util.c nss_engine_rand.c
 
 INCLUDES = -I at apache_inc@ @nspr_inc@ @nss_inc@ @apr_inc@
 LIBS = @nspr_lib@ @nss_lib@ -lssl3 -lsmime3 -lnss3 -lsoftokn3 -lplc4 -lplds4 -lnspr4
@@ -133,7 +133,7 @@ am_libmodnss_la_OBJECTS = mod_nss.lo nss_engine_config.lo \
 	nss_engine_init.lo nss_engine_io.lo nss_engine_kernel.lo \
 	nss_engine_log.lo nss_engine_pphrase.lo nss_engine_vars.lo \
 	nss_expr.lo nss_expr_eval.lo nss_expr_parse.lo nss_expr_scan.lo \
-	nss_util.lo
+	nss_util.lo nss_engine_rand.lo
 libmodnss_la_OBJECTS = $(am_libmodnss_la_OBJECTS)
 bin_PROGRAMS = nss_pcache$(EXEEXT)
 PROGRAMS = $(bin_PROGRAMS)
@@ -157,6 +157,7 @@ am__depfiles_maybe = depfiles
 @AMDEP_TRUE@	./$(DEPDIR)/nss_engine_kernel.Plo \
 @AMDEP_TRUE@	./$(DEPDIR)/nss_engine_log.Plo \
 @AMDEP_TRUE@	./$(DEPDIR)/nss_engine_pphrase.Plo \
+ at AMDEP_TRUE@	./$(DEPDIR)/nss_engine_rand.Plo \
 @AMDEP_TRUE@	./$(DEPDIR)/nss_engine_vars.Plo \
 @AMDEP_TRUE@	./$(DEPDIR)/nss_expr.Plo \
 @AMDEP_TRUE@	./$(DEPDIR)/nss_expr_eval.Plo \
@@ -256,6 +257,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_engine_kernel.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_engine_log.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_engine_pphrase.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_engine_rand.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_engine_vars.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_expr.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/nss_expr_eval.Plo at am__quote@
diff --git a/docs/mod_nss.html b/docs/mod_nss.html
index 7d6f5f1..71d1ada 100644
--- a/docs/mod_nss.html
+++ b/docs/mod_nss.html
@@ -249,7 +249,6 @@ to verify that the migration was successful.<br>
 <h1><a name="Directives"></a>Configuration Directives</h1>
 The following mod_ssl Directives are not applicable to mod_nss:<br>
 <ul>
-  <li>SSLRandomSeed</li>
   <li>SSLSessionCache</li>
   <li>SSLMutex</li>
   <li>SSLCertificateChainFile</li>
@@ -371,6 +370,35 @@ The default value is 86400 (24 hours).<br>
 <br>
 <code>NSSSession3CacheTimeout 86400</code><br>
 <br>
+<big><big>NSSRandomSeed</big></big><br>
+<br>
+Configures sources to seed the NSS Random Number Generator (RNG) at
+startup.  Currently this only supports seeding the RNG at startup.
+<br>
+<br>
+The following sources are available:<br>
+<ul>
+  <li><code>builtin:</code> Combines the current system time, the
+current process id
+and a randomly choosen 128-byte extract of the process stack. This is
+not a particularly strong source of entropy.</li>
+  <li><code>file:/path/to/source:</code> Reads from the specified file.
+If the number of bytes to read is specified it just reads that amount.
+Be aware that some operating systems block on /dev/random if not enough
+entropy is available. This means that the server will wait until that
+data is available to continue startup. These systems generally offer a
+non-blocking device as well, /dev/urandom.</li>
+  <li><code>exec:/path/to/program: Executes the given program and takes
+the stdout of it as the entryop. If the bytes argument is included it
+reads that many bytes, otherwise it reads until the program exits.</code><br>
+  </li>
+</ul>
+<span style="font-weight: bold;">Example</span><br>
+<br>
+<code>NSSRandomSeed startup builtin<br>
+NSSRandomSeed startup /dev/urandom 512<br>
+NSSRandomSeed startup /usr/bin/makerandom</code><br>
+<br>
 <big><big>NSSEngine</big></big><br>
 <br>
 Enables or disables the SSL protocol. This is usually used within a
diff --git a/mod_nss.c b/mod_nss.c
index 2dd2f3c..b1f8721 100644
--- a/mod_nss.c
+++ b/mod_nss.c
@@ -63,6 +63,9 @@ static const command_rec nss_config_cmds[] = {
     SSL_CMD_SRV(OCSP, FLAG,
                 "OCSP (Online Certificate Status Protocol)"
                 "(`on', `off')")
+     SSL_CMD_SRV(RandomSeed, TAKE23,
+                "SSL Pseudo Random Number Generator (PRNG) seeding source "
+                "(`startup builtin|file:/path|exec:/path [bytes]')")
 
     /*
      * Per-server context configuration directives
diff --git a/mod_nss.h b/mod_nss.h
index a2a4bef..029ce41 100644
--- a/mod_nss.h
+++ b/mod_nss.h
@@ -163,6 +163,26 @@ typedef struct {
 } nss_require_t;
 
 /*
+ * Define the SSL random number generator seeding source. The CONNECT
+ * method is not currently used.
+ */
+typedef enum {
+    SSL_RSCTX_STARTUP = 1,
+    SSL_RSCTX_CONNECT = 2
+} ssl_rsctx_t;
+typedef enum {
+    SSL_RSSRC_BUILTIN = 1,
+    SSL_RSSRC_FILE    = 2,
+    SSL_RSSRC_EXEC    = 3
+} ssl_rssrc_t;
+typedef struct {
+    ssl_rsctx_t  nCtx;
+    ssl_rssrc_t  nSrc;
+    char        *cpPath;
+    int          nBytes;
+} ssl_randseed_t;
+
+/*
  * Define the SSL verify levels
  */
 typedef enum {
@@ -217,6 +237,8 @@ typedef struct {
     apr_proc_t      proc;
     apr_procattr_t *procattr;
 
+    apr_array_header_t   *aRandSeed;
+
     struct {
         void *pV1, *pV2, *pV3, *pV4, *pV5, *pV6, *pV7, *pV8, *pV9, *pV10;
     } rCtx;
@@ -328,6 +350,7 @@ const char *nss_cmd_NSSSession3CacheTimeout(cmd_parms *cmd, void *dcfg, const ch
 const char *nss_cmd_NSSSessionCacheSize(cmd_parms *cmd, void *dcfg, const char *arg);
 const char *nss_cmd_NSSPassPhraseDialog(cmd_parms *cmd, void *dcfg, const char *arg);
 const char *nss_cmd_NSSPassPhraseHelper(cmd_parms *cmd, void *dcfg, const char *arg);
+const char *nss_cmd_NSSRandomSeed(cmd_parms *, void *, const char *, const char *, const char *);
 const char *nss_cmd_NSSUserName(cmd_parms *cmd, void *dcfg, const char *arg);
 const char *nss_cmd_NSSOptions(cmd_parms *, void *, const char *);
 const char *nss_cmd_NSSRequireSSL(cmd_parms *cmd, void *dcfg);
diff --git a/nss.conf.in b/nss.conf.in
index db9fe3e..88787a7 100644
--- a/nss.conf.in
+++ b/nss.conf.in
@@ -50,6 +50,20 @@ NSSSessionCacheSize 10000
 NSSSessionCacheTimeout 100
 NSSSession3CacheTimeout 86400
 
+#
+# Pseudo Random Number Generator (PRNG):
+# Configure one or more sources to seed the PRNG of the SSL library.
+# The seed data should be of good random quality.
+# WARNING! On some platforms /dev/random blocks if not enough entropy
+# is available. Those platforms usually also provide a non-blocking
+# device, /dev/urandom, which may be used instead.
+#
+# This does not support seeding the RNG with each connection.
+
+NSSRandomSeed startup builtin
+#NSSRandomSeed startup file:/dev/random  512
+#NSSRandomSeed startup file:/dev/urandom 512
+
 ##
 ## SSL Virtual Host Context
 ##
diff --git a/nss_engine_config.c b/nss_engine_config.c
index a13cdab..bd067c3 100644
--- a/nss_engine_config.c
+++ b/nss_engine_config.c
@@ -51,6 +51,8 @@ SSLModConfigRec *nss_config_global_create(server_rec *s)
     mc->ssl3_session_cache_timeout  = UNSET;
     mc->pphrase_dialog_helper       = NULL;
     mc->pphrase_dialog_path         = NULL;
+    mc->aRandSeed                   = apr_array_make(pool, 4,
+                                                     sizeof(ssl_randseed_t));
 
     apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY,
                           apr_pool_cleanup_null,
@@ -561,6 +563,93 @@ const char *nss_cmd_NSSPassPhraseHelper(cmd_parms *cmd,
     return NULL;
 }
 
+const char *nss_cmd_NSSRandomSeed(cmd_parms *cmd,
+                                  void *dcfg,
+                                  const char *arg1,
+                                  const char *arg2,
+                                  const char *arg3)
+{   
+    SSLModConfigRec *mc = myModConfig(cmd->server);
+    const char *err;
+    ssl_randseed_t *seed;
+    int arg2len = strlen(arg2);
+    
+    if ((err = ap_check_cmd_context(cmd, GLOBAL_ONLY))) {
+        return err;
+    }
+    
+    /* Only run through this once. Otherwise the random seed sources are
+     * pushed into the array for each server start (and we are guaranteed 2) */
+    if (mc->nInitCount >= 1) {
+        return NULL;
+    }
+
+    seed = apr_array_push(mc->aRandSeed);
+
+    if (strcEQ(arg1, "startup")) {
+        seed->nCtx = SSL_RSCTX_STARTUP;
+    }
+    else if (strcEQ(arg1, "connect")) {
+        return apr_pstrcat(cmd->pool, "NSSRandomSeed: "
+                           "mod_nss doesn't do per-connection random seeding",
+                           NULL);
+    }
+    else {
+        return apr_pstrcat(cmd->pool, "NSSRandomSeed: "
+                           "invalid context: `", arg1, "'",
+                           NULL);
+    }
+
+    if ((arg2len > 5) && strEQn(arg2, "file:", 5)) {
+        seed->nSrc   = SSL_RSSRC_FILE;
+        seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
+    }
+    else if ((arg2len > 5) && strEQn(arg2, "exec:", 5)) {
+        seed->nSrc   = SSL_RSSRC_EXEC;
+        seed->cpPath = ap_server_root_relative(mc->pPool, arg2+5);
+    }
+    else if (strcEQ(arg2, "builtin")) {
+        seed->nSrc   = SSL_RSSRC_BUILTIN;
+        seed->cpPath = NULL;
+    }
+    else {
+        seed->nSrc   = SSL_RSSRC_FILE;
+        seed->cpPath = ap_server_root_relative(mc->pPool, arg2);
+    }
+
+    if (seed->nSrc != SSL_RSSRC_BUILTIN) {
+        apr_finfo_t finfo;
+        if (!seed->cpPath) {
+            return apr_pstrcat(cmd->pool,
+                               "Invalid NSSRandomSeed path ",
+                               arg2, NULL);
+        }
+        if (apr_stat(&finfo, seed->cpPath, APR_FINFO_TYPE|APR_FINFO_SIZE, cmd->pool) != 0) {
+            return apr_pstrcat(cmd->pool,
+                               "NSSRandomSeed: source path '",
+                               seed->cpPath, "' does not exist", NULL);
+        }
+    }
+
+    if (!arg3) {
+        seed->nBytes = 0; /* read whole file */
+    }
+    else {
+        if (seed->nSrc == SSL_RSSRC_BUILTIN) {
+            return "NSSRandomSeed: byte specification not "
+                   "allowed for builtin seed source";
+        }
+
+        seed->nBytes = atoi(arg3);
+
+        if (seed->nBytes < 0) {
+            return "NSSRandomSeed: invalid number of bytes specified";
+        }
+    }
+
+    return NULL;
+}
+
 const char *nss_cmd_NSSUserName(cmd_parms *cmd, void *dcfg,
                                 const char *arg)
 {
diff --git a/nss_engine_init.c b/nss_engine_init.c
index 7eda971..a9ae8d0 100644
--- a/nss_engine_init.c
+++ b/nss_engine_init.c
@@ -348,8 +348,14 @@ int nss_init_Module(apr_pool_t *p, apr_pool_t *plog,
 
     /* Load our layer */
     nss_io_layer_init();
-    ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
-                 "done layer");
+
+    /* 
+     * Seed the Pseudo Random Number Generator (PRNG)
+     * only need ptemp here; nothing inside allocated from the pool
+     * needs to live once we return from nss_rand_seed().
+     */
+    if (mc->nInitCount > 1)
+        nss_rand_seed(base_server, ptemp, SSL_RSCTX_STARTUP, "Init: ");
 
     /*
      *  initialize servers
diff --git a/nss_engine_rand.c b/nss_engine_rand.c
new file mode 100644
index 0000000..cf0b66c
--- /dev/null
+++ b/nss_engine_rand.c
@@ -0,0 +1,151 @@
+/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mod_nss.h"
+
+/*  _________________________________________________________________
+**
+**  Support for better seeding of SSL library's RNG
+**  _________________________________________________________________
+*/
+
+static int nss_rand_choosenum(int, int);
+static int nss_rand_feedfp(apr_pool_t *, apr_file_t *, int);
+
+int nss_rand_seed(server_rec *s, apr_pool_t *p, ssl_rsctx_t nCtx, char *prefix)
+{
+    SSLModConfigRec *mc;
+    apr_array_header_t *apRandSeed;
+    ssl_randseed_t *pRandSeeds;
+    ssl_randseed_t *pRandSeed;
+    unsigned char stackdata[256];
+    int nReq, nDone;
+    apr_file_t *fp;
+    int i, n, l;
+
+    mc = myModConfig(s);
+    nReq  = 0;
+    nDone = 0;
+    apRandSeed = mc->aRandSeed;
+    pRandSeeds = (ssl_randseed_t *)apRandSeed->elts;
+    for (i = 0; i < apRandSeed->nelts; i++) {
+        pRandSeed = &pRandSeeds[i];
+        if (pRandSeed->nCtx == nCtx) {
+            nReq += pRandSeed->nBytes;
+            if (pRandSeed->nSrc == SSL_RSSRC_FILE) {
+                /*
+                 * seed in contents of an external file
+                 */
+                if (apr_file_open(&fp, pRandSeed->cpPath, 
+                                  APR_READ, APR_OS_DEFAULT, p) != APR_SUCCESS)
+                    continue;
+                nDone += nss_rand_feedfp(p, fp, pRandSeed->nBytes);
+                apr_file_close(fp);
+            }
+            else if (pRandSeed->nSrc == SSL_RSSRC_EXEC) {
+                const char *cmd = pRandSeed->cpPath;
+                const char **argv = apr_palloc(p, sizeof(char *) * 3);
+                /*
+                 * seed in contents generated by an external program
+                 */
+                argv[0] = cmd;
+                argv[1] = apr_itoa(p, pRandSeed->nBytes);
+                argv[2] = NULL;
+
+                if ((fp = nss_util_ppopen(s, p, cmd, argv)) == NULL)
+                    continue;
+                nDone += nss_rand_feedfp(p, fp, pRandSeed->nBytes);
+                nss_util_ppclose(s, p, fp);
+            }
+            else if (pRandSeed->nSrc == SSL_RSSRC_BUILTIN) {
+                struct {
+                    time_t t;
+                    pid_t pid;
+                } my_seed;
+
+                /*
+                 * seed in the current time (usually just 4 bytes)
+                 */
+                my_seed.t = time(NULL);
+
+                /*
+                 * seed in the current process id (usually just 4 bytes)
+                 */
+                my_seed.pid = mc->pid;
+
+                l = sizeof(my_seed);
+                PK11_RandomUpdate((unsigned char *)&my_seed, l);
+                nDone += l;
+                
+                /*
+                 * seed in some current state of the run-time stack (128 bytes)
+                 */
+                n = nss_rand_choosenum(0, sizeof(stackdata)-128-1);
+                PK11_RandomUpdate(stackdata+n, 128);
+                nDone += 128;
+
+            }
+        }
+    }
+    if (nDone > 0)
+        ap_log_error(APLOG_MARK, APLOG_INFO, 0, s,
+                     "%sSeeding PRNG with %d bytes of entropy", prefix, nDone);
+
+    return nDone;
+}
+
+#define BUFSIZE 8192
+
+static int nss_rand_feedfp(apr_pool_t *p, apr_file_t *fp, int nReq)
+{
+    apr_size_t nDone;
+    unsigned char caBuf[BUFSIZE];
+    apr_size_t nBuf;
+    apr_size_t nRead;
+    apr_size_t nTodo;
+
+    nDone = 0;
+    nRead = BUFSIZE;
+    nTodo = nReq;
+    while (1) {
+        if (nReq > 0)
+            nRead = (nTodo < BUFSIZE ? nTodo : BUFSIZE);
+        nBuf = nRead;
+        if (apr_file_read(fp, caBuf, &nBuf) != APR_SUCCESS)
+            break;
+        PK11_RandomUpdate(caBuf, nBuf);
+        nDone += nBuf;
+        if (nReq > 0) {
+            nTodo -= nBuf;
+            if (nTodo <= 0)
+                break;
+        }
+    }
+    return nDone;
+}
+
+static int nss_rand_choosenum(int l, int h)
+{
+    int i;
+    char buf[50];
+
+    apr_snprintf(buf, sizeof(buf), "%.0f",
+                 (((double)(rand()%RAND_MAX)/RAND_MAX)*(h-l)));
+    i = atoi(buf)+1;
+    if (i < l) i = l;
+    if (i > h) i = h;
+    return i;
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-fedora-ds/libapache2-mod-nss.git



More information about the Pkg-fedora-ds-maintainers mailing list