[Fedora-directory-commits] mod_nss nss_engine_rand.c, NONE, 1.1 Makefile.am, 1.6, 1.7 Makefile.in, 1.9, 1.10 mod_nss.c, 1.8, 1.9 mod_nss.h, 1.7, 1.8 nss.conf.in, 1.6, 1.7 nss_engine_config.c, 1.8, 1.9 nss_engine_init.c, 1.13, 1.14

Robert Crittenden (rcritten) fedora-directory-commits at redhat.com
Mon Oct 3 14:59:28 UTC 2005


Author: rcritten

Update of /cvs/dirsec/mod_nss
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv11437

Modified Files:
	Makefile.am Makefile.in mod_nss.c mod_nss.h nss.conf.in 
	nss_engine_config.c nss_engine_init.c 
Added Files:
	nss_engine_rand.c 
Log Message:
Add support for seeding the NSS Random Number Generator. This adds
a new directive, NSSRandomSeed based on the mod_ssl SSLRandomSeed
directive.



--- NEW FILE nss_engine_rand.c ---
/* 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;
}


Index: Makefile.am
===================================================================
RCS file: /cvs/dirsec/mod_nss/Makefile.am,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Makefile.am	13 Sep 2005 19:34:39 -0000	1.6
+++ Makefile.am	3 Oct 2005 14:59:26 -0000	1.7
@@ -6,7 +6,7 @@
 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@


Index: Makefile.in
===================================================================
RCS file: /cvs/dirsec/mod_nss/Makefile.in,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- Makefile.in	26 Sep 2005 20:01:24 -0000	1.9
+++ Makefile.in	3 Oct 2005 14:59:26 -0000	1.10
@@ -107,7 +107,7 @@
 
 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 @@
 	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 @@
 @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 @@
 @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@


Index: mod_nss.c
===================================================================
RCS file: /cvs/dirsec/mod_nss/mod_nss.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- mod_nss.c	29 Sep 2005 19:35:43 -0000	1.8
+++ mod_nss.c	3 Oct 2005 14:59:26 -0000	1.9
@@ -63,6 +63,9 @@
     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


Index: mod_nss.h
===================================================================
RCS file: /cvs/dirsec/mod_nss/mod_nss.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- mod_nss.h	29 Sep 2005 19:35:43 -0000	1.7
+++ mod_nss.h	3 Oct 2005 14:59:26 -0000	1.8
@@ -163,6 +163,26 @@
 } 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 @@
     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_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);


Index: nss.conf.in
===================================================================
RCS file: /cvs/dirsec/mod_nss/nss.conf.in,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- nss.conf.in	13 Sep 2005 19:34:39 -0000	1.6
+++ nss.conf.in	3 Oct 2005 14:59:26 -0000	1.7
@@ -50,6 +50,20 @@
 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
 ##


Index: nss_engine_config.c
===================================================================
RCS file: /cvs/dirsec/mod_nss/nss_engine_config.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- nss_engine_config.c	29 Sep 2005 19:35:43 -0000	1.8
+++ nss_engine_config.c	3 Oct 2005 14:59:26 -0000	1.9
@@ -51,6 +51,8 @@
     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 @@
     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)
 {


Index: nss_engine_init.c
===================================================================
RCS file: /cvs/dirsec/mod_nss/nss_engine_init.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- nss_engine_init.c	29 Sep 2005 19:35:43 -0000	1.13
+++ nss_engine_init.c	3 Oct 2005 14:59:26 -0000	1.14
@@ -348,8 +348,14 @@
 
     /* 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




More information about the Fedora-directory-commits mailing list