increase log level for this failed setsockopt call. EINVAL is a normal error on Solar...
[jra/samba/.git] / source / lib / genrand.c
index ee8bc0b1d5abc59a11e75596cdc39872d3a0c874..4590b812c58271c85c820b456f6ef26084f1860e 100644 (file)
@@ -7,7 +7,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 
-static unsigned char hash[258];
+static unsigned char smb_arc4_state[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_data = (unsigned char *)memdup(data, len);
-       if (reseed_data)
-               reseed_data_size = len;
+       reseed_callback = fn;
+       set_need_random_reseed();
 }
 
-/**************************************************************** 
- Setup the seed.
-*****************************************************************/
-
-static void seed_random_stream(unsigned char *seedval, size_t seedlen)
+void set_need_random_reseed(void)
 {
-       unsigned char j = 0;
-       size_t ind;
-
-       for (ind = 0; ind < 256; ind++)
-               hash[ind] = (unsigned char)ind;
-
-       for( ind = 0; ind < 256; ind++) {
-               unsigned char tc;
-
-               j += (hash[ind] + seedval[ind%seedlen]);
-
-               tc = hash[ind];
-               hash[ind] = hash[j];
-               hash[j] = tc;
-       }
-
-       hash[256] = 0;
-       hash[257] = 0;
+       done_reseed = False;
 }
 
-/**************************************************************** 
- Get datasize bytes worth of random data.
-*****************************************************************/
-
-static void get_random_stream(unsigned char *data, size_t datasize)
+static void get_rand_reseed_data(int *reseed_data)
 {
-       unsigned char index_i = hash[256];
-       unsigned char index_j = hash[257];
-       size_t ind;
-
-       for( ind = 0; ind < datasize; ind++) {
-               unsigned char tc;
-               unsigned char t;
-
-               index_i++;
-               index_j += hash[index_i];
-
-               tc = hash[index_i];
-               hash[index_i] = hash[index_j];
-               hash[index_j] = tc;
-
-               t = hash[index_i] + hash[index_j];
-               data[ind] = hash[t];
+       if (reseed_callback) {
+               reseed_callback(reseed_data);
+       } else {
+               *reseed_data = 0;
        }
-
-       hash[256] = index_i;
-       hash[257] = index_j;
 }
 
 /****************************************************************
@@ -101,7 +56,7 @@ static void get_random_stream(unsigned char *data, size_t datasize)
  Note that the hash is not initialised.
 *****************************************************************/
 
-static void do_filehash(char *fname, unsigned char *the_hash)
+static void do_filehash(const char *fname, unsigned char *the_hash)
 {
        unsigned char buf[1011]; /* deliberate weird size */
        unsigned char tmp_md4[16];
@@ -131,11 +86,12 @@ static void do_filehash(char *fname, unsigned char *the_hash)
  above...
 **************************************************************/
 
-static int do_reseed(BOOL use_fd, int fd)
+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)
@@ -157,14 +113,14 @@ static int do_reseed(BOOL use_fd, int fd)
         * seriously this will be secret.
         */
 
-       pw = getpwnam_alloc("root");
+       pw = getpwnam_alloc(NULL, "root");
        if (pw && pw->pw_passwd) {
                size_t i;
                unsigned char md4_tmp[16];
                mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd));
                for (i=0;i<16;i++)
                        seed_inbuf[8+i] ^= md4_tmp[i];
-               passwd_free(&pw);
+               TALLOC_FREE(pw);
        }
 
        /*
@@ -183,13 +139,14 @@ 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));
+       smb_arc4_init(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf));
 
        return -1;
 }
@@ -198,15 +155,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;
        }
@@ -234,7 +190,7 @@ void generate_random_buffer( unsigned char *out, int len, BOOL do_reseed_now)
        while(len > 0) {
                int copy_len = len > 16 ? 16 : len;
 
-               get_random_stream(md4_buf, sizeof(md4_buf));
+               smb_arc4_crypt(smb_arc4_state, md4_buf, sizeof(md4_buf));
                mdfour(tmp_buf, md4_buf, sizeof(md4_buf));
                memcpy(p, tmp_buf, copy_len);
                p += copy_len;
@@ -257,9 +213,9 @@ 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) ];
+               retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ];
 
        retstr[i] = '\0';