diff options
-rw-r--r-- | source3/Makefile.in | 5 | ||||
-rw-r--r-- | source3/include/proto.h | 2 | ||||
-rw-r--r-- | source3/lib/genrand.c | 220 | ||||
-rw-r--r-- | source3/passdb/secrets.c | 4 |
4 files changed, 6 insertions, 225 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index 120b98064e..dad046f0e1 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -320,7 +320,8 @@ UTIL_OBJ = ../lib/util/rbtree.o ../lib/util/signal.o ../lib/util/time.o \ ../lib/util/xfile.o ../lib/util/util_strlist.o \ ../lib/util/util_file.o ../lib/util/data_blob.o \ ../lib/util/util.o ../lib/util/fsusage.o \ - ../lib/util/params.o ../lib/util/talloc_stack.o + ../lib/util/params.o ../lib/util/talloc_stack.o \ + ../lib/util/genrand.o CRYPTO_OBJ = ../lib/crypto/crc32.o ../lib/crypto/md5.o \ ../lib/crypto/hmacmd5.o ../lib/crypto/arcfour.o \ @@ -336,7 +337,7 @@ LIB_OBJ = $(LIBSAMBAUTIL_OBJ) $(UTIL_OBJ) $(CRYPTO_OBJ) \ $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/interface.o lib/pidfile.o \ lib/system.o lib/sendfile.o lib/recvfile.o lib/time.o \ - lib/genrand.o lib/username.o \ + lib/username.o \ lib/util_pw.o lib/access.o lib/smbrun.o \ lib/bitmap.o lib/dprintf.o $(UTIL_REG_OBJ) \ lib/wins_srv.o \ diff --git a/source3/include/proto.h b/source3/include/proto.h index 966ddb9f63..37f934abc7 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -575,7 +575,7 @@ void gencache_unlock_entry( const char *key ); /* The following definitions come from lib/genrand.c */ -void set_rand_reseed_callback(void (*fn)(int *)); +void set_rand_reseed_callback(void (*fn)(void *, int *), void *userdata); void set_need_random_reseed(void); void generate_random_buffer(uint8_t *out, int len); char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len); diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c deleted file mode 100644 index 076a2fd518..0000000000 --- a/source3/lib/genrand.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Functions to create reasonable random numbers for crypto use. - - Copyright (C) Jeremy Allison 2001 - - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - 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, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" - -static struct arcfour_state smb_arc4_state; -static uint32 counter; - -static bool done_reseed = False; -static void (*reseed_callback)(int *newseed); - -/**************************************************************** - Copy any user given reseed data. -*****************************************************************/ - -void set_rand_reseed_callback(void (*fn)(int *)) -{ - reseed_callback = fn; - set_need_random_reseed(); -} - -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; - } -} - -/**************************************************************** - Get a 16 byte hash from the contents of a file. - Note that the hash is not initialised. -*****************************************************************/ - -static void do_filehash(const char *fname, unsigned char *the_hash) -{ - unsigned char buf[1011]; /* deliberate weird size */ - unsigned char tmp_md4[16]; - int fd, n; - - fd = sys_open(fname,O_RDONLY,0); - if (fd == -1) - return; - - while ((n = read(fd, (char *)buf, sizeof(buf))) > 0) { - mdfour(tmp_md4, buf, n); - for (n=0;n<16;n++) - the_hash[n] ^= tmp_md4[n]; - } - close(fd); -} - -/************************************************************** - Try and get a good random number seed. Try a number of - different factors. Firstly, try /dev/urandom - use if exists. - - We use /dev/urandom as a read of /dev/random can block if - the entropy pool dries up. This leads clients to timeout - or be very slow on connect. - - If we can't use /dev/urandom then seed the stream random generator - above... -**************************************************************/ - -static int do_reseed(bool use_fd, int fd) -{ - unsigned char seed_inbuf[40]; - DATA_BLOB seed_blob = { 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) - return fd; - - fd = sys_open( "/dev/urandom", O_RDONLY,0); - if(fd >= 0) - return fd; - } - - /* Add in some secret file contents */ - - do_filehash("/etc/shadow", &seed_inbuf[0]); - do_filehash(lp_smb_passwd_file(), &seed_inbuf[16]); - - /* - * Add in the root encrypted password. - * On any system where security is taken - * seriously this will be secret. - */ - - 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]; - TALLOC_FREE(pw); - } - - /* - * Add the counter, time of day, and pid. - */ - - GetTimeOfDay(&tval); - mypid = sys_getpid(); - v1 = (counter++) + mypid + tval.tv_sec; - v2 = (counter++) * mypid + tval.tv_usec; - - SIVAL(seed_inbuf, 32, v1 ^ IVAL(seed_inbuf, 32)); - SIVAL(seed_inbuf, 36, v2 ^ IVAL(seed_inbuf, 36)); - - /* - * 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] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; - } - - arcfour_init(&smb_arc4_state, &seed_blob); - - return -1; -} - -/******************************************************************* - Interface to the (hopefully) good crypto random number generator. -********************************************************************/ - -void generate_random_buffer(uint8_t *out, int len) -{ - static int urand_fd = -1; - unsigned char md4_buf[64]; - unsigned char tmp_buf[16]; - unsigned char *p; - - if(!done_reseed) { - urand_fd = do_reseed(True, urand_fd); - done_reseed = True; - } - - if (urand_fd != -1 && len > 0) { - - if (read(urand_fd, out, len) == len) - return; /* len bytes of random data read from urandom. */ - - /* Read of urand error, drop back to non urand method. */ - close(urand_fd); - urand_fd = -1; - do_reseed(False, -1); - done_reseed = True; - } - - /* - * Generate random numbers in chunks of 64 bytes, - * then md4 them & copy to the output buffer. - * This way the raw state of the stream is never externally - * seen. - */ - - p = out; - while(len > 0) { - int copy_len = len > 16 ? 16 : len; - - arcfour_crypt_sbox(&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; - len -= copy_len; - } -} - -/******************************************************************* - Use the random number generator to generate a random string. -********************************************************************/ - -static char c_list[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,"; - -char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len) -{ - unsigned char *retstr = talloc_zero_array(mem_ctx, unsigned char, len); - size_t i; - - generate_random_buffer( retstr, len); - for (i = 0; i < len; i++) - retstr[i] = c_list[ retstr[i] % (sizeof(c_list)-1) ]; - - retstr[i] = '\0'; - - return (char *)retstr; -} diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index a6adb904e2..8e64a49e22 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -40,7 +40,7 @@ bool global_machine_password_needs_changing; * * @note Not called by systems with a working /dev/urandom. */ -static void get_rand_seed(int *new_seed) +static void get_rand_seed(void *userdata, int *new_seed) { *new_seed = sys_getpid(); if (db_ctx) { @@ -81,7 +81,7 @@ bool secrets_init(void) * This avoids a problem where systems without /dev/urandom * could send the same challenge to multiple clients */ - set_rand_reseed_callback(get_rand_seed); + set_rand_reseed_callback(get_rand_seed, NULL); /* Ensure that the reseed is done now, while we are root, etc */ generate_random_buffer(&dummy, sizeof(dummy)); |