]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add mul + mod without overflow and fixup rlm_passwd hash function
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 4 Jun 2020 18:12:25 +0000 (13:12 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 4 Jun 2020 18:12:25 +0000 (13:12 -0500)
src/lib/util/misc.c
src/lib/util/misc.h
src/modules/rlm_passwd/rlm_passwd.c

index cb386b0cd493bbc8a58036da8946a0d947786516..75edb0d0c059d375ad809ee8c26b579278e6e6a2 100644 (file)
@@ -997,6 +997,8 @@ int fr_size_from_str(size_t *out, char const *str)
 }
 
 /** Multiply, checking for overflow
+ *
+ * Multiplication will only occur if it would not overflow.
  *
  * @param[out] result  of multiplication.
  * @param[in] lhs      First operand.
@@ -1008,9 +1010,37 @@ int fr_size_from_str(size_t *out, char const *str)
  */
 bool fr_multiply(uint64_t *result, uint64_t lhs, uint64_t rhs)
 {
-        *result = lhs * rhs;
+       if (rhs > 0 && (UINT64_MAX / rhs) < lhs) return true;
+
+        *result = lhs * rhs;   /* ubsan would flag this */
+
+        return false;
+}
+
+/** Multiply with modulo wrap
+ *
+ * Avoids multiplication overflow.
+ *
+ * @param[in] lhs      First operand.
+ * @param[in] rhs      Second operand.
+ * @param[in] mod      Modulo.
+ * @return
+ *     - Result.
+ */
+uint64_t fr_multiply_mod(uint64_t lhs, uint64_t rhs, uint64_t mod)
+{
+       uint64_t res;
+
+       lhs %= mod;
+
+       while (rhs > 0) {
+               if (rhs & 0x01) res = (res + lhs) % mod;
+
+               lhs = (lhs * 2) % mod;
+               rhs /= 2;
+       }
 
-        return rhs > 0 && (UINT64_MAX / rhs) < lhs;
+       return res % mod;
 }
 
 /** Compares two pointers
index af1e64664ab068f32e9e11fbed18c6110ca3c7a3..42eb10aeee6bbd0a1ca5d29310da29a3a39a163d 100644 (file)
@@ -207,6 +207,8 @@ size_t              fr_snprint_uint128(char *out, size_t outlen, uint128_t const num);
 int            fr_unix_time_from_str(fr_unix_time_t *date, char const *date_str);
 
 bool           fr_multiply(uint64_t *result, uint64_t lhs, uint64_t rhs);
+uint64_t       fr_multiply_mod(uint64_t lhs, uint64_t rhs, uint64_t mod);
+
 int            fr_size_from_str(size_t *out, char const *str);
 int8_t         fr_pointer_cmp(void const *a, void const *b);
 void           fr_quick_sort(void const *to_sort[], int min_idx, int max_idx, fr_cmp_t cmp);
index 91865cd5c571638d3143059246a3fca8ae3ee0ba..808823e55f6db65936cea902569dbb73a4257e62 100644 (file)
@@ -131,11 +131,11 @@ static void destroy_password (struct mypasswd * pass)
 
 static unsigned int hash(char const * username, unsigned int tablesize)
 {
-       int h=1;
-       while (*username) {
-               h = h * 7907 + *username++;
-       }
-       return h%tablesize;
+       uint64_t h = 1;
+
+       while (*username) h = fr_multiply_mod(h, (7907 + *username++), tablesize);
+
+       return (unsigned int)h;
 }
 
 static void release_hash_table(struct hashtable * ht){