From 8e0d5fb2474c3d5d58ed26f523365a5d27564f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= <come@opensides.be> Date: Wed, 19 Sep 2018 13:50:09 +0200 Subject: [PATCH] :ambulance: fix(core) Add fallback for hash_equals for PHP<5.6 for FD 1.2 branch issue #5890 --- include/functions.inc | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/include/functions.inc b/include/functions.inc index 71e0d8dcd..5aa092f2f 100644 --- a/include/functions.inc +++ b/include/functions.inc @@ -2674,6 +2674,47 @@ if (!function_exists('random_int')) { } } +if (!function_exists('hash_equals')) { + /** + * Timing attack safe string comparison + * + * Fallback for PHP<5.6 + * + * Compares two strings using the same time whether they're equal or not. + * This function should be used to mitigate timing attacks; for instance, when testing crypt() password hashes. + * + * @param string $known_string The string of known length to compare against + * @param string $user_string The user-supplied string + * @return boolean Returns TRUE when the two strings are equal, FALSE otherwise. + */ + function hash_equals($known_string, $user_string) + { + if (func_num_args() !== 2) { + trigger_error('hash_equals() expects exactly 2 parameters, '.func_num_args().' given', E_USER_WARNING); + return NULL; + } + if (!is_string($known_string) || !is_string($user_string)) { + trigger_error('hash_equals(): Expected both parameters to be a string, '.gettype($known_string).' and '.gettype($user_string).' given', E_USER_WARNING); + return FALSE; + } + $known_string_len = strlen($known_string); + $user_string_len = strlen($user_string); + if ($known_string_len !== $user_string_len) { + // use $known_string instead of $user_string to handle strings of different length. + $res = $known_string ^ $known_string; + // set $ret to 1 to make sure false is returned + $ret = 1; + } else { + $res = $known_string ^ $user_string; + $ret = 0; + } + for ($i = strlen($res) - 1; $i >= 0; $i--) { + $ret |= ord($res[$i]); + } + return ($ret === 0); + } +} + function ldap_escape_f($str, $ignore = '') { return ldap_escape($str, $ignore, LDAP_ESCAPE_FILTER); -- GitLab