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));
#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]);
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];
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);
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)
* 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));
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;
}
}
}
-
/*
very basic password quality checker
*/
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) ];
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;
}
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;
}
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);
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,
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);
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);
/* 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);
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
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)) {
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;
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;
}
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;
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"));
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);
}
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)) {
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)) {
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)) {
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;
return False;
}
- generate_random_buffer((uint8_t *)confounder, 16, False);
+ generate_random_buffer((uint8_t *)confounder, 16);
MD5Init(&ctx);
MD5Update(&ctx, confounder, 16);
return False;
}
- generate_random_buffer((uint8_t *)confounder, 16, False);
+ generate_random_buffer((uint8_t *)confounder, 16);
MD5Init(&ctx);
MD5Update(&ctx, confounder, 16);
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));