summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2004-07-14 12:14:07 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:57:35 -0500
commitf607197054436a8195e3d0a695fe31574b418059 (patch)
tree90efd6698cf4cf7a499d7b3307c513b8c85d3690
parent71d28b8265726a50b6f077115e7dacdb8c4b06f8 (diff)
downloadsamba-f607197054436a8195e3d0a695fe31574b418059.tar.gz
samba-f607197054436a8195e3d0a695fe31574b418059.tar.bz2
samba-f607197054436a8195e3d0a695fe31574b418059.zip
r1498: (merge from 3.0)
Rework our random number generation system. On systems with /dev/urandom, this avoids a change to secrets.tdb for every fork(). For other systems, we now only re-seed after a fork, and on startup. No need to do it per-operation. This removes the 'need_reseed' parameter from generate_random_buffer(). This also requires that we start the secrets subsystem, as that is where the reseed value is stored, for systems without /dev/urandom. In order to aviod identical streams in forked children, the random state is re-initialised after the fork(), at the same point were we do that to the tdbs. Andrew Bartlett (This used to be commit b97d3cb2efd68310b1aea8a3ac40a64979c8cdae)
-rw-r--r--source4/auth/auth.c2
-rw-r--r--source4/lib/genrand.c77
-rw-r--r--source4/lib/util_uuid.c2
-rw-r--r--source4/libcli/auth/ntlmssp.c6
-rw-r--r--source4/libcli/auth/schannel.c2
-rw-r--r--source4/libcli/util/smbencrypt.c6
-rw-r--r--source4/librpc/rpc/dcerpc_schannel.c2
-rw-r--r--source4/passdb/secrets.c29
-rw-r--r--source4/rpc_server/netlogon/dcerpc_netlogon.c3
-rw-r--r--source4/smbd/process_standard.c4
-rw-r--r--source4/smbd/rewrite.c7
-rw-r--r--source4/torture/rpc/netlogon.c9
-rw-r--r--source4/torture/rpc/samr.c4
-rw-r--r--source4/torture/torture.c2
14 files changed, 102 insertions, 53 deletions
diff --git a/source4/auth/auth.c b/source4/auth/auth.c
index 32913f9996..206f431a05 100644
--- a/source4/auth/auth.c
+++ b/source4/auth/auth.c
@@ -77,7 +77,7 @@ static const uint8_t *get_ntlm_challenge(struct auth_context *auth_context)
if (!challenge_set_by) {
uint8_t chal[8];
- generate_random_buffer(chal, sizeof(chal), False);
+ generate_random_buffer(chal, sizeof(chal));
auth_context->challenge = data_blob_talloc(auth_context->mem_ctx,
chal, sizeof(chal));
diff --git a/source4/lib/genrand.c b/source4/lib/genrand.c
index b37078b284..adc6d7344e 100644
--- a/source4/lib/genrand.c
+++ b/source4/lib/genrand.c
@@ -22,39 +22,50 @@
#include "includes.h"
-static uint8_t hash[258];
-static uint32_t counter;
-static uint8_t *reseed_data;
-static size_t reseed_data_size;
+static unsigned char hash[258];
+static uint32 counter;
+
+static BOOL done_reseed = False;
+static void (*reseed_callback)(int *newseed);
/****************************************************************
Copy any user given reseed data.
*****************************************************************/
-void set_rand_reseed_data(uint8_t *data, size_t len)
+void set_rand_reseed_callback(void (*fn)(int *))
+{
+ reseed_callback = fn;
+ set_need_random_reseed();
+}
+
+void set_need_random_reseed(void)
{
- SAFE_FREE(reseed_data);
- reseed_data_size = 0;
+ done_reseed = False;
+}
- reseed_data = (uint8_t *)memdup(data, len);
- if (reseed_data)
- reseed_data_size = len;
+static void get_rand_reseed_data(int *reseed_data)
+{
+ if (reseed_callback) {
+ reseed_callback(reseed_data);
+ } else {
+ *reseed_data = 0;
+ }
}
/****************************************************************
Setup the seed.
*****************************************************************/
-static void seed_random_stream(uint8_t *seedval, size_t seedlen)
+static void seed_random_stream(unsigned char *seedval, size_t seedlen)
{
- uint8_t j = 0;
+ unsigned char j = 0;
size_t ind;
for (ind = 0; ind < 256; ind++)
- hash[ind] = (uint8_t)ind;
+ hash[ind] = (unsigned char)ind;
for( ind = 0; ind < 256; ind++) {
- uint8_t tc;
+ unsigned char tc;
j += (hash[ind] + seedval[ind%seedlen]);
@@ -71,15 +82,15 @@ static void seed_random_stream(uint8_t *seedval, size_t seedlen)
Get datasize bytes worth of random data.
*****************************************************************/
-static void get_random_stream(uint8_t *data, size_t datasize)
+static void get_random_stream(unsigned char *data, size_t datasize)
{
- uint8_t index_i = hash[256];
- uint8_t index_j = hash[257];
+ unsigned char index_i = hash[256];
+ unsigned char index_j = hash[257];
size_t ind;
for( ind = 0; ind < datasize; ind++) {
- uint8_t tc;
- uint8_t t;
+ unsigned char tc;
+ unsigned char t;
index_i++;
index_j += hash[index_i];
@@ -101,10 +112,10 @@ static void get_random_stream(uint8_t *data, size_t datasize)
Note that the hash is not initialised.
*****************************************************************/
-static void do_filehash(const char *fname, uint8_t *the_hash)
+static void do_filehash(const char *fname, unsigned char *the_hash)
{
- uint8_t buf[1011]; /* deliberate weird size */
- uint8_t tmp_md4[16];
+ unsigned char buf[1011]; /* deliberate weird size */
+ unsigned char tmp_md4[16];
int fd, n;
fd = sys_open(fname,O_RDONLY,0);
@@ -133,8 +144,9 @@ static void do_filehash(const char *fname, uint8_t *the_hash)
static int do_reseed(BOOL use_fd, int fd)
{
- uint8_t seed_inbuf[40];
- uint32_t v1, v2; struct timeval tval; pid_t mypid;
+ unsigned char seed_inbuf[40];
+ uint32 v1, v2; struct timeval tval; pid_t mypid;
+ int reseed_data = 0;
if (use_fd) {
if (fd != -1)
@@ -166,10 +178,11 @@ static int do_reseed(BOOL use_fd, int fd)
* Add any user-given reseed data.
*/
+ get_rand_reseed_data(&reseed_data);
if (reseed_data) {
size_t i;
for (i = 0; i < sizeof(seed_inbuf); i++)
- seed_inbuf[i] ^= reseed_data[i % reseed_data_size];
+ seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)];
}
seed_random_stream(seed_inbuf, sizeof(seed_inbuf));
@@ -181,15 +194,14 @@ static int do_reseed(BOOL use_fd, int fd)
Interface to the (hopefully) good crypto random number generator.
********************************************************************/
-void generate_random_buffer( uint8_t *out, int len, BOOL do_reseed_now)
+void generate_random_buffer( unsigned char *out, int len)
{
- static BOOL done_reseed = False;
static int urand_fd = -1;
- uint8_t md4_buf[64];
- uint8_t tmp_buf[16];
- uint8_t *p;
+ unsigned char md4_buf[64];
+ unsigned char tmp_buf[16];
+ unsigned char *p;
- if(!done_reseed || do_reseed_now) {
+ if(!done_reseed) {
urand_fd = do_reseed(True, urand_fd);
done_reseed = True;
}
@@ -225,7 +237,6 @@ void generate_random_buffer( uint8_t *out, int len, BOOL do_reseed_now)
}
}
-
/*
very basic password quality checker
*/
@@ -262,7 +273,7 @@ char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len)
return NULL;
again:
- generate_random_buffer(retstr, len, False);
+ generate_random_buffer(retstr, len);
for (i = 0; i < len; i++)
retstr[i] = c_list[retstr[i] % (sizeof(c_list)-1) ];
diff --git a/source4/lib/util_uuid.c b/source4/lib/util_uuid.c
index 6a705a4f30..156f20e53e 100644
--- a/source4/lib/util_uuid.c
+++ b/source4/lib/util_uuid.c
@@ -24,7 +24,7 @@
void uuid_generate_random(struct GUID *out)
{
- generate_random_buffer(out, sizeof(struct GUID), False);
+ generate_random_buffer(out, sizeof(struct GUID));
out->clock_seq[0] = (out->clock_seq[0] & 0x3F) | 0x80;
out->time_hi_and_version = (out->time_hi_and_version & 0x0FFF) | 0x4000;
}
diff --git a/source4/libcli/auth/ntlmssp.c b/source4/libcli/auth/ntlmssp.c
index 3c656f4e9e..75c1e30f56 100644
--- a/source4/libcli/auth/ntlmssp.c
+++ b/source4/libcli/auth/ntlmssp.c
@@ -108,7 +108,7 @@ void debug_ntlmssp_flags(uint32_t neg_flags)
static const uint8_t *get_challenge(const struct ntlmssp_state *ntlmssp_state)
{
static uint8_t chal[8];
- generate_random_buffer(chal, sizeof(chal), False);
+ generate_random_buffer(chal, sizeof(chal));
return chal;
}
@@ -1112,7 +1112,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
E_md4hash(ntlmssp_state->password, nt_hash);
lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
- generate_random_buffer(lm_response.data, 8, False);
+ generate_random_buffer(lm_response.data, 8);
memset(lm_response.data+8, 0, 16);
memcpy(session_nonce, challenge_blob.data, 8);
@@ -1202,7 +1202,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
/* Make up a new session key */
uint8_t client_session_key[16];
- generate_random_buffer(client_session_key, sizeof(client_session_key), False);
+ generate_random_buffer(client_session_key, sizeof(client_session_key));
/* Encrypt the new session key with the old one */
encrypted_session_key = data_blob_talloc(ntlmssp_state->mem_ctx,
diff --git a/source4/libcli/auth/schannel.c b/source4/libcli/auth/schannel.c
index 8a261a506c..aa89e7b84f 100644
--- a/source4/libcli/auth/schannel.c
+++ b/source4/libcli/auth/schannel.c
@@ -194,7 +194,7 @@ NTSTATUS schannel_seal_packet(struct schannel_state *state,
uint8_t sealing_key[16];
static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
- generate_random_buffer(confounder, 8, False);
+ generate_random_buffer(confounder, 8);
RSIVAL(seq_num, 0, state->seq_num);
SIVAL(seq_num, 4, state->initiator?0x80:0);
diff --git a/source4/libcli/util/smbencrypt.c b/source4/libcli/util/smbencrypt.c
index 72c6589097..a02fdaa38b 100644
--- a/source4/libcli/util/smbencrypt.c
+++ b/source4/libcli/util/smbencrypt.c
@@ -283,7 +283,7 @@ static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLO
unix_to_nt_time(&nttime, time(NULL));
- generate_random_buffer(client_chal, sizeof(client_chal), False);
+ generate_random_buffer(client_chal, sizeof(client_chal));
push_nttime(long_date, 0, nttime);
@@ -343,7 +343,7 @@ static DATA_BLOB LMv2_generate_response(const uint8_t ntlm_v2_hash[16],
/* LMv2 */
/* client-supplied random data */
- generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False);
+ generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length);
/* Given that data, and the challenge from the server, generate a response */
SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response);
@@ -413,7 +413,7 @@ BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags)
memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
- generate_random_buffer((uint8_t *)buffer, 512 - new_pw_len, False);
+ generate_random_buffer((uint8_t *)buffer, 512 - new_pw_len);
/*
* The length of the new password is in the last 4 bytes of
diff --git a/source4/librpc/rpc/dcerpc_schannel.c b/source4/librpc/rpc/dcerpc_schannel.c
index 73d27cdfa9..bf5d835d44 100644
--- a/source4/librpc/rpc/dcerpc_schannel.c
+++ b/source4/librpc/rpc/dcerpc_schannel.c
@@ -373,7 +373,7 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
r.in.credentials = &credentials1;
r.out.credentials = &credentials2;
- generate_random_buffer(credentials1.data, sizeof(credentials1.data), False);
+ generate_random_buffer(credentials1.data, sizeof(credentials1.data));
status = dcerpc_netr_ServerReqChallenge(p2, p->mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source4/passdb/secrets.c b/source4/passdb/secrets.c
index b5bae614b6..21938db154 100644
--- a/source4/passdb/secrets.c
+++ b/source4/passdb/secrets.c
@@ -29,10 +29,27 @@
static TDB_CONTEXT *tdb;
+/**
+ * Use a TDB to store an incrementing random seed.
+ *
+ * Initialised to the current pid, the very first time Samba starts,
+ * and incremented by one each time it is needed.
+ *
+ * @note Not called by systems with a working /dev/urandom.
+ */
+static void get_rand_seed(int *new_seed)
+{
+ *new_seed = getpid();
+ if (tdb) {
+ tdb_change_int32_atomic(tdb, "INFO/random_seed", new_seed, 1);
+ }
+}
+
/* open up the secrets database */
BOOL secrets_init(void)
{
pstring fname;
+ char dummy;
if (tdb)
return True;
@@ -46,6 +63,18 @@ BOOL secrets_init(void)
DEBUG(0,("Failed to open %s\n", fname));
return False;
}
+
+ /**
+ * Set a reseed function for the crypto random generator
+ *
+ * This avoids a problem where systems without /dev/urandom
+ * could send the same challenge to multiple clients
+ */
+ set_rand_reseed_callback(get_rand_seed);
+
+ /* Ensure that the reseed is done now, while we are root, etc */
+ generate_random_buffer(&dummy, sizeof(dummy));
+
return True;
}
diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c
index 9f0ca5443a..a4ef06128c 100644
--- a/source4/rpc_server/netlogon/dcerpc_netlogon.c
+++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c
@@ -150,8 +150,7 @@ static NTSTATUS netr_ServerReqChallenge(struct dcesrv_call_state *dce_call, TALL
pipe_state->client_challenge = *r->in.credentials;
generate_random_buffer(pipe_state->server_challenge.data,
- sizeof(pipe_state->server_challenge.data),
- False);
+ sizeof(pipe_state->server_challenge.data));
*r->out.credentials = pipe_state->server_challenge;
diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c
index cc02e84d57..5c2a0a3410 100644
--- a/source4/smbd/process_standard.c
+++ b/source4/smbd/process_standard.c
@@ -74,6 +74,10 @@ static void standard_accept_connection(struct event_context *ev, struct fd_event
DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n"));
}
+ /* Ensure that the forked children do not expose identical random streams */
+
+ set_need_random_reseed();
+
mem_ctx = talloc_init("server_service_connection");
if (!mem_ctx) {
DEBUG(0,("talloc_init(server_service_connection) failed\n"));
diff --git a/source4/smbd/rewrite.c b/source4/smbd/rewrite.c
index d0a4bad374..ac241958c7 100644
--- a/source4/smbd/rewrite.c
+++ b/source4/smbd/rewrite.c
@@ -70,6 +70,13 @@ void smbd_process_init(void)
if (!init_change_notify())
exit(1);
+ /* Start old-style secrets subsystem */
+
+ /* We must perform secrets_init(), as it sets up important
+ * seeding for the random number generator.
+ */
+ secrets_init();
+
talloc_destroy(mem_ctx);
}
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index 427701d2c9..f668c17d89 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -88,7 +88,7 @@ static BOOL test_SetupCredentials(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.credentials = &credentials1;
r.out.credentials = &credentials2;
- generate_random_buffer(credentials1.data, sizeof(credentials1.data), False);
+ generate_random_buffer(credentials1.data, sizeof(credentials1.data));
status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -148,7 +148,7 @@ static BOOL test_SetupCredentials2(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.credentials = &credentials1;
r.out.credentials = &credentials2;
- generate_random_buffer(credentials1.data, sizeof(credentials1.data), False);
+ generate_random_buffer(credentials1.data, sizeof(credentials1.data));
status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -214,7 +214,7 @@ static BOOL test_SetupCredentials3(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
r.in.credentials = &credentials1;
r.out.credentials = &credentials2;
- generate_random_buffer(credentials1.data, sizeof(credentials1.data), False);
+ generate_random_buffer(credentials1.data, sizeof(credentials1.data));
status = dcerpc_netr_ServerReqChallenge(p, mem_ctx, &r);
if (!NT_STATUS_IS_OK(status)) {
@@ -893,8 +893,7 @@ static BOOL test_SamLogon(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx)
samlogon_state.chall = data_blob_talloc(mem_ctx, NULL, 8);
- generate_random_buffer(samlogon_state.chall.data,
- 8, False);
+ generate_random_buffer(samlogon_state.chall.data, 8);
if (!test_SetupCredentials2(p, mem_ctx, NETLOGON_NEG_AUTH2_FLAGS, &samlogon_state.creds)) {
return False;
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index e6a22a6921..bd5c44a732 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -452,7 +452,7 @@ static BOOL test_SetUserPassEx(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
- generate_random_buffer((uint8_t *)confounder, 16, False);
+ generate_random_buffer((uint8_t *)confounder, 16);
MD5Init(&ctx);
MD5Update(&ctx, confounder, 16);
@@ -506,7 +506,7 @@ static BOOL test_SetUserPass_25(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
return False;
}
- generate_random_buffer((uint8_t *)confounder, 16, False);
+ generate_random_buffer((uint8_t *)confounder, 16);
MD5Init(&ctx);
MD5Update(&ctx, confounder, 16);
diff --git a/source4/torture/torture.c b/source4/torture/torture.c
index 8f72b63e6c..804dd34f2a 100644
--- a/source4/torture/torture.c
+++ b/source4/torture/torture.c
@@ -458,7 +458,7 @@ static BOOL rw_torture2(struct cli_state *c1, struct cli_state *c2)
printf("%d\r", i); fflush(stdout);
}
- generate_random_buffer(buf, buf_size, False);
+ generate_random_buffer(buf, buf_size);
if ((bytes_written = cli_write(c1->tree, fnum1, 0, buf, 0, buf_size)) != buf_size) {
printf("write failed (%s)\n", cli_errstr(c1->tree));