From 9d0783bf211dffe58845b36b0669f05bf8bf25b5 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 14 Jul 2004 04:36:01 +0000 Subject: 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 36741d3cf53a7bd17d361251f2bb50851cdb035f) --- source3/auth/auth.c | 2 +- source3/lib/afs.c | 2 +- source3/lib/genrand.c | 38 +++++++++++++++--------- source3/lib/util_uuid.c | 2 +- source3/libsmb/ntlmssp.c | 6 ++-- source3/libsmb/smbencrypt.c | 6 ++-- source3/nsswitch/wbinfo.c | 2 +- source3/nsswitch/winbindd_pam.c | 2 +- source3/passdb/machine_sid.c | 2 +- source3/passdb/secrets.c | 60 ++++++++++++++++++-------------------- source3/python/py_winbind.c | 4 +-- source3/rpc_client/cli_netlogon.c | 4 +-- source3/rpc_parse/parse_prs.c | 2 +- source3/rpc_server/srv_netlog_nt.c | 2 +- source3/rpc_server/srv_pipe.c | 2 +- source3/smbd/server.c | 11 +++---- source3/torture/torture.c | 2 +- source3/utils/ntlm_auth.c | 2 +- source3/wrepld/server.c | 2 +- 19 files changed, 82 insertions(+), 71 deletions(-) diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 1b49699fbc..7cfe3fc639 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -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)); diff --git a/source3/lib/afs.c b/source3/lib/afs.c index 0830a3a0e7..8688fde6b1 100644 --- a/source3/lib/afs.c +++ b/source3/lib/afs.c @@ -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 ... */ diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c index bc9f21c640..9ccddfa4c5 100644 --- a/source3/lib/genrand.c +++ b/source3/lib/genrand.c @@ -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) ]; diff --git a/source3/lib/util_uuid.c b/source3/lib/util_uuid.c index dc9bc92023..8f86c2109e 100644 --- a/source3/lib/util_uuid.c +++ b/source3/lib/util_uuid.c @@ -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; diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 66d48afc46..6e41a61bf1 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -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)); diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 44f7428086..9f936b77ae 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -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 diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index ce48e9ae65..b6a09bf2a1 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -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); diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 25f53e7a53..81d4e69ccd 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -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); diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c index 47b9e2d487..ce1354ce81 100644 --- a/source3/passdb/machine_sid.c +++ b/source3/passdb/machine_sid.c @@ -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); } diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 2b3175bed2..e7637f689d 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -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; diff --git a/source3/python/py_winbind.c b/source3/python/py_winbind.c index 130f78d7e1..7256f77002 100644 --- a/source3/python/py_winbind.c +++ b/source3/python/py_winbind.c @@ -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, diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 02d2611d88..3fb032234f 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -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); diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 92c5b13632..c70011c648 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -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)); diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 264b7a74a7..b5871a7e56 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -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); diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index c5b0b5694d..bcf5eb533f 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -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 ***/ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c3e0da542e..16281dd86c 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -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 */ diff --git a/source3/torture/torture.c b/source3/torture/torture.c index e3960d3406..6c3860e233 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -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)); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 39dcd9993d..fd8424065c 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -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; } diff --git a/source3/wrepld/server.c b/source3/wrepld/server.c index 80694a616b..d78e0b206f 100644 --- a/source3/wrepld/server.c +++ b/source3/wrepld/server.c @@ -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 */ -- cgit