*/
#include "includes.h"
+#include "system/iconv.h"
+#include "system/filesys.h"
+#include "lib/crypto/crypto.h"
static unsigned char hash[258];
-static uint32 counter;
-static unsigned char *reseed_data;
-static size_t reseed_data_size;
+static uint32_t counter;
+
+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();
+}
+
+void set_need_random_reseed(void)
+{
+ done_reseed = False;
+}
- reseed_data = (unsigned char *)memdup(data, len);
- if (reseed_data)
- reseed_data_size = len;
+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.
+ Get a 16 byte hash from the contents of a file.
+
+ Note that the hash is initialised, because the extra entropy is not
+ worth the valgrind pain.
*****************************************************************/
static void do_filehash(const char *fname, unsigned char *the_hash)
unsigned char tmp_md4[16];
int fd, n;
- fd = sys_open(fname,O_RDONLY,0);
+ ZERO_STRUCT(tmp_md4);
+
+ fd = open(fname,O_RDONLY,0);
if (fd == -1)
return;
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;
+ uint32_t v1, v2; struct timeval tval; pid_t mypid;
+ int reseed_data = 0;
if (use_fd) {
if (fd != -1)
return fd;
- fd = sys_open( "/dev/urandom", O_RDONLY,0);
+ fd = open( "/dev/urandom", O_RDONLY,0);
if(fd >= 0)
return fd;
}
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("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);
- }
-
/*
* Add the counter, time of day, and pid.
*/
* 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));
return -1;
}
-/*******************************************************************
+/*
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(uint8_t *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;
}
}
}
+/*
+ generate a single random uint32_t
+*/
+uint32_t generate_random(void)
+{
+ uint8_t v[4];
+ generate_random_buffer(v, 4);
+ return IVAL(v, 0);
+}
+
/*
very basic password quality checker
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)
+char *generate_random_str_list(TALLOC_CTX *mem_ctx, size_t len, const char *list)
{
size_t i;
+ size_t list_len = strlen(list);
+
+ char *retstr = talloc_array(mem_ctx, char, len + 1);
+ if (!retstr) return NULL;
- char *retstr = talloc(mem_ctx, len + 1);
+ generate_random_buffer((uint8_t *)retstr, len);
+ for (i = 0; i < len; i++) {
+ retstr[i] = list[retstr[i] % list_len];
+ }
+ retstr[i] = '\0';
- if (!retstr)
- return NULL;
+ return retstr;
+}
-again:
- generate_random_buffer(retstr, len, False);
- for (i = 0; i < len; i++)
- retstr[i] = c_list[retstr[i] % (sizeof(c_list)-1) ];
+char *generate_random_str(TALLOC_CTX *mem_ctx, size_t len)
+{
+ char *retstr;
+ const char *c_list = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+_-#.,";
- retstr[i] = '\0';
+again:
+ retstr = generate_random_str_list(mem_ctx, len, c_list);
+ if (!retstr) return NULL;
/* we need to make sure the random string passes basic quality tests
or it might be rejected by windows as a password */
if (len >= 7 && !check_password_quality(retstr)) {
+ talloc_free(retstr);
goto again;
}