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().
Andrew Bartlett
if (!challenge_set_by) {
uchar 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));
p += 4;
/* We need to create a session key */
- generate_random_buffer(p, 8, False);
+ generate_random_buffer(p, 8);
/* Our client code needs the the key in the clear, it does not
know the server-key ... */
static unsigned char hash[258];
static uint32 counter;
-static unsigned char *reseed_data;
-static size_t reseed_data_size;
+
+static BOOL done_reseed = False;
+static void (*reseed_callback)(int *newseed);
/****************************************************************
Copy any user given reseed data.
*****************************************************************/
-void set_rand_reseed_data(unsigned char *data, size_t len)
+void set_rand_reseed_callback(void (*fn)(int *))
{
- SAFE_FREE(reseed_data);
- reseed_data_size = 0;
+ reseed_callback = fn;
+ set_need_random_reseed();
+}
- reseed_data = (unsigned char *)memdup(data, len);
- if (reseed_data)
- reseed_data_size = len;
+void set_need_random_reseed(void)
+{
+ done_reseed = False;
+}
+
+static void get_rand_reseed_data(int *reseed_data)
+{
+ if (reseed_callback) {
+ reseed_callback(reseed_data);
+ } else {
+ *reseed_data = 0;
+ }
}
/****************************************************************
unsigned char seed_inbuf[40];
uint32 v1, v2; struct timeval tval; pid_t mypid;
struct passwd *pw;
+ 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( unsigned char *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;
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;
}
if (len > sizeof(retstr)-1)
len = sizeof(retstr) -1;
- 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) ];
{
UUID_FLAT tmp;
- generate_random_buffer(tmp.info, sizeof(tmp.info), True);
+ generate_random_buffer(tmp.info, sizeof(tmp.info));
smb_uuid_unpack(tmp, uu);
uu->clock_seq[0] = (uu->clock_seq[0] & 0x3F) | 0x80;
static const uint8 *get_challenge(const struct ntlmssp_state *ntlmssp_state)
{
static uchar 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 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(client_session_key, sizeof(client_session_key));
DATA_BLOB response = data_blob(NULL, 0);
char long_date[8];
- generate_random_buffer(client_chal, sizeof(client_chal), False);
+ generate_random_buffer(client_chal, sizeof(client_chal));
put_long_date(long_date, time(NULL));
/* 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((unsigned char *)buffer, 512 - new_pw_len, True);
+ generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len);
/*
* The length of the new password is in the last 4 bytes of
return False;
}
- generate_random_buffer(request.data.auth_crap.chal, 8, False);
+ generate_random_buffer(request.data.auth_crap.chal, 8);
SMBencrypt(pass, request.data.auth_crap.chal,
(uchar *)request.data.auth_crap.lm_resp);
/* do password magic */
- generate_random_buffer(chal, 8, False);
+ generate_random_buffer(chal, 8);
SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);
sid->num_auths = 0;
sid->sub_auths[sid->num_auths++] = 21;
- generate_random_buffer(raw_sid_data, 12, True);
+ generate_random_buffer(raw_sid_data, 12);
for (i = 0; i < 3; i++)
sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4);
}
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 = sys_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;
}
}
-/*******************************************************************
- Reset the 'done' variables so after a client process is created
- from a fork call these calls will be re-done. This should be
- expanded if more variables need reseting.
- ******************************************************************/
-
-void reset_globals_after_fork(void)
-{
- unsigned char dummy;
-
- secrets_init();
-
- /*
- * Increment the global seed value to ensure every smbd starts
- * with a new random seed.
- */
-
- if (tdb) {
- uint32 initial_val = sys_getpid();
- tdb_change_int32_atomic(tdb, "INFO/random_seed", (int *)&initial_val, 1);
- set_rand_reseed_data((unsigned char *)&initial_val, sizeof(initial_val));
- }
-
- /*
- * Re-seed the random crypto generator, so all smbd's
- * started from the same parent won't generate the same
- * sequence.
- */
- generate_random_buffer( &dummy, 1, True);
-}
-
BOOL secrets_store_ldap_pw(const char* dn, char* pw)
{
char *key = NULL;
return NULL;
}
- generate_random_buffer(request.data.auth_crap.chal, 8, False);
+ generate_random_buffer(request.data.auth_crap.chal, 8);
if (use_lm_hash) {
SMBencrypt((uchar *)password, request.data.auth_crap.chal,
return NULL;
}
- generate_random_buffer(request.data.smbd_auth_crap.chal, 8, False);
+ generate_random_buffer(request.data.smbd_auth_crap.chal, 8);
if (use_lm_hash) {
SMBencrypt((uchar *)password,
/******************* Request Challenge ********************/
- generate_random_buffer(clnt_chal.data, 8, False);
+ generate_random_buffer(clnt_chal.data, 8);
/* send a client challenge; receive a server challenge */
result = cli_net_req_chal(cli, &clnt_chal, &srv_chal);
unsigned char local_lm_response[24];
unsigned char local_nt_response[24];
- generate_random_buffer(chal, 8, False);
+ generate_random_buffer(chal, 8);
SMBencrypt(password, chal, local_lm_response);
SMBNTencrypt(password, chal, local_nt_response);
}
/* fill the 'confounder' with random data */
- generate_random_buffer(confounder, sizeof(confounder), False);
+ generate_random_buffer(confounder, sizeof(confounder));
dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));
/* create a server challenge for the client */
/* Set these to random values. */
- generate_random_buffer(p->dc.srv_chal.data, 8, False);
+ generate_random_buffer(p->dc.srv_chal.data, 8);
memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
RPC_AUTH_VERIFIER auth_verifier;
RPC_AUTH_NTLMSSP_CHAL ntlmssp_chal;
- generate_random_buffer(p->challenge, 8, False);
+ generate_random_buffer(p->challenge, 8);
/*** Authentication info ***/
in smbstatus for port 445 connects */
set_remote_machine_name(get_peer_addr(smbd_server_fd()), False);
- /* Reset global variables in util.c so
- that client substitutions will be
- done correctly in the process. */
- reset_globals_after_fork();
+ /* Reset the state of the random
+ * number generation system, so
+ * children do not get the same random
+ * numbers as each other */
+ set_need_random_reseed();
/* tdb needs special fork handling - remove CLEAR_IF_FIRST flags */
if (tdb_reopen_all() == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
/* we want to re-seed early to prevent time delays causing
client problems at a later date. (tridge) */
- generate_random_buffer(NULL, 0, False);
+ generate_random_buffer(NULL, 0);
/* make absolutely sure we run as root - to handle cases where people
are crazy enough to have it setuid */
printf("%d\r", i); fflush(stdout);
}
- generate_random_buffer(buf, buf_size, False);
+ generate_random_buffer(buf, buf_size);
if (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
printf("write failed (%s)\n", cli_errstr(c1));
chal = data_blob(NULL, 8);
- generate_random_buffer(chal.data, chal.length, False);
+ generate_random_buffer(chal.data, chal.length);
return chal;
}
/* we want to re-seed early to prevent time delays causing
client problems at a later date. (tridge) */
- generate_random_buffer(NULL, 0, False);
+ generate_random_buffer(NULL, 0);
/* make absolutely sure we run as root - to handle cases where people
are crazy enough to have it setuid */