]> git.ipfire.org Git - thirdparty/openldap.git/commitdiff
ITS#8196/ITS#9714 Switch to xorshift
authorOndřej Kuzník <ondra@mistotebe.net>
Fri, 16 Sep 2022 13:49:11 +0000 (14:49 +0100)
committerQuanah Gibson-Mount <quanah@openldap.org>
Mon, 19 Sep 2022 16:32:39 +0000 (16:32 +0000)
libraries/libldap/dnssrv.c

index 433c37f5e012c3953f1f151c6f793b5620c22b9d..4c7803577786c95de3bc1f10e6152514d1224162 100644 (file)
@@ -184,22 +184,28 @@ typedef struct srv_record {
     char hostname[MAXHOST];
 } srv_record;
 
-/* Linear Congruential Generator - we don't need
- * high quality randomness, and we don't want to
+/*
+ * xorshift - we don't need high quality randomness, and we don't want to
  * interfere with anyone else's use of srand().
  *
- * The PRNG here cycles thru 941,955 numbers.
+ * The PRNG here cycles thru all nonzero 32bit numbers.
  */
-static float srv_seed;
+static ac_uint4 srv_seed;
 
-static void srv_srand(int seed) {
-       srv_seed = (float)seed / (float)RAND_MAX;
+static void
+srv_srand( int seed )
+{
+       srv_seed = seed;
 }
 
-static float srv_rand() {
-       float val = 9821.0 * srv_seed + .211327;
-       srv_seed = val - (int)val;
-       return srv_seed;
+static ac_uint4
+srv_rand( void ) {
+       ac_uint4 val = srv_seed;
+       val ^= val << 13;
+       val ^= val >> 17;
+       val ^= val << 5;
+       srv_seed = val;
+       return val;
 }
 
 static int srv_cmp(const void *aa, const void *bb){
@@ -221,9 +227,11 @@ static void srv_shuffle(srv_record *a, int n) {
                if (!total) {
                        /* all remaining weights are zero,
                           do a straight Fisher-Yates shuffle */
-                       j = srv_rand() * p;
+                       j = srv_rand() % p;
                } else {
-                       r = srv_rand() * total;
+                       /* Extra share for the first (possibly 0-weight entry),
+                        * RFC2782 Errata (rejected) discusses the effects. */
+                       r = srv_rand() % (total+1);
                        for (j=0; j<p; j++) {
                                r -= a[j].weight;
                                if (r < 0) {
@@ -291,10 +299,11 @@ int ldap_domain2hostlist(
        unsigned char *p;
        char host[DNSBUFSIZ];
        int status;
-       u_short port, priority, weight;
+       u_short query_id, port, priority, weight;
 
        /* Parse out query */
        p = reply;
+       query_id = (p[0] << 8) | p[1];
 
 #ifdef NS_HFIXEDSZ
        /* Bind 8/9 interface */
@@ -362,8 +371,12 @@ add_size:;
        if (!hostent_head) goto out;
     qsort(hostent_head, hostent_count, sizeof(srv_record), srv_cmp);
 
-       if (!srv_seed)
-               srv_srand(time(0L));
+       if (!srv_seed) {
+               int seed = time( NULL ) ^ query_id;
+               /* Make sure we never pass 0 as a seed */
+               if ( !seed ) seed++;
+               srv_srand( seed );
+       }
 
        /* shuffle records of same priority */
        j = 0;