mirror of
https://github.com/samba-team/samba.git
synced 2025-08-04 08:22:08 +03:00
r1492: 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().
Andrew Bartlett
(This used to be commit 36741d3cf5
)
This commit is contained in:
committed by
Gerald (Jerry) Carter
parent
8f93b50032
commit
9d0783bf21
@ -124,7 +124,7 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context)
|
||||
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));
|
||||
|
||||
|
@ -116,7 +116,7 @@ static BOOL afs_createtoken(const char *username, const char *cell,
|
||||
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 ... */
|
||||
|
@ -24,21 +24,32 @@
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
@ -136,6 +147,7 @@ static int do_reseed(BOOL use_fd, int fd)
|
||||
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)
|
||||
@ -183,10 +195,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));
|
||||
@ -198,15 +211,14 @@ static int do_reseed(BOOL use_fd, int fd)
|
||||
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;
|
||||
}
|
||||
@ -257,7 +269,7 @@ char *generate_random_str(size_t len)
|
||||
|
||||
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) ];
|
||||
|
||||
|
@ -57,7 +57,7 @@ void smb_uuid_generate_random(struct uuid *uu)
|
||||
{
|
||||
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;
|
||||
|
@ -103,7 +103,7 @@ void debug_ntlmssp_flags(uint32 neg_flags)
|
||||
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;
|
||||
}
|
||||
@ -960,7 +960,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);
|
||||
@ -1022,7 +1022,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 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));
|
||||
|
@ -352,7 +352,7 @@ static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob)
|
||||
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));
|
||||
|
||||
@ -406,7 +406,7 @@ static DATA_BLOB LMv2_generate_response(const uchar 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);
|
||||
@ -476,7 +476,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((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
|
||||
|
@ -580,7 +580,7 @@ static BOOL wbinfo_auth_crap(char *username)
|
||||
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);
|
||||
|
@ -190,7 +190,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
|
||||
|
||||
/* 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);
|
||||
|
@ -67,7 +67,7 @@ static void generate_random_sid(DOM_SID *sid)
|
||||
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);
|
||||
}
|
||||
|
@ -30,10 +30,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 = 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;
|
||||
@ -47,6 +64,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;
|
||||
}
|
||||
|
||||
@ -504,37 +533,6 @@ BOOL trusted_domain_password_delete(const char *domain)
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
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;
|
||||
|
@ -432,7 +432,7 @@ static PyObject *py_auth_crap(PyObject *self, PyObject *args, PyObject *kw)
|
||||
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,
|
||||
@ -481,7 +481,7 @@ static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw)
|
||||
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,
|
||||
|
@ -247,7 +247,7 @@ NTSTATUS cli_nt_setup_creds(struct cli_state *cli,
|
||||
|
||||
/******************* 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);
|
||||
@ -580,7 +580,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
|
||||
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);
|
||||
|
@ -1471,7 +1471,7 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
|
||||
}
|
||||
|
||||
/* 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));
|
||||
|
||||
|
@ -276,7 +276,7 @@ NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u
|
||||
|
||||
/* 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);
|
||||
|
||||
|
@ -1097,7 +1097,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
|
||||
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 ***/
|
||||
|
||||
|
@ -409,11 +409,12 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
|
||||
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"));
|
||||
@ -717,7 +718,7 @@ void build_options(BOOL screen);
|
||||
|
||||
/* 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 */
|
||||
|
@ -493,7 +493,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 (cli_write(c1, fnum1, 0, buf, 0, buf_size) != buf_size) {
|
||||
printf("write failed (%s)\n", cli_errstr(c1));
|
||||
|
@ -181,7 +181,7 @@ DATA_BLOB get_challenge(void)
|
||||
|
||||
chal = data_blob(NULL, 8);
|
||||
|
||||
generate_random_buffer(chal.data, chal.length, False);
|
||||
generate_random_buffer(chal.data, chal.length);
|
||||
return chal;
|
||||
}
|
||||
|
||||
|
@ -551,7 +551,7 @@ static void process(void)
|
||||
|
||||
/* 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 */
|
||||
|
Reference in New Issue
Block a user