summaryrefslogtreecommitdiff
path: root/random/unix/apr_random.c
diff options
context:
space:
mode:
authorben <ben@13f79535-47bb-0310-9956-ffa450edef68>2003-11-03 17:50:37 +0000
committerben <ben@13f79535-47bb-0310-9956-ffa450edef68>2003-11-03 17:50:37 +0000
commitb160cdad907e1027cf994d7051718058b561cfd3 (patch)
tree1378d5d765345e9ddccc25f0a919ccd9be13b218 /random/unix/apr_random.c
parentdb1cc1627da5788db0d5969139756555711d0d2e (diff)
downloadlibapr-b160cdad907e1027cf994d7051718058b561cfd3.tar.gz
Make sure randomness is different after a fork.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@64716 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'random/unix/apr_random.c')
-rw-r--r--random/unix/apr_random.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/random/unix/apr_random.c b/random/unix/apr_random.c
index d62177b10..06762804b 100644
--- a/random/unix/apr_random.c
+++ b/random/unix/apr_random.c
@@ -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 @@ struct apr_random_t
#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 @@ struct apr_random_t
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 @@ void apr_random_init(apr_random_t *g,apr_pool_t *p,
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 @@ apr_random_t *apr_random_standard_new(apr_pool_t *p)
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));