diff --git a/CHANGES b/CHANGES index c7d7e5996f..93ba234a56 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,8 @@ 1500. [bug] host failed to lookup MX records. Also look up AAAA records. +1405. [func] Use arc4random() if available. + 1403. [func] dnssec-signzone, dnssec-keygen, dnssec-makekeyset dnssec-signkey now report their version in the usage message. @@ -432,6 +434,9 @@ --- 9.2.3rc1 released --- +1499. [bug] isc_random need to be seeded better if arc4random() + is not used. + 1498. [port] bsdos: 5.x support. 1497. [protocol] dig, nslookup and host now perform nibble lookups diff --git a/acconfig.h b/acconfig.h index 8a9217b3ed..e8607a9f23 100644 --- a/acconfig.h +++ b/acconfig.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: acconfig.h,v 1.35.2.4 2003/07/25 07:38:22 marka Exp $ */ +/* $Id: acconfig.h,v 1.35.2.4.2.1 2003/08/25 05:06:04 marka Exp $ */ /*** *** This file is not to be included by any public header files, because @@ -76,6 +76,9 @@ /* define if gai_strerror() exists */ #undef HAVE_GAISTRERROR +/* define if arc4random() exists */ +#undef HAVE_ARC4RANDOM + /* define if pthread_setconcurrency() should be called to tell the * OS how many threads we might want to run. */ diff --git a/bin/tests/genrandom.c b/bin/tests/genrandom.c index e90cbacc65..1634f4e97a 100644 --- a/bin/tests/genrandom.c +++ b/bin/tests/genrandom.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: genrandom.c,v 1.8 2001/01/09 21:41:04 bwelling Exp $ */ +/* $Id: genrandom.c,v 1.8.74.1 2003/08/25 05:06:10 marka Exp $ */ #include @@ -47,9 +47,15 @@ main(int argc, char **argv) { exit(1); } +#ifndef HAVE_ARC4RANDOM srand(0x12345678); +#endif while (bytes > 0) { +#ifndef HAVE_ARC4RANDOM unsigned short int x = (rand() & 0xFFFF); +#else + unsigned short int x = (arc4random() & 0xFFFF); +#endif unsigned char c = x & 0xFF; if (putc(c, fp) == EOF) { printf("error writing to file\n"); diff --git a/configure b/configure index ee87eba4f4..9f5f93c1fe 100755 --- a/configure +++ b/configure @@ -4618,6 +4618,99 @@ echo "${ECHO_T}using \"$use_randomdev\"" >&6 ;; esac +# +# Do we have arc4random() ? +# +echo "$as_me:$LINENO: checking for arc4random" >&5 +echo $ECHO_N "checking for arc4random... $ECHO_C" >&6 +if test "${ac_cv_func_arc4random+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +#include "confdefs.h" +/* From autoconf 2.57 */ +/* Define arc4random to an innocuous variant, in case declares arc4random. + For example, HP-UX 11i declares gettimeofday. */ +#define arc4random innocuous_arc4random + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char arc4random (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef arc4random + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char arc4random (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_arc4random) || defined (__stub___arc4random) +choke me +#else +char (*f) () = arc4random; +#endif +#ifdef __cplusplus +} +#endif + +#ifdef F77_DUMMY_MAIN +# ifdef __cplusplus + extern "C" +# endif + int F77_DUMMY_MAIN() { return 1; } +#endif +int +main () +{ +return f != arc4random; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_arc4random=yes +else + echo "$as_me: failed program was:" >&5 +cat conftest.$ac_ext >&5 +ac_cv_func_arc4random=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_arc4random" >&5 +echo "${ECHO_T}$ac_cv_func_arc4random" >&6 +if test $ac_cv_func_arc4random = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_ARC4RANDOM 1 +_ACEOF + +fi + + # # Begin pthreads checking. # @@ -7543,7 +7636,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes case $host in *-*-irix6*) # Find out which ABI we are using. - echo '#line 7546 "configure"' > conftest.$ac_ext + echo '#line 7639 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8093,7 +8186,7 @@ chmod -w . save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -o out/conftest2.$ac_objext" compiler_c_o=no -if { (eval echo configure:8096: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then +if { (eval echo configure:8189: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s out/conftest.err; then @@ -9960,7 +10053,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext < #include #include +#include #include #include @@ -370,7 +371,10 @@ towiresorted(dns_rdataset_t *rdataset, dns_name_t *owner_name, */ for (i = 0; i < count; i++) { dns_rdata_t rdata; - choice = i + (((u_int)rand()>>3) % (count - i)); + isc_uint32_t val; + + isc_random_get(&val); + choice = i + (val % (count - i)); rdata = shuffled[i]; shuffled[i] = shuffled[choice]; shuffled[choice] = rdata; @@ -385,7 +389,11 @@ towiresorted(dns_rdataset_t *rdataset, dns_name_t *owner_name, /* * "Cyclic" order. */ - unsigned int j = (((unsigned int)rand()) >> 3) % count; + isc_uint32_t val; + unsigned int j; + + isc_random_get(&val); + j = val % count; for (i = 0; i < count; i++) { if (order != NULL) sorted[j].key = (*order)(&shuffled[i], diff --git a/lib/isc/random.c b/lib/isc/random.c index 4ed13d977d..b76410ded7 100644 --- a/lib/isc/random.c +++ b/lib/isc/random.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: random.c,v 1.15 2001/01/09 21:56:22 bwelling Exp $ */ +/* $Id: random.c,v 1.15.74.1 2003/08/25 05:06:11 marka Exp $ */ #include @@ -33,7 +33,17 @@ static isc_once_t once = ISC_ONCE_INIT; static void initialize_rand(void) { - srand(time(NULL)); +#ifndef HAVE_ARC4RANDOM + unsigned int pid = getpid(); + + /* + * The low bits of pid generally change faster. + * Xor them with the high bits of time which change slowly. + */ + pid = ((pid << 16) & 0xffff0000) | ((pid >> 16) & 0xffff); + + srand(time(NULL) ^ pid); +#endif } static void @@ -47,7 +57,11 @@ isc_random_seed(isc_uint32_t seed) { initialize(); +#ifndef HAVE_ARC4RANDOM srand(seed); +#else + arc4random_addrandom((u_char *) &seed, sizeof(isc_uint32_t)); +#endif } void @@ -57,7 +71,15 @@ isc_random_get(isc_uint32_t *val) initialize(); - *val = rand(); +#ifndef HAVE_ARC4RANDOM + /* + * rand()'s lower bits are not random. + * rand()'s upper bit is zero. + */ + *val = ((rand() >> 4) & 0xffff) | ((rand() << 12) & 0xffff0000) ; +#else + *val = arc4random(); +#endif } isc_uint32_t @@ -66,5 +88,9 @@ isc_random_jitter(isc_uint32_t max, isc_uint32_t jitter) { if (jitter == 0) return (max); else +#ifndef HAVE_ARC4RANDOM return (max - rand() % jitter); +#else + return (max - arc4random() % jitter); +#endif }