r1492: Rework our random number generation system.
authorAndrew Bartlett <abartlet@samba.org>
Wed, 14 Jul 2004 04:36:01 +0000 (04:36 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:52:13 +0000 (10:52 -0500)
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)

19 files changed:
source3/auth/auth.c
source3/lib/afs.c
source3/lib/genrand.c
source3/lib/util_uuid.c
source3/libsmb/ntlmssp.c
source3/libsmb/smbencrypt.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd_pam.c
source3/passdb/machine_sid.c
source3/passdb/secrets.c
source3/python/py_winbind.c
source3/rpc_client/cli_netlogon.c
source3/rpc_parse/parse_prs.c
source3/rpc_server/srv_netlog_nt.c
source3/rpc_server/srv_pipe.c
source3/smbd/server.c
source3/torture/torture.c
source3/utils/ntlm_auth.c
source3/wrepld/server.c

index 1b49699fbca5e711f126d2fcfee15c415787292a..7cfe3fc63945a8866ae2b15d42a4e40d22e55f43 100644 (file)
@@ -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));
                
index 0830a3a0e7fba878d64d8aa14f56fe7b39c6b927..8688fde6b1c4d4082c74cc1f3e4978fedee1b6db 100644 (file)
@@ -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 ... */
index bc9f21c6403fab8bb22d93c65082d5a8c9fa80a3..9ccddfa4c53776dca2c3c52716bd6917de226d0c 100644 (file)
 
 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) ];
 
index dc9bc920230ef65245d779550308d3e8e408c7ca..8f86c2109ea48ef1cd82c993b89f54d8f0d7933e 100644 (file)
@@ -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;
index 66d48afc4633a528326128d5686ca3590b3dacfe..6e41a61bf1bb492eef497fce96731050cc5ae887 100644 (file)
@@ -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));
index 44f7428086b24071306e5789bd9dc7b46220752e..9f936b77aec973322f79a0054087c0f3cc456ec5 100644 (file)
@@ -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
index ce48e9ae6521741279157a7e100d8128fb0abc7d..b6a09bf2a1f38d54d922fa53df618988a55d4444 100644 (file)
@@ -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);
index 25f53e7a535c3c4f97c33f83e826f8877a1d93b3..81d4e69ccd6b819175e6fd60d3fa6e7c966b2bb6 100644 (file)
@@ -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);
index 47b9e2d487e6ad799e86083e912dc5862295b566..ce1354ce81830b995b701ec5ece29da981482b42 100644 (file)
@@ -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);
 }
index 2b3175bed2321af994a1891bf146221a36bad45b..e7637f689d2d8b53737e35fe6f3eca388ca09941 100644 (file)
 
 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;
index 130f78d7e126e424330232f0177f10f1017b4a2a..7256f77002b19c6c3dc367a0a2344679d11ec4b2 100644 (file)
@@ -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, 
index 02d2611d88cd30cde8b5b858fb86ddfeb670bd21..3fb032234f5936a70e59da89eab3a6f72f8f0246 100644 (file)
@@ -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);
index 92c5b13632a817a9a67c00483e83d8e5127071d0..c70011c6484c3bfac8af2ee6b1d60b4fa0607195 100644 (file)
@@ -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));
 
index 264b7a74a7994715b7f90547b9eae98a95643eb7..b5871a7e56dfa572a32dc381963d3a7d307ab993 100644 (file)
@@ -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);
 
index c5b0b5694d5f89c1bfb4469a839c8814db8bcbcd..bcf5eb533fd743afd567484386d451e57ab84c0d 100644 (file)
@@ -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 ***/
 
index c3e0da542e2a4b4bae2ac4cfe29df042b8a051ea..16281dd86cbaad0ed128aa62584265086336b2d4 100644 (file)
@@ -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 */
index e3960d34061818ec996d312f9d63e742bb5ceba2..6c3860e233e0f15adb826160f94e4e032eec8f63 100644 (file)
@@ -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));
index 39dcd9993d070979b07b7dce2d984a2b1eb31ff2..fd8424065c879073a156cf9753a4ec47cab43531 100644 (file)
@@ -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;
 }
 
index 80694a616bb51df0e4a587b8f5018cac361391ac..d78e0b206f35fdfedd2b4af814e26164e754e64d 100644 (file)
@@ -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 */