You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by be...@apache.org on 2003/11/03 18:50:37 UTC
cvs commit: apr/threadproc/unix proc.c
ben 2003/11/03 09:50:37
Modified: include apr_random.h
random/unix apr_random.c
test testrand2.c
threadproc/unix proc.c
Log:
Make sure randomness is different after a fork.
Revision Changes Path
1.2 +13 -0 apr/include/apr_random.h
Index: apr_random.h
===================================================================
RCS file: /home/cvs/apr/include/apr_random.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- apr_random.h 3 Nov 2003 13:25:00 -0000 1.1
+++ apr_random.h 3 Nov 2003 17:50:37 -0000 1.2
@@ -93,4 +93,17 @@
apr_status_t apr_random_secure_ready(apr_random_t *r);
apr_status_t apr_random_insecure_ready(apr_random_t *r);
+/* Call this in the child after forking to mix the randomness
+ pools. Note that its generally a bad idea to fork a process with a
+ real PRNG in it - better to have the PRNG externally and get the
+ randomness from there. However, if you really must do it, then you
+ should supply all your entropy to all the PRNGs - don't worry, they
+ won't produce the same output.
+
+ Note that apr_proc_fork() calls this for you, so only weird
+ applications need ever call it themselves.
+*/
+struct apr_proc_t;
+void apr_random_after_fork(struct apr_proc_t *proc);
+
#endif /* ndef APR_RANDOM_H */
1.2 +45 -2 apr/random/unix/apr_random.c
Index: apr_random.c
===================================================================
RCS file: /home/cvs/apr/random/unix/apr_random.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- apr_random.c 3 Nov 2003 13:25:00 -0000 1.1
+++ apr_random.c 3 Nov 2003 17:50:37 -0000 1.2
@@ -58,6 +58,7 @@
#include "apr.h"
#include "apr_pools.h"
#include "apr_random.h"
+#include "apr_thread_proc.h"
#include <assert.h>
#define min(a,b) ((a) < (b) ? (a) : (b))
@@ -99,9 +100,13 @@
#define K_size(g) ((g)->key_hash->size)
apr_crypto_hash_t *prng_hash;
#define B_size(g) ((g)->prng_hash->size)
+
unsigned char *H;
unsigned char *H_waiting;
#define H_size(g) (B_size(g)+K_size(g))
+#define H_current(g) (((g)->insecure_started && !(g)->secure_started) \
+ ? (g)->H_waiting : (g)->H)
+
unsigned char *randomness;
apr_size_t random_bytes;
unsigned int g_for_insecure;
@@ -109,8 +114,12 @@
unsigned int secure_base;
unsigned char insecure_started:1;
unsigned char secure_started:1;
+
+ apr_random_t *next;
};
+static apr_random_t *all_random;
+
void apr_random_init(apr_random_t *g,apr_pool_t *p,
apr_crypto_hash_t *pool_hash,apr_crypto_hash_t *key_hash,
apr_crypto_hash_t *prng_hash)
@@ -145,6 +154,41 @@
g->secure_base=0;
g->g_for_secure=APR_RANDOM_DEFAULT_G_FOR_SECURE;
g->secure_started=g->insecure_started=0;
+
+ g->next=all_random;
+ all_random=g;
+ }
+
+static void mix_pid(apr_random_t *g,unsigned char *H,pid_t pid)
+ {
+ hash_init(g->key_hash);
+ hash_add(g->key_hash,H,H_size(g));
+ hash_add(g->key_hash,&pid,sizeof pid);
+ hash_finish(g->key_hash,H);
+ }
+
+static void mixer(apr_random_t *g,pid_t pid)
+ {
+ unsigned char *H=H_current(g);
+
+ /* mix the PID into the current H */
+ mix_pid(g,H,pid);
+ /* if we are in waiting, then also mix into main H */
+ if(H != g->H)
+ mix_pid(g,g->H,pid);
+ /* change order of pool mixing for good measure - note that going
+ backwards is much better than going forwards */
+ --g->generation;
+ /* blow away any lingering randomness */
+ g->random_bytes=0;
+ }
+
+void apr_random_after_fork(apr_proc_t *proc)
+ {
+ apr_random_t *r;
+
+ for(r=all_random ; r ; r=r->next)
+ mixer(r,proc->pid);
}
apr_random_t *apr_random_standard_new(apr_pool_t *p)
@@ -159,8 +203,7 @@
static void rekey(apr_random_t *g)
{
int n;
- unsigned char *H=(g->insecure_started && !g->secure_started) ? g->H_waiting
- : g->H;
+ unsigned char *H=H_current(g);
hash_init(g->key_hash);
hash_add(g->key_hash,H,H_size(g));
1.2 +83 -0 apr/test/testrand2.c
Index: testrand2.c
===================================================================
RCS file: /home/cvs/apr/test/testrand2.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- testrand2.c 3 Nov 2003 13:25:01 -0000 1.1
+++ testrand2.c 3 Nov 2003 17:50:37 -0000 1.2
@@ -54,6 +54,7 @@
#include "apr_general.h"
#include "apr_random.h"
+#include "apr_thread_proc.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
@@ -102,6 +103,20 @@
}
}
+static int rand_check_kat(rnd_fn *f,apr_random_t *r,
+ const unsigned char expected[128])
+ {
+ unsigned char c[128];
+ apr_status_t rv;
+
+ rv=f(r,c,128);
+ if(rv)
+ return 2;
+ if(memcmp(c,expected,128))
+ return 1;
+ return 0;
+ }
+
static void rand_add_zeroes(apr_random_t *r)
{
static unsigned char c[2048];
@@ -234,6 +249,73 @@
rand_run_kat(tc,apr_random_secure_bytes,r,expected);
}
+static void rand_fork(CuTest *tc)
+ {
+ apr_proc_t proc;
+ apr_status_t rv;
+ unsigned char expected[128]=
+ { 0xac,0x93,0xd2,0x5c,0xc7,0xf5,0x8d,0xc2,
+ 0xd8,0x8d,0xb6,0x7a,0x94,0xe1,0x83,0x4c,
+ 0x26,0xe2,0x38,0x6d,0xf5,0xbd,0x9d,0x6e,
+ 0x91,0x77,0x3a,0x4b,0x9b,0xef,0x9b,0xa3,
+ 0x9f,0xf6,0x6d,0x0c,0xdc,0x4b,0x02,0xe9,
+ 0x5d,0x3d,0xfc,0x92,0x6b,0xdf,0xc9,0xef,
+ 0xb9,0xa8,0x74,0x09,0xa3,0xff,0x64,0x8d,
+ 0x19,0xc1,0x31,0x31,0x17,0xe1,0xb7,0x7a,
+ 0xe7,0x55,0x14,0x92,0x05,0xe3,0x1e,0xb8,
+ 0x9b,0x1b,0xdc,0xac,0x0e,0x15,0x08,0xa2,
+ 0x93,0x13,0xf6,0x04,0xc6,0x9d,0xf8,0x7f,
+ 0x26,0x32,0x68,0x43,0x2e,0x5a,0x4f,0x47,
+ 0xe8,0xf8,0x59,0xb7,0xfb,0xbe,0x30,0x04,
+ 0xb6,0x63,0x6f,0x19,0xf3,0x2c,0xd4,0xeb,
+ 0x32,0x8a,0x54,0x01,0xd0,0xaf,0x3f,0x13,
+ 0xc1,0x7f,0x10,0x2e,0x08,0x1c,0x28,0x4b, };
+
+ rv=apr_proc_fork(&proc,p);
+ if(rv == APR_INCHILD)
+ {
+ int n;
+
+ n=rand_check_kat(apr_random_secure_bytes,r,expected);
+
+ exit(n);
+ }
+ else if(rv == APR_INPARENT)
+ {
+ int exitcode;
+ apr_exit_why_e why;
+
+ rand_run_kat(tc,apr_random_secure_bytes,r,expected);
+ apr_proc_wait(&proc,&exitcode,&why,APR_WAIT);
+ if(why != APR_PROC_EXIT)
+ {
+ CuFail(tc,"Child terminated abnormally");
+ return;
+ }
+ if(exitcode == 0)
+ {
+ CuFail(tc,"Child produced our randomness");
+ return;
+ }
+ else if(exitcode == 2)
+ {
+ CuFail(tc,"Child randomness failed");
+ return;
+ }
+ else if(exitcode != 1)
+ {
+ CuFail(tc,"Uknown child error");
+ return;
+ }
+ }
+ else
+ {
+ CuFail(tc,"Fork failed");
+ return;
+ }
+ }
+
+
CuSuite *testrand2(void)
{
CuSuite *suite = CuSuiteNew("Random2");
@@ -245,6 +327,7 @@
SUITE_ADD_TEST(suite, rand_barrier);
SUITE_ADD_TEST(suite, rand_kat3);
SUITE_ADD_TEST(suite, rand_kat4);
+ SUITE_ADD_TEST(suite, rand_fork);
return suite;
}
1.68 +3 -0 apr/threadproc/unix/proc.c
Index: proc.c
===================================================================
RCS file: /home/cvs/apr/threadproc/unix/proc.c,v
retrieving revision 1.67
retrieving revision 1.68
diff -u -r1.67 -r1.68
--- proc.c 8 May 2003 08:51:02 -0000 1.67
+++ proc.c 3 Nov 2003 17:50:37 -0000 1.68
@@ -56,6 +56,7 @@
#include "apr_strings.h"
#include "apr_portable.h"
#include "apr_signal.h"
+#include "apr_random.h"
APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,
apr_pool_t *pool)
@@ -231,6 +232,8 @@
proc->in = NULL;
proc->out = NULL;
proc->err = NULL;
+
+ apr_random_after_fork(proc);
return APR_INCHILD;
}