From 3a0dd248d05e2b15a2c899fc72cb3f122c216917 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 10:00:13 +0200 Subject: [PATCH 01/94] [feature/passwords] Add basic implementation of passwords manager The passwords manager is capable of checking and hashing passwords. It will support different hashing algorithms. PHPBB3-11610 --- phpBB/config/services.yml | 7 ++ phpBB/includes/crypto/manager.php | 200 ++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 phpBB/includes/crypto/manager.php diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 8abc413a5a..32dd2759b3 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -121,6 +121,13 @@ services: - @config - @dbal.conn + crypto.manager: + class: phpbb_crypto_manager + arguments: + - @config + - @service_container + - @crypto.driver_collection + dispatcher: class: phpbb_event_dispatcher arguments: diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php new file mode 100644 index 0000000000..e54baba9b4 --- /dev/null +++ b/phpBB/includes/crypto/manager.php @@ -0,0 +1,200 @@ +config = $config; + $this->container = $container; + $this->type = 'phpbb_crypto_driver_bcrypt'; // might want to make this flexible + + $this->fill_type_map($hashing_algorithms); + $this->load_crypto_helper(); + } + + /** + * Fill algorithm type map + * + * @param phpbb_di_service_collection $hashing_algorithms + */ + protected function fill_type_map($hashing_algorithms) + { + if ($this->type_map !== false) + { + return; + } + + foreach ($hashing_algorithms as $algorithm) + { + if (!isset($this->type_map[$algorithm->get_prefix()])) + { + $this->type_map[$algorithm->get_prefix()] = $algorithm; + } + } + } + + /** + * Load crypto helper class + */ + protected function load_crypto_helper() + { + if ($this->helper === NULL) + { + $this->helper = new phpbb_crypto_helper($this); + } + } + + /** + * Get the hash type from the supplied hash + * + * @param string $hash Password hash that should be checked + * + * @return object The hash type object + * + * @throws RunTimeException If hash type is not supported + */ + public function get_hashing_algorithm($hash) + { + // preg_match() will also show hashing algos like $2a\H$, which + // is a combination of bcrypt and phpass + if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) + { + // Legacy support needed + throw new RunTimeException('NO_LEGACY_SUPPORT'); + } + + // Be on the lookout for multiple hashing algorithms + // 2 is correct: H\2a > 2, H\P > 2 + if (strlen($match[1]) > 2) + { + $hash_types = explode('\\', $match[1]); + $return_ary = array(); + foreach ($hash_types as $type) + { + if (isset($this->type_map["\${$type}\$"])) + { + $return_ary[$type] = $this->type_map["\${$type}\$"]; + } + else + { + throw new \RunTimeException('HASH_TYPE_NOT_SUPPORTED'); + } + } + return $return_ary; + } + if (isset($this->type_map[$match[0]])) + { + return $this->type_map[$match[0]]; + } + else + { + throw new RunTimeException('UNKNOWN_HASH_TYPE'); + } + } + + /** + * Hash supplied password + * + * @param string $password Password that should be hashed + * @param string $type Hash type. Will default to standard hash type if + * none is supplied + * @return string Password hash of supplied password + * + * @throws RunTimeException If hash type is not supported + */ + public function hash_password($password, $type = '') + { + if ($type === '') + { + return $this->container->get($this->type)->hash($password); + } + else + { + return $this->container->get($type)->hash($password); + } + } + + public function check_hash($password, $hash) + { + if (!$this->type_map) + { + // This obviously shouldn't happen + return false; + } + + // First find out what kind of hash we're dealing with + $stored_hash_type = $this->get_hashing_algorithm($hash); + if ($stored_hash_type == false) + { + return false; + } + + // Multiple hash passes needed + if (is_array($stored_hash_type)) + { + + return $this->helper->check_combined_hash($password, $stored_hash_type, $hash); + } + + return $stored_hash_type->check($password, $hash); + if ($stored_hash_type->get_type() !== $this->type) + { + // check with "old" hash and convert to new one + } + else + { + // check with default type + } + } +} From d66cae7cbcf9fb2d8105b1c62c3876dd3f4c0c14 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 10:02:02 +0200 Subject: [PATCH 02/94] [feature/passwords] Add service collection file crypto.yml This will contain definitions of the services and the service collection that will be passed to the passwords manager. PHPBB3-11610 --- phpBB/config/crypto.yml | 35 +++++++++++++++++++++++++++++++++++ phpBB/config/services.yml | 1 + 2 files changed, 36 insertions(+) create mode 100644 phpBB/config/crypto.yml diff --git a/phpBB/config/crypto.yml b/phpBB/config/crypto.yml new file mode 100644 index 0000000000..03a7cdce2e --- /dev/null +++ b/phpBB/config/crypto.yml @@ -0,0 +1,35 @@ +services: + crypto.driver.bcrypt: + class: phpbb_crypto_driver_bcrypt + arguments: + - @config + tags: + - { name: crypto.driver } + + crypto.driver.bcrypt_2y: + class: phpbb_crypto_driver_bcrypt_2y + arguments: + - @config + tags: + - { name: crypto.driver } + + crypto.driver.salted_md5: + class: phpbb_crypto_driver_salted_md5 + arguments: + - @config + tags: + - { name: crypto.driver } + + crypto.driver.phpass: + class: phpbb_crypto_driver_phpass + arguments: + - @config + tags: + - { name: crypto.driver } + + crypto.driver_collection: + class: phpbb_di_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: crypto.driver } diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 32dd2759b3..e7c3232fa7 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -6,6 +6,7 @@ imports: - { resource: avatars.yml } - { resource: feed.yml } - { resource: auth_providers.yml } + - { resource: crypto.yml } services: acl.permissions: From fbdbf41dc8378c16b37b9e6594107f00dc9a6241 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 10:04:10 +0200 Subject: [PATCH 03/94] [feature/passwords] Add helper functions, i.e. for combined hashes Combined hashes can be used for i.e. converting already existing password hashes to bcrypt. While this will not provide the same security a pure bcrypt hash provides, it will still be significantly more secure than a standard salted md5. A combined hash will look as follows: $H\2y${salted_for_H_prefix}${salt_+_settings_for_2y_prefix}${hash} The prefixes are seperated by a backslash. Individual settings (which can include either just the salt or a salt and possible additional settings) are seperated by dollar signs. As backslashes and dollar signs are not allowed in hashes or salts, they will be used for seperating the settings from the salt. Here is an example of a password hash: $H\2a$9zv1uIaq1$10\1ff4640409fb96a449c1fO$/oN1O0cdUmFSMZT3UZKrgAyalhnt1LC The 'H' prefix stands for the salted md5 implementation of phpBB 3.0. Its settings will be parsed as 9zv1uIaq1 resulting in a hash for the check as follows: $H$9zv1uIaq1{hash} Since the password is used for hashing, the {hash} can be left blank and will basically be filled by the hashing algorithm. The {hash} will then be used as password for the next hashing algorithm. In this case that would be the bcrypt algorithm. The settings are set to 10\1ff4640409fb96a449c1fO which will be transformed to 10$1ff4640409fb96a449c1fO resulting in a hash like this for the bcrypt hashing function: $2a$10$1ff4640409fb96a449c1fO{hash} The {hash} will again be basically filled by the hashing algorithm. Afterwards, the {hash} will be extracted from the returned hash and put at the end of the already known hash settings: $H\2a$9zv1uIaq1$10\1ff4640409fb96a449c1fO$ If the password is correct, the combined hash will of course be the same as the stored one. PHPBB3-11610 --- phpBB/includes/crypto/helper.php | 140 +++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 phpBB/includes/crypto/helper.php diff --git a/phpBB/includes/crypto/helper.php b/phpBB/includes/crypto/helper.php new file mode 100644 index 0000000000..3021bef2c1 --- /dev/null +++ b/phpBB/includes/crypto/helper.php @@ -0,0 +1,140 @@ +manager = $manager; + } + + /** + * Get hash settings from combined hash + * + * @param string $hash Password hash of combined hash + * + * @return array An array containing the hash settings for the hash + * types in successive order as described by the comined + * password hash + */ + protected function get_combined_hash_settings($hash) + { + preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); + $hash_settings = substr($hash, strpos($hash, $match[1]) + strlen($match[1]) + 1); + foreach ($match as $cur_type) + { + $dollar_position = strpos($hash_settings, '$'); + $output[] = substr($hash_settings, 0, ($dollar_position != false) ? $dollar_position : strlen($hash_settings)); + $hash_settings = substr($hash_settings, $dollar_position + 1); + } + + return $output; + } + + /** + * Check combined password hash against the supplied password + * + * @param string $password Password entered by user + * @param array $stored_hash_type An array containing the hash types + * as described by stored password hash + * @param string $hash Stored password hash + * + * @return bool True if password is correct, false if not + */ + public function check_combined_hash($password, $stored_hash_type, $hash) + { + $cur_hash = ''; + $i = 0; + $data = array( + 'prefix' => '$', + 'settings' => '$', + ); + $hash_settings = $this->get_combined_hash_settings($hash); + foreach ($stored_hash_type as $key => $hash_type) + { + $rebuilt_hash = $this->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]); + $this->combine_hash_output($data, 'prefix', $key); + $this->combine_hash_output($data, 'settings', $hash_settings[$i]); + $cur_hash = $hash_type->hash($password, $rebuilt_hash); + $password = str_replace($rebuilt_hash, '', $cur_hash); + $i++; + } + return ($hash === $this->combine_hash_output($data, 'hash', $password)); + } + + /** + * Combine hash prefixes, settings, and actual hash + * + * @param array $data Array containing the keys 'prefix' and 'settings'. + * It will hold the prefixes and settings + * @param string $type Data type of the supplied value + * @param string $value Value that should be put into the data array + * + * @return string|none Return complete combined hash if type is neither + * 'prefix' nor 'settings', nothing if it is + */ + protected function combine_hash_output(&$data, $type, $value) + { + if ($type == 'prefix') + { + $data[$type] .= ($data[$type] !== '$') ? '\\' : ''; + $data[$type] .= $value; + } + elseif ($type == 'settings') + { + $data[$type] .= ($data[$type] !== '$') ? '$' : ''; + $data[$type] .= $value; + } + else + { + // Return full hash + return $data['prefix'] . $data['settings'] . '$' . $value; + } + } + + /** + * Rebuild hash for hashing functions + * + * @param string $prefix Hash prefix + * @param string $settings Hash settings + * + * @return string Rebuilt hash for hashing functions + */ + protected function rebuild_hash($prefix, $settings) + { + $rebuilt_hash = $prefix; + if (strpos($settings, '\\') !== false) + { + $settings = str_replace('\\', '$', $settings); + } + $rebuilt_hash .= $settings; + return $rebuilt_hash; + } +} From 4b6646d1be63b8e4d099d84d58ae77a485744d1a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 10:08:45 +0200 Subject: [PATCH 04/94] [feature/passwords] Add crypto driver base class and interface PHPBB3-11610 --- phpBB/includes/crypto/driver/base.php | 43 +++++++++++++++++ phpBB/includes/crypto/driver/interface.php | 56 ++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 phpBB/includes/crypto/driver/base.php create mode 100644 phpBB/includes/crypto/driver/interface.php diff --git a/phpBB/includes/crypto/driver/base.php b/phpBB/includes/crypto/driver/base.php new file mode 100644 index 0000000000..c913767989 --- /dev/null +++ b/phpBB/includes/crypto/driver/base.php @@ -0,0 +1,43 @@ +config = $config; + } + + /** + * @inheritdoc + */ + public function is_supported() + { + return true; + } +} diff --git a/phpBB/includes/crypto/driver/interface.php b/phpBB/includes/crypto/driver/interface.php new file mode 100644 index 0000000000..b8383bda5a --- /dev/null +++ b/phpBB/includes/crypto/driver/interface.php @@ -0,0 +1,56 @@ + Date: Sat, 15 Jun 2013 10:09:44 +0200 Subject: [PATCH 05/94] [feature/passwords] Add salted md5 (phpBB3 default) and phpass drivers The phpass driver extends the standard salted md5 driver of phpBB3. It will only support the $P$ prefix that phpass uses. PHPBB3-11610 --- phpBB/includes/crypto/driver/phpass.php | 40 +++++ phpBB/includes/crypto/driver/salted_md5.php | 186 ++++++++++++++++++++ 2 files changed, 226 insertions(+) create mode 100644 phpBB/includes/crypto/driver/phpass.php create mode 100644 phpBB/includes/crypto/driver/salted_md5.php diff --git a/phpBB/includes/crypto/driver/phpass.php b/phpBB/includes/crypto/driver/phpass.php new file mode 100644 index 0000000000..4868464d73 --- /dev/null +++ b/phpBB/includes/crypto/driver/phpass.php @@ -0,0 +1,40 @@ +get_hash_settings($setting)) === false) + { + return false; + } + } + else + { + if (($settings = $this->get_hash_settings($this->generate_salt())) === false) + { + return false; + } + } + + $hash = md5($settings['salt'] . $password, true); + do + { + $hash = md5($hash . $password, true); + } + while (--$settings['count']); + + $output = $settings['full']; + $output .= _hash_encode64($hash, 16, $this->itoa); + + if (strlen($output) == 34) + { + return $output; + } + + // Should we really just return the md5 of the password? O.o + return md5($password); + } + + /** + * @inheritdoc + */ + public function check($password, $hash) + { + if (strlen($hash) != 34) + { + return false; + } + // No need to check prefix, already did that in manage + + if ($hash === $this->hash($password, $hash)) + { + return true; + } + return false; + } + + /** + * Return unique id + * @param string $extra additional entropy + */ + protected function unique_id($extra = 'c') + { + static $dss_seeded = false; + + $val = $this->config['rand_seed'] . microtime(); + $val = md5($val); + $this->config['rand_seed'] = md5($this->config['rand_seed'] . $val . $extra); + + if ($dss_seeded !== true && ($this->config['rand_seed_last_update'] < time() - rand(1,10))) + { + set_config('rand_seed_last_update', time(), true); + set_config('rand_seed', $this->config['rand_seed'], true); + $dss_seeded = true; + } + + return substr($val, 4, 16); + } + + /** + * Generate salt for hashing method + * + * @return string Salt for hashing method + */ + protected function generate_salt() + { + $salt = ''; + $random = ''; + $count = 6; + + if (($fh = @fopen('/dev/urandom', 'rb'))) + { + $random = fread($fh, $count); + fclose($fh); + } + + if (strlen($random) < $count) + { + $random = ''; + $random_state = unique_id(); + + for ($i = 0; $i < $count; $i += 16) + { + $random_state = md5(unique_id() . $random_state); + $random .= pack('H*', md5($random_state)); + } + $random = substr($random, 0, $count); + } + + $salt = '$H$'; + $salt .= $this->itoa[min($count + 5, 30)]; + $salt .= _hash_encode64($random, 6, $this->itoa); + var_dump($salt); + + return $salt; + } + + /** + * Get hash settings + * + * @return array Array containing the count_log2, salt, and full hash + * settings string + */ + public function get_hash_settings($hash) + { + if (empty($hash)) + { + return false; + } + $count_log2 = strpos($this->itoa, $hash[3]); + $salt = substr($hash, 4, 8); + + if ($count_log2 < 7 || $count_log2 > 30 || strlen($salt) != 8) + { + return false; + } + + return array( + 'count' => 1 << $count_log2, + 'salt' => $salt, + 'full' => substr($hash, 0, 12), + ); + } +} From 78a83691738a2bcd0e6cb27b5dcbda8809a5d615 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 10:11:05 +0200 Subject: [PATCH 06/94] [feature/passwords] Add basic bcrypt drivers for $2a$ & $2y$ prefix The $2a$ prefix is the basic implementation with the $2y$ prefix extending that class. However, the default hashes for phpBB should be generated with $2y$ unless the PHP version is older than 5.3.7. PHPBB3-11610 --- phpBB/includes/crypto/driver/bcrypt.php | 87 ++++++++++++++++++++++ phpBB/includes/crypto/driver/bcrypt_2y.php | 48 ++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 phpBB/includes/crypto/driver/bcrypt.php create mode 100644 phpBB/includes/crypto/driver/bcrypt_2y.php diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/includes/crypto/driver/bcrypt.php new file mode 100644 index 0000000000..8fe9b91ab8 --- /dev/null +++ b/phpBB/includes/crypto/driver/bcrypt.php @@ -0,0 +1,87 @@ +is_supported()) ? '$2a$' : self::PREFIX; + + if ($salt == '') + { + $salt = $prefix . '10$' . $this->get_random_salt(); + } + + $hash = crypt($password, $salt); + return $hash; + } + + /** + * @inheritdoc + */ + public function check($password, $hash) + { + $salt = substr($hash, strpos($hash, '$', 4) + 1, 22); + var_dump('bcrypt salt: ' . $salt . ' with length ' . strlen($salt)); + if (strlen($salt) != 22) + { + return false; + } + + if ($hash == $this->hash($password, $salt)) + { + return true; + } + return false; + } + + /** + * Get a random salt value with a length of 22 characters + * + * @return string Salt for password hashing + */ + protected function get_random_salt() + { + return substr(str_replace('+', '.', bin2hex(openssl_random_pseudo_bytes(22))), 0, 22); + } +} diff --git a/phpBB/includes/crypto/driver/bcrypt_2y.php b/phpBB/includes/crypto/driver/bcrypt_2y.php new file mode 100644 index 0000000000..8bce171a25 --- /dev/null +++ b/phpBB/includes/crypto/driver/bcrypt_2y.php @@ -0,0 +1,48 @@ + Date: Sat, 15 Jun 2013 10:37:10 +0200 Subject: [PATCH 07/94] [feature/passwords] Default to bcrypt with $2y$ prefix if possible PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index e54baba9b4..2647836cc8 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -57,7 +57,7 @@ class phpbb_crypto_manager { $this->config = $config; $this->container = $container; - $this->type = 'phpbb_crypto_driver_bcrypt'; // might want to make this flexible + $this->type = 'crypto.driver.bcrypt_2y'; // might want to make this flexible $this->fill_type_map($hashing_algorithms); $this->load_crypto_helper(); From c9afda5a655f5eec8819c4c090a0b31a73e35b87 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 12:09:00 +0200 Subject: [PATCH 08/94] [feature/passwords] Use correct prefix for bcrypt type PHPBB3-11610 --- phpBB/includes/crypto/driver/bcrypt.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/includes/crypto/driver/bcrypt.php index 8fe9b91ab8..12400cf376 100644 --- a/phpBB/includes/crypto/driver/bcrypt.php +++ b/phpBB/includes/crypto/driver/bcrypt.php @@ -45,7 +45,7 @@ class phpbb_crypto_driver_bcrypt extends phpbb_crypto_driver_base { // The 2x and 2y prefixes of bcrypt might not be supported // Revert to 2a if this is the case - $prefix = (!$this->is_supported()) ? '$2a$' : self::PREFIX; + $prefix = (!$this->is_supported()) ? '$2a$' : $this->get_prefix(); if ($salt == '') { From d3d317a2dea4b3c9c7732975d9a41834ef080a49 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 12:10:03 +0200 Subject: [PATCH 09/94] [feature/passwords] Correctly supply hash salt and settings to bcrypt PHPBB3-11610 --- phpBB/includes/crypto/driver/bcrypt.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/includes/crypto/driver/bcrypt.php index 12400cf376..82ff2fb844 100644 --- a/phpBB/includes/crypto/driver/bcrypt.php +++ b/phpBB/includes/crypto/driver/bcrypt.php @@ -61,9 +61,8 @@ class phpbb_crypto_driver_bcrypt extends phpbb_crypto_driver_base */ public function check($password, $hash) { - $salt = substr($hash, strpos($hash, '$', 4) + 1, 22); - var_dump('bcrypt salt: ' . $salt . ' with length ' . strlen($salt)); - if (strlen($salt) != 22) + $salt = substr($hash, 0, 29); + if (strlen($salt) != 29) { return false; } From 8795fe9c77d634cb99d6f1f30a0022a6ba972785 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 12:10:56 +0200 Subject: [PATCH 10/94] [feature/passwords] Add convert flag for converting to default PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 2647836cc8..1f6ba78666 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -30,6 +30,11 @@ class phpbb_crypto_manager */ protected $type_map = false; + /** + * Password convert flag. Password should be converted + */ + public $convert_flag = false; + /** * Crypto helper * @var phpbb_crypto_helper @@ -183,18 +188,14 @@ class phpbb_crypto_manager // Multiple hash passes needed if (is_array($stored_hash_type)) { - return $this->helper->check_combined_hash($password, $stored_hash_type, $hash); } - return $stored_hash_type->check($password, $hash); if ($stored_hash_type->get_type() !== $this->type) { - // check with "old" hash and convert to new one - } - else - { - // check with default type + $this->convert_flag = true; } + + return $stored_hash_type->check($password, $hash); } } From f8bcf99c7fe0b20f447e502cf2cb5b3d0648f68a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 12:11:51 +0200 Subject: [PATCH 11/94] [feature/passwords] Do not support 8-bit characters with $2a$ bcrypt 8-bit unicode characters might reduce the security of the password hash when using the $2a$ bcrypt prefix. Those types of characters are usually not used in passwords but we should prevent this possible issue anyway. PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 1f6ba78666..93b99743d1 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -154,20 +154,26 @@ class phpbb_crypto_manager * @param string $password Password that should be hashed * @param string $type Hash type. Will default to standard hash type if * none is supplied - * @return string Password hash of supplied password + * @return string|bool Password hash of supplied password or false if + * if something went wrong during hashing * * @throws RunTimeException If hash type is not supported */ public function hash_password($password, $type = '') { - if ($type === '') + $type = ($type === '') ? $this->type : $type; + + $hashing_algorithm = $this->container->get($type); + // Do not support 8-bit characters with $2a$ bcrypt + if ($type === 'crypto.driver.bcrypt' || ($type === 'crypto.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) { - return $this->container->get($this->type)->hash($password); - } - else - { - return $this->container->get($type)->hash($password); + if (ord($password[strlen($password)-1]) & 128) + { + return false; + } } + + return $this->container->get($type)->hash($password); } public function check_hash($password, $hash) From c9fafcefd3a7cc65109ed610e9c4ff68979e3a1a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 12:14:16 +0200 Subject: [PATCH 12/94] [feature/passwords] Add basic passwords manager test file PHPBB3-11610 --- tests/crypto/manager_test.php | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 tests/crypto/manager_test.php diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php new file mode 100644 index 0000000000..ce6ac1684f --- /dev/null +++ b/tests/crypto/manager_test.php @@ -0,0 +1,65 @@ +phpbb_container = new phpbb_mock_container_builder; + + // Prepare dependencies for manager and driver + $config = new phpbb_config(array()); + + $crypto_drivers = array( + 'crypto.driver.bcrypt' => new phpbb_crypto_driver_bcrypt($config), + 'crypto.driver.bcrypt_2y' => new phpbb_crypto_driver_bcrypt_2y($config), + 'crypto.driver.salted_md5' => new phpbb_crypto_driver_salted_md5($config), + ); + + foreach ($crypto_drivers as $key => $driver) + { + $this->phpbb_container->set($key, $driver); + } +/* + $config['allow_avatar_' . get_class($this->avatar_foobar)] = true; + $config['allow_avatar_' . get_class($this->avatar_barfoo)] = false; +*/ + // Set up avatar manager + $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $crypto_drivers); + } + + public function hash_password_data() + { + return array( + array('', '2y', 60), + array('crypto.driver.bcrypt_2y', '2y', 60), + array('crypto.driver.bcrypt', '2a', 60), + //array('crypto.driver.salted_md5', '$H$', 45), + ); + } + + /** + * @dataProvider hash_password_data + */ + public function test_hash_password($type, $prefix, $length) + { + $hash = $this->manager->hash_password('foobar', $type); + preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); + $this->assertEquals($prefix, $match[1]); + $this->assertEquals($length, strlen($hash)); + } +} From 61e98fbd6350a03b85442a3d9b40ff7aac810264 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 13:34:05 +0200 Subject: [PATCH 13/94] [feature/passwords] Add driver helper class for additional functions Functions for the helper class might be used in other drivers as well and therefore shouldn't be limited to just one driver. PHPBB3-11610 --- phpBB/includes/crypto/driver/base.php | 4 +++ phpBB/includes/crypto/driver/salted_md5.php | 31 +++------------------ tests/crypto/manager_test.php | 2 +- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/phpBB/includes/crypto/driver/base.php b/phpBB/includes/crypto/driver/base.php index c913767989..c134122174 100644 --- a/phpBB/includes/crypto/driver/base.php +++ b/phpBB/includes/crypto/driver/base.php @@ -23,6 +23,9 @@ abstract class phpbb_crypto_driver_base implements phpbb_crypto_driver_interface /** @var phpbb_config */ protected $config; + /** @var phpbb_crypto_driver_helper */ + protected $helper; + /** * Constructor of crypto driver object * @@ -31,6 +34,7 @@ abstract class phpbb_crypto_driver_base implements phpbb_crypto_driver_interface public function __construct(phpbb_config $config) { $this->config = $config; + $this->helper = new phpbb_crypto_driver_helper($this); } /** diff --git a/phpBB/includes/crypto/driver/salted_md5.php b/phpBB/includes/crypto/driver/salted_md5.php index 30b510b8dc..8e1c8a0d05 100644 --- a/phpBB/includes/crypto/driver/salted_md5.php +++ b/phpBB/includes/crypto/driver/salted_md5.php @@ -68,7 +68,7 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base while (--$settings['count']); $output = $settings['full']; - $output .= _hash_encode64($hash, 16, $this->itoa); + $output .= $this->helper->hash_encode64($hash, 16, $this->itoa); if (strlen($output) == 34) { @@ -97,28 +97,6 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base return false; } - /** - * Return unique id - * @param string $extra additional entropy - */ - protected function unique_id($extra = 'c') - { - static $dss_seeded = false; - - $val = $this->config['rand_seed'] . microtime(); - $val = md5($val); - $this->config['rand_seed'] = md5($this->config['rand_seed'] . $val . $extra); - - if ($dss_seeded !== true && ($this->config['rand_seed_last_update'] < time() - rand(1,10))) - { - set_config('rand_seed_last_update', time(), true); - set_config('rand_seed', $this->config['rand_seed'], true); - $dss_seeded = true; - } - - return substr($val, 4, 16); - } - /** * Generate salt for hashing method * @@ -139,11 +117,11 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base if (strlen($random) < $count) { $random = ''; - $random_state = unique_id(); + $random_state = $this->helper->unique_id(); for ($i = 0; $i < $count; $i += 16) { - $random_state = md5(unique_id() . $random_state); + $random_state = md5($this->helper->unique_id() . $random_state); $random .= pack('H*', md5($random_state)); } $random = substr($random, 0, $count); @@ -151,8 +129,7 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base $salt = '$H$'; $salt .= $this->itoa[min($count + 5, 30)]; - $salt .= _hash_encode64($random, 6, $this->itoa); - var_dump($salt); + $salt .= $this->helper->hash_encode64($random, 6, $this->itoa); return $salt; } diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index ce6ac1684f..b2f2862e5f 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -48,7 +48,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase array('', '2y', 60), array('crypto.driver.bcrypt_2y', '2y', 60), array('crypto.driver.bcrypt', '2a', 60), - //array('crypto.driver.salted_md5', '$H$', 45), + array('crypto.driver.salted_md5', 'H', 34), ); } From 33725f6e2f4f77396aef2d17cc3762e9ad5f936c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 13:40:14 +0200 Subject: [PATCH 14/94] [feature/passwords] Include driver helper in manager_test PHPBB3-11610 --- tests/crypto/manager_test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index b2f2862e5f..b5957d5f85 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -11,6 +11,7 @@ require_once dirname(__FILE__) . '/../mock/container_builder.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/bcrypt.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/bcrypt_2y.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/salted_md5.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/helper.php'; class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { From 5574b2a8e995b998910689fe7cb5b44c54cff0c7 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 13:43:57 +0200 Subject: [PATCH 15/94] [feature/passwords] Add driver helper class file PHPBB3-11610 --- phpBB/includes/crypto/driver/helper.php | 108 ++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 phpBB/includes/crypto/driver/helper.php diff --git a/phpBB/includes/crypto/driver/helper.php b/phpBB/includes/crypto/driver/helper.php new file mode 100644 index 0000000000..2931058629 --- /dev/null +++ b/phpBB/includes/crypto/driver/helper.php @@ -0,0 +1,108 @@ +driver = $driver; + } + + /** + * Base64 encode hash + * + * @param string $input Input string + * @param int $count Input string length + * @param string $itoa64 Allowed characters string + * + * @return string base64 encoded string + */ + public function hash_encode64($input, $count, &$itoa64) + { + $output = ''; + $i = 0; + + do + { + $value = ord($input[$i++]); + $output .= $itoa64[$value & 0x3f]; + + if ($i < $count) + { + $value |= ord($input[$i]) << 8; + } + + $output .= $itoa64[($value >> 6) & 0x3f]; + + if ($i++ >= $count) + { + break; + } + + if ($i < $count) + { + $value |= ord($input[$i]) << 16; + } + + $output .= $itoa64[($value >> 12) & 0x3f]; + + if ($i++ >= $count) + { + break; + } + + $output .= $itoa64[($value >> 18) & 0x3f]; + } + while ($i < $count); + + return $output; + } + + /** + * Return unique id + * @param string $extra additional entropy + * + * @return string Unique id + */ + public function unique_id($extra = 'c') + { + static $dss_seeded = false; + global $config; + + $val = $config['rand_seed'] . microtime(); + $val = md5($val); + $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra); + + if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10))) + { + set_config('rand_seed_last_update', time(), true); + set_config('rand_seed', $config['rand_seed'], true); + $dss_seeded = true; + } + + return substr($val, 4, 16); + } +} From 3f70699aa378cce091c441bb4c06c38866ff10a9 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 16:25:03 +0200 Subject: [PATCH 16/94] [feature/passwords] Use common salt generation function for all types We will be using the same method inside the driver helper class for all hash types. This is the same function that has been used for the salted md5 hash of phpBB 3.0. PHPBB3-11610 --- phpBB/includes/crypto/driver/bcrypt.php | 2 +- phpBB/includes/crypto/driver/helper.php | 47 ++++++++++++++++++--- phpBB/includes/crypto/driver/salted_md5.php | 29 +++---------- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/includes/crypto/driver/bcrypt.php index 82ff2fb844..d98bf8c940 100644 --- a/phpBB/includes/crypto/driver/bcrypt.php +++ b/phpBB/includes/crypto/driver/bcrypt.php @@ -81,6 +81,6 @@ class phpbb_crypto_driver_bcrypt extends phpbb_crypto_driver_base */ protected function get_random_salt() { - return substr(str_replace('+', '.', bin2hex(openssl_random_pseudo_bytes(22))), 0, 22); + return $this->helper->hash_encode64($this->helper->get_random_salt(22), 22); } } diff --git a/phpBB/includes/crypto/driver/helper.php b/phpBB/includes/crypto/driver/helper.php index 2931058629..3eafdf1ecc 100644 --- a/phpBB/includes/crypto/driver/helper.php +++ b/phpBB/includes/crypto/driver/helper.php @@ -23,6 +23,12 @@ class phpbb_crypto_driver_helper /** @var phpbb_config */ protected $driver; + /** + * base64 alphabet + * @var string + */ + public $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + /** * Constructor of crypto driver helper object */ @@ -36,11 +42,10 @@ class phpbb_crypto_driver_helper * * @param string $input Input string * @param int $count Input string length - * @param string $itoa64 Allowed characters string * * @return string base64 encoded string */ - public function hash_encode64($input, $count, &$itoa64) + public function hash_encode64($input, $count) { $output = ''; $i = 0; @@ -48,14 +53,14 @@ class phpbb_crypto_driver_helper do { $value = ord($input[$i++]); - $output .= $itoa64[$value & 0x3f]; + $output .= $this->itoa64[$value & 0x3f]; if ($i < $count) { $value |= ord($input[$i]) << 8; } - $output .= $itoa64[($value >> 6) & 0x3f]; + $output .= $this->itoa64[($value >> 6) & 0x3f]; if ($i++ >= $count) { @@ -67,14 +72,14 @@ class phpbb_crypto_driver_helper $value |= ord($input[$i]) << 16; } - $output .= $itoa64[($value >> 12) & 0x3f]; + $output .= $this->itoa64[($value >> 12) & 0x3f]; if ($i++ >= $count) { break; } - $output .= $itoa64[($value >> 18) & 0x3f]; + $output .= $this->itoa64[($value >> 18) & 0x3f]; } while ($i < $count); @@ -105,4 +110,34 @@ class phpbb_crypto_driver_helper return substr($val, 4, 16); } + + /** + * Get random salt with specified length + * + * @param int $length Salt length + */ + public function get_random_salt($length) + { + $random = ''; + + if (($fh = @fopen('/dev/urandom', 'rb'))) + { + $random = fread($fh, $length); + fclose($fh); + } + + if (strlen($random) < $length) + { + $random = ''; + $random_state = $this->helper->unique_id(); + + for ($i = 0; $i < $length; $i += 16) + { + $random_state = md5($this->helper->unique_id() . $random_state); + $random .= pack('H*', md5($random_state)); + } + $random = substr($random, 0, $length); + } + return $random; + } } diff --git a/phpBB/includes/crypto/driver/salted_md5.php b/phpBB/includes/crypto/driver/salted_md5.php index 8e1c8a0d05..1bb7a17afc 100644 --- a/phpBB/includes/crypto/driver/salted_md5.php +++ b/phpBB/includes/crypto/driver/salted_md5.php @@ -20,8 +20,6 @@ if (!defined('IN_PHPBB')) */ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base { - protected $itoa = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - const PREFIX = '$H$'; /** @@ -68,7 +66,7 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base while (--$settings['count']); $output = $settings['full']; - $output .= $this->helper->hash_encode64($hash, 16, $this->itoa); + $output .= $this->helper->hash_encode64($hash, 16); if (strlen($output) == 34) { @@ -108,28 +106,11 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base $random = ''; $count = 6; - if (($fh = @fopen('/dev/urandom', 'rb'))) - { - $random = fread($fh, $count); - fclose($fh); - } - - if (strlen($random) < $count) - { - $random = ''; - $random_state = $this->helper->unique_id(); - - for ($i = 0; $i < $count; $i += 16) - { - $random_state = md5($this->helper->unique_id() . $random_state); - $random .= pack('H*', md5($random_state)); - } - $random = substr($random, 0, $count); - } + $random = $this->helper->get_random_salt($count); $salt = '$H$'; - $salt .= $this->itoa[min($count + 5, 30)]; - $salt .= $this->helper->hash_encode64($random, 6, $this->itoa); + $salt .= $this->helper->itoa64[min($count + 5, 30)]; + $salt .= $this->helper->hash_encode64($random, $count); return $salt; } @@ -146,7 +127,7 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base { return false; } - $count_log2 = strpos($this->itoa, $hash[3]); + $count_log2 = strpos($this->helper->itoa64, $hash[3]); $salt = substr($hash, 4, 8); if ($count_log2 < 7 || $count_log2 > 30 || strlen($salt) != 8) From 13d25e6a327728fc5bc28759ffe9f2248f6cb9a0 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 16:35:27 +0200 Subject: [PATCH 17/94] [feature/passwords] Fix tests for PHP version < 5.3.7 PHPBB3-11610 --- tests/crypto/manager_test.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index b5957d5f85..eb1a0eeed3 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -45,12 +45,24 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase public function hash_password_data() { - return array( - array('', '2y', 60), - array('crypto.driver.bcrypt_2y', '2y', 60), - array('crypto.driver.bcrypt', '2a', 60), - array('crypto.driver.salted_md5', 'H', 34), - ); + if (version_compare(PHP_VERSION, '5.3.7', '<')) + { + return array( + array('', '2a', 60), + array('crypto.driver.bcrypt_2y', '2a', 60), + array('crypto.driver.bcrypt', '2a', 60), + array('crypto.driver.salted_md5', 'H', 34), + ); + } + else + { + return array( + array('', '2y', 60), + array('crypto.driver.bcrypt_2y', '2y', 60), + array('crypto.driver.bcrypt', '2a', 60), + array('crypto.driver.salted_md5', 'H', 34), + ); + } } /** From e7b3daeb292d3066b12d8e699d0a64b5a165d36a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 15 Jun 2013 17:56:29 +0200 Subject: [PATCH 18/94] [feature/passwords] Add tests for manager check_hash() method Tests cover all supported hashing algorithms. PHPBB3-11610 --- tests/crypto/manager_test.php | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index eb1a0eeed3..a6172c52b1 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -11,6 +11,7 @@ require_once dirname(__FILE__) . '/../mock/container_builder.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/bcrypt.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/bcrypt_2y.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/salted_md5.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/phpass.php'; require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/helper.php'; class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase @@ -29,6 +30,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase 'crypto.driver.bcrypt' => new phpbb_crypto_driver_bcrypt($config), 'crypto.driver.bcrypt_2y' => new phpbb_crypto_driver_bcrypt_2y($config), 'crypto.driver.salted_md5' => new phpbb_crypto_driver_salted_md5($config), + 'crypto.driver.phpass' => new phpbb_crypto_driver_phpass($config), ); foreach ($crypto_drivers as $key => $driver) @@ -75,4 +77,42 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase $this->assertEquals($prefix, $match[1]); $this->assertEquals($length, strlen($hash)); } + + public function check_password_data() + { + if (version_compare(PHP_VERSION, '5.3.7', '<')) + { + return array( + array('foobar', 'crypto.driver.bcrypt'), + array('foobar', 'crypto.driver.salted_md5'), + array('barfoo', 'crypto.driver.phpass'), + ); + } + else + { + return array( + array('foobar', 'crypto.driver.bcrypt_2y'), + array('barfoo', 'crypto.driver.bcrypt'), + array('foobar', 'crypto.driver.salted_md5'), + array('barfoo', 'crypto.driver.phpass'), + ); + } + } + + /** + * @dataProvider check_password_data + */ + public function test_check_password($password, $hash_type) + { + $hash = $this->manager->hash_password($password, $hash_type); + $test_word = $password; + $time = microtime(true); + + // Limit each test to 3 seconds + while ((microtime(true) - $time) < 3) + { + $this->assertEquals($test_word === $password, $this->manager->check_hash($test_word, $hash)); + $test_word = str_shuffle($test_word); + } + } } From 7ddf004489879aa0cc21fcd69225ab78ef472d50 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 16 Jun 2013 21:30:47 +0200 Subject: [PATCH 19/94] [feature/passwords] Make method get_hashing_algorithm() protected There is currently no use for it being public. PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 93b99743d1..d2cb1b5029 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -109,7 +109,7 @@ class phpbb_crypto_manager * * @throws RunTimeException If hash type is not supported */ - public function get_hashing_algorithm($hash) + protected function get_hashing_algorithm($hash) { // preg_match() will also show hashing algos like $2a\H$, which // is a combination of bcrypt and phpass From 4b81b93d102b1657ab59cbc98cfa5c1d66d94304 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 16 Jun 2013 23:55:33 +0200 Subject: [PATCH 20/94] [feature/passwords] Make sure hash has the required length Also added tests to make sure that crypto drivers are enforcing the hash length. PHPBB3-11610 --- phpBB/includes/crypto/driver/bcrypt.php | 4 ++++ tests/crypto/manager_test.php | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/includes/crypto/driver/bcrypt.php index d98bf8c940..c6334d1779 100644 --- a/phpBB/includes/crypto/driver/bcrypt.php +++ b/phpBB/includes/crypto/driver/bcrypt.php @@ -53,6 +53,10 @@ class phpbb_crypto_driver_bcrypt extends phpbb_crypto_driver_base } $hash = crypt($password, $salt); + if (strlen($hash) < 60) + { + return false; + } return $hash; } diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index a6172c52b1..36ea277602 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -16,6 +16,8 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/helper.php class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { + protected $crypto_drivers; + public function setUp() { global $phpbb_root_path, $phpEx; @@ -26,14 +28,14 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase // Prepare dependencies for manager and driver $config = new phpbb_config(array()); - $crypto_drivers = array( + $this->crypto_drivers = array( 'crypto.driver.bcrypt' => new phpbb_crypto_driver_bcrypt($config), 'crypto.driver.bcrypt_2y' => new phpbb_crypto_driver_bcrypt_2y($config), 'crypto.driver.salted_md5' => new phpbb_crypto_driver_salted_md5($config), 'crypto.driver.phpass' => new phpbb_crypto_driver_phpass($config), ); - foreach ($crypto_drivers as $key => $driver) + foreach ($this->crypto_drivers as $key => $driver) { $this->phpbb_container->set($key, $driver); } @@ -42,7 +44,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase $config['allow_avatar_' . get_class($this->avatar_barfoo)] = false; */ // Set up avatar manager - $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $crypto_drivers); + $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $this->crypto_drivers); } public function hash_password_data() @@ -115,4 +117,12 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase $test_word = str_shuffle($test_word); } } + + public function test_hash_password_length() + { + foreach ($this->crypto_drivers as $driver) + { + $this->assertEquals(false, $driver->hash('foobar', 'foobar')); + } + } } From dae4327cfcd0908dc751f47cbbc462df454d153c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 17 Jun 2013 23:04:22 +0200 Subject: [PATCH 21/94] [feature/passwords] Add schema changes for new hash types PHPBB3-11610 --- phpBB/develop/create_schema_files.php | 2 +- .../includes/db/migration/data/310/crypto.php | 63 +++++++++++++++++++ phpBB/install/schemas/firebird_schema.sql | 2 +- phpBB/install/schemas/mssql_schema.sql | 2 +- phpBB/install/schemas/mysql_40_schema.sql | 2 +- phpBB/install/schemas/mysql_41_schema.sql | 2 +- phpBB/install/schemas/oracle_schema.sql | 4 +- phpBB/install/schemas/postgres_schema.sql | 2 +- phpBB/install/schemas/sqlite_schema.sql | 2 +- 9 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 phpBB/includes/db/migration/data/310/crypto.php diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 316fbe19e6..91201e7a9d 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -1862,7 +1862,7 @@ function get_schema_struct() 'user_regdate' => array('TIMESTAMP', 0), 'username' => array('VCHAR_CI', ''), 'username_clean' => array('VCHAR_CI', ''), - 'user_password' => array('VCHAR_UNI:40', ''), + 'user_password' => array('VCHAR_CI', ''), 'user_passchg' => array('TIMESTAMP', 0), 'user_pass_convert' => array('BOOL', 0), 'user_email' => array('VCHAR_UNI:100', ''), diff --git a/phpBB/includes/db/migration/data/310/crypto.php b/phpBB/includes/db/migration/data/310/crypto.php new file mode 100644 index 0000000000..c8ac8360ad --- /dev/null +++ b/phpBB/includes/db/migration/data/310/crypto.php @@ -0,0 +1,63 @@ +db->sql_return_on_error(true); + // Set user_password to 64 character long string + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_password = '" . md5('foobar') . md5('foobar') . "' + WHERE user_id = '" . ANONYMOUS . "'"; + $this->db->sql_query($sql); + $this->db->sql_return_on_error(false); + + if ($this->db->sql_affectedrows()) + { + $ret = true; + } + + // Reset user password + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_password = '' + WHERE user_id = '" . ANONYMOUS . "'"; + $this->db->sql_query($sql); + + return $ret; + } + + static public function depends_on() + { + return array('phpbb_db_migration_data_30x_3_0_11'); + } + + public function update_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:255', ''), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:40', ''), + ), + ), + ); + } +} diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index ca68ea387d..73bdfe777c 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -1344,7 +1344,7 @@ CREATE TABLE phpbb_users ( user_regdate INTEGER DEFAULT 0 NOT NULL, username VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, username_clean VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - user_password VARCHAR(40) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, + user_password VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, user_passchg INTEGER DEFAULT 0 NOT NULL, user_pass_convert INTEGER DEFAULT 0 NOT NULL, user_email VARCHAR(100) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index a2a6d2192c..cbf824ce8d 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -1644,7 +1644,7 @@ CREATE TABLE [phpbb_users] ( [user_regdate] [int] DEFAULT (0) NOT NULL , [username] [varchar] (255) DEFAULT ('') NOT NULL , [username_clean] [varchar] (255) DEFAULT ('') NOT NULL , - [user_password] [varchar] (40) DEFAULT ('') NOT NULL , + [user_password] [varchar] (255) DEFAULT ('') NOT NULL , [user_passchg] [int] DEFAULT (0) NOT NULL , [user_pass_convert] [int] DEFAULT (0) NOT NULL , [user_email] [varchar] (100) DEFAULT ('') NOT NULL , diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 2c5931bae4..6d487335bb 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -954,7 +954,7 @@ CREATE TABLE phpbb_users ( user_regdate int(11) UNSIGNED DEFAULT '0' NOT NULL, username blob NOT NULL, username_clean blob NOT NULL, - user_password varbinary(120) DEFAULT '' NOT NULL, + user_password blob DEFAULT '' NOT NULL, user_passchg int(11) UNSIGNED DEFAULT '0' NOT NULL, user_pass_convert tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, user_email blob NOT NULL, diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 7b7be3c462..5b64027d4e 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -954,7 +954,7 @@ CREATE TABLE phpbb_users ( user_regdate int(11) UNSIGNED DEFAULT '0' NOT NULL, username varchar(255) DEFAULT '' NOT NULL, username_clean varchar(255) DEFAULT '' NOT NULL, - user_password varchar(40) DEFAULT '' NOT NULL, + user_password varchar(255) DEFAULT '' NOT NULL, user_passchg int(11) UNSIGNED DEFAULT '0' NOT NULL, user_pass_convert tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, user_email varchar(100) DEFAULT '' NOT NULL, diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index 75c01446d8..598910c143 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -958,7 +958,7 @@ CREATE TABLE phpbb_poll_votes ( topic_id number(8) DEFAULT '0' NOT NULL, poll_option_id number(4) DEFAULT '0' NOT NULL, vote_user_id number(8) DEFAULT '0' NOT NULL, - vote_user_ip varchar2(40) DEFAULT '' + vote_user_ip varchar2(40) DEFAULT '' ) / @@ -1770,7 +1770,7 @@ CREATE TABLE phpbb_users ( user_regdate number(11) DEFAULT '0' NOT NULL, username varchar2(255) DEFAULT '' , username_clean varchar2(255) DEFAULT '' , - user_password varchar2(120) DEFAULT '' , + user_password varchar2(255) DEFAULT '' , user_passchg number(11) DEFAULT '0' NOT NULL, user_pass_convert number(1) DEFAULT '0' NOT NULL, user_email varchar2(300) DEFAULT '' , diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index c7fbe9a507..fe90befb72 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -1222,7 +1222,7 @@ CREATE TABLE phpbb_users ( user_regdate INT4 DEFAULT '0' NOT NULL CHECK (user_regdate >= 0), username varchar_ci DEFAULT '' NOT NULL, username_clean varchar_ci DEFAULT '' NOT NULL, - user_password varchar(40) DEFAULT '' NOT NULL, + user_password varchar_ci DEFAULT '' NOT NULL, user_passchg INT4 DEFAULT '0' NOT NULL CHECK (user_passchg >= 0), user_pass_convert INT2 DEFAULT '0' NOT NULL CHECK (user_pass_convert >= 0), user_email varchar(100) DEFAULT '' NOT NULL, diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 72b2b276da..6224a37df4 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -925,7 +925,7 @@ CREATE TABLE phpbb_users ( user_regdate INTEGER UNSIGNED NOT NULL DEFAULT '0', username varchar(255) NOT NULL DEFAULT '', username_clean varchar(255) NOT NULL DEFAULT '', - user_password varchar(40) NOT NULL DEFAULT '', + user_password varchar(255) NOT NULL DEFAULT '', user_passchg INTEGER UNSIGNED NOT NULL DEFAULT '0', user_pass_convert INTEGER UNSIGNED NOT NULL DEFAULT '0', user_email varchar(100) NOT NULL DEFAULT '', From 857b90057b6b613c844b0358340f452cd8174df5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:20:47 +0200 Subject: [PATCH 22/94] [feature/passwords] Add method for obtaining the hash settings only This is needed for combined hashing of passwords. PHPBB3-11610 --- phpBB/includes/crypto/driver/bcrypt.php | 18 ++++++++++++++++++ phpBB/includes/crypto/driver/interface.php | 12 ++++++++++++ phpBB/includes/crypto/driver/salted_md5.php | 8 ++++++++ 3 files changed, 38 insertions(+) diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/includes/crypto/driver/bcrypt.php index c6334d1779..ad5a8036c3 100644 --- a/phpBB/includes/crypto/driver/bcrypt.php +++ b/phpBB/includes/crypto/driver/bcrypt.php @@ -87,4 +87,22 @@ class phpbb_crypto_driver_bcrypt extends phpbb_crypto_driver_base { return $this->helper->hash_encode64($this->helper->get_random_salt(22), 22); } + + /** + * @inheritdoc + */ + public function get_settings_only($hash, $full = false) + { + if ($full) + { + $pos = stripos($hash, '$', 1) + 1; + $length = 22 + (strripos($hash, '$') + 1 - $pos); + } + else + { + $pos = strripos($hash, '$') + 1; + $length = 22; + } + return substr($hash, $pos, $length); + } } diff --git a/phpBB/includes/crypto/driver/interface.php b/phpBB/includes/crypto/driver/interface.php index b8383bda5a..9686aa33de 100644 --- a/phpBB/includes/crypto/driver/interface.php +++ b/phpBB/includes/crypto/driver/interface.php @@ -50,7 +50,19 @@ interface phpbb_crypto_driver_interface /** * Check the password against the supplied hash * + * @param string $password The password to check + * @param string $hash The password hash to check against * @return bool True if password is correct, else false */ public function check($password, $hash); + + /** + * Get only the settings of the specified hash + * + * @param string $hash Password hash + * @param bool $full Return full settings or only settings + * related to the salt + * @return string String containing the hash settings + */ + public function get_settings_only($hash, $full = false); } diff --git a/phpBB/includes/crypto/driver/salted_md5.php b/phpBB/includes/crypto/driver/salted_md5.php index 1bb7a17afc..26331e9a5b 100644 --- a/phpBB/includes/crypto/driver/salted_md5.php +++ b/phpBB/includes/crypto/driver/salted_md5.php @@ -141,4 +141,12 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base 'full' => substr($hash, 0, 12), ); } + + /** + * @inheritdoc + */ + public function get_settings_only($hash, $full = false) + { + return substr($hash, 3, 9); + } } From e4a5aacf2a6a7177604b9e4ecd61292fab192fba Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:21:59 +0200 Subject: [PATCH 23/94] [feature/passwords] Use correct prefix for salt in salted_md5 PHPBB3-11610 --- phpBB/includes/crypto/driver/salted_md5.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/driver/salted_md5.php b/phpBB/includes/crypto/driver/salted_md5.php index 26331e9a5b..76bbdccbc4 100644 --- a/phpBB/includes/crypto/driver/salted_md5.php +++ b/phpBB/includes/crypto/driver/salted_md5.php @@ -108,7 +108,7 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base $random = $this->helper->get_random_salt($count); - $salt = '$H$'; + $salt = $this->get_prefix(); $salt .= $this->helper->itoa64[min($count + 5, 30)]; $salt .= $this->helper->hash_encode64($random, $count); From ab068799b1eb2039840d3fba2563a0203a5dd4ba Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:23:20 +0200 Subject: [PATCH 24/94] [feature/passwords] Pass phpbb_container to passwords helper PHPBB3-11610 --- phpBB/includes/crypto/helper.php | 9 ++++++++- phpBB/includes/crypto/manager.php | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/crypto/helper.php b/phpBB/includes/crypto/helper.php index 3021bef2c1..3db126d3b1 100644 --- a/phpBB/includes/crypto/helper.php +++ b/phpBB/includes/crypto/helper.php @@ -25,14 +25,21 @@ class phpbb_crypto_helper */ protected $manager; + /** + * @var phpbb_container + */ + protected $container; + /** * Construct a phpbb_crypto_helper object * * @param phpbb_crypto_manager $manager Crypto manager object + * @param phpbb_container $container phpBB container object */ - public function __construct($manager) + public function __construct($manager, $container) { $this->manager = $manager; + $this->container = $container; } /** diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index d2cb1b5029..6f1aed25be 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -96,7 +96,7 @@ class phpbb_crypto_manager { if ($this->helper === NULL) { - $this->helper = new phpbb_crypto_helper($this); + $this->helper = new phpbb_crypto_helper($this, $this->container); } } From 16e5d0dc350fbeb15bf662757dba21bd0e729e8c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:25:50 +0200 Subject: [PATCH 25/94] [feature/passwords] Fix minor code limitations in helper These limitations caused it to only allow a specific input to combined hashes. PHPBB3-11610 --- phpBB/includes/crypto/helper.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/crypto/helper.php b/phpBB/includes/crypto/helper.php index 3db126d3b1..a65cacc73a 100644 --- a/phpBB/includes/crypto/helper.php +++ b/phpBB/includes/crypto/helper.php @@ -55,7 +55,8 @@ class phpbb_crypto_helper { preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); $hash_settings = substr($hash, strpos($hash, $match[1]) + strlen($match[1]) + 1); - foreach ($match as $cur_type) + $matches = explode('\\', $match[1]); + foreach ($matches as $cur_type) { $dollar_position = strpos($hash_settings, '$'); $output[] = substr($hash_settings, 0, ($dollar_position != false) ? $dollar_position : strlen($hash_settings)); @@ -112,7 +113,7 @@ class phpbb_crypto_helper if ($type == 'prefix') { $data[$type] .= ($data[$type] !== '$') ? '\\' : ''; - $data[$type] .= $value; + $data[$type] .= str_replace('$', '', $value); } elseif ($type == 'settings') { From c67f7dba60631c9e1d0f58a32e866c783fe7216b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:27:11 +0200 Subject: [PATCH 26/94] [feature/passwords] Add function for obtaining only the hash to helper This is also needed for combined hashing of passwords. PHPBB3-11610 --- phpBB/includes/crypto/helper.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/phpBB/includes/crypto/helper.php b/phpBB/includes/crypto/helper.php index a65cacc73a..0871738d56 100644 --- a/phpBB/includes/crypto/helper.php +++ b/phpBB/includes/crypto/helper.php @@ -145,4 +145,15 @@ class phpbb_crypto_helper $rebuilt_hash .= $settings; return $rebuilt_hash; } + + /** + * Obtain only the actual hash after the prefixes + * + * @param string $hash The full password hash + * @return string Actual hash (incl. settings) + */ + protected function obtain_hash_only($hash) + { + return substr($hash, strripos($hash, '$') + 1); + } } From dc76146cefd6fd26f2325bb86b17e1266bc2ccc0 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:28:06 +0200 Subject: [PATCH 27/94] [feature/passwords] Add combined hashing method to helper This will allow to hash a previously hashed password with another hashing method, i.e. as upgrade path from phpBB 3.0 to 3.1. PHPBB3-11610 --- phpBB/includes/crypto/helper.php | 35 +++++++++++++++++++++++++++++++ phpBB/includes/crypto/manager.php | 5 +++++ 2 files changed, 40 insertions(+) diff --git a/phpBB/includes/crypto/helper.php b/phpBB/includes/crypto/helper.php index 0871738d56..9c802b3c01 100644 --- a/phpBB/includes/crypto/helper.php +++ b/phpBB/includes/crypto/helper.php @@ -66,6 +66,41 @@ class phpbb_crypto_helper return $output; } + /** + * Create combined hash from already hashed password + * + * @param string $password_hash Complete current password hash + * @param string $type Type of the hashing algorithm the password hash + * should be combined with + * @return string|bool Combined password hash if combined hashing was + * successful, else false + */ + public function combined_hash_password($password_hash, $type) + { + $data = array( + 'prefix' => '$', + 'settings' => '$', + ); + $hash_settings = $this->get_combined_hash_settings($password_hash); + $hash = $hash_settings[0]; + + // Put settings of current hash into data array + $stored_hash_type = $this->manager->get_hashing_algorithm($password_hash); + $this->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix()); + $this->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash)); + + // Hash current hash with the defined types + foreach ($type as $cur_type) + { + $new_hash_type = $this->container->get($cur_type); + $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash)); + $this->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix()); + $this->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0)); + $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->obtain_hash_only($new_hash)); + } + return $this->combine_hash_output($data, 'hash', $hash); + } + /** * Check combined password hash against the supplied password * diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 6f1aed25be..bbb844adab 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -163,6 +163,11 @@ class phpbb_crypto_manager { $type = ($type === '') ? $this->type : $type; + if (is_array($type)) + { + return $this->helper->combined_hash_password($password, $type); + } + $hashing_algorithm = $this->container->get($type); // Do not support 8-bit characters with $2a$ bcrypt if ($type === 'crypto.driver.bcrypt' || ($type === 'crypto.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) From 6f33ca85a23a53a7c50d2cfb44a60da9b0b4d02f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:29:23 +0200 Subject: [PATCH 28/94] [feature/passwords] Add tests for combined hashing of passwords PHPBB3-11610 --- tests/crypto/manager_test.php | 41 +++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index 36ea277602..d0ca96e324 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -110,8 +110,8 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase $test_word = $password; $time = microtime(true); - // Limit each test to 3 seconds - while ((microtime(true) - $time) < 3) + // Limit each test to 1 second + while ((microtime(true) - $time) < 1) { $this->assertEquals($test_word === $password, $this->manager->check_hash($test_word, $hash)); $test_word = str_shuffle($test_word); @@ -125,4 +125,41 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase $this->assertEquals(false, $driver->hash('foobar', 'foobar')); } } + + public function test_combined_hash_data() + { + return array( + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), + ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt'), + ), + array( + 'crypto.driver.phpass', + array('crypto.driver.salted_md5'), + ), + ); + } + + /** + * @dataProvider test_combined_hash_data + */ + public function test_combined_hash_password($first_type, $second_type) + { + $password = 'foobar'; + $test_word = $password; + $hash = $this->manager->hash_password($password, $first_type); + $combined_hash = $this->manager->hash_password($hash, $second_type); + + $time = microtime(true); + // Limit each test to 1 second + while ((microtime(true) - $time) < 1) + { + $this->assertEquals(($test_word === $password), $this->manager->check_hash($test_word, $combined_hash)); + $test_word = str_shuffle($test_word); + } + } } From 556048177fa25df140f3126f46fb541ec4b0ac8b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 14:30:48 +0200 Subject: [PATCH 29/94] [feature/passwords] Make method get_hashing_public_algorithm public Combined hashing requires it for checking the supplied password hash for its hashing algorithm. PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index bbb844adab..d54f612443 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -109,7 +109,7 @@ class phpbb_crypto_manager * * @throws RunTimeException If hash type is not supported */ - protected function get_hashing_algorithm($hash) + public function get_hashing_algorithm($hash) { // preg_match() will also show hashing algos like $2a\H$, which // is a combination of bcrypt and phpass From cfbd858bd734a45394b1faa05f202a906653bf03 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 27 Jun 2013 16:14:08 +0200 Subject: [PATCH 30/94] [feature/passwords] Properly treat duplicates in combined hashes PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 4 ++++ tests/crypto/manager_test.php | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index d54f612443..b57c6ce9a0 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -129,6 +129,10 @@ class phpbb_crypto_manager { if (isset($this->type_map["\${$type}\$"])) { + while(isset($return_ary[$type])) + { + $type = $type + ' '; + } $return_ary[$type] = $this->type_map["\${$type}\$"]; } else diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index d0ca96e324..9b14383f5d 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -131,7 +131,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase return array( array( 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), + array('crypto.driver.bcrypt_2y'), ), array( 'crypto.driver.salted_md5', @@ -141,6 +141,10 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase 'crypto.driver.phpass', array('crypto.driver.salted_md5'), ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), + ), ); } From ddc207fae83ad260f592c6a99c83971263e7eb5a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jun 2013 00:04:02 +0200 Subject: [PATCH 31/94] [feature/passwords] Fix tests on PHP versions < 5.3.7 PHPBB3-11610 --- tests/crypto/manager_test.php | 56 ++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index 9b14383f5d..f2eb9a160b 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -128,24 +128,44 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase public function test_combined_hash_data() { - return array( - array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt_2y'), - ), - array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt'), - ), - array( - 'crypto.driver.phpass', - array('crypto.driver.salted_md5'), - ), - array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), - ), - ); + if (version_compare(PHP_VERSION, '5.3.7', '<')) + { + return array( + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt'), + ), + array( + 'crypto.driver.phpass', + array('crypto.driver.salted_md5'), + ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.phpass', 'crypto.driver.bcrypt'), + ), + ); + } + else + { + return array( + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt_2y'), + ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt'), + ), + array( + 'crypto.driver.phpass', + array('crypto.driver.salted_md5'), + ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), + ), + ); + } } /** From fcb71308232f8cd121096fe627e020463cd67593 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 29 Jun 2013 18:24:55 +0200 Subject: [PATCH 32/94] [feature/passwords] Use randomly generated password for tests The password will start with 'foobar' and then continue with random characters that will be appended every iteration. PHPBB3-11610 --- tests/crypto/manager_test.php | 64 ++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index f2eb9a160b..17d6e9e420 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -18,6 +18,10 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { protected $crypto_drivers; + protected $pw_characters = '0123456789abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVXYZ.,_!?/\\'; + + protected $default_pw = 'foobar'; + public function setUp() { global $phpbb_root_path, $phpEx; @@ -39,10 +43,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { $this->phpbb_container->set($key, $driver); } -/* - $config['allow_avatar_' . get_class($this->avatar_foobar)] = true; - $config['allow_avatar_' . get_class($this->avatar_barfoo)] = false; -*/ + // Set up avatar manager $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $this->crypto_drivers); } @@ -74,10 +75,18 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase */ public function test_hash_password($type, $prefix, $length) { - $hash = $this->manager->hash_password('foobar', $type); - preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); - $this->assertEquals($prefix, $match[1]); - $this->assertEquals($length, strlen($hash)); + $password = $this->default_pw; + $time = microtime(true); + + // Limit each test to 1 second + while ((microtime(true) - $time) < 1) + { + $hash = $this->manager->hash_password($password, $type); + preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); + $this->assertEquals($prefix, $match[1]); + $this->assertEquals($length, strlen($hash)); + $password .= $this->pw_characters[mt_rand(0, 66)]; + } } public function check_password_data() @@ -85,18 +94,18 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase if (version_compare(PHP_VERSION, '5.3.7', '<')) { return array( - array('foobar', 'crypto.driver.bcrypt'), - array('foobar', 'crypto.driver.salted_md5'), - array('barfoo', 'crypto.driver.phpass'), + array('crypto.driver.bcrypt'), + array('crypto.driver.salted_md5'), + array('crypto.driver.phpass'), ); } else { return array( - array('foobar', 'crypto.driver.bcrypt_2y'), - array('barfoo', 'crypto.driver.bcrypt'), - array('foobar', 'crypto.driver.salted_md5'), - array('barfoo', 'crypto.driver.phpass'), + array('crypto.driver.bcrypt_2y'), + array('crypto.driver.bcrypt'), + array('crypto.driver.salted_md5'), + array('crypto.driver.phpass'), ); } } @@ -104,17 +113,17 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase /** * @dataProvider check_password_data */ - public function test_check_password($password, $hash_type) + public function test_check_password($hash_type) { - $hash = $this->manager->hash_password($password, $hash_type); - $test_word = $password; + $password = $this->default_pw; $time = microtime(true); - // Limit each test to 1 second while ((microtime(true) - $time) < 1) { - $this->assertEquals($test_word === $password, $this->manager->check_hash($test_word, $hash)); - $test_word = str_shuffle($test_word); + $hash = $this->manager->hash_password($password, $hash_type); + $this->assertEquals(true, $this->manager->check_hash($password, $hash)); + $password .= $this->pw_characters[mt_rand(0, 66)]; + $this->assertEquals(false, $this->manager->check_hash($password, $hash)); } } @@ -173,17 +182,16 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase */ public function test_combined_hash_password($first_type, $second_type) { - $password = 'foobar'; - $test_word = $password; - $hash = $this->manager->hash_password($password, $first_type); - $combined_hash = $this->manager->hash_password($hash, $second_type); - + $password = $this->default_pw; $time = microtime(true); // Limit each test to 1 second while ((microtime(true) - $time) < 1) { - $this->assertEquals(($test_word === $password), $this->manager->check_hash($test_word, $combined_hash)); - $test_word = str_shuffle($test_word); + $hash = $this->manager->hash_password($password, $first_type); + $combined_hash = $this->manager->hash_password($hash, $second_type); + $this->assertEquals(true, $this->manager->check_hash($password, $combined_hash)); + $password .= $this->pw_characters[mt_rand(0, 66)]; + $this->assertEquals(false, $this->manager->check_hash($password, $combined_hash)); } } } From 8f863d1d498fb4e3855ca2a3a1b4094d08d876b1 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 5 Jul 2013 23:56:57 +0200 Subject: [PATCH 33/94] [feature/passwords] Do not check if type_map is empty If the type map is empty the service container is incomplete or broken. There is no need to check this as other components would probably be broken at the same time. PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index b57c6ce9a0..26b80087b8 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -75,11 +75,6 @@ class phpbb_crypto_manager */ protected function fill_type_map($hashing_algorithms) { - if ($this->type_map !== false) - { - return; - } - foreach ($hashing_algorithms as $algorithm) { if (!isset($this->type_map[$algorithm->get_prefix()])) @@ -187,12 +182,6 @@ class phpbb_crypto_manager public function check_hash($password, $hash) { - if (!$this->type_map) - { - // This obviously shouldn't happen - return false; - } - // First find out what kind of hash we're dealing with $stored_hash_type = $this->get_hashing_algorithm($hash); if ($stored_hash_type == false) From dbd6d33e9f474fff61c10a374bf6180c84a60940 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 5 Jul 2013 23:59:09 +0200 Subject: [PATCH 34/94] [feature/passwords] NULL should be null according to coding guidelines PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 26b80087b8..6af8cc840e 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -89,7 +89,7 @@ class phpbb_crypto_manager */ protected function load_crypto_helper() { - if ($this->helper === NULL) + if ($this->helper === null) { $this->helper = new phpbb_crypto_helper($this, $this->container); } From a4b0a8ceb9e289980aa13a8990a8e00919325caf Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 6 Jul 2013 00:00:47 +0200 Subject: [PATCH 35/94] [feature/passwords] Do not use specific errors but just return false The authentication system should handle the possible errors for now. Additional error returns can be added later on if they are needed. PHPBB3-11610 --- phpBB/includes/crypto/manager.php | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 6af8cc840e..7f95bcdf60 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -101,17 +101,18 @@ class phpbb_crypto_manager * @param string $hash Password hash that should be checked * * @return object The hash type object - * - * @throws RunTimeException If hash type is not supported */ public function get_hashing_algorithm($hash) { - // preg_match() will also show hashing algos like $2a\H$, which - // is a combination of bcrypt and phpass + /* + * preg_match() will also show hashing algos like $2a\H$, which + * is a combination of bcrypt and phpass. Legacy algorithms + * like md5 will not be matched by this and need to be treated + * differently. + */ if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) { - // Legacy support needed - throw new RunTimeException('NO_LEGACY_SUPPORT'); + return false; } // Be on the lookout for multiple hashing algorithms @@ -124,15 +125,17 @@ class phpbb_crypto_manager { if (isset($this->type_map["\${$type}\$"])) { - while(isset($return_ary[$type])) + // we do not support the same hashing + // algorithm more than once + if (isset($return_ary[$type])) { - $type = $type + ' '; + return false; } $return_ary[$type] = $this->type_map["\${$type}\$"]; } else { - throw new \RunTimeException('HASH_TYPE_NOT_SUPPORTED'); + return false; } } return $return_ary; @@ -143,7 +146,7 @@ class phpbb_crypto_manager } else { - throw new RunTimeException('UNKNOWN_HASH_TYPE'); + return false; } } @@ -155,8 +158,6 @@ class phpbb_crypto_manager * none is supplied * @return string|bool Password hash of supplied password or false if * if something went wrong during hashing - * - * @throws RunTimeException If hash type is not supported */ public function hash_password($password, $type = '') { From b6473a515b4c163171d3cda471ffd348797a0d8f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 6 Jul 2013 00:02:14 +0200 Subject: [PATCH 36/94] [feature/passwords] Increase manager test coverage to cover all methods All methods in the manager are now fully covered. PHPBB3-11610 --- tests/crypto/manager_test.php | 44 +++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index 17d6e9e420..1632159ea7 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -127,6 +127,24 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase } } + + public function check_hash_exceptions_data() + { + return array( + array('foobar', '3858F62230AC3C915F300C664312C63F', false), + array('foobar', '$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false), + array('foobar', '$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false), + ); + } + + /** + * @dataProvider check_hash_exceptions_data + */ + public function test_check_hash_exceptions($password, $hash, $expected) + { + $this->assertEquals($expected, $this->manager->check_hash($password, $hash)); + } + public function test_hash_password_length() { foreach ($this->crypto_drivers as $driver) @@ -135,6 +153,11 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase } } + public function test_hash_password_8bit_bcrypt() + { + $this->assertEquals(false, $this->manager->hash_password('foobar𝄞', 'crypto.driver.bcrypt')); + } + public function test_combined_hash_data() { if (version_compare(PHP_VERSION, '5.3.7', '<')) @@ -152,6 +175,11 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase 'crypto.driver.salted_md5', array('crypto.driver.phpass', 'crypto.driver.bcrypt'), ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.salted_md5'), + false, + ), ); } else @@ -173,6 +201,11 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase 'crypto.driver.salted_md5', array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), ), + array( + 'crypto.driver.salted_md5', + array('crypto.driver.salted_md5'), + false, + ), ); } } @@ -180,7 +213,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase /** * @dataProvider test_combined_hash_data */ - public function test_combined_hash_password($first_type, $second_type) + public function test_combined_hash_password($first_type, $second_type, $expected = true) { $password = $this->default_pw; $time = microtime(true); @@ -189,9 +222,16 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { $hash = $this->manager->hash_password($password, $first_type); $combined_hash = $this->manager->hash_password($hash, $second_type); - $this->assertEquals(true, $this->manager->check_hash($password, $combined_hash)); + $this->assertEquals($expected, $this->manager->check_hash($password, $combined_hash)); $password .= $this->pw_characters[mt_rand(0, 66)]; $this->assertEquals(false, $this->manager->check_hash($password, $combined_hash)); + + // If we are expecting the check to fail then there is + // no need to run this more than once + if (!$expected) + { + break; + } } } } From 05a5ac282d1f62324ac07f91346bf9b08dc203aa Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 6 Jul 2013 00:17:32 +0200 Subject: [PATCH 37/94] [feature/passwords] Fix incorrect call to helper instead of $this The driver helper method unique_id is called inside the helper. Therefore, it shouldn't be called via $this->helper but rather via $this. PHPBB3-11610 --- phpBB/includes/crypto/driver/helper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/crypto/driver/helper.php b/phpBB/includes/crypto/driver/helper.php index 3eafdf1ecc..308ee7dce2 100644 --- a/phpBB/includes/crypto/driver/helper.php +++ b/phpBB/includes/crypto/driver/helper.php @@ -129,11 +129,11 @@ class phpbb_crypto_driver_helper if (strlen($random) < $length) { $random = ''; - $random_state = $this->helper->unique_id(); + $random_state = $this->unique_id(); for ($i = 0; $i < $length; $i += 16) { - $random_state = md5($this->helper->unique_id() . $random_state); + $random_state = md5($this->unique_id() . $random_state); $random .= pack('H*', md5($random_state)); } $random = substr($random, 0, $length); From 3a776ed0afeede830a54ab30c8053325492f2521 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 6 Jul 2013 00:22:31 +0200 Subject: [PATCH 38/94] [feature/passwords] Increase test coverage of salted_md5 driver PHPBB3-11610 --- tests/crypto/manager_test.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index 1632159ea7..41d14bc565 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -134,6 +134,8 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase array('foobar', '3858F62230AC3C915F300C664312C63F', false), array('foobar', '$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false), array('foobar', '$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false), + array('foobar', '$H$kklk938d023k//k3023', false), + array('foobar', '$H$3PtYMgXb39lrIWkgoxYLWtRkZtY3AY/', false), ); } From bd4664807fad02819fb680f827fb1a4411364911 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 6 Jul 2013 00:43:06 +0200 Subject: [PATCH 39/94] [feature/passwords] Increase code coverage in bcrypt driver PHPBB3-11610 --- tests/crypto/manager_test.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index 41d14bc565..df3e51bd75 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -136,6 +136,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase array('foobar', '$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false), array('foobar', '$H$kklk938d023k//k3023', false), array('foobar', '$H$3PtYMgXb39lrIWkgoxYLWtRkZtY3AY/', false), + array('foobar', '$2a$kwiweorurlaeirw', false), ); } From 2e453eb2cb682031d7e521d23c3904c8dfeef70c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 19 Jul 2013 20:14:25 +0200 Subject: [PATCH 40/94] [feature/passwords] Add legacy support for md5 passwords PHPBB3-11610 --- phpBB/includes/crypto/driver/salted_md5.php | 4 ++-- phpBB/includes/crypto/manager.php | 2 +- tests/crypto/manager_test.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpBB/includes/crypto/driver/salted_md5.php b/phpBB/includes/crypto/driver/salted_md5.php index 76bbdccbc4..c5a8345453 100644 --- a/phpBB/includes/crypto/driver/salted_md5.php +++ b/phpBB/includes/crypto/driver/salted_md5.php @@ -82,9 +82,9 @@ class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base */ public function check($password, $hash) { - if (strlen($hash) != 34) + if (strlen($hash) !== 34) { - return false; + return (md5($password) === $hash) ? true : false; } // No need to check prefix, already did that in manage diff --git a/phpBB/includes/crypto/manager.php b/phpBB/includes/crypto/manager.php index 7f95bcdf60..753a86ae84 100644 --- a/phpBB/includes/crypto/manager.php +++ b/phpBB/includes/crypto/manager.php @@ -112,7 +112,7 @@ class phpbb_crypto_manager */ if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) { - return false; + return $this->type_map['$H$']; } // Be on the lookout for multiple hashing algorithms diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index df3e51bd75..2b6e1b311e 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -131,7 +131,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase public function check_hash_exceptions_data() { return array( - array('foobar', '3858F62230AC3C915F300C664312C63F', false), + array('foobar', '3858f62230ac3c915f300c664312c63f', true), array('foobar', '$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false), array('foobar', '$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false), array('foobar', '$H$kklk938d023k//k3023', false), From 9b24fda5cd1f6e85c536dc2bc3e5f1bbdef5b7c2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 19 Jul 2013 20:49:24 +0200 Subject: [PATCH 41/94] [feature/passwords] Move files after namespacing changes PHPBB3-11610 --- phpBB/{includes => phpbb}/crypto/driver/base.php | 0 phpBB/{includes => phpbb}/crypto/driver/bcrypt.php | 0 phpBB/{includes => phpbb}/crypto/driver/bcrypt_2y.php | 0 phpBB/{includes => phpbb}/crypto/driver/helper.php | 0 phpBB/{includes => phpbb}/crypto/driver/interface.php | 0 phpBB/{includes => phpbb}/crypto/driver/phpass.php | 0 phpBB/{includes => phpbb}/crypto/driver/salted_md5.php | 0 phpBB/{includes => phpbb}/crypto/helper.php | 0 phpBB/{includes => phpbb}/crypto/manager.php | 0 tests/crypto/manager_test.php | 10 +++++----- 10 files changed, 5 insertions(+), 5 deletions(-) rename phpBB/{includes => phpbb}/crypto/driver/base.php (100%) rename phpBB/{includes => phpbb}/crypto/driver/bcrypt.php (100%) rename phpBB/{includes => phpbb}/crypto/driver/bcrypt_2y.php (100%) rename phpBB/{includes => phpbb}/crypto/driver/helper.php (100%) rename phpBB/{includes => phpbb}/crypto/driver/interface.php (100%) rename phpBB/{includes => phpbb}/crypto/driver/phpass.php (100%) rename phpBB/{includes => phpbb}/crypto/driver/salted_md5.php (100%) rename phpBB/{includes => phpbb}/crypto/helper.php (100%) rename phpBB/{includes => phpbb}/crypto/manager.php (100%) diff --git a/phpBB/includes/crypto/driver/base.php b/phpBB/phpbb/crypto/driver/base.php similarity index 100% rename from phpBB/includes/crypto/driver/base.php rename to phpBB/phpbb/crypto/driver/base.php diff --git a/phpBB/includes/crypto/driver/bcrypt.php b/phpBB/phpbb/crypto/driver/bcrypt.php similarity index 100% rename from phpBB/includes/crypto/driver/bcrypt.php rename to phpBB/phpbb/crypto/driver/bcrypt.php diff --git a/phpBB/includes/crypto/driver/bcrypt_2y.php b/phpBB/phpbb/crypto/driver/bcrypt_2y.php similarity index 100% rename from phpBB/includes/crypto/driver/bcrypt_2y.php rename to phpBB/phpbb/crypto/driver/bcrypt_2y.php diff --git a/phpBB/includes/crypto/driver/helper.php b/phpBB/phpbb/crypto/driver/helper.php similarity index 100% rename from phpBB/includes/crypto/driver/helper.php rename to phpBB/phpbb/crypto/driver/helper.php diff --git a/phpBB/includes/crypto/driver/interface.php b/phpBB/phpbb/crypto/driver/interface.php similarity index 100% rename from phpBB/includes/crypto/driver/interface.php rename to phpBB/phpbb/crypto/driver/interface.php diff --git a/phpBB/includes/crypto/driver/phpass.php b/phpBB/phpbb/crypto/driver/phpass.php similarity index 100% rename from phpBB/includes/crypto/driver/phpass.php rename to phpBB/phpbb/crypto/driver/phpass.php diff --git a/phpBB/includes/crypto/driver/salted_md5.php b/phpBB/phpbb/crypto/driver/salted_md5.php similarity index 100% rename from phpBB/includes/crypto/driver/salted_md5.php rename to phpBB/phpbb/crypto/driver/salted_md5.php diff --git a/phpBB/includes/crypto/helper.php b/phpBB/phpbb/crypto/helper.php similarity index 100% rename from phpBB/includes/crypto/helper.php rename to phpBB/phpbb/crypto/helper.php diff --git a/phpBB/includes/crypto/manager.php b/phpBB/phpbb/crypto/manager.php similarity index 100% rename from phpBB/includes/crypto/manager.php rename to phpBB/phpbb/crypto/manager.php diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index 2b6e1b311e..ba13c9c8ad 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -8,11 +8,11 @@ */ require_once dirname(__FILE__) . '/../mock/container_builder.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/bcrypt.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/bcrypt_2y.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/salted_md5.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/phpass.php'; -require_once dirname(__FILE__) . '/../../phpBB/includes/crypto/driver/helper.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/bcrypt.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/bcrypt_2y.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/salted_md5.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/phpass.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/helper.php'; class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { From df8e5f4c3c333be677489d2317f6991598a6cebf Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 11 Aug 2013 15:04:25 -0500 Subject: [PATCH 42/94] [feature/passwords] Move migrations file to phpbb folder PHPBB3-11610 --- phpBB/{includes => phpbb}/db/migration/data/310/crypto.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename phpBB/{includes => phpbb}/db/migration/data/310/crypto.php (100%) diff --git a/phpBB/includes/db/migration/data/310/crypto.php b/phpBB/phpbb/db/migration/data/310/crypto.php similarity index 100% rename from phpBB/includes/db/migration/data/310/crypto.php rename to phpBB/phpbb/db/migration/data/310/crypto.php From 58755c4972128923f12cc1511bd24c36912bf890 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 21 Aug 2013 16:31:57 -0500 Subject: [PATCH 43/94] [feature/passwords] Add get_name() method to drivers This will allow us to actually properly differentiate between the available drivers. PHPBB3-11610 --- phpBB/config/crypto.yml | 8 ++++++++ phpBB/phpbb/crypto/driver/base.php | 21 +++++++++++++++++++++ phpBB/phpbb/crypto/driver/interface.php | 7 +++++++ 3 files changed, 36 insertions(+) diff --git a/phpBB/config/crypto.yml b/phpBB/config/crypto.yml index 03a7cdce2e..072995a8a8 100644 --- a/phpBB/config/crypto.yml +++ b/phpBB/config/crypto.yml @@ -3,6 +3,8 @@ services: class: phpbb_crypto_driver_bcrypt arguments: - @config + calls: + - [set_name, [crypto.driver.bcrypt]] tags: - { name: crypto.driver } @@ -10,6 +12,8 @@ services: class: phpbb_crypto_driver_bcrypt_2y arguments: - @config + calls: + - [set_name, [crypto.driver.bcrypt_2y]] tags: - { name: crypto.driver } @@ -17,6 +21,8 @@ services: class: phpbb_crypto_driver_salted_md5 arguments: - @config + calls: + - [set_name, [crypto.driver.salted_md5]] tags: - { name: crypto.driver } @@ -24,6 +30,8 @@ services: class: phpbb_crypto_driver_phpass arguments: - @config + calls: + - [set_name, [crypto.driver.phpass]] tags: - { name: crypto.driver } diff --git a/phpBB/phpbb/crypto/driver/base.php b/phpBB/phpbb/crypto/driver/base.php index c134122174..f75031dabd 100644 --- a/phpBB/phpbb/crypto/driver/base.php +++ b/phpBB/phpbb/crypto/driver/base.php @@ -26,6 +26,9 @@ abstract class phpbb_crypto_driver_base implements phpbb_crypto_driver_interface /** @var phpbb_crypto_driver_helper */ protected $helper; + /** @var driver name */ + protected $name; + /** * Constructor of crypto driver object * @@ -44,4 +47,22 @@ abstract class phpbb_crypto_driver_base implements phpbb_crypto_driver_interface { return true; } + + /** + * @inheritdoc + */ + public function get_name() + { + return $this->name; + } + + /** + * Set driver name + * + * @param string $name Driver name + */ + public function set_name($name) + { + $this->name = $name; + } } diff --git a/phpBB/phpbb/crypto/driver/interface.php b/phpBB/phpbb/crypto/driver/interface.php index 9686aa33de..68313fbedd 100644 --- a/phpBB/phpbb/crypto/driver/interface.php +++ b/phpBB/phpbb/crypto/driver/interface.php @@ -65,4 +65,11 @@ interface phpbb_crypto_driver_interface * @return string String containing the hash settings */ public function get_settings_only($hash, $full = false); + + /** + * Get the driver name + * + * @return string Driver name + */ + public function get_name(); } From 8b9370c6a956447be304b609eb63d029cb19f2dc Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 22 Aug 2013 19:21:42 -0500 Subject: [PATCH 44/94] [feature/passwords] Define default hashing algorithm in container file The default hashing algorithm type is defined as a parameter in the service definition file for the password hashing system. This will allow us to change this in the future but it will also prevent unexperienced admins from changing the hashing algorithm. PHPBB3-11610 --- phpBB/config/crypto.yml | 11 +++++++++++ phpBB/config/services.yml | 7 ------- phpBB/phpbb/crypto/manager.php | 4 ++-- tests/crypto/manager_test.php | 3 ++- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/phpBB/config/crypto.yml b/phpBB/config/crypto.yml index 072995a8a8..2ef942df66 100644 --- a/phpBB/config/crypto.yml +++ b/phpBB/config/crypto.yml @@ -1,3 +1,6 @@ +parameters: + password_hashing.algorithm: crypto.driver.bcrypt_2y + services: crypto.driver.bcrypt: class: phpbb_crypto_driver_bcrypt @@ -41,3 +44,11 @@ services: - @service_container tags: - { name: service_collection, tag: crypto.driver } + + crypto.manager: + class: phpbb_crypto_manager + arguments: + - @config + - @service_container + - @crypto.driver_collection + - %password_hashing.algorithm% diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index e7c3232fa7..486df3f556 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -122,13 +122,6 @@ services: - @config - @dbal.conn - crypto.manager: - class: phpbb_crypto_manager - arguments: - - @config - - @service_container - - @crypto.driver_collection - dispatcher: class: phpbb_event_dispatcher arguments: diff --git a/phpBB/phpbb/crypto/manager.php b/phpBB/phpbb/crypto/manager.php index 753a86ae84..e314b08865 100644 --- a/phpBB/phpbb/crypto/manager.php +++ b/phpBB/phpbb/crypto/manager.php @@ -58,11 +58,11 @@ class phpbb_crypto_manager * * @param phpbb_config $config phpBB configuration */ - public function __construct($config, $container, $hashing_algorithms) + public function __construct($config, $container, $hashing_algorithms, $default) { $this->config = $config; $this->container = $container; - $this->type = 'crypto.driver.bcrypt_2y'; // might want to make this flexible + $this->type = $default; $this->fill_type_map($hashing_algorithms); $this->load_crypto_helper(); diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index ba13c9c8ad..ceeb45b5b8 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -41,11 +41,12 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase foreach ($this->crypto_drivers as $key => $driver) { + $driver->set_name($key); $this->phpbb_container->set($key, $driver); } // Set up avatar manager - $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $this->crypto_drivers); + $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $this->crypto_drivers, 'crypto.driver.bcrypt_2y'); } public function hash_password_data() From b810957c4bc4ffa86dd4db4cce26bd49d7008670 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 22 Aug 2013 19:31:35 -0500 Subject: [PATCH 45/94] [feature/passwords] Properly set convert_flag and add test for it PHPBB3-11610 --- phpBB/phpbb/crypto/manager.php | 6 +++++- tests/crypto/manager_test.php | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/crypto/manager.php b/phpBB/phpbb/crypto/manager.php index e314b08865..885bf719bf 100644 --- a/phpBB/phpbb/crypto/manager.php +++ b/phpBB/phpbb/crypto/manager.php @@ -196,10 +196,14 @@ class phpbb_crypto_manager return $this->helper->check_combined_hash($password, $stored_hash_type, $hash); } - if ($stored_hash_type->get_type() !== $this->type) + if ($stored_hash_type->get_name() !== $this->type) { $this->convert_flag = true; } + else + { + $this->convert_flag = false; + } return $stored_hash_type->check($password, $hash); } diff --git a/tests/crypto/manager_test.php b/tests/crypto/manager_test.php index ceeb45b5b8..c396d092c1 100644 --- a/tests/crypto/manager_test.php +++ b/tests/crypto/manager_test.php @@ -126,6 +126,9 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase $password .= $this->pw_characters[mt_rand(0, 66)]; $this->assertEquals(false, $this->manager->check_hash($password, $hash)); } + + // Check if convert_flag is correctly set + $this->assertEquals(($hash_type !== 'crypto.driver.bcrypt_2y'), $this->manager->convert_flag); } From 19512b2595cef521099a95b1ab8c24dbe51c5b2f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 14 Sep 2013 14:04:48 +0200 Subject: [PATCH 46/94] [feature/passwords] Rename "crypto" files to "passwords" files PHPBB3-11610 --- phpBB/config/crypto.yml | 54 ----------- phpBB/config/passwords.yml | 54 +++++++++++ phpBB/config/services.yml | 2 +- .../{crypto => passwords}/driver/base.php | 10 +- .../{crypto => passwords}/driver/bcrypt.php | 4 +- .../driver/bcrypt_2y.php | 4 +- .../{crypto => passwords}/driver/helper.php | 6 +- .../driver/interface.php | 4 +- .../{crypto => passwords}/driver/phpass.php | 4 +- .../driver/salted_md5.php | 4 +- phpBB/phpbb/{crypto => passwords}/helper.php | 10 +- phpBB/phpbb/{crypto => passwords}/manager.php | 18 ++-- tests/{crypto => passwords}/manager_test.php | 96 +++++++++---------- 13 files changed, 135 insertions(+), 135 deletions(-) delete mode 100644 phpBB/config/crypto.yml create mode 100644 phpBB/config/passwords.yml rename phpBB/phpbb/{crypto => passwords}/driver/base.php (74%) rename phpBB/phpbb/{crypto => passwords}/driver/bcrypt.php (94%) rename phpBB/phpbb/{crypto => passwords}/driver/bcrypt_2y.php (84%) rename phpBB/phpbb/{crypto => passwords}/driver/helper.php (95%) rename phpBB/phpbb/{crypto => passwords}/driver/interface.php (95%) rename phpBB/phpbb/{crypto => passwords}/driver/phpass.php (80%) rename phpBB/phpbb/{crypto => passwords}/driver/salted_md5.php (96%) rename phpBB/phpbb/{crypto => passwords}/helper.php (96%) rename phpBB/phpbb/{crypto => passwords}/manager.php (90%) rename tests/{crypto => passwords}/manager_test.php (62%) diff --git a/phpBB/config/crypto.yml b/phpBB/config/crypto.yml deleted file mode 100644 index 2ef942df66..0000000000 --- a/phpBB/config/crypto.yml +++ /dev/null @@ -1,54 +0,0 @@ -parameters: - password_hashing.algorithm: crypto.driver.bcrypt_2y - -services: - crypto.driver.bcrypt: - class: phpbb_crypto_driver_bcrypt - arguments: - - @config - calls: - - [set_name, [crypto.driver.bcrypt]] - tags: - - { name: crypto.driver } - - crypto.driver.bcrypt_2y: - class: phpbb_crypto_driver_bcrypt_2y - arguments: - - @config - calls: - - [set_name, [crypto.driver.bcrypt_2y]] - tags: - - { name: crypto.driver } - - crypto.driver.salted_md5: - class: phpbb_crypto_driver_salted_md5 - arguments: - - @config - calls: - - [set_name, [crypto.driver.salted_md5]] - tags: - - { name: crypto.driver } - - crypto.driver.phpass: - class: phpbb_crypto_driver_phpass - arguments: - - @config - calls: - - [set_name, [crypto.driver.phpass]] - tags: - - { name: crypto.driver } - - crypto.driver_collection: - class: phpbb_di_service_collection - arguments: - - @service_container - tags: - - { name: service_collection, tag: crypto.driver } - - crypto.manager: - class: phpbb_crypto_manager - arguments: - - @config - - @service_container - - @crypto.driver_collection - - %password_hashing.algorithm% diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml new file mode 100644 index 0000000000..c9f9e238e8 --- /dev/null +++ b/phpBB/config/passwords.yml @@ -0,0 +1,54 @@ +parameters: + passwords.algorithm: passwords.driver.bcrypt_2y + +services: + passwords.driver.bcrypt: + class: phpbb_passwords_driver_bcrypt + arguments: + - @config + calls: + - [set_name, [passwords.driver.bcrypt]] + tags: + - { name: passwords.driver } + + passwords.driver.bcrypt_2y: + class: phpbb_passwords_driver_bcrypt_2y + arguments: + - @config + calls: + - [set_name, [passwords.driver.bcrypt_2y]] + tags: + - { name: passwords.driver } + + passwords.driver.salted_md5: + class: phpbb_passwords_driver_salted_md5 + arguments: + - @config + calls: + - [set_name, [passwords.driver.salted_md5]] + tags: + - { name: passwords.driver } + + passwords.driver.phpass: + class: phpbb_passwords_driver_phpass + arguments: + - @config + calls: + - [set_name, [passwords.driver.phpass]] + tags: + - { name: passwords.driver } + + passwords.driver_collection: + class: phpbb_di_service_collection + arguments: + - @service_container + tags: + - { name: service_collection, tag: passwords.driver } + + passwords.manager: + class: phpbb_passwords_manager + arguments: + - @config + - @service_container + - @passwords.driver_collection + - %passwords.algorithm% diff --git a/phpBB/config/services.yml b/phpBB/config/services.yml index 486df3f556..576e16d5d4 100644 --- a/phpBB/config/services.yml +++ b/phpBB/config/services.yml @@ -6,7 +6,7 @@ imports: - { resource: avatars.yml } - { resource: feed.yml } - { resource: auth_providers.yml } - - { resource: crypto.yml } + - { resource: passwords.yml } services: acl.permissions: diff --git a/phpBB/phpbb/crypto/driver/base.php b/phpBB/phpbb/passwords/driver/base.php similarity index 74% rename from phpBB/phpbb/crypto/driver/base.php rename to phpBB/phpbb/passwords/driver/base.php index f75031dabd..67cbe4decf 100644 --- a/phpBB/phpbb/crypto/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -16,28 +16,28 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -abstract class phpbb_crypto_driver_base implements phpbb_crypto_driver_interface +abstract class phpbb_passwords_driver_base implements phpbb_passwords_driver_interface { /** @var phpbb_config */ protected $config; - /** @var phpbb_crypto_driver_helper */ + /** @var phpbb_passwords_driver_helper */ protected $helper; /** @var driver name */ protected $name; /** - * Constructor of crypto driver object + * Constructor of passwords driver object * * @return string Hash prefix */ public function __construct(phpbb_config $config) { $this->config = $config; - $this->helper = new phpbb_crypto_driver_helper($this); + $this->helper = new phpbb_passwords_driver_helper($this); } /** diff --git a/phpBB/phpbb/crypto/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php similarity index 94% rename from phpBB/phpbb/crypto/driver/bcrypt.php rename to phpBB/phpbb/passwords/driver/bcrypt.php index ad5a8036c3..2c2ab8e7b7 100644 --- a/phpBB/phpbb/crypto/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_driver_bcrypt extends phpbb_crypto_driver_base +class phpbb_passwords_driver_bcrypt extends phpbb_passwords_driver_base { const PREFIX = '$2a$'; diff --git a/phpBB/phpbb/crypto/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php similarity index 84% rename from phpBB/phpbb/crypto/driver/bcrypt_2y.php rename to phpBB/phpbb/passwords/driver/bcrypt_2y.php index 8bce171a25..9277414d13 100644 --- a/phpBB/phpbb/crypto/driver/bcrypt_2y.php +++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_driver_bcrypt_2y extends phpbb_crypto_driver_bcrypt +class phpbb_passwords_driver_bcrypt_2y extends phpbb_passwords_driver_bcrypt { const PREFIX = '$2y$'; diff --git a/phpBB/phpbb/crypto/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php similarity index 95% rename from phpBB/phpbb/crypto/driver/helper.php rename to phpBB/phpbb/passwords/driver/helper.php index 308ee7dce2..dcd07263d5 100644 --- a/phpBB/phpbb/crypto/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_driver_helper +class phpbb_passwords_driver_helper { /** @var phpbb_config */ protected $driver; @@ -30,7 +30,7 @@ class phpbb_crypto_driver_helper public $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; /** - * Constructor of crypto driver helper object + * Constructor of passwords driver helper object */ public function __construct($driver) { diff --git a/phpBB/phpbb/crypto/driver/interface.php b/phpBB/phpbb/passwords/driver/interface.php similarity index 95% rename from phpBB/phpbb/crypto/driver/interface.php rename to phpBB/phpbb/passwords/driver/interface.php index 68313fbedd..a019830cb4 100644 --- a/phpBB/phpbb/crypto/driver/interface.php +++ b/phpBB/phpbb/passwords/driver/interface.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -interface phpbb_crypto_driver_interface +interface phpbb_passwords_driver_interface { /** * Check if hash type is supported diff --git a/phpBB/phpbb/crypto/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php similarity index 80% rename from phpBB/phpbb/crypto/driver/phpass.php rename to phpBB/phpbb/passwords/driver/phpass.php index 4868464d73..14ba60f279 100644 --- a/phpBB/phpbb/crypto/driver/phpass.php +++ b/phpBB/phpbb/passwords/driver/phpass.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_driver_phpass extends phpbb_crypto_driver_salted_md5 +class phpbb_passwords_driver_phpass extends phpbb_passwords_driver_salted_md5 { const PREFIX = '$P$'; diff --git a/phpBB/phpbb/crypto/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php similarity index 96% rename from phpBB/phpbb/crypto/driver/salted_md5.php rename to phpBB/phpbb/passwords/driver/salted_md5.php index c5a8345453..b87daae4e3 100644 --- a/phpBB/phpbb/crypto/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_driver_salted_md5 extends phpbb_crypto_driver_base +class phpbb_passwords_driver_salted_md5 extends phpbb_passwords_driver_base { const PREFIX = '$H$'; diff --git a/phpBB/phpbb/crypto/helper.php b/phpBB/phpbb/passwords/helper.php similarity index 96% rename from phpBB/phpbb/crypto/helper.php rename to phpBB/phpbb/passwords/helper.php index 9c802b3c01..952f491669 100644 --- a/phpBB/phpbb/crypto/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -16,12 +16,12 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_helper +class phpbb_passwords_helper { /** - * @var phpbb_crypto_manager + * @var phpbb_passwords_manager */ protected $manager; @@ -31,9 +31,9 @@ class phpbb_crypto_helper protected $container; /** - * Construct a phpbb_crypto_helper object + * Construct a phpbb_passwords_helper object * - * @param phpbb_crypto_manager $manager Crypto manager object + * @param phpbb_passwords_manager $manager Crypto manager object * @param phpbb_container $container phpBB container object */ public function __construct($manager, $container) diff --git a/phpBB/phpbb/crypto/manager.php b/phpBB/phpbb/passwords/manager.php similarity index 90% rename from phpBB/phpbb/crypto/manager.php rename to phpBB/phpbb/passwords/manager.php index 885bf719bf..9477ef5c2b 100644 --- a/phpBB/phpbb/crypto/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -16,9 +16,9 @@ if (!defined('IN_PHPBB')) } /** -* @package crypto +* @package passwords */ -class phpbb_crypto_manager +class phpbb_passwords_manager { /** * Default hashing method @@ -37,7 +37,7 @@ class phpbb_crypto_manager /** * Crypto helper - * @var phpbb_crypto_helper + * @var phpbb_passwords_helper */ protected $helper; @@ -54,7 +54,7 @@ class phpbb_crypto_manager protected $container; /** - * Construct a crypto object + * Construct a passwords object * * @param phpbb_config $config phpBB configuration */ @@ -65,7 +65,7 @@ class phpbb_crypto_manager $this->type = $default; $this->fill_type_map($hashing_algorithms); - $this->load_crypto_helper(); + $this->load_passwords_helper(); } /** @@ -85,13 +85,13 @@ class phpbb_crypto_manager } /** - * Load crypto helper class + * Load passwords helper class */ - protected function load_crypto_helper() + protected function load_passwords_helper() { if ($this->helper === null) { - $this->helper = new phpbb_crypto_helper($this, $this->container); + $this->helper = new phpbb_passwords_helper($this, $this->container); } } @@ -170,7 +170,7 @@ class phpbb_crypto_manager $hashing_algorithm = $this->container->get($type); // Do not support 8-bit characters with $2a$ bcrypt - if ($type === 'crypto.driver.bcrypt' || ($type === 'crypto.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) + if ($type === 'passwords.driver.bcrypt' || ($type === 'passwords.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) { if (ord($password[strlen($password)-1]) & 128) { diff --git a/tests/crypto/manager_test.php b/tests/passwords/manager_test.php similarity index 62% rename from tests/crypto/manager_test.php rename to tests/passwords/manager_test.php index c396d092c1..a069c9692e 100644 --- a/tests/crypto/manager_test.php +++ b/tests/passwords/manager_test.php @@ -8,15 +8,15 @@ */ require_once dirname(__FILE__) . '/../mock/container_builder.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/bcrypt.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/bcrypt_2y.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/salted_md5.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/phpass.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/crypto/driver/helper.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/bcrypt.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/bcrypt_2y.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/salted_md5.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/phpass.php'; +require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/helper.php'; -class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase +class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase { - protected $crypto_drivers; + protected $passwords_drivers; protected $pw_characters = '0123456789abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVXYZ.,_!?/\\'; @@ -32,21 +32,21 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase // Prepare dependencies for manager and driver $config = new phpbb_config(array()); - $this->crypto_drivers = array( - 'crypto.driver.bcrypt' => new phpbb_crypto_driver_bcrypt($config), - 'crypto.driver.bcrypt_2y' => new phpbb_crypto_driver_bcrypt_2y($config), - 'crypto.driver.salted_md5' => new phpbb_crypto_driver_salted_md5($config), - 'crypto.driver.phpass' => new phpbb_crypto_driver_phpass($config), + $this->passwords_drivers = array( + 'passwords.driver.bcrypt' => new phpbb_passwords_driver_bcrypt($config), + 'passwords.driver.bcrypt_2y' => new phpbb_passwords_driver_bcrypt_2y($config), + 'passwords.driver.salted_md5' => new phpbb_passwords_driver_salted_md5($config), + 'passwords.driver.phpass' => new phpbb_passwords_driver_phpass($config), ); - foreach ($this->crypto_drivers as $key => $driver) + foreach ($this->passwords_drivers as $key => $driver) { $driver->set_name($key); $this->phpbb_container->set($key, $driver); } // Set up avatar manager - $this->manager = new phpbb_crypto_manager($config, $this->phpbb_container, $this->crypto_drivers, 'crypto.driver.bcrypt_2y'); + $this->manager = new phpbb_passwords_manager($config, $this->phpbb_container, $this->passwords_drivers, 'passwords.driver.bcrypt_2y'); } public function hash_password_data() @@ -55,18 +55,18 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { return array( array('', '2a', 60), - array('crypto.driver.bcrypt_2y', '2a', 60), - array('crypto.driver.bcrypt', '2a', 60), - array('crypto.driver.salted_md5', 'H', 34), + array('passwords.driver.bcrypt_2y', '2a', 60), + array('passwords.driver.bcrypt', '2a', 60), + array('passwords.driver.salted_md5', 'H', 34), ); } else { return array( array('', '2y', 60), - array('crypto.driver.bcrypt_2y', '2y', 60), - array('crypto.driver.bcrypt', '2a', 60), - array('crypto.driver.salted_md5', 'H', 34), + array('passwords.driver.bcrypt_2y', '2y', 60), + array('passwords.driver.bcrypt', '2a', 60), + array('passwords.driver.salted_md5', 'H', 34), ); } } @@ -95,18 +95,18 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase if (version_compare(PHP_VERSION, '5.3.7', '<')) { return array( - array('crypto.driver.bcrypt'), - array('crypto.driver.salted_md5'), - array('crypto.driver.phpass'), + array('passwords.driver.bcrypt'), + array('passwords.driver.salted_md5'), + array('passwords.driver.phpass'), ); } else { return array( - array('crypto.driver.bcrypt_2y'), - array('crypto.driver.bcrypt'), - array('crypto.driver.salted_md5'), - array('crypto.driver.phpass'), + array('passwords.driver.bcrypt_2y'), + array('passwords.driver.bcrypt'), + array('passwords.driver.salted_md5'), + array('passwords.driver.phpass'), ); } } @@ -128,7 +128,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase } // Check if convert_flag is correctly set - $this->assertEquals(($hash_type !== 'crypto.driver.bcrypt_2y'), $this->manager->convert_flag); + $this->assertEquals(($hash_type !== 'passwords.driver.bcrypt_2y'), $this->manager->convert_flag); } @@ -154,7 +154,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase public function test_hash_password_length() { - foreach ($this->crypto_drivers as $driver) + foreach ($this->passwords_drivers as $driver) { $this->assertEquals(false, $driver->hash('foobar', 'foobar')); } @@ -162,7 +162,7 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase public function test_hash_password_8bit_bcrypt() { - $this->assertEquals(false, $this->manager->hash_password('foobar𝄞', 'crypto.driver.bcrypt')); + $this->assertEquals(false, $this->manager->hash_password('foobar𝄞', 'passwords.driver.bcrypt')); } public function test_combined_hash_data() @@ -171,20 +171,20 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { return array( array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt'), + 'passwords.driver.salted_md5', + array('passwords.driver.bcrypt'), ), array( - 'crypto.driver.phpass', - array('crypto.driver.salted_md5'), + 'passwords.driver.phpass', + array('passwords.driver.salted_md5'), ), array( - 'crypto.driver.salted_md5', - array('crypto.driver.phpass', 'crypto.driver.bcrypt'), + 'passwords.driver.salted_md5', + array('passwords.driver.phpass', 'passwords.driver.bcrypt'), ), array( - 'crypto.driver.salted_md5', - array('crypto.driver.salted_md5'), + 'passwords.driver.salted_md5', + array('passwords.driver.salted_md5'), false, ), ); @@ -193,24 +193,24 @@ class phpbb_crypto_manager_test extends PHPUnit_Framework_TestCase { return array( array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt_2y'), + 'passwords.driver.salted_md5', + array('passwords.driver.bcrypt_2y'), ), array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt'), + 'passwords.driver.salted_md5', + array('passwords.driver.bcrypt'), ), array( - 'crypto.driver.phpass', - array('crypto.driver.salted_md5'), + 'passwords.driver.phpass', + array('passwords.driver.salted_md5'), ), array( - 'crypto.driver.salted_md5', - array('crypto.driver.bcrypt_2y', 'crypto.driver.bcrypt'), + 'passwords.driver.salted_md5', + array('passwords.driver.bcrypt_2y', 'passwords.driver.bcrypt'), ), array( - 'crypto.driver.salted_md5', - array('crypto.driver.salted_md5'), + 'passwords.driver.salted_md5', + array('passwords.driver.salted_md5'), false, ), ); From beafef00004007024d3c8c769d630d7d5ec9b698 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 14 Sep 2013 14:17:14 +0200 Subject: [PATCH 47/94] [feature/passwords] Add missing function documentation Additionally, a new line has been added to make the code look nicer. PHPBB3-11610 --- phpBB/phpbb/passwords/manager.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 9477ef5c2b..da6d65c487 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -140,6 +140,7 @@ class phpbb_passwords_manager } return $return_ary; } + if (isset($this->type_map[$match[0]])) { return $this->type_map[$match[0]]; @@ -169,7 +170,9 @@ class phpbb_passwords_manager } $hashing_algorithm = $this->container->get($type); + // Do not support 8-bit characters with $2a$ bcrypt + // Also see http://www.php.net/security/crypt_blowfish.php if ($type === 'passwords.driver.bcrypt' || ($type === 'passwords.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) { if (ord($password[strlen($password)-1]) & 128) @@ -181,6 +184,14 @@ class phpbb_passwords_manager return $this->container->get($type)->hash($password); } + /** + * Check supplied password against hash and set convert_flag if password + * needs to be converted to different format (preferrably newer one) + * + * @param string $password Password that should be checked + * @param string $hash Stored hash + * @return string|bool True if password is correct, false if not + */ public function check_hash($password, $hash) { // First find out what kind of hash we're dealing with From a00854c406215d787465422d7ea7def8c24180f5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 20 Sep 2013 17:31:32 +0200 Subject: [PATCH 48/94] [feature/passwords] Do not pass phpbb_container to passwords manager PHPBB3-11610 --- phpBB/config/passwords.yml | 1 - phpBB/phpbb/passwords/driver/bcrypt.php | 8 -- phpBB/phpbb/passwords/driver/bcrypt_2y.php | 8 -- phpBB/phpbb/passwords/driver/interface.php | 7 -- phpBB/phpbb/passwords/driver/phpass.php | 8 -- phpBB/phpbb/passwords/driver/salted_md5.php | 8 -- phpBB/phpbb/passwords/helper.php | 21 ++-- phpBB/phpbb/passwords/manager.php | 102 +++++++++++++------- tests/passwords/manager_test.php | 10 +- 9 files changed, 86 insertions(+), 87 deletions(-) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index c9f9e238e8..26f604c2e2 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -49,6 +49,5 @@ services: class: phpbb_passwords_manager arguments: - @config - - @service_container - @passwords.driver_collection - %passwords.algorithm% diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index 2c2ab8e7b7..db41fe6b38 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -30,14 +30,6 @@ class phpbb_passwords_driver_bcrypt extends phpbb_passwords_driver_base return self::PREFIX; } - /** - * @inheritdoc - */ - public function get_type() - { - return get_class($this); - } - /** * @inheritdoc */ diff --git a/phpBB/phpbb/passwords/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php index 9277414d13..5b0dbdd311 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt_2y.php +++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php @@ -30,14 +30,6 @@ class phpbb_passwords_driver_bcrypt_2y extends phpbb_passwords_driver_bcrypt return self::PREFIX; } - /** - * @inheritdoc - */ - public function get_type() - { - return get_class($this); - } - /** * @inheritdoc */ diff --git a/phpBB/phpbb/passwords/driver/interface.php b/phpBB/phpbb/passwords/driver/interface.php index a019830cb4..a2088db81c 100644 --- a/phpBB/phpbb/passwords/driver/interface.php +++ b/phpBB/phpbb/passwords/driver/interface.php @@ -33,13 +33,6 @@ interface phpbb_passwords_driver_interface */ public function get_prefix(); - /** - * Returns the name of the hash type - * - * @return string Hash type of driver - */ - public function get_type(); - /** * Hash the password * diff --git a/phpBB/phpbb/passwords/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php index 14ba60f279..d52ce96d11 100644 --- a/phpBB/phpbb/passwords/driver/phpass.php +++ b/phpBB/phpbb/passwords/driver/phpass.php @@ -29,12 +29,4 @@ class phpbb_passwords_driver_phpass extends phpbb_passwords_driver_salted_md5 { return self::PREFIX; } - - /** - * @inheritdoc - */ - public function get_type() - { - return get_class($this); - } } diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index b87daae4e3..6fa12948be 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -30,14 +30,6 @@ class phpbb_passwords_driver_salted_md5 extends phpbb_passwords_driver_base return self::PREFIX; } - /** - * @inheritdoc - */ - public function get_type() - { - return get_class($this); - } - /** * @inheritdoc */ diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 952f491669..d91edb90a1 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -25,21 +25,14 @@ class phpbb_passwords_helper */ protected $manager; - /** - * @var phpbb_container - */ - protected $container; - /** * Construct a phpbb_passwords_helper object * * @param phpbb_passwords_manager $manager Crypto manager object - * @param phpbb_container $container phpBB container object */ - public function __construct($manager, $container) + public function __construct($manager) { $this->manager = $manager; - $this->container = $container; } /** @@ -85,14 +78,22 @@ class phpbb_passwords_helper $hash = $hash_settings[0]; // Put settings of current hash into data array - $stored_hash_type = $this->manager->get_hashing_algorithm($password_hash); + $stored_hash_type = $this->manager->detect_algorithm($password_hash); $this->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix()); $this->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash)); // Hash current hash with the defined types foreach ($type as $cur_type) { - $new_hash_type = $this->container->get($cur_type); + if (isset($this->manager->algorithms[$cur_type])) + { + $new_hash_type = $this->manager->algorithms[$cur_type]; + } + else + { + return false; + } + $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash)); $this->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix()); $this->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0)); diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index da6d65c487..cf6eddd135 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -26,12 +26,19 @@ class phpbb_passwords_manager protected $type = false; /** - * Hashing algorithm types + * Hashing algorithm type map + * Will be used to map hash prefix to type */ protected $type_map = false; /** - * Password convert flag. Password should be converted + * Service collection of hashing algorithms + * Needs to be public for passwords helper + */ + public $algorithms = false; + + /** + * Password convert flag. Signals that password should be converted */ public $convert_flag = false; @@ -47,21 +54,17 @@ class phpbb_passwords_manager */ protected $config; - /** - * phpBB compiled container - * @var service_container - */ - protected $container; - /** * Construct a passwords object * * @param phpbb_config $config phpBB configuration + * @param phpbb_di_service_collection $hashing_algorithms Hashing driver + * service collection + * @param string $default Default driver name */ - public function __construct($config, $container, $hashing_algorithms, $default) + public function __construct($config, $hashing_algorithms, $default) { $this->config = $config; - $this->container = $container; $this->type = $default; $this->fill_type_map($hashing_algorithms); @@ -77,9 +80,14 @@ class phpbb_passwords_manager { foreach ($hashing_algorithms as $algorithm) { + if (!isset($this->algorithms[$algorithm->get_name()])) + { + $this->algorithms[$algorithm->get_name()] = $algorithm; + } + if (!isset($this->type_map[$algorithm->get_prefix()])) { - $this->type_map[$algorithm->get_prefix()] = $algorithm; + $this->type_map[$algorithm->get_prefix()] = $algorithm->get_name(); } } } @@ -91,18 +99,38 @@ class phpbb_passwords_manager { if ($this->helper === null) { - $this->helper = new phpbb_passwords_helper($this, $this->container); + $this->helper = new phpbb_passwords_helper($this); } } /** - * Get the hash type from the supplied hash + * Get the algorithm specified by a specific prefix * - * @param string $hash Password hash that should be checked + * @param string $prefix Password hash prefix * * @return object The hash type object */ - public function get_hashing_algorithm($hash) + protected function get_algorithm($prefix) + { + if (isset($this->type_map[$prefix]) && isset($this->algorithms[$this->type_map[$prefix]])) + { + return $this->algorithms[$this->type_map[$prefix]]; + } + else + { + return false; + } + } + + /** + * Detect the hash type of the supplied hash + * + * @param string $hash Password hash that should be checked + * + * @return object|bool The hash type object or false if the specified + * type is not supported + */ + public function detect_algorithm($hash) { /* * preg_match() will also show hashing algos like $2a\H$, which @@ -112,7 +140,7 @@ class phpbb_passwords_manager */ if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) { - return $this->type_map['$H$']; + return $this->get_algorithm('$H$'); } // Be on the lookout for multiple hashing algorithms @@ -123,32 +151,27 @@ class phpbb_passwords_manager $return_ary = array(); foreach ($hash_types as $type) { - if (isset($this->type_map["\${$type}\$"])) + // we do not support the same hashing + // algorithm more than once + if (isset($return_ary[$type])) { - // we do not support the same hashing - // algorithm more than once - if (isset($return_ary[$type])) - { - return false; - } - $return_ary[$type] = $this->type_map["\${$type}\$"]; + return false; } - else + + $return_ary[$type] = $this->get_algorithm("\${$type}\$"); + + if (empty($return_ary[$type])) { + return false; } } return $return_ary; } - if (isset($this->type_map[$match[0]])) - { - return $this->type_map[$match[0]]; - } - else - { - return false; - } + // get_algorithm() will automatically return false if prefix + // is not supported + return $this->get_algorithm($match[0]); } /** @@ -169,7 +192,14 @@ class phpbb_passwords_manager return $this->helper->combined_hash_password($password, $type); } - $hashing_algorithm = $this->container->get($type); + if (isset($this->algorithms[$type])) + { + $hashing_algorithm = $this->algorithms[$type]; + } + else + { + return false; + } // Do not support 8-bit characters with $2a$ bcrypt // Also see http://www.php.net/security/crypt_blowfish.php @@ -181,7 +211,7 @@ class phpbb_passwords_manager } } - return $this->container->get($type)->hash($password); + return $hashing_algorithm->hash($password); } /** @@ -195,7 +225,7 @@ class phpbb_passwords_manager public function check_hash($password, $hash) { // First find out what kind of hash we're dealing with - $stored_hash_type = $this->get_hashing_algorithm($hash); + $stored_hash_type = $this->detect_algorithm($hash); if ($stored_hash_type == false) { return false; diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index a069c9692e..aa05c8d641 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -46,7 +46,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase } // Set up avatar manager - $this->manager = new phpbb_passwords_manager($config, $this->phpbb_container, $this->passwords_drivers, 'passwords.driver.bcrypt_2y'); + $this->manager = new phpbb_passwords_manager($config, $this->passwords_drivers, 'passwords.driver.bcrypt_2y'); } public function hash_password_data() @@ -58,6 +58,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase array('passwords.driver.bcrypt_2y', '2a', 60), array('passwords.driver.bcrypt', '2a', 60), array('passwords.driver.salted_md5', 'H', 34), + array('passwords.driver.foobar', '', false), ); } else @@ -67,6 +68,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase array('passwords.driver.bcrypt_2y', '2y', 60), array('passwords.driver.bcrypt', '2a', 60), array('passwords.driver.salted_md5', 'H', 34), + array('passwords.driver.foobar', '', false), ); } } @@ -77,6 +79,12 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase public function test_hash_password($type, $prefix, $length) { $password = $this->default_pw; + + if (!$length) + { + $this->assertEquals(false, $hash = $this->manager->hash_password($password, $type)); + return; + } $time = microtime(true); // Limit each test to 1 second From 211f99d881bea35286a41bd3d74ad1b4517ecd45 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 20 Sep 2013 17:53:33 +0200 Subject: [PATCH 49/94] [feature/passwords] Do not manually include passwords drivers in tests PHPBB3-11610 --- tests/passwords/manager_test.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index aa05c8d641..1ec7c40878 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -8,11 +8,6 @@ */ require_once dirname(__FILE__) . '/../mock/container_builder.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/bcrypt.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/bcrypt_2y.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/salted_md5.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/phpass.php'; -require_once dirname(__FILE__) . '/../../phpBB/phpbb/passwords/driver/helper.php'; class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase { From 1970c69c8c9d6b898680aa3e94d5222c8f150d58 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 20 Sep 2013 18:10:42 +0200 Subject: [PATCH 50/94] [feature/passwords] Rename migrations file to passwords Also removed the effectively_installed() check that is not needed according to EXreaction. PHPBB3-11610 --- phpBB/phpbb/db/migration/data/310/crypto.php | 63 ------------------- .../phpbb/db/migration/data/310/passwords.php | 38 +++++++++++ 2 files changed, 38 insertions(+), 63 deletions(-) delete mode 100644 phpBB/phpbb/db/migration/data/310/crypto.php create mode 100644 phpBB/phpbb/db/migration/data/310/passwords.php diff --git a/phpBB/phpbb/db/migration/data/310/crypto.php b/phpBB/phpbb/db/migration/data/310/crypto.php deleted file mode 100644 index c8ac8360ad..0000000000 --- a/phpBB/phpbb/db/migration/data/310/crypto.php +++ /dev/null @@ -1,63 +0,0 @@ -db->sql_return_on_error(true); - // Set user_password to 64 character long string - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_password = '" . md5('foobar') . md5('foobar') . "' - WHERE user_id = '" . ANONYMOUS . "'"; - $this->db->sql_query($sql); - $this->db->sql_return_on_error(false); - - if ($this->db->sql_affectedrows()) - { - $ret = true; - } - - // Reset user password - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_password = '' - WHERE user_id = '" . ANONYMOUS . "'"; - $this->db->sql_query($sql); - - return $ret; - } - - static public function depends_on() - { - return array('phpbb_db_migration_data_30x_3_0_11'); - } - - public function update_schema() - { - return array( - 'change_columns' => array( - $this->table_prefix . 'users' => array( - 'user_password' => array('VCHAR:255', ''), - ), - ), - ); - } - - public function revert_schema() - { - return array( - 'change_columns' => array( - $this->table_prefix . 'users' => array( - 'user_password' => array('VCHAR:40', ''), - ), - ), - ); - } -} diff --git a/phpBB/phpbb/db/migration/data/310/passwords.php b/phpBB/phpbb/db/migration/data/310/passwords.php new file mode 100644 index 0000000000..0611abb79d --- /dev/null +++ b/phpBB/phpbb/db/migration/data/310/passwords.php @@ -0,0 +1,38 @@ + array( + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:255', ''), + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'change_columns' => array( + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:40', ''), + ), + ), + ); + } +} From f5eb0d744e46a2931aa667dbc7a8a4d9ea0229e6 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 22 Sep 2013 21:17:30 +0200 Subject: [PATCH 51/94] [feature/passwords] Use dependency injection for helper This will now be used instead of manually loading the passwords helper instance in the passwords manager. PHPBB3-11610 --- phpBB/config/passwords.yml | 4 ++++ phpBB/phpbb/passwords/helper.php | 9 ++++++--- phpBB/phpbb/passwords/manager.php | 12 ++++++++---- tests/passwords/manager_test.php | 5 +++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index 26f604c2e2..efd23d814c 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -50,4 +50,8 @@ services: arguments: - @config - @passwords.driver_collection + - @passwords.helper - %passwords.algorithm% + + passwords.helper: + class: phpbb_passwords_helper diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index d91edb90a1..0ce1d3be45 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -26,13 +26,16 @@ class phpbb_passwords_helper protected $manager; /** - * Construct a phpbb_passwords_helper object + * Set the passwords manager instance * * @param phpbb_passwords_manager $manager Crypto manager object */ - public function __construct($manager) + public function set_manager(phpbb_passwords_manager $manager) { - $this->manager = $manager; + if ($this->manager === null) + { + $this->manager = $manager; + } } /** diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index cf6eddd135..6cc3510f8e 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -60,15 +60,16 @@ class phpbb_passwords_manager * @param phpbb_config $config phpBB configuration * @param phpbb_di_service_collection $hashing_algorithms Hashing driver * service collection + * @param phpbb_passwords_helper $helper Passwords helper object * @param string $default Default driver name */ - public function __construct($config, $hashing_algorithms, $default) + public function __construct($config, $hashing_algorithms, $helper, $default) { $this->config = $config; $this->type = $default; $this->fill_type_map($hashing_algorithms); - $this->load_passwords_helper(); + $this->load_passwords_helper($helper); } /** @@ -94,12 +95,15 @@ class phpbb_passwords_manager /** * Load passwords helper class + * + * @param phpbb_passwords_helper $helper Passwords helper object */ - protected function load_passwords_helper() + protected function load_passwords_helper($helper) { if ($this->helper === null) { - $this->helper = new phpbb_passwords_helper($this); + $this->helper = $helper; + $this->helper->set_manager($this); } } diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 1ec7c40878..c695735aa6 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -40,8 +40,9 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->phpbb_container->set($key, $driver); } - // Set up avatar manager - $this->manager = new phpbb_passwords_manager($config, $this->passwords_drivers, 'passwords.driver.bcrypt_2y'); + $this->helper = new phpbb_passwords_helper; + // Set up passwords manager + $this->manager = new phpbb_passwords_manager($config, $this->passwords_drivers, $this->helper, 'passwords.driver.bcrypt_2y'); } public function hash_password_data() From 01512104b5823d15eed64d362b41b9594f870f0c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 22 Sep 2013 22:53:10 +0200 Subject: [PATCH 52/94] [feature/passwords] Use dependency injection for passwords driver helper The passwords driver helper is now injected into the driver base instead of being manually loaded. PHPBB3-11610 --- phpBB/config/passwords.yml | 7 +++++++ phpBB/phpbb/passwords/driver/base.php | 4 ++-- phpBB/phpbb/passwords/driver/helper.php | 11 ----------- tests/passwords/manager_test.php | 9 +++++---- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index efd23d814c..41373fc83f 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -6,6 +6,7 @@ services: class: phpbb_passwords_driver_bcrypt arguments: - @config + - @passwords.driver_helper calls: - [set_name, [passwords.driver.bcrypt]] tags: @@ -15,6 +16,7 @@ services: class: phpbb_passwords_driver_bcrypt_2y arguments: - @config + - @passwords.driver_helper calls: - [set_name, [passwords.driver.bcrypt_2y]] tags: @@ -24,6 +26,7 @@ services: class: phpbb_passwords_driver_salted_md5 arguments: - @config + - @passwords.driver_helper calls: - [set_name, [passwords.driver.salted_md5]] tags: @@ -33,6 +36,7 @@ services: class: phpbb_passwords_driver_phpass arguments: - @config + - @passwords.driver_helper calls: - [set_name, [passwords.driver.phpass]] tags: @@ -45,6 +49,9 @@ services: tags: - { name: service_collection, tag: passwords.driver } + passwords.driver_helper: + class: phpbb_passwords_driver_helper + passwords.manager: class: phpbb_passwords_manager arguments: diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index 67cbe4decf..2984dafef7 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -34,10 +34,10 @@ abstract class phpbb_passwords_driver_base implements phpbb_passwords_driver_int * * @return string Hash prefix */ - public function __construct(phpbb_config $config) + public function __construct(phpbb_config $config, phpbb_passwords_driver_helper $helper) { $this->config = $config; - $this->helper = new phpbb_passwords_driver_helper($this); + $this->helper = $helper; } /** diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index dcd07263d5..a50ac8819e 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -20,23 +20,12 @@ if (!defined('IN_PHPBB')) */ class phpbb_passwords_driver_helper { - /** @var phpbb_config */ - protected $driver; - /** * base64 alphabet * @var string */ public $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - /** - * Constructor of passwords driver helper object - */ - public function __construct($driver) - { - $this->driver = $driver; - } - /** * Base64 encode hash * diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index c695735aa6..d06e09a014 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -26,12 +26,13 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Prepare dependencies for manager and driver $config = new phpbb_config(array()); + $driver_helper = new phpbb_passwords_driver_helper; $this->passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb_passwords_driver_bcrypt($config), - 'passwords.driver.bcrypt_2y' => new phpbb_passwords_driver_bcrypt_2y($config), - 'passwords.driver.salted_md5' => new phpbb_passwords_driver_salted_md5($config), - 'passwords.driver.phpass' => new phpbb_passwords_driver_phpass($config), + 'passwords.driver.bcrypt' => new phpbb_passwords_driver_bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new phpbb_passwords_driver_bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new phpbb_passwords_driver_salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new phpbb_passwords_driver_phpass($config, $driver_helper), ); foreach ($this->passwords_drivers as $key => $driver) From e41c9ef6cdab65921f1bc283504e7c5fb552d659 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 27 Sep 2013 10:48:00 +0200 Subject: [PATCH 53/94] [feature/passwords] Add schema changes to schema_data for new hash types PHPBB3-11610 --- phpBB/includes/db/schema_data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php index 69d39e0f8c..40f4ac34ab 100644 --- a/phpBB/includes/db/schema_data.php +++ b/phpBB/includes/db/schema_data.php @@ -1112,7 +1112,7 @@ $schema_data['phpbb_users'] = array( 'user_regdate' => array('TIMESTAMP', 0), 'username' => array('VCHAR_CI', ''), 'username_clean' => array('VCHAR_CI', ''), - 'user_password' => array('VCHAR_UNI:40', ''), + 'user_password' => array('VCHAR_CI', ''), 'user_passchg' => array('TIMESTAMP', 0), 'user_pass_convert' => array('BOOL', 0), 'user_email' => array('VCHAR_UNI:100', ''), From 3f63b9b470b2848abdd6288a45ca56331a3bb77c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 27 Sep 2013 11:16:47 +0200 Subject: [PATCH 54/94] [feature/passwords] Modify passwords files for namespacing changes PHPBB3-11610 --- phpBB/phpbb/passwords/driver/base.php | 10 ++++++---- phpBB/phpbb/passwords/driver/bcrypt.php | 4 +++- phpBB/phpbb/passwords/driver/bcrypt_2y.php | 4 +++- .../{interface.php => driver_interface.php} | 4 +++- phpBB/phpbb/passwords/driver/helper.php | 4 +++- phpBB/phpbb/passwords/driver/phpass.php | 4 +++- phpBB/phpbb/passwords/driver/salted_md5.php | 4 +++- phpBB/phpbb/passwords/helper.php | 6 ++++-- phpBB/phpbb/passwords/manager.php | 14 ++++++++------ tests/passwords/manager_test.php | 16 ++++++++-------- 10 files changed, 44 insertions(+), 26 deletions(-) rename phpBB/phpbb/passwords/driver/{interface.php => driver_interface.php} (95%) diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index 2984dafef7..298b7367ad 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,12 +20,12 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -abstract class phpbb_passwords_driver_base implements phpbb_passwords_driver_interface +abstract class base implements \phpbb\passwords\driver\driver_interface { - /** @var phpbb_config */ + /** @var phpbb\config\config */ protected $config; - /** @var phpbb_passwords_driver_helper */ + /** @var phpbb\passwords\driver\helper */ protected $helper; /** @var driver name */ @@ -34,7 +36,7 @@ abstract class phpbb_passwords_driver_base implements phpbb_passwords_driver_int * * @return string Hash prefix */ - public function __construct(phpbb_config $config, phpbb_passwords_driver_helper $helper) + public function __construct(\phpbb\config\config $config, \phpbb\passwords\driver\helper $helper) { $this->config = $config; $this->helper = $helper; diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index db41fe6b38..2f6cc1b381 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_driver_bcrypt extends phpbb_passwords_driver_base +class bcrypt extends \phpbb\passwords\driver\base { const PREFIX = '$2a$'; diff --git a/phpBB/phpbb/passwords/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php index 5b0dbdd311..8da8c8dbc8 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt_2y.php +++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_driver_bcrypt_2y extends phpbb_passwords_driver_bcrypt +class bcrypt_2y extends \phpbb\passwords\driver\bcrypt { const PREFIX = '$2y$'; diff --git a/phpBB/phpbb/passwords/driver/interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php similarity index 95% rename from phpBB/phpbb/passwords/driver/interface.php rename to phpBB/phpbb/passwords/driver/driver_interface.php index a2088db81c..8c12834641 100644 --- a/phpBB/phpbb/passwords/driver/interface.php +++ b/phpBB/phpbb/passwords/driver/driver_interface.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -interface phpbb_passwords_driver_interface +interface driver_interface { /** * Check if hash type is supported diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index a50ac8819e..fbb6f9bb2b 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_driver_helper +class helper { /** * base64 alphabet diff --git a/phpBB/phpbb/passwords/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php index d52ce96d11..32ccc399ba 100644 --- a/phpBB/phpbb/passwords/driver/phpass.php +++ b/phpBB/phpbb/passwords/driver/phpass.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_driver_phpass extends phpbb_passwords_driver_salted_md5 +class phpass extends \phpbb\passwords\driver\salted_md5 { const PREFIX = '$P$'; diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 6fa12948be..13d25560fe 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords\driver; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_driver_salted_md5 extends phpbb_passwords_driver_base +class salted_md5 extends \phpbb\passwords\driver\base { const PREFIX = '$H$'; diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 0ce1d3be45..22d2ea4edb 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_helper +class helper { /** * @var phpbb_passwords_manager @@ -30,7 +32,7 @@ class phpbb_passwords_helper * * @param phpbb_passwords_manager $manager Crypto manager object */ - public function set_manager(phpbb_passwords_manager $manager) + public function set_manager(\phpbb\passwords\manager $manager) { if ($this->manager === null) { diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 6cc3510f8e..3aaacbee35 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -7,6 +7,8 @@ * */ +namespace phpbb\passwords; + /** * @ignore */ @@ -18,7 +20,7 @@ if (!defined('IN_PHPBB')) /** * @package passwords */ -class phpbb_passwords_manager +class manager { /** * Default hashing method @@ -57,10 +59,10 @@ class phpbb_passwords_manager /** * Construct a passwords object * - * @param phpbb_config $config phpBB configuration - * @param phpbb_di_service_collection $hashing_algorithms Hashing driver + * @param phpbb\config\config $config phpBB configuration + * @param phpbb\di\service_collection $hashing_algorithms Hashing driver * service collection - * @param phpbb_passwords_helper $helper Passwords helper object + * @param phpbb\passwords\helper $helper Passwords helper object * @param string $default Default driver name */ public function __construct($config, $hashing_algorithms, $helper, $default) @@ -75,7 +77,7 @@ class phpbb_passwords_manager /** * Fill algorithm type map * - * @param phpbb_di_service_collection $hashing_algorithms + * @param phpbb\di\service_collection $hashing_algorithms */ protected function fill_type_map($hashing_algorithms) { @@ -96,7 +98,7 @@ class phpbb_passwords_manager /** * Load passwords helper class * - * @param phpbb_passwords_helper $helper Passwords helper object + * @param phpbb\passwords\helper $helper Passwords helper object */ protected function load_passwords_helper($helper) { diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index d06e09a014..c6ab731d7b 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -25,14 +25,14 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->phpbb_container = new phpbb_mock_container_builder; // Prepare dependencies for manager and driver - $config = new phpbb_config(array()); - $driver_helper = new phpbb_passwords_driver_helper; + $config = new \phpbb\config\config(array()); + $driver_helper = new phpbb\passwords\driver\helper; $this->passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb_passwords_driver_bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new phpbb_passwords_driver_bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new phpbb_passwords_driver_salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new phpbb_passwords_driver_phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), ); foreach ($this->passwords_drivers as $key => $driver) @@ -41,9 +41,9 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->phpbb_container->set($key, $driver); } - $this->helper = new phpbb_passwords_helper; + $this->helper = new phpbb\passwords\helper; // Set up passwords manager - $this->manager = new phpbb_passwords_manager($config, $this->passwords_drivers, $this->helper, 'passwords.driver.bcrypt_2y'); + $this->manager = new phpbb\passwords\manager($config, $this->passwords_drivers, $this->helper, 'passwords.driver.bcrypt_2y'); } public function hash_password_data() From 5bc5e4716cc7437941e9cdb6a2b15ed1f4f19b95 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 27 Sep 2013 16:58:06 +0200 Subject: [PATCH 55/94] [feature/passwords] More changes due to namespacing PHPBB3-11610 --- phpBB/config/passwords.yml | 16 ++++++++-------- .../migration/data/{310 => v310}/passwords.php | 6 ++++-- 2 files changed, 12 insertions(+), 10 deletions(-) rename phpBB/phpbb/db/migration/data/{310 => v310}/passwords.php (79%) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index 41373fc83f..9e83bbd918 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -3,7 +3,7 @@ parameters: services: passwords.driver.bcrypt: - class: phpbb_passwords_driver_bcrypt + class: phpbb\passwords\driver\bcrypt arguments: - @config - @passwords.driver_helper @@ -13,7 +13,7 @@ services: - { name: passwords.driver } passwords.driver.bcrypt_2y: - class: phpbb_passwords_driver_bcrypt_2y + class: phpbb\passwords\driver\bcrypt_2y arguments: - @config - @passwords.driver_helper @@ -23,7 +23,7 @@ services: - { name: passwords.driver } passwords.driver.salted_md5: - class: phpbb_passwords_driver_salted_md5 + class: phpbb\passwords\driver\salted_md5 arguments: - @config - @passwords.driver_helper @@ -33,7 +33,7 @@ services: - { name: passwords.driver } passwords.driver.phpass: - class: phpbb_passwords_driver_phpass + class: phpbb\passwords\driver\phpass arguments: - @config - @passwords.driver_helper @@ -43,17 +43,17 @@ services: - { name: passwords.driver } passwords.driver_collection: - class: phpbb_di_service_collection + class: phpbb\di\service_collection arguments: - @service_container tags: - { name: service_collection, tag: passwords.driver } passwords.driver_helper: - class: phpbb_passwords_driver_helper + class: phpbb\passwords\driver\helper passwords.manager: - class: phpbb_passwords_manager + class: phpbb\passwords\manager arguments: - @config - @passwords.driver_collection @@ -61,4 +61,4 @@ services: - %passwords.algorithm% passwords.helper: - class: phpbb_passwords_helper + class: phpbb\passwords\helper diff --git a/phpBB/phpbb/db/migration/data/310/passwords.php b/phpBB/phpbb/db/migration/data/v310/passwords.php similarity index 79% rename from phpBB/phpbb/db/migration/data/310/passwords.php rename to phpBB/phpbb/db/migration/data/v310/passwords.php index 0611abb79d..c422f681ba 100644 --- a/phpBB/phpbb/db/migration/data/310/passwords.php +++ b/phpBB/phpbb/db/migration/data/v310/passwords.php @@ -7,11 +7,13 @@ * */ -class phpbb_db_migration_data_310_passwords extends phpbb_db_migration +namespace phpbb\db\migration\data\v310; + +class passwords extends \phpbb\db\migration\migration { static public function depends_on() { - return array('phpbb_db_migration_data_30x_3_0_11'); + return array('\phpbb\db\migration\data\v30x\release_3_0_11'); } public function update_schema() From de087d537e781741a0137e8ba9162d5baf3f37bb Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 28 Sep 2013 12:41:02 +0200 Subject: [PATCH 56/94] [feature/passwords] A few more corrections in methods due to namespacing PHPBB3-11610 --- phpBB/phpbb/passwords/helper.php | 4 ++-- phpBB/phpbb/passwords/manager.php | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 22d2ea4edb..28a13d2224 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -23,14 +23,14 @@ if (!defined('IN_PHPBB')) class helper { /** - * @var phpbb_passwords_manager + * @var phpbb\passwords\manager */ protected $manager; /** * Set the passwords manager instance * - * @param phpbb_passwords_manager $manager Crypto manager object + * @param phpbb\passwords\manager $manager Crypto manager object */ public function set_manager(\phpbb\passwords\manager $manager) { diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 3aaacbee35..52644b05ac 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -46,13 +46,13 @@ class manager /** * Crypto helper - * @var phpbb_passwords_helper + * @var phpbb\passwords\helper */ protected $helper; /** * phpBB configuration - * @var phpbb_config + * @var phpbb\config\config */ protected $config; @@ -60,12 +60,12 @@ class manager * Construct a passwords object * * @param phpbb\config\config $config phpBB configuration - * @param phpbb\di\service_collection $hashing_algorithms Hashing driver + * @param array $hashing_algorithms Hashing driver * service collection * @param phpbb\passwords\helper $helper Passwords helper object * @param string $default Default driver name */ - public function __construct($config, $hashing_algorithms, $helper, $default) + public function __construct(\phpbb\config\config $config, $hashing_algorithms, \phpbb\passwords\helper $helper, $default) { $this->config = $config; $this->type = $default; @@ -100,7 +100,7 @@ class manager * * @param phpbb\passwords\helper $helper Passwords helper object */ - protected function load_passwords_helper($helper) + protected function load_passwords_helper(\phpbb\passwords\helper $helper) { if ($this->helper === null) { From 3ebff0a96042ba366e316727cbb83b063bc0700d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 28 Sep 2013 12:42:11 +0200 Subject: [PATCH 57/94] [feature/passwords] Pass config via service container to driver helper This will get rid of the global $config in the driver helper PHPBB3-11610 --- phpBB/config/passwords.yml | 2 ++ phpBB/phpbb/passwords/driver/helper.php | 26 +++++++++++++++++++------ tests/passwords/manager_test.php | 2 +- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index 9e83bbd918..511f10c31c 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -51,6 +51,8 @@ services: passwords.driver_helper: class: phpbb\passwords\driver\helper + arguments: + - @config passwords.manager: class: phpbb\passwords\manager diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index fbb6f9bb2b..da66347ac3 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -22,12 +22,27 @@ if (!defined('IN_PHPBB')) */ class helper { + /** + * @var phpbb\config\config + */ + protected $config; + /** * base64 alphabet * @var string */ public $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + /** + * Construct a driver helper object + * + * @param phpbb\config\config $config phpBB configuration + */ + public function __construct(\phpbb\config\config $config) + { + $this->config = $config; + } + /** * Base64 encode hash * @@ -86,16 +101,15 @@ class helper public function unique_id($extra = 'c') { static $dss_seeded = false; - global $config; - $val = $config['rand_seed'] . microtime(); + $val = $this->config['rand_seed'] . microtime(); $val = md5($val); - $config['rand_seed'] = md5($config['rand_seed'] . $val . $extra); + $this->config['rand_seed'] = md5($this->config['rand_seed'] . $val . $extra); - if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10))) + if ($dss_seeded !== true && ($this->config['rand_seed_last_update'] < time() - rand(1,10))) { - set_config('rand_seed_last_update', time(), true); - set_config('rand_seed', $config['rand_seed'], true); + $this->config->set('rand_seed_last_update', time(), true); + $this->config->set('rand_seed', $this->config['rand_seed'], true); $dss_seeded = true; } diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index c6ab731d7b..082b309501 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -26,7 +26,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Prepare dependencies for manager and driver $config = new \phpbb\config\config(array()); - $driver_helper = new phpbb\passwords\driver\helper; + $driver_helper = new phpbb\passwords\driver\helper($config); $this->passwords_drivers = array( 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), From 61e4c0f25172231d203799e4c3c5920e665ab4fa Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Tue, 1 Oct 2013 17:38:52 +0200 Subject: [PATCH 58/94] [feature/passwords] Do not hash passwords longer than 4096 bytes PHPBB3-11610 --- phpBB/phpbb/passwords/manager.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 52644b05ac..b90775126c 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -191,6 +191,13 @@ class manager */ public function hash_password($password, $type = '') { + if (strlen($password) > 4096) + { + // If the password is too huge, we will simply reject it + // and not let the server try to hash it. + return false; + } + $type = ($type === '') ? $this->type : $type; if (is_array($type)) @@ -230,6 +237,13 @@ class manager */ public function check_hash($password, $hash) { + if (strlen($password) > 4096) + { + // If the password is too huge, we will simply reject it + // and not let the server try to hash it. + return false; + } + // First find out what kind of hash we're dealing with $stored_hash_type = $this->detect_algorithm($hash); if ($stored_hash_type == false) From 356f3eef0760f85b947cbffbf87918544e0f6c9d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Oct 2013 13:28:38 +0200 Subject: [PATCH 59/94] [feature/passwords] Inject passwords manager into auth providers The passwords manager will replace the old method of using the functions phpbb_hash() and phpbb_check_hash(). PHPBB3-11610 --- phpBB/config/auth_providers.yml | 3 +++ phpBB/phpbb/auth/provider/apache.php | 13 ++++++++++-- phpBB/phpbb/auth/provider/db.php | 30 ++++++++++++++++++---------- phpBB/phpbb/auth/provider/ldap.php | 19 +++++++++++++----- tests/auth/provider_apache_test.php | 18 ++++++++++++++++- tests/auth/provider_db_test.php | 19 +++++++++++++++++- 6 files changed, 82 insertions(+), 20 deletions(-) diff --git a/phpBB/config/auth_providers.yml b/phpBB/config/auth_providers.yml index e1c289334e..43648b4ad3 100644 --- a/phpBB/config/auth_providers.yml +++ b/phpBB/config/auth_providers.yml @@ -10,6 +10,7 @@ services: arguments: - @dbal.conn - @config + - @passwords.manager - @request - @user - %core.root_path% @@ -21,6 +22,7 @@ services: arguments: - @dbal.conn - @config + - @passwords.manager - @request - @user - %core.root_path% @@ -32,6 +34,7 @@ services: arguments: - @dbal.conn - @config + - @passwords.manager - @user tags: - { name: auth.provider } diff --git a/phpBB/phpbb/auth/provider/apache.php b/phpBB/phpbb/auth/provider/apache.php index 5cbb63c4fc..f111672a23 100644 --- a/phpBB/phpbb/auth/provider/apache.php +++ b/phpBB/phpbb/auth/provider/apache.php @@ -24,20 +24,29 @@ if (!defined('IN_PHPBB')) */ class apache extends \phpbb\auth\provider\base { + /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; + /** * Apache Authentication Constructor * * @param \phpbb\db\driver\driver $db * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager * @param \phpbb\request\request $request * @param \phpbb\user $user * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; + $this->passwords_manager = $passwords_manager; $this->request = $request; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; @@ -228,7 +237,7 @@ class apache extends \phpbb\auth\provider\base // generate user account data return array( 'username' => $username, - 'user_password' => phpbb_hash($password), + 'user_password' => $this->passwords_manager->hash($password), 'user_email' => '', 'group_id' => (int) $row['group_id'], 'user_type' => USER_NORMAL, diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index 4654e49fb5..de07a84cf5 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -26,21 +26,29 @@ if (!defined('IN_PHPBB')) */ class db extends \phpbb\auth\provider\base { + /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; /** * Database Authentication Constructor * - * @param \phpbb\db\driver\driver $db - * @param \phpbb\config\config $config - * @param \phpbb\request\request $request - * @param \phpbb\user $user - * @param string $phpbb_root_path - * @param string $php_ext + * @param \phpbb\db\driver\driver $db + * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\request\request $request + * @param \phpbb\user $user + * @param string $phpbb_root_path + * @param string $php_ext */ - public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) + public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\request\request $request, \phpbb\user $user, $phpbb_root_path, $php_ext) { $this->db = $db; $this->config = $config; + $this->passwords_manager = $passwords_manager; $this->request = $request; $this->user = $user; $this->phpbb_root_path = $phpbb_root_path; @@ -199,10 +207,10 @@ class db extends \phpbb\auth\provider\base // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding // plain md5 support left in for conversions from other systems. - if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password']))) + if ((strlen($row['user_password']) == 34 && ($this->passwords_manager->check(md5($password_old_format), $row['user_password']) || $this->passwords_manager->check(md5(utf8_to_cp1252($password_old_format)), $row['user_password']))) || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password']))) { - $hash = phpbb_hash($password_new_format); + $hash = $this->passwords_manager->hash($password_new_format); // Update the password in the users table to the new format and remove user_pass_convert flag $sql = 'UPDATE ' . USERS_TABLE . ' @@ -234,12 +242,12 @@ class db extends \phpbb\auth\provider\base } // Check password ... - if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password'])) + if (!$row['user_pass_convert'] && $this->passwords_manager->check($password, $row['user_password'])) { // Check for old password hash... if (strlen($row['user_password']) == 32) { - $hash = phpbb_hash($password); + $hash = $this->passwords_manager->hash($password); // Update the password in the users table to the new format $sql = 'UPDATE ' . USERS_TABLE . " diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index 9d29789567..1e4dffde5b 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -26,17 +26,26 @@ if (!defined('IN_PHPBB')) */ class ldap extends \phpbb\auth\provider\base { + /** + * phpBB passwords manager + * + * @var \phpbb\passwords\manager + */ + protected $passwords_manager; + /** * LDAP Authentication Constructor * - * @param \phpbb\db\driver\driver $db - * @param \phpbb\config\config $config - * @param \phpbb\user $user + * @param \phpbb\db\driver\driver $db + * @param \phpbb\config\config $config + * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\user $user */ - public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\user $user) + public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\user $user) { $this->db = $db; $this->config = $config; + $this->passwords_manager = $passwords_manager; $this->user = $user; } @@ -244,7 +253,7 @@ class ldap extends \phpbb\auth\provider\base // generate user account data $ldap_user_row = array( 'username' => $username, - 'user_password' => phpbb_hash($password), + 'user_password' => $this->passwords_manager->hash($password), 'user_email' => (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($this->config['ldap_email'])][0]) : '', 'group_id' => (int) $row['group_id'], 'user_type' => USER_NORMAL, diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index e135a1f002..5388ae0b0d 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -25,8 +25,24 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case $config = new \phpbb\config\config(array()); $this->request = $this->getMock('\phpbb\request\request'); $this->user = $this->getMock('\phpbb\user'); + $driver_helper = new phpbb\passwords\driver\helper($config); + $passwords_drivers = array( + 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + ); - $this->provider = new \phpbb\auth\provider\apache($db, $config, $this->request, $this->user, $phpbb_root_path, $phpEx); + foreach ($passwords_drivers as $key => $driver) + { + $driver->set_name($key); + } + + $passwords_helper = new phpbb\passwords\helper; + // Set up passwords manager + $passwords_manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + + $this->provider = new \phpbb\auth\provider\apache($db, $config, $passwords_manager, $this->request, $this->user, $phpbb_root_path, $phpEx); } public function getDataSet() diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index 140a28cd3d..74615a01ed 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -28,7 +28,24 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case )); $request = $this->getMock('\phpbb\request\request'); $user = $this->getMock('\phpbb\user'); - $provider = new \phpbb\auth\provider\db($db, $config, $request, $user, $phpbb_root_path, $phpEx); + $driver_helper = new phpbb\passwords\driver\helper($config); + $passwords_drivers = array( + 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + ); + + foreach ($passwords_drivers as $key => $driver) + { + $driver->set_name($key); + } + + $passwords_helper = new phpbb\passwords\helper; + // Set up passwords manager + $passwords_manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + + $provider = new \phpbb\auth\provider\db($db, $config, $passwords_manager, $request, $user, $phpbb_root_path, $phpEx); $expected = array( 'status' => LOGIN_SUCCESS, From afb7d2e616db95add3c6ad9cc908df4218c6f3b7 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Oct 2013 13:30:36 +0200 Subject: [PATCH 60/94] [feature/passwords] Rename manager methods to check() and hash() These method names are more straightforward than the previous ones. PHPBB3-11610 --- phpBB/phpbb/passwords/manager.php | 4 ++-- tests/passwords/manager_test.php | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index b90775126c..6ec9eefaed 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -189,7 +189,7 @@ class manager * @return string|bool Password hash of supplied password or false if * if something went wrong during hashing */ - public function hash_password($password, $type = '') + public function hash($password, $type = '') { if (strlen($password) > 4096) { @@ -235,7 +235,7 @@ class manager * @param string $hash Stored hash * @return string|bool True if password is correct, false if not */ - public function check_hash($password, $hash) + public function check($password, $hash) { if (strlen($password) > 4096) { diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 082b309501..7e9ec3dfcf 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -79,7 +79,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase if (!$length) { - $this->assertEquals(false, $hash = $this->manager->hash_password($password, $type)); + $this->assertEquals(false, $hash = $this->manager->hash($password, $type)); return; } $time = microtime(true); @@ -87,7 +87,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Limit each test to 1 second while ((microtime(true) - $time) < 1) { - $hash = $this->manager->hash_password($password, $type); + $hash = $this->manager->hash($password, $type); preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); $this->assertEquals($prefix, $match[1]); $this->assertEquals($length, strlen($hash)); @@ -126,10 +126,10 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Limit each test to 1 second while ((microtime(true) - $time) < 1) { - $hash = $this->manager->hash_password($password, $hash_type); - $this->assertEquals(true, $this->manager->check_hash($password, $hash)); + $hash = $this->manager->hash($password, $hash_type); + $this->assertEquals(true, $this->manager->check($password, $hash)); $password .= $this->pw_characters[mt_rand(0, 66)]; - $this->assertEquals(false, $this->manager->check_hash($password, $hash)); + $this->assertEquals(false, $this->manager->check($password, $hash)); } // Check if convert_flag is correctly set @@ -154,7 +154,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase */ public function test_check_hash_exceptions($password, $hash, $expected) { - $this->assertEquals($expected, $this->manager->check_hash($password, $hash)); + $this->assertEquals($expected, $this->manager->check($password, $hash)); } public function test_hash_password_length() @@ -167,7 +167,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase public function test_hash_password_8bit_bcrypt() { - $this->assertEquals(false, $this->manager->hash_password('foobar𝄞', 'passwords.driver.bcrypt')); + $this->assertEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt')); } public function test_combined_hash_data() @@ -232,11 +232,11 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Limit each test to 1 second while ((microtime(true) - $time) < 1) { - $hash = $this->manager->hash_password($password, $first_type); - $combined_hash = $this->manager->hash_password($hash, $second_type); - $this->assertEquals($expected, $this->manager->check_hash($password, $combined_hash)); + $hash = $this->manager->hash($password, $first_type); + $combined_hash = $this->manager->hash($hash, $second_type); + $this->assertEquals($expected, $this->manager->check($password, $combined_hash)); $password .= $this->pw_characters[mt_rand(0, 66)]; - $this->assertEquals(false, $this->manager->check_hash($password, $combined_hash)); + $this->assertEquals(false, $this->manager->check($password, $combined_hash)); // If we are expecting the check to fail then there is // no need to run this more than once From 3aba3235d5590efc6fbccd537641ebc87b3cfbfa Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Oct 2013 15:33:17 +0200 Subject: [PATCH 61/94] [feature/passwords] Use passwords manager in phpBB hash functions PHPBB3-11610 --- phpBB/includes/functions.php | 43 +++++------------------------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index b3e50847fd..c49c1d809b 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -398,38 +398,10 @@ function still_on_time($extra_time = 15) */ function phpbb_hash($password) { - $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + global $phpbb_container; - $random_state = unique_id(); - $random = ''; - $count = 6; - - if (($fh = @fopen('/dev/urandom', 'rb'))) - { - $random = fread($fh, $count); - fclose($fh); - } - - if (strlen($random) < $count) - { - $random = ''; - - for ($i = 0; $i < $count; $i += 16) - { - $random_state = md5(unique_id() . $random_state); - $random .= pack('H*', md5($random_state)); - } - $random = substr($random, 0, $count); - } - - $hash = _hash_crypt_private($password, _hash_gensalt_private($random, $itoa64), $itoa64); - - if (strlen($hash) == 34) - { - return $hash; - } - - return md5($password); + $passwords_manager = $phpbb_container->get('passwords.manager'); + return $passwords_manager->hash($password); } /** @@ -442,13 +414,10 @@ function phpbb_hash($password) */ function phpbb_check_hash($password, $hash) { - $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - if (strlen($hash) == 34) - { - return (_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false; - } + global $phpbb_container; - return (md5($password) === $hash) ? true : false; + $passwords_manager = $phpbb_container->get('passwords.manager'); + return $passwords_manager->check($password, $hash); } /** From e7e11112b17d6a8d4811d28376f1cc545243c08c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Oct 2013 17:24:11 +0200 Subject: [PATCH 62/94] [feature/passwords] Fix tests after changes to phpBB hashing functions PHPBB3-11610 --- tests/security/hash_test.php | 27 +++++++++++++++ .../phpbb_functional_test_case.php | 33 ++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index 0c2580c19b..b4c4dba48f 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -13,6 +13,33 @@ class phpbb_security_hash_test extends phpbb_test_case { public function test_check_hash_with_phpass() { + global $phpbb_container; + + $config = new phpbb\config\config(array()); + $phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); + $driver_helper = new phpbb\passwords\driver\helper($config); + $passwords_drivers = array( + 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + ); + + foreach ($passwords_drivers as $key => $driver) + { + $driver->set_name($key); + } + + $passwords_helper = new phpbb\passwords\helper; + // Set up passwords manager + $passwords_manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + + $phpbb_container + ->expects($this->any()) + ->method('get') + ->with('passwords.manager') + ->will($this->returnValue($passwords_manager)); + $this->assertTrue(phpbb_check_hash('test', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); $this->assertTrue(phpbb_check_hash('test', '$P$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); $this->assertFalse(phpbb_check_hash('foo', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index f87b3538a1..065227b050 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -509,6 +509,7 @@ class phpbb_functional_test_case extends phpbb_test_case set_config(null, null, null, $config); set_config_count(null, null, null, $config); $phpbb_dispatcher = new phpbb_mock_event_dispatcher(); + $passwords_manager = $this->get_passwords_manager(); $user_row = array( 'username' => $username, @@ -518,7 +519,7 @@ class phpbb_functional_test_case extends phpbb_test_case 'user_lang' => 'en', 'user_timezone' => 0, 'user_dateformat' => '', - 'user_password' => phpbb_hash($username . $username), + 'user_password' => $passwords_manager->hash($username . $username), ); return user_add($user_row); } @@ -995,4 +996,34 @@ class phpbb_functional_test_case extends phpbb_test_case } return null; } + + /** + * Return a passwords manager instance + * + * @return phpbb\passwords\manager + */ + public function get_passwords_manager() + { + // Prepare dependencies for manager and driver + $config = new phpbb\config\config(array()); + $driver_helper = new phpbb\passwords\driver\helper($config); + + $passwords_drivers = array( + 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + ); + + foreach ($passwords_drivers as $key => $driver) + { + $driver->set_name($key); + } + + $passwords_helper = new phpbb\passwords\helper; + // Set up passwords manager + $manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + + return $manager; + } } From 93531e7fb0df7d9cd2de04ca06aa9eb6a847a1c4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 2 Oct 2013 23:45:32 +0200 Subject: [PATCH 63/94] [feature/passwords] Add prepending backslash to class namespaces PHPBB3-11610 --- tests/auth/provider_apache_test.php | 14 +++++++------- tests/auth/provider_db_test.php | 14 +++++++------- tests/passwords/manager_test.php | 14 +++++++------- tests/security/hash_test.php | 16 ++++++++-------- .../phpbb_functional_test_case.php | 16 ++++++++-------- 5 files changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index 5388ae0b0d..8f65e8ad39 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -25,12 +25,12 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case $config = new \phpbb\config\config(array()); $this->request = $this->getMock('\phpbb\request\request'); $this->user = $this->getMock('\phpbb\user'); - $driver_helper = new phpbb\passwords\driver\helper($config); + $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); foreach ($passwords_drivers as $key => $driver) @@ -38,9 +38,9 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case $driver->set_name($key); } - $passwords_helper = new phpbb\passwords\helper; + $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $passwords_manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); $this->provider = new \phpbb\auth\provider\apache($db, $config, $passwords_manager, $this->request, $this->user, $phpbb_root_path, $phpEx); } diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index 74615a01ed..b979ab34c5 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -28,12 +28,12 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case )); $request = $this->getMock('\phpbb\request\request'); $user = $this->getMock('\phpbb\user'); - $driver_helper = new phpbb\passwords\driver\helper($config); + $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); foreach ($passwords_drivers as $key => $driver) @@ -41,9 +41,9 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case $driver->set_name($key); } - $passwords_helper = new phpbb\passwords\helper; + $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $passwords_manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); $provider = new \phpbb\auth\provider\db($db, $config, $passwords_manager, $request, $user, $phpbb_root_path, $phpEx); diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 7e9ec3dfcf..a8dbabf74f 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -26,13 +26,13 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Prepare dependencies for manager and driver $config = new \phpbb\config\config(array()); - $driver_helper = new phpbb\passwords\driver\helper($config); + $driver_helper = new \phpbb\passwords\driver\helper($config); $this->passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); foreach ($this->passwords_drivers as $key => $driver) @@ -41,9 +41,9 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->phpbb_container->set($key, $driver); } - $this->helper = new phpbb\passwords\helper; + $this->helper = new \phpbb\passwords\helper; // Set up passwords manager - $this->manager = new phpbb\passwords\manager($config, $this->passwords_drivers, $this->helper, 'passwords.driver.bcrypt_2y'); + $this->manager = new \phpbb\passwords\manager($config, $this->passwords_drivers, $this->helper, 'passwords.driver.bcrypt_2y'); } public function hash_password_data() diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index b4c4dba48f..76d7d22a00 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -15,14 +15,14 @@ class phpbb_security_hash_test extends phpbb_test_case { global $phpbb_container; - $config = new phpbb\config\config(array()); + $config = new \phpbb\config\config(array()); $phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); - $driver_helper = new phpbb\passwords\driver\helper($config); + $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); foreach ($passwords_drivers as $key => $driver) @@ -30,9 +30,9 @@ class phpbb_security_hash_test extends phpbb_test_case $driver->set_name($key); } - $passwords_helper = new phpbb\passwords\helper; + $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $passwords_manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); $phpbb_container ->expects($this->any()) diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index 065227b050..e078b09082 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -1005,14 +1005,14 @@ class phpbb_functional_test_case extends phpbb_test_case public function get_passwords_manager() { // Prepare dependencies for manager and driver - $config = new phpbb\config\config(array()); - $driver_helper = new phpbb\passwords\driver\helper($config); + $config = new \phpbb\config\config(array()); + $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new phpbb\passwords\driver\bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new phpbb\passwords\driver\salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new phpbb\passwords\driver\phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); foreach ($passwords_drivers as $key => $driver) @@ -1020,9 +1020,9 @@ class phpbb_functional_test_case extends phpbb_test_case $driver->set_name($key); } - $passwords_helper = new phpbb\passwords\helper; + $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $manager = new phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); return $manager; } From 035db5e08b961055f0e74a26491ac35b289469cd Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 3 Oct 2013 10:23:17 +0200 Subject: [PATCH 64/94] [feature/passwords] Fix hash_test for use of passwords manager PHPBB3-11610 --- tests/security/hash_test.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index f7d2c0dad8..c1a8c206a8 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -11,7 +11,7 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_security_hash_test extends phpbb_test_case { - public function test_check_hash_with_phpass() + public function setUp() { global $phpbb_container; @@ -39,7 +39,10 @@ class phpbb_security_hash_test extends phpbb_test_case ->method('get') ->with('passwords.manager') ->will($this->returnValue($passwords_manager)); + } + public function test_check_hash_with_phpass() + { $this->assertTrue(phpbb_check_hash('test', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); $this->assertTrue(phpbb_check_hash('test', '$P$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); $this->assertFalse(phpbb_check_hash('foo', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); From f1d29499859a060b8c59a9efbeada74958eee720 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 7 Oct 2013 16:00:52 +0200 Subject: [PATCH 65/94] [feature/passwords] Move check for 8-bit characters to bcrypt driver PHPBB3-11610 --- phpBB/phpbb/passwords/driver/bcrypt.php | 10 ++++++++++ phpBB/phpbb/passwords/manager.php | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index 2f6cc1b381..e29379a36f 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -41,6 +41,16 @@ class bcrypt extends \phpbb\passwords\driver\base // Revert to 2a if this is the case $prefix = (!$this->is_supported()) ? '$2a$' : $this->get_prefix(); + // Do not support 8-bit characters with $2a$ bcrypt + // Also see http://www.php.net/security/crypt_blowfish.php + if ($prefix === self::PREFIX) + { + if (ord($password[strlen($password)-1]) & 128) + { + return false; + } + } + if ($salt == '') { $salt = $prefix . '10$' . $this->get_random_salt(); diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 6ec9eefaed..0b41d3a8c3 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -214,16 +214,6 @@ class manager return false; } - // Do not support 8-bit characters with $2a$ bcrypt - // Also see http://www.php.net/security/crypt_blowfish.php - if ($type === 'passwords.driver.bcrypt' || ($type === 'passwords.driver.bcrypt_2y' && !$hashing_algorithm->is_supported())) - { - if (ord($password[strlen($password)-1]) & 128) - { - return false; - } - } - return $hashing_algorithm->hash($password); } From 3b6038cfcd6e00aaf8e9b5f68f2a925c9a85da51 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 9 Oct 2013 14:28:57 +0200 Subject: [PATCH 66/94] [feature/passwords] Add tests for unique_id() method in helper PHPBB3-11610 --- tests/passwords/manager_test.php | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index a8dbabf74f..4ad5b439d6 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -26,13 +26,13 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase // Prepare dependencies for manager and driver $config = new \phpbb\config\config(array()); - $driver_helper = new \phpbb\passwords\driver\helper($config); + $this->driver_helper = new \phpbb\passwords\driver\helper($config); $this->passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), - 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), - 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), - 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), ); foreach ($this->passwords_drivers as $key => $driver) @@ -246,4 +246,15 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase } } } + + public function test_unique_id() + { + $time = microtime(true); + $first_id = $this->driver_helper->unique_id(); + // Limit test to 1 second + while ((microtime(true) - $time) < 1) + { + $this->assertNotEquals($first_id, $this->driver_helper->unique_id()); + } + } } From cd74fb094629cf07209b4fa13ebf0ddf5b4ce47c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Wed, 9 Oct 2013 22:53:13 +0200 Subject: [PATCH 67/94] [feature/passwords] Increase test coverage to 35 out ouf 36 methods Only one small code part in the salted md5 driver can't be tested right now. Passwords helper and passwords driver helper are now fully covered by tests. PHPBB3-11610 --- phpBB/phpbb/passwords/driver/helper.php | 5 +- phpBB/phpbb/passwords/driver/salted_md5.php | 5 +- tests/passwords/drivers_test.php | 86 +++++++++++++++++++++ tests/passwords/manager_test.php | 29 +++++-- 4 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 tests/passwords/drivers_test.php diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index da66347ac3..086edb6b65 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -120,12 +120,13 @@ class helper * Get random salt with specified length * * @param int $length Salt length + * @param string $rand_seed Seed for random data (optional). For tests. */ - public function get_random_salt($length) + public function get_random_salt($length, $rand_seed = '/dev/urandom') { $random = ''; - if (($fh = @fopen('/dev/urandom', 'rb'))) + if (($fh = @fopen($rand_seed, 'rb'))) { $random = fread($fh, $length); fclose($fh); diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 13d25560fe..23ae25c0c9 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -46,10 +46,7 @@ class salted_md5 extends \phpbb\passwords\driver\base } else { - if (($settings = $this->get_hash_settings($this->generate_salt())) === false) - { - return false; - } + $settings = $this->get_hash_settings($this->generate_salt()); } $hash = md5($settings['salt'] . $password, true); diff --git a/tests/passwords/drivers_test.php b/tests/passwords/drivers_test.php new file mode 100644 index 0000000000..1fc51b1dd2 --- /dev/null +++ b/tests/passwords/drivers_test.php @@ -0,0 +1,86 @@ +driver_helper = new \phpbb\passwords\driver\helper($config); + + $this->passwords_drivers = array( + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper), + 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper), + 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), + ); + + foreach ($this->passwords_drivers as $key => $driver) + { + $driver->set_name($key); + } + } + + public function data_helper_encode64() + { + return array( + array('foobar', 6, 'axqPW3aQ'), + array('foobar', 7, 'axqPW3aQ..'), + array('foobar', 5, 'axqPW34'), + ); + } + + /** + * @dataProvider data_helper_encode64 + */ + public function test_helper_encode64($input, $length, $output) + { + $return = $this->driver_helper->hash_encode64($input, $length); + $this->assertEquals($output, $return); + } + + public function data_get_random_salt() + { + return array( + array(24, false), + array(24, '/dev/foobar'), + ); + } + + /** + * @dataProvider data_get_random_salt + */ + public function test_get_random_salt($length, $rand_seed) + { + $rand_string = (empty($rand_seed)) ? $this->driver_helper->get_random_salt($length) : $this->driver_helper->get_random_salt($length, $rand_seed); + $start = microtime(true); + + // Run each test for max. 1 second + while ((microtime(true) - $start) < 1) + { + $urandom_string = (empty($rand_seed)) ? $this->driver_helper->get_random_salt($length) : $this->driver_helper->get_random_salt($length, $rand_seed); + $this->assertEquals($length, strlen($urandom_string)); + $this->assertNotEquals($rand_string, $urandom_string); + } + } + + public function test_get_hash_settings_salted_md5() + { + $settings = $this->passwords_drivers['passwords.driver.salted_md5']->get_hash_settings('$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1'); + $this->assertEquals(array( + 'count' => pow(2, 11), + 'salt' => 'isfrtKXW', + 'full' => '$H$9isfrtKXW', + ), + $settings + ); + $this->assertEquals(false, $this->passwords_drivers['passwords.driver.salted_md5']->get_hash_settings(false)); + } +} diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 4ad5b439d6..568c53be3f 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -7,8 +7,6 @@ * */ -require_once dirname(__FILE__) . '/../mock/container_builder.php'; - class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase { protected $passwords_drivers; @@ -19,11 +17,6 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase public function setUp() { - global $phpbb_root_path, $phpEx; - - // Mock phpbb_container - $this->phpbb_container = new phpbb_mock_container_builder; - // Prepare dependencies for manager and driver $config = new \phpbb\config\config(array()); $this->driver_helper = new \phpbb\passwords\driver\helper($config); @@ -38,7 +31,6 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase foreach ($this->passwords_drivers as $key => $driver) { $driver->set_name($key); - $this->phpbb_container->set($key, $driver); } $this->helper = new \phpbb\passwords\helper; @@ -218,6 +210,11 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase array('passwords.driver.salted_md5'), false, ), + array( + 'passwords.driver.bcrypt_2y', + array('passwords.driver.salted_md4'), + false, + ), ); } } @@ -257,4 +254,20 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->assertNotEquals($first_id, $this->driver_helper->unique_id()); } } + + public function test_check_hash_with_large_input() + { + // 16 MB password, should be rejected quite fast + $start_time = time(); + $this->assertFalse($this->manager->check(str_repeat('a', 1024 * 1024 * 16), '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); + $this->assertLessThanOrEqual(5, time() - $start_time); + } + + public function test_hash_password_with_large_input() + { + // 16 MB password, should be rejected quite fast + $start_time = time(); + $this->assertFalse($this->manager->hash(str_repeat('a', 1024 * 1024 * 16))); + $this->assertLessThanOrEqual(5, time() - $start_time); + } } From fdf9ae7c18146ce58531bc6bbbb1eff5461691d2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 10 Oct 2013 12:01:10 +0200 Subject: [PATCH 68/94] [feature/passwords] Increase test coverage to 100% of methods Obsolete code that is impossible to hit has been removed and the logic of the salted md5 driver has been changed to correctly implement the phpBB 3.0 phpbb_hash() function. PHPBB3-11610 --- phpBB/phpbb/passwords/driver/salted_md5.php | 16 ++++++++-------- tests/passwords/manager_test.php | 21 ++++++++++++++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 23ae25c0c9..c44da540a6 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -41,7 +41,13 @@ class salted_md5 extends \phpbb\passwords\driver\base { if (($settings = $this->get_hash_settings($setting)) === false) { - return false; + // Return md5 of password if settings do not + // comply with our standards. This will only + // happen if pre-determined settings are + // directly passed to the driver. The manager + // will not do this. Same as the old hashing + // implementatio in phpBB 3.0 + return md5($password); } } else @@ -59,13 +65,7 @@ class salted_md5 extends \phpbb\passwords\driver\base $output = $settings['full']; $output .= $this->helper->hash_encode64($hash, 16); - if (strlen($output) == 34) - { - return $output; - } - - // Should we really just return the md5 of the password? O.o - return md5($password); + return $output; } /** diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 568c53be3f..77955bd464 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -149,17 +149,28 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->assertEquals($expected, $this->manager->check($password, $hash)); } - public function test_hash_password_length() + public function data_hash_password_length() { - foreach ($this->passwords_drivers as $driver) - { - $this->assertEquals(false, $driver->hash('foobar', 'foobar')); - } + return array( + array('passwords.driver.bcrypt', false), + array('passwords.driver.bcrypt_2y', false), + array('passwords.driver.salted_md5', '3858f62230ac3c915f300c664312c63f'), + array('passwords.driver.phpass', '3858f62230ac3c915f300c664312c63f'), + ); + } + + /** + * @dataProvider data_hash_password_length + */ + public function test_hash_password_length($driver, $expected) + { + $this->assertEquals($expected, $this->passwords_drivers[$driver]->hash('foobar', 'foobar')); } public function test_hash_password_8bit_bcrypt() { $this->assertEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt')); + $this->assertNotEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt_2y')); } public function test_combined_hash_data() From 7c347864a4388ceac780ef25c4cee680ef80aaf4 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Thu, 10 Oct 2013 12:09:50 +0200 Subject: [PATCH 69/94] [feature/passwords] Fix tests for 8th bit characters in bcrypt on PHP < 5.3.7 PHPBB3-11610 --- tests/passwords/manager_test.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 77955bd464..f68ca25a2f 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -170,7 +170,14 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase public function test_hash_password_8bit_bcrypt() { $this->assertEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt')); - $this->assertNotEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt_2y')); + if (version_compare(PHP_VERSION, '5.3.7', '<')) + { + $this->assertEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt_2y')); + } + else + { + $this->assertNotEquals(false, $this->manager->hash('foobar𝄞', 'passwords.driver.bcrypt_2y')); + } } public function test_combined_hash_data() From ce51f878eb8ced7d79fb6aadc1ad831fbf73a66e Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 11 Oct 2013 09:43:30 +0200 Subject: [PATCH 70/94] [feature/passwords] Add phpass copyright notice to salted md5 driver PHPBB3-11610 --- phpBB/phpbb/passwords/driver/salted_md5.php | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index c44da540a6..bccf61dc07 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -17,6 +17,34 @@ if (!defined('IN_PHPBB')) exit; } +/** +* +* @version Version 0.1 / slightly modified for phpBB 3.1.x (using $H$ as hash type identifier) +* +* Portable PHP password hashing framework. +* +* Written by Solar Designer in 2004-2006 and placed in +* the public domain. +* +* There's absolutely no warranty. +* +* The homepage URL for this framework is: +* +* http://www.openwall.com/phpass/ +* +* Please be sure to update the Version line if you edit this file in any way. +* It is suggested that you leave the main version number intact, but indicate +* your project name (after the slash) and add your own revision information. +* +* Please do not change the "private" password hashing method implemented in +* here, thereby making your hashes incompatible. However, if you must, please +* change the hash type identifier (the "$P$") to something different. +* +* Obviously, since this code is in the public domain, the above are not +* requirements (there can be none), but merely suggestions. +* +*/ + /** * @package passwords */ From da39707d16500d18ca642587cb08958a3c09369c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 11 Oct 2013 13:34:15 +0200 Subject: [PATCH 71/94] [feature/passwords] Mark old hashing functions as deprecated PHPBB3-11610 --- phpBB/includes/functions.php | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 953c0a3b1c..06fa307614 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -368,33 +368,13 @@ function still_on_time($extra_time = 15) } /** -* -* @version Version 0.1 / slightly modified for phpBB 3.1.x (using $H$ as hash type identifier) -* -* Portable PHP password hashing framework. -* -* Written by Solar Designer in 2004-2006 and placed in -* the public domain. -* -* There's absolutely no warranty. -* -* The homepage URL for this framework is: -* -* http://www.openwall.com/phpass/ -* -* Please be sure to update the Version line if you edit this file in any way. -* It is suggested that you leave the main version number intact, but indicate -* your project name (after the slash) and add your own revision information. -* -* Please do not change the "private" password hashing method implemented in -* here, thereby making your hashes incompatible. However, if you must, please -* change the hash type identifier (the "$P$") to something different. -* -* Obviously, since this code is in the public domain, the above are not -* requirements (there can be none), but merely suggestions. -* -* * Hash the password +* +* @deprecated 3.1.0-a2 (To be removed: 3.3.0) +* +* @param string $password Password to be hashed +* +* @return string Password hash or false if something went wrong during hashing */ function phpbb_hash($password) { @@ -407,6 +387,8 @@ function phpbb_hash($password) /** * Check for correct password * +* @deprecated 3.1.0-a2 (To be removed: 3.3.0) +* * @param string $password The password in plain text * @param string $hash The stored password hash * From b795ce8b7dec4831de702947c97ad698aec5bbe2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 11 Oct 2013 13:34:40 +0200 Subject: [PATCH 72/94] [feature/passwords] Remove obsolete hashing functions from functions.php These hashing functions have been worked into the salted md5 driver. PHPBB3-11610 --- phpBB/includes/functions.php | 110 ----------------------------------- 1 file changed, 110 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 06fa307614..561ebaabb4 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -402,116 +402,6 @@ function phpbb_check_hash($password, $hash) return $passwords_manager->check($password, $hash); } -/** -* Generate salt for hash generation -*/ -function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6) -{ - if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) - { - $iteration_count_log2 = 8; - } - - $output = '$H$'; - $output .= $itoa64[min($iteration_count_log2 + 5, 30)]; - $output .= _hash_encode64($input, 6, $itoa64); - - return $output; -} - -/** -* Encode hash -*/ -function _hash_encode64($input, $count, &$itoa64) -{ - $output = ''; - $i = 0; - - do - { - $value = ord($input[$i++]); - $output .= $itoa64[$value & 0x3f]; - - if ($i < $count) - { - $value |= ord($input[$i]) << 8; - } - - $output .= $itoa64[($value >> 6) & 0x3f]; - - if ($i++ >= $count) - { - break; - } - - if ($i < $count) - { - $value |= ord($input[$i]) << 16; - } - - $output .= $itoa64[($value >> 12) & 0x3f]; - - if ($i++ >= $count) - { - break; - } - - $output .= $itoa64[($value >> 18) & 0x3f]; - } - while ($i < $count); - - return $output; -} - -/** -* The crypt function/replacement -*/ -function _hash_crypt_private($password, $setting, &$itoa64) -{ - $output = '*'; - - // Check for correct hash - if (substr($setting, 0, 3) != '$H$' && substr($setting, 0, 3) != '$P$') - { - return $output; - } - - $count_log2 = strpos($itoa64, $setting[3]); - - if ($count_log2 < 7 || $count_log2 > 30) - { - return $output; - } - - $count = 1 << $count_log2; - $salt = substr($setting, 4, 8); - - if (strlen($salt) != 8) - { - return $output; - } - - /** - * We're kind of forced to use MD5 here since it's the only - * cryptographic primitive available in all versions of PHP - * currently in use. To implement our own low-level crypto - * in PHP would result in much worse performance and - * consequently in lower iteration counts and hashes that are - * quicker to crack (by non-PHP code). - */ - $hash = md5($salt . $password, true); - do - { - $hash = md5($hash . $password, true); - } - while (--$count); - - $output = substr($setting, 0, 12); - $output .= _hash_encode64($hash, 16, $itoa64); - - return $output; -} - /** * Hashes an email address to a big integer * From 841dd6b19f08a575fe6d6e4794bdb9729e2ce6b8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Oct 2013 11:33:59 +0200 Subject: [PATCH 73/94] [feature/passwords] Modify forum_password column type for new hash types PHPBB3-11610 --- phpBB/includes/db/schema_data.php | 2 +- phpBB/install/schemas/firebird_schema.sql | 2 +- phpBB/install/schemas/mssql_schema.sql | 2 +- phpBB/install/schemas/mysql_40_schema.sql | 2 +- phpBB/install/schemas/mysql_41_schema.sql | 2 +- phpBB/install/schemas/oracle_schema.sql | 2 +- phpBB/install/schemas/postgres_schema.sql | 2 +- phpBB/install/schemas/sqlite_schema.sql | 2 +- phpBB/phpbb/db/migration/data/v310/passwords.php | 14 ++++++++++---- 9 files changed, 18 insertions(+), 12 deletions(-) diff --git a/phpBB/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php index 40f4ac34ab..6ac1252fb4 100644 --- a/phpBB/includes/db/schema_data.php +++ b/phpBB/includes/db/schema_data.php @@ -318,7 +318,7 @@ $schema_data['phpbb_forums'] = array( 'forum_desc_options' => array('UINT:11', 7), 'forum_desc_uid' => array('VCHAR:8', ''), 'forum_link' => array('VCHAR_UNI', ''), - 'forum_password' => array('VCHAR_UNI:40', ''), + 'forum_password' => array('VCHAR_UNI', ''), 'forum_style' => array('UINT', 0), 'forum_image' => array('VCHAR', ''), 'forum_rules' => array('TEXT_UNI', ''), diff --git a/phpBB/install/schemas/firebird_schema.sql b/phpBB/install/schemas/firebird_schema.sql index a9b7f58099..a90a60e7d0 100644 --- a/phpBB/install/schemas/firebird_schema.sql +++ b/phpBB/install/schemas/firebird_schema.sql @@ -382,7 +382,7 @@ CREATE TABLE phpbb_forums ( forum_desc_options INTEGER DEFAULT 7 NOT NULL, forum_desc_uid VARCHAR(8) CHARACTER SET NONE DEFAULT '' NOT NULL, forum_link VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - forum_password VARCHAR(40) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, + forum_password VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, forum_style INTEGER DEFAULT 0 NOT NULL, forum_image VARCHAR(255) CHARACTER SET NONE DEFAULT '' NOT NULL, forum_rules BLOB SUB_TYPE TEXT CHARACTER SET UTF8 DEFAULT '' NOT NULL, diff --git a/phpBB/install/schemas/mssql_schema.sql b/phpBB/install/schemas/mssql_schema.sql index bea116b7d6..a9ebaeb990 100644 --- a/phpBB/install/schemas/mssql_schema.sql +++ b/phpBB/install/schemas/mssql_schema.sql @@ -485,7 +485,7 @@ CREATE TABLE [phpbb_forums] ( [forum_desc_options] [int] DEFAULT (7) NOT NULL , [forum_desc_uid] [varchar] (8) DEFAULT ('') NOT NULL , [forum_link] [varchar] (255) DEFAULT ('') NOT NULL , - [forum_password] [varchar] (40) DEFAULT ('') NOT NULL , + [forum_password] [varchar] (255) DEFAULT ('') NOT NULL , [forum_style] [int] DEFAULT (0) NOT NULL , [forum_image] [varchar] (255) DEFAULT ('') NOT NULL , [forum_rules] [varchar] (4000) DEFAULT ('') NOT NULL , diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index da464f3ae7..c3bce73e50 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -266,7 +266,7 @@ CREATE TABLE phpbb_forums ( forum_desc_options int(11) UNSIGNED DEFAULT '7' NOT NULL, forum_desc_uid varbinary(8) DEFAULT '' NOT NULL, forum_link blob NOT NULL, - forum_password varbinary(120) DEFAULT '' NOT NULL, + forum_password blob DEFAULT '' NOT NULL, forum_style mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, forum_image varbinary(255) DEFAULT '' NOT NULL, forum_rules blob NOT NULL, diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index fa8929d860..d538564740 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -266,7 +266,7 @@ CREATE TABLE phpbb_forums ( forum_desc_options int(11) UNSIGNED DEFAULT '7' NOT NULL, forum_desc_uid varchar(8) DEFAULT '' NOT NULL, forum_link varchar(255) DEFAULT '' NOT NULL, - forum_password varchar(40) DEFAULT '' NOT NULL, + forum_password varchar(255) DEFAULT '' NOT NULL, forum_style mediumint(8) UNSIGNED DEFAULT '0' NOT NULL, forum_image varchar(255) DEFAULT '' NOT NULL, forum_rules text NOT NULL, diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index a2e9780b9f..4cd8aabd67 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -537,7 +537,7 @@ CREATE TABLE phpbb_forums ( forum_desc_options number(11) DEFAULT '7' NOT NULL, forum_desc_uid varchar2(8) DEFAULT '' , forum_link varchar2(765) DEFAULT '' , - forum_password varchar2(120) DEFAULT '' , + forum_password varchar2(255) DEFAULT '' , forum_style number(8) DEFAULT '0' NOT NULL, forum_image varchar2(255) DEFAULT '' , forum_rules clob DEFAULT '' , diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index ecafe8f43f..d152b750dd 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -408,7 +408,7 @@ CREATE TABLE phpbb_forums ( forum_desc_options INT4 DEFAULT '7' NOT NULL CHECK (forum_desc_options >= 0), forum_desc_uid varchar(8) DEFAULT '' NOT NULL, forum_link varchar(255) DEFAULT '' NOT NULL, - forum_password varchar(40) DEFAULT '' NOT NULL, + forum_password varchar(255) DEFAULT '' NOT NULL, forum_style INT4 DEFAULT '0' NOT NULL CHECK (forum_style >= 0), forum_image varchar(255) DEFAULT '' NOT NULL, forum_rules varchar(4000) DEFAULT '' NOT NULL, diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index d076b9823b..d55aead9b2 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -259,7 +259,7 @@ CREATE TABLE phpbb_forums ( forum_desc_options INTEGER UNSIGNED NOT NULL DEFAULT '7', forum_desc_uid varchar(8) NOT NULL DEFAULT '', forum_link varchar(255) NOT NULL DEFAULT '', - forum_password varchar(40) NOT NULL DEFAULT '', + forum_password varchar(255) NOT NULL DEFAULT '', forum_style INTEGER UNSIGNED NOT NULL DEFAULT '0', forum_image varchar(255) NOT NULL DEFAULT '', forum_rules text(65535) NOT NULL DEFAULT '', diff --git a/phpBB/phpbb/db/migration/data/v310/passwords.php b/phpBB/phpbb/db/migration/data/v310/passwords.php index c422f681ba..3422f75917 100644 --- a/phpBB/phpbb/db/migration/data/v310/passwords.php +++ b/phpBB/phpbb/db/migration/data/v310/passwords.php @@ -20,8 +20,11 @@ class passwords extends \phpbb\db\migration\migration { return array( 'change_columns' => array( - $this->table_prefix . 'users' => array( - 'user_password' => array('VCHAR:255', ''), + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:255', ''), + ), + $this->table_prefix . 'forums' => array( + 'forum_password' => array('VCHAR:255', ''), ), ), ); @@ -31,8 +34,11 @@ class passwords extends \phpbb\db\migration\migration { return array( 'change_columns' => array( - $this->table_prefix . 'users' => array( - 'user_password' => array('VCHAR:40', ''), + $this->table_prefix . 'users' => array( + 'user_password' => array('VCHAR:40', ''), + ), + $this->table_prefix . 'forums' => array( + 'forum_password' => array('VCHAR:40', ''), ), ), ); From 1d57ec1f65246c98d6fe47eb50ab297cb772d1c5 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Oct 2013 11:36:19 +0200 Subject: [PATCH 74/94] [feature/passwords] Add functional tests for forum passwords PHPBB3-11610 --- tests/functional/forum_password_test.php | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 tests/functional/forum_password_test.php diff --git a/tests/functional/forum_password_test.php b/tests/functional/forum_password_test.php new file mode 100644 index 0000000000..40a8059ad1 --- /dev/null +++ b/tests/functional/forum_password_test.php @@ -0,0 +1,55 @@ +login(); + $this->admin_login(); + + $crawler = self::request('GET', "adm/index.php?i=acp_forums&mode=manage&sid={$this->sid}"); + $form = $crawler->selectButton('addforum')->form(array( + 'forum_name' => 'Password protected', + )); + $crawler = self::submit($form); + $form = $crawler->selectButton('update')->form(array( + 'forum_perm_from' => 2, + 'forum_password' => 'foobar', + 'forum_password_confirm' => 'foobar', + )); + $crawler = self::submit($form); + } + + public function data_enter_forum_with_password() + { + return array( + array('foowrong', 'WRONG_PASSWORD'), + array('foobar', 'NO_TOPICS'), + ); + } + + /** + * @dataProvider data_enter_forum_with_password + */ + public function test_enter_forum_with_password($password, $message) + { + $crawler = self::request('GET', "index.php?sid={$this->sid}"); + preg_match('/.?f=([0-9])/', $crawler->selectLink('Password protected')->link()->getUri(), $match); + $crawler = self::request('GET', "viewforum.php?f={$match[1]}&sid={$this->sid}"); + $form = $crawler->selectButton('login')->form(array( + 'password' => $password, + )); + $crawler = self::submit($form); + $this->assertContainsLang($message, $crawler->text()); + } +} From 0f64843ac82ad49e02392459e62fdc1c5e92477c Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Oct 2013 11:37:22 +0200 Subject: [PATCH 75/94] [feature/passwords] Use VCHAR_UNI instead of VCHAR_CI for user_passwords PHPBB3-11610 --- phpBB/includes/db/schema_data.php | 2 +- phpBB/install/schemas/postgres_schema.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/includes/db/schema_data.php b/phpBB/includes/db/schema_data.php index 6ac1252fb4..e3e37f4c42 100644 --- a/phpBB/includes/db/schema_data.php +++ b/phpBB/includes/db/schema_data.php @@ -1112,7 +1112,7 @@ $schema_data['phpbb_users'] = array( 'user_regdate' => array('TIMESTAMP', 0), 'username' => array('VCHAR_CI', ''), 'username_clean' => array('VCHAR_CI', ''), - 'user_password' => array('VCHAR_CI', ''), + 'user_password' => array('VCHAR_UNI', ''), 'user_passchg' => array('TIMESTAMP', 0), 'user_pass_convert' => array('BOOL', 0), 'user_email' => array('VCHAR_UNI:100', ''), diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index d152b750dd..c1eabdf1ee 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -1246,7 +1246,7 @@ CREATE TABLE phpbb_users ( user_regdate INT4 DEFAULT '0' NOT NULL CHECK (user_regdate >= 0), username varchar_ci DEFAULT '' NOT NULL, username_clean varchar_ci DEFAULT '' NOT NULL, - user_password varchar_ci DEFAULT '' NOT NULL, + user_password varchar(255) DEFAULT '' NOT NULL, user_passchg INT4 DEFAULT '0' NOT NULL CHECK (user_passchg >= 0), user_pass_convert INT2 DEFAULT '0' NOT NULL CHECK (user_pass_convert >= 0), user_email varchar(100) DEFAULT '' NOT NULL, From e674313559c0aa4705923fd79312ef14117abb9b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Oct 2013 16:09:55 +0200 Subject: [PATCH 76/94] [feature/passwords] Use passwords.manager service in login_forum_box() Additionally, unused variables have been removed from the globals and the request class is now used instead of the request_var() function. PHPBB3-11610 --- phpBB/includes/functions.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 561ebaabb4..0a2dcc8b25 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -3310,9 +3310,9 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa */ function login_forum_box($forum_data) { - global $db, $config, $user, $template, $phpEx; + global $db, $phpbb_container, $request, $template, $user; - $password = request_var('password', '', true); + $password = $request->variable('password', '', true); $sql = 'SELECT forum_id FROM ' . FORUMS_ACCESS_TABLE . ' @@ -3353,7 +3353,9 @@ function login_forum_box($forum_data) } $db->sql_freeresult($result); - if (phpbb_check_hash($password, $forum_data['forum_password'])) + $passwords_manager = $phpbb_container->get('passwords.manager'); + + if ($passwords_manager->check($password, $forum_data['forum_password'])) { $sql_ary = array( 'forum_id' => (int) $forum_data['forum_id'], From 61f60d395a5f16105a18790f2f73eddcd830e475 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 13 Oct 2013 16:32:37 +0200 Subject: [PATCH 77/94] [feature/passwords] Use passwords manager service instead of functions The old functions phpbb_hash() and phpbb_check_hash() have been replaced with the passwords manager service in all front-end related files. The phpBB2 converter and the release_3_0_5_rc1 migration file have not been changed. The same applies to the security/hash_test that still tests the function phpbb_check_hash(). This will however make sure that the old function still works. PHPBB3-11610 --- phpBB/includes/acp/acp_forums.php | 7 +++++-- phpBB/includes/acp/acp_users.php | 7 +++++-- phpBB/includes/ucp/ucp_profile.php | 11 +++++++---- phpBB/includes/ucp/ucp_register.php | 5 ++++- phpBB/includes/ucp/ucp_remind.php | 7 +++++-- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 258aabcc0d..6a86e5683d 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -926,7 +926,7 @@ class acp_forums */ function update_forum_data(&$forum_data) { - global $db, $user, $cache, $phpbb_root_path, $phpbb_dispatcher; + global $db, $user, $cache, $phpbb_root_path, $phpbb_container, $phpbb_dispatcher; $errors = array(); @@ -1030,7 +1030,10 @@ class acp_forums } else { - $forum_data_sql['forum_password'] = phpbb_hash($forum_data_sql['forum_password']); + // Instantiate passwords manager + $passwords_manager = $phpbb_container->get('passwords.manager'); + + $forum_data_sql['forum_password'] = $passwords_manager->hash($forum_data_sql['forum_password']); } unset($forum_data_sql['forum_password_unset']); diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 8853200ddc..2d560e41f3 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -821,9 +821,12 @@ class acp_users $error[] = 'FORM_INVALID'; } + // Instantiate passwords manager + $passwords_manager = $phpbb_container->get('passwords.manager'); + // Which updates do we need to do? $update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false; - $update_password = ($data['new_password'] && !phpbb_check_hash($data['new_password'], $user_row['user_password'])) ? true : false; + $update_password = ($data['new_password'] && !$passwords_manager->check($data['new_password'], $user_row['user_password'])) ? true : false; $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false; if (!sizeof($error)) @@ -907,7 +910,7 @@ class acp_users if ($update_password) { $sql_ary += array( - 'user_password' => phpbb_hash($data['new_password']), + 'user_password' => $passwords_manager->hash($data['new_password']), 'user_passchg' => time(), 'user_pass_convert' => 0, ); diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 8ae7acaa11..ce2dbf48ea 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -82,13 +82,16 @@ class ucp_profile $error[] = ($data['password_confirm']) ? 'NEW_PASSWORD_ERROR' : 'NEW_PASSWORD_CONFIRM_EMPTY'; } + // Instantiate passwords manager + $passwords_manager = $phpbb_container->get('passwords.manager'); + // Only check the new password against the previous password if there have been no errors - if (!sizeof($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && phpbb_check_hash($data['new_password'], $user->data['user_password'])) + if (!sizeof($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && $passwords_manager->check($data['new_password'], $user->data['user_password'])) { $error[] = 'SAME_PASSWORD_ERROR'; } - if (!phpbb_check_hash($data['cur_password'], $user->data['user_password'])) + if (!$passwords_manager->check($data['cur_password'], $user->data['user_password'])) { $error[] = ($data['cur_password']) ? 'CUR_PASSWORD_ERROR' : 'CUR_PASSWORD_EMPTY'; } @@ -105,7 +108,7 @@ class ucp_profile 'username_clean' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? utf8_clean_string($data['username']) : $user->data['username_clean'], 'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'], 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? phpbb_email_hash($data['email']) : $user->data['user_email_hash'], - 'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? phpbb_hash($data['new_password']) : $user->data['user_password'], + 'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? $passwords_manager->hash($data['new_password']) : $user->data['user_password'], 'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0, ); @@ -114,7 +117,7 @@ class ucp_profile add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']); } - if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !phpbb_check_hash($data['new_password'], $user->data['user_password'])) + if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !$passwords_manager->check($data['new_password'], $user->data['user_password'])) { $user->reset_login_keys(); add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']); diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 1f9ab23326..5c7ef462fc 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -294,9 +294,12 @@ class ucp_register $user_inactive_time = 0; } + // Instantiate passwords manager + $passwords_manager = $phpbb_container->get('passwords.manager'); + $user_row = array( 'username' => $data['username'], - 'user_password' => phpbb_hash($data['new_password']), + 'user_password' => $passwords_manager->hash($data['new_password']), 'user_email' => $data['email'], 'group_id' => (int) $group_id, 'user_timezone' => $data['tz'], diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index b3def63896..44395abb44 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -27,7 +27,7 @@ class ucp_remind function main($id, $mode) { global $config, $phpbb_root_path, $phpEx; - global $db, $user, $auth, $template; + global $db, $user, $auth, $template, $phpbb_container;; if (!$config['allow_password_reset']) { @@ -88,8 +88,11 @@ class ucp_remind // For the activation key a random length between 6 and 10 will do. $user_actkey = gen_rand_string(mt_rand(6, 10)); + // Instantiate passwords manager + $passwords_manager = $phpbb_container->get('passwords.manager'); + $sql = 'UPDATE ' . USERS_TABLE . " - SET user_newpasswd = '" . $db->sql_escape(phpbb_hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "' + SET user_newpasswd = '" . $db->sql_escape($passwords_manager->hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "' WHERE user_id = " . $user_row['user_id']; $db->sql_query($sql); From 87bd628241b002c866c0d425cd8c95a42d04f31a Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Mon, 14 Oct 2013 14:31:00 +0200 Subject: [PATCH 78/94] [feature/passwords] Minor cleanup in passwords files PHPBB3-11610 --- phpBB/phpbb/passwords/driver/salted_md5.php | 3 --- phpBB/phpbb/passwords/helper.php | 1 - phpBB/phpbb/passwords/manager.php | 3 +-- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index bccf61dc07..96dd298789 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -105,7 +105,6 @@ class salted_md5 extends \phpbb\passwords\driver\base { return (md5($password) === $hash) ? true : false; } - // No need to check prefix, already did that in manage if ($hash === $this->hash($password, $hash)) { @@ -121,8 +120,6 @@ class salted_md5 extends \phpbb\passwords\driver\base */ protected function generate_salt() { - $salt = ''; - $random = ''; $count = 6; $random = $this->helper->get_random_salt($count); diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 28a13d2224..0a0bf1d6b1 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -119,7 +119,6 @@ class helper */ public function check_combined_hash($password, $stored_hash_type, $hash) { - $cur_hash = ''; $i = 0; $data = array( 'prefix' => '$', diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 0b41d3a8c3..dde81a9818 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -164,11 +164,10 @@ class manager return false; } - $return_ary[$type] = $this->get_algorithm("\${$type}\$"); + $return_ary[$type] = $this->get_algorithm('$' . $type . '$'); if (empty($return_ary[$type])) { - return false; } } From bb836b65e3c16fadf5c13510cce73daf432f7ad8 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Fri, 25 Oct 2013 15:21:09 +0200 Subject: [PATCH 79/94] [feature/passwords] Integrate convert_flag with db auth provider PHPBB3-11610 --- phpBB/phpbb/auth/provider/db.php | 2 +- phpBB/phpbb/passwords/manager.php | 4 +++- tests/auth/fixtures/user.xml | 15 +++++++++++++++ tests/auth/provider_apache_test.php | 4 ++-- tests/auth/provider_db_test.php | 7 ++++++- 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index de07a84cf5..aa597c8e9f 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -245,7 +245,7 @@ class db extends \phpbb\auth\provider\base if (!$row['user_pass_convert'] && $this->passwords_manager->check($password, $row['user_password'])) { // Check for old password hash... - if (strlen($row['user_password']) == 32) + if ($this->passwords_manager->convert_flag || strlen($row['user_password']) == 32) { $hash = $this->passwords_manager->hash($password); diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index dde81a9818..0c9eb4f067 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -243,7 +243,9 @@ class manager // Multiple hash passes needed if (is_array($stored_hash_type)) { - return $this->helper->check_combined_hash($password, $stored_hash_type, $hash); + $correct = $this->helper->check_combined_hash($password, $stored_hash_type, $hash); + $this->convert_flag = ($correct === true) ? true : false; + return $correct; } if ($stored_hash_type->get_name() !== $this->type) diff --git a/tests/auth/fixtures/user.xml b/tests/auth/fixtures/user.xml index 34584babbf..6d475930a4 100644 --- a/tests/auth/fixtures/user.xml +++ b/tests/auth/fixtures/user.xml @@ -18,6 +18,21 @@ 1 foobar foobar + $2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i + 0 + 0 + example@example.com + 0 + 0 + + + + + + + 2 + foobar2 + foobar2 $H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/ 0 0 diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index 8f65e8ad39..4c09af33e5 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -94,7 +94,7 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case 'user_row' => array( 'user_id' => '1', 'username' => 'foobar', - 'user_password' => '$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/', + 'user_password' => '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i', 'user_passchg' => '0', 'user_email' => 'example@example.com', 'user_type' => '0', @@ -130,7 +130,7 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case 'user_regdate' => '0', 'username' => 'foobar', 'username_clean' => 'foobar', - 'user_password' => '$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/', + 'user_password' => '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i', 'user_passchg' => '0', 'user_pass_convert' => '0', 'user_email' => 'example@example.com', diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index b979ab34c5..a6fe636edd 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -53,7 +53,7 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case 'user_row' => array( 'user_id' => '1', 'username' => 'foobar', - 'user_password' => '$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/', + 'user_password' => '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i', 'user_passchg' => '0', 'user_pass_convert' => '0', 'user_email' => 'example@example.com', @@ -63,5 +63,10 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case ); $this->assertEquals($expected, $provider->login('foobar', 'example')); + + // Check if convert works + $login_return = $provider->login('foobar2', 'example'); + $password_start = (version_compare(PHP_VERSION, '5.3.7', '<')) ? '$2a$10$' : '$2y$10$'; + $this->assertStringStartsWith($password_start, $login_return['user_row']['user_password']); } } From 760f148a2ba581df61a25d3efd0e438b5ea77e7b Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 27 Oct 2013 13:22:53 +0100 Subject: [PATCH 80/94] [feature/passwords] Fix tests on PHP < 5.3.3 again PHPBB3-11610 --- tests/auth/fixtures/user_533.xml | 48 +++++++++++++++++++++++++++++ tests/auth/provider_apache_test.php | 22 +++++++++++-- tests/auth/provider_db_test.php | 19 ++++++++++-- 3 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 tests/auth/fixtures/user_533.xml diff --git a/tests/auth/fixtures/user_533.xml b/tests/auth/fixtures/user_533.xml new file mode 100644 index 0000000000..c2a86ea0f9 --- /dev/null +++ b/tests/auth/fixtures/user_533.xml @@ -0,0 +1,48 @@ + + + + user_id + username + username_clean + user_password + user_passchg + user_pass_convert + user_email + user_type + user_login_attempts + user_permissions + user_sig + user_occ + user_interests + + 1 + foobar + foobar + $2a$10$e01Syh9PbJjUkio66eFuUu4FhCE2nRgG7QPc1JACalsPXcIuG2bbi + 0 + 0 + example@example.com + 0 + 0 + + + + + + + 2 + foobar2 + foobar2 + $H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/ + 0 + 0 + example@example.com + 0 + 0 + + + + + +
+
diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index 4c09af33e5..34da8e1dab 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -42,12 +42,28 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case // Set up passwords manager $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + if (version_compare(PHP_VERSION, '5.3.7', '<')) + { + $this->password_hash = '$2a$10$e01Syh9PbJjUkio66eFuUu4FhCE2nRgG7QPc1JACalsPXcIuG2bbi'; + } + else + { + $this->password_hash = '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i'; + } + $this->provider = new \phpbb\auth\provider\apache($db, $config, $passwords_manager, $this->request, $this->user, $phpbb_root_path, $phpEx); } public function getDataSet() { - return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/user.xml'); + if ((version_compare(PHP_VERSION, '5.3.7', '<'))) + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/user_533.xml'); + } + else + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/user.xml'); + } } /** @@ -94,7 +110,7 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case 'user_row' => array( 'user_id' => '1', 'username' => 'foobar', - 'user_password' => '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i', + 'user_password' => $this->password_hash, 'user_passchg' => '0', 'user_email' => 'example@example.com', 'user_type' => '0', @@ -130,7 +146,7 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case 'user_regdate' => '0', 'username' => 'foobar', 'username_clean' => 'foobar', - 'user_password' => '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i', + 'user_password' => $this->password_hash, 'user_passchg' => '0', 'user_pass_convert' => '0', 'user_email' => 'example@example.com', diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index a6fe636edd..c46d115da8 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -13,7 +13,14 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case { public function getDataSet() { - return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/user.xml'); + if ((version_compare(PHP_VERSION, '5.3.7', '<'))) + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/user_533.xml'); + } + else + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/user.xml'); + } } public function test_login() @@ -46,6 +53,14 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); $provider = new \phpbb\auth\provider\db($db, $config, $passwords_manager, $request, $user, $phpbb_root_path, $phpEx); + if (version_compare(PHP_VERSION, '5.3.7', '<')) + { + $password_hash = '$2a$10$e01Syh9PbJjUkio66eFuUu4FhCE2nRgG7QPc1JACalsPXcIuG2bbi'; + } + else + { + $password_hash = '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i'; + } $expected = array( 'status' => LOGIN_SUCCESS, @@ -53,7 +68,7 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case 'user_row' => array( 'user_id' => '1', 'username' => 'foobar', - 'user_password' => '$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i', + 'user_password' => $password_hash, 'user_passchg' => '0', 'user_pass_convert' => '0', 'user_email' => 'example@example.com', From 5193b3279cfcd4f7f5d656ec806b87e971c5523f Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 27 Oct 2013 14:18:02 +0100 Subject: [PATCH 81/94] [feature/passwords] Pass list of default types to passwords manager This list is in the order of how the driver types would be used. If a driver is not supported we will try the subsequent one. PHPBB3-11610 --- phpBB/config/passwords.yml | 8 ++++-- phpBB/phpbb/passwords/manager.php | 25 ++++++++++++++++--- tests/auth/provider_apache_test.php | 4 +-- tests/auth/provider_db_test.php | 4 +-- tests/passwords/drivers_test.php | 2 +- tests/passwords/manager_test.php | 4 +-- tests/security/hash_test.php | 4 +-- .../phpbb_functional_test_case.php | 4 +-- 8 files changed, 39 insertions(+), 16 deletions(-) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index 511f10c31c..4eeca4e34f 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -1,5 +1,9 @@ parameters: - passwords.algorithm: passwords.driver.bcrypt_2y + passwords.algorithms: + - passwords.driver.bcrypt_2y + - passwords.driver.bcrypt + - passwords.driver.salted_md5 + - passwords.driver.phpass services: passwords.driver.bcrypt: @@ -60,7 +64,7 @@ services: - @config - @passwords.driver_collection - @passwords.helper - - %passwords.algorithm% + - %passwords.algorithms% passwords.helper: class: phpbb\passwords\helper diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 0c9eb4f067..8abe7b9f79 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -63,15 +63,34 @@ class manager * @param array $hashing_algorithms Hashing driver * service collection * @param phpbb\passwords\helper $helper Passwords helper object - * @param string $default Default driver name + * @param string $defaults List of default driver types */ - public function __construct(\phpbb\config\config $config, $hashing_algorithms, \phpbb\passwords\helper $helper, $default) + public function __construct(\phpbb\config\config $config, $hashing_algorithms, \phpbb\passwords\helper $helper, $defaults) { $this->config = $config; - $this->type = $default; $this->fill_type_map($hashing_algorithms); $this->load_passwords_helper($helper); + $this->register_default_type($defaults); + } + + /** + * Register default type + * Will register the first supported type from the list of default types + * + * @param array $defaults List of default types in order from first to + * use to last to use + */ + protected function register_default_type($defaults) + { + foreach ($defaults as $type) + { + if ($this->algorithms[$type]->is_supported()) + { + $this->type = $type; + break; + } + } } /** diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index 34da8e1dab..b4322922b8 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -27,8 +27,8 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case $this->user = $this->getMock('\phpbb\user'); $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); @@ -40,7 +40,7 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); if (version_compare(PHP_VERSION, '5.3.7', '<')) { diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index c46d115da8..32c2a82710 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -37,8 +37,8 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case $user = $this->getMock('\phpbb\user'); $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); @@ -50,7 +50,7 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); $provider = new \phpbb\auth\provider\db($db, $config, $passwords_manager, $request, $user, $phpbb_root_path, $phpEx); if (version_compare(PHP_VERSION, '5.3.7', '<')) diff --git a/tests/passwords/drivers_test.php b/tests/passwords/drivers_test.php index 1fc51b1dd2..fd45c22fc1 100644 --- a/tests/passwords/drivers_test.php +++ b/tests/passwords/drivers_test.php @@ -16,8 +16,8 @@ class phpbb_passwords_helper_test extends PHPUnit_Framework_TestCase $this->driver_helper = new \phpbb\passwords\driver\helper($config); $this->passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper), 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper), 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), ); diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index f68ca25a2f..4ddd8742ae 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -22,8 +22,8 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->driver_helper = new \phpbb\passwords\driver\helper($config); $this->passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper), 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $this->driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $this->driver_helper), 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), ); @@ -35,7 +35,7 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase $this->helper = new \phpbb\passwords\helper; // Set up passwords manager - $this->manager = new \phpbb\passwords\manager($config, $this->passwords_drivers, $this->helper, 'passwords.driver.bcrypt_2y'); + $this->manager = new \phpbb\passwords\manager($config, $this->passwords_drivers, $this->helper, array_keys($this->passwords_drivers)); } public function hash_password_data() diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index c1a8c206a8..1bccc6726f 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -19,8 +19,8 @@ class phpbb_security_hash_test extends phpbb_test_case $phpbb_container = $this->getMock('Symfony\Component\DependencyInjection\ContainerInterface'); $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); @@ -32,7 +32,7 @@ class phpbb_security_hash_test extends phpbb_test_case $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); $phpbb_container ->expects($this->any()) diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index f5e2e2c77d..76487077c2 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -1003,8 +1003,8 @@ class phpbb_functional_test_case extends phpbb_test_case $driver_helper = new \phpbb\passwords\driver\helper($config); $passwords_drivers = array( - 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($config, $driver_helper), + 'passwords.driver.bcrypt' => new \phpbb\passwords\driver\bcrypt($config, $driver_helper), 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); @@ -1016,7 +1016,7 @@ class phpbb_functional_test_case extends phpbb_test_case $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager - $manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, 'passwords.driver.bcrypt_2y'); + $manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); return $manager; } From a4d50d52b67ac6e3e359dd10ecf6c156ac7cc9c2 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 27 Oct 2013 14:29:36 +0100 Subject: [PATCH 82/94] [feature/passwords] Use correct default type in manager_test PHPBB3-11610 --- tests/passwords/manager_test.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 4ddd8742ae..e965e3a692 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -125,7 +125,8 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase } // Check if convert_flag is correctly set - $this->assertEquals(($hash_type !== 'passwords.driver.bcrypt_2y'), $this->manager->convert_flag); + $default_type = (version_compare(PHP_VERSION, '5.3.7', '<')) ? 'passwords.driver.bcrypt' : 'passwords.driver.bcrypt_2y'; + $this->assertEquals(($hash_type !== $default_type), $this->manager->convert_flag); } From ac131a51592f5e45e5a555ae0ac04543d02f9c31 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sat, 28 Dec 2013 16:54:41 +0100 Subject: [PATCH 83/94] [feature/passwords] Fix indentation in auth providers PHPBB3-11610 --- phpBB/phpbb/auth/provider/apache.php | 2 +- phpBB/phpbb/auth/provider/ldap.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/auth/provider/apache.php b/phpBB/phpbb/auth/provider/apache.php index f111672a23..9bd738c3e9 100644 --- a/phpBB/phpbb/auth/provider/apache.php +++ b/phpBB/phpbb/auth/provider/apache.php @@ -36,7 +36,7 @@ class apache extends \phpbb\auth\provider\base * * @param \phpbb\db\driver\driver $db * @param \phpbb\config\config $config - * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\passwords\manager $passwords_manager * @param \phpbb\request\request $request * @param \phpbb\user $user * @param string $phpbb_root_path diff --git a/phpBB/phpbb/auth/provider/ldap.php b/phpBB/phpbb/auth/provider/ldap.php index 1e4dffde5b..00beeea21b 100644 --- a/phpBB/phpbb/auth/provider/ldap.php +++ b/phpBB/phpbb/auth/provider/ldap.php @@ -38,7 +38,7 @@ class ldap extends \phpbb\auth\provider\base * * @param \phpbb\db\driver\driver $db * @param \phpbb\config\config $config - * @param \phpbb\passwords\manager $passwords_manager + * @param \phpbb\passwords\manager $passwords_manager * @param \phpbb\user $user */ public function __construct(\phpbb\db\driver\driver $db, \phpbb\config\config $config, \phpbb\passwords\manager $passwords_manager, \phpbb\user $user) From b37549ce6343154abc603999e64a372ba7f2f902 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 14:07:27 +0100 Subject: [PATCH 84/94] [feature/passwords] Remove IN_PHPBB check from passwords files PHPBB3-11610 --- phpBB/phpbb/passwords/driver/base.php | 8 -------- phpBB/phpbb/passwords/driver/bcrypt.php | 8 -------- phpBB/phpbb/passwords/driver/bcrypt_2y.php | 8 -------- phpBB/phpbb/passwords/driver/driver_interface.php | 8 -------- phpBB/phpbb/passwords/driver/helper.php | 8 -------- phpBB/phpbb/passwords/driver/phpass.php | 8 -------- phpBB/phpbb/passwords/driver/salted_md5.php | 8 -------- phpBB/phpbb/passwords/helper.php | 8 -------- phpBB/phpbb/passwords/manager.php | 8 -------- 9 files changed, 72 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index 298b7367ad..75b9aecfdc 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index e29379a36f..04c3806fcc 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php index 8da8c8dbc8..0d4a78ad85 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt_2y.php +++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php index 8c12834641..c4b57fd96e 100644 --- a/phpBB/phpbb/passwords/driver/driver_interface.php +++ b/phpBB/phpbb/passwords/driver/driver_interface.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index 086edb6b65..77c8a87d06 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php index 32ccc399ba..2c97607717 100644 --- a/phpBB/phpbb/passwords/driver/phpass.php +++ b/phpBB/phpbb/passwords/driver/phpass.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 96dd298789..95d6df66bf 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -9,14 +9,6 @@ namespace phpbb\passwords\driver; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * * @version Version 0.1 / slightly modified for phpBB 3.1.x (using $H$ as hash type identifier) diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 0a0bf1d6b1..20c24c5ee0 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -9,14 +9,6 @@ namespace phpbb\passwords; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 8abe7b9f79..e792b2bdaa 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -9,14 +9,6 @@ namespace phpbb\passwords; -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - /** * @package passwords */ From 555cd025b2d53e681dd02756f7de3ba0bf7df321 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 16:17:37 +0100 Subject: [PATCH 85/94] [feature/passwords] Remove unnecessary specification of namespace in drivers PHPBB3-11610 --- phpBB/phpbb/passwords/driver/base.php | 2 +- phpBB/phpbb/passwords/driver/bcrypt.php | 2 +- phpBB/phpbb/passwords/driver/bcrypt_2y.php | 2 +- phpBB/phpbb/passwords/driver/phpass.php | 2 +- phpBB/phpbb/passwords/driver/salted_md5.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index 75b9aecfdc..b5414fccdc 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -12,7 +12,7 @@ namespace phpbb\passwords\driver; /** * @package passwords */ -abstract class base implements \phpbb\passwords\driver\driver_interface +abstract class base implements driver_interface { /** @var phpbb\config\config */ protected $config; diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index 04c3806fcc..1d1b1e267d 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -12,7 +12,7 @@ namespace phpbb\passwords\driver; /** * @package passwords */ -class bcrypt extends \phpbb\passwords\driver\base +class bcrypt extends base { const PREFIX = '$2a$'; diff --git a/phpBB/phpbb/passwords/driver/bcrypt_2y.php b/phpBB/phpbb/passwords/driver/bcrypt_2y.php index 0d4a78ad85..11c3617e49 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt_2y.php +++ b/phpBB/phpbb/passwords/driver/bcrypt_2y.php @@ -12,7 +12,7 @@ namespace phpbb\passwords\driver; /** * @package passwords */ -class bcrypt_2y extends \phpbb\passwords\driver\bcrypt +class bcrypt_2y extends bcrypt { const PREFIX = '$2y$'; diff --git a/phpBB/phpbb/passwords/driver/phpass.php b/phpBB/phpbb/passwords/driver/phpass.php index 2c97607717..80c4d7a7f0 100644 --- a/phpBB/phpbb/passwords/driver/phpass.php +++ b/phpBB/phpbb/passwords/driver/phpass.php @@ -12,7 +12,7 @@ namespace phpbb\passwords\driver; /** * @package passwords */ -class phpass extends \phpbb\passwords\driver\salted_md5 +class phpass extends salted_md5 { const PREFIX = '$P$'; diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 95d6df66bf..08b0db29a0 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -40,7 +40,7 @@ namespace phpbb\passwords\driver; /** * @package passwords */ -class salted_md5 extends \phpbb\passwords\driver\base +class salted_md5 extends base { const PREFIX = '$H$'; From 808c54fa89f556e6f4701d4f8c6c418393ddfc13 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 16:33:09 +0100 Subject: [PATCH 86/94] [feature/passwords] Get rid of unneeded code complexity Simplified a little bit of code as pointed out by imkingdavid on github. PHPBB3-11610 --- phpBB/includes/acp/acp_users.php | 2 +- phpBB/phpbb/passwords/driver/bcrypt.php | 5 ++--- phpBB/phpbb/passwords/driver/salted_md5.php | 10 +++------- phpBB/phpbb/passwords/helper.php | 5 +---- 4 files changed, 7 insertions(+), 15 deletions(-) diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 8a3c7eabcc..d77152e0cf 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -829,7 +829,7 @@ class acp_users // Which updates do we need to do? $update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false; - $update_password = ($data['new_password'] && !$passwords_manager->check($data['new_password'], $user_row['user_password'])) ? true : false; + $update_password = $data['new_password'] && !$passwords_manager->check($data['new_password'], $user_row['user_password']); $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false; if (!sizeof($error)) diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index 1d1b1e267d..b16d2ada56 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -29,9 +29,8 @@ class bcrypt extends base */ public function hash($password, $salt = '') { - // The 2x and 2y prefixes of bcrypt might not be supported - // Revert to 2a if this is the case - $prefix = (!$this->is_supported()) ? '$2a$' : $this->get_prefix(); + // Get prefix of this driver + $prefix = $this->get_prefix(); // Do not support 8-bit characters with $2a$ bcrypt // Also see http://www.php.net/security/crypt_blowfish.php diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 08b0db29a0..72db8d200f 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -57,7 +57,7 @@ class salted_md5 extends base */ public function hash($password, $setting = '') { - if ($setting != '') + if ($setting) { if (($settings = $this->get_hash_settings($setting)) === false) { @@ -95,14 +95,10 @@ class salted_md5 extends base { if (strlen($hash) !== 34) { - return (md5($password) === $hash) ? true : false; + return md5($password) === $hash; } - if ($hash === $this->hash($password, $hash)) - { - return true; - } - return false; + return $hash === $this->hash($password, $hash); } /** diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 20c24c5ee0..59f0bd24ef 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -26,10 +26,7 @@ class helper */ public function set_manager(\phpbb\passwords\manager $manager) { - if ($this->manager === null) - { - $this->manager = $manager; - } + $this->manager = $manager; } /** From 141bef75cb924644191c90bd722a250ef60099b7 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 17:04:38 +0100 Subject: [PATCH 87/94] [feature/passwords] Undo simplification to bcrypt driver By simplifying, a needed part was removed that is actually required. PHPBB3-11610 --- phpBB/phpbb/passwords/driver/bcrypt.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index b16d2ada56..1d1b1e267d 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -29,8 +29,9 @@ class bcrypt extends base */ public function hash($password, $salt = '') { - // Get prefix of this driver - $prefix = $this->get_prefix(); + // The 2x and 2y prefixes of bcrypt might not be supported + // Revert to 2a if this is the case + $prefix = (!$this->is_supported()) ? '$2a$' : $this->get_prefix(); // Do not support 8-bit characters with $2a$ bcrypt // Also see http://www.php.net/security/crypt_blowfish.php From 8383d1f1d3b5f3ac12248920f7cf79d8aa6399fc Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 17:55:00 +0100 Subject: [PATCH 88/94] [feature/passwords] Add missing documentation to docblocks Also contains some minor spacing changes. PHPBB3-11610 --- phpBB/phpbb/passwords/driver/base.php | 3 ++- phpBB/phpbb/passwords/driver/driver_interface.php | 7 ++++++- phpBB/phpbb/passwords/driver/helper.php | 5 ++++- phpBB/phpbb/passwords/driver/salted_md5.php | 8 ++++++-- phpBB/phpbb/passwords/helper.php | 9 +++++---- phpBB/phpbb/passwords/manager.php | 5 +++-- 6 files changed, 26 insertions(+), 11 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index b5414fccdc..f938bdd587 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -26,7 +26,8 @@ abstract class base implements driver_interface /** * Constructor of passwords driver object * - * @return string Hash prefix + * @param \phpbb\config\config $config phpBB config + * @param \phpbb\passwords\driver\helper $helper Password driver helper */ public function __construct(\phpbb\config\config $config, \phpbb\passwords\driver\helper $helper) { diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php index c4b57fd96e..53065dfb02 100644 --- a/phpBB/phpbb/passwords/driver/driver_interface.php +++ b/phpBB/phpbb/passwords/driver/driver_interface.php @@ -20,6 +20,7 @@ interface driver_interface * @return bool True if supported, false if not */ public function is_supported(); + /** * Returns the hash prefix * @@ -30,7 +31,10 @@ interface driver_interface /** * Hash the password * - * @return string Password hash + * @param string $password The password that should be hashed + * + * @return bool|string Password hash or false if something went wrong + * during hashing */ public function hash($password); @@ -39,6 +43,7 @@ interface driver_interface * * @param string $password The password to check * @param string $hash The password hash to check against + * * @return bool True if password is correct, else false */ public function check($password, $hash); diff --git a/phpBB/phpbb/passwords/driver/helper.php b/phpBB/phpbb/passwords/driver/helper.php index 77c8a87d06..4b8dc9a123 100644 --- a/phpBB/phpbb/passwords/driver/helper.php +++ b/phpBB/phpbb/passwords/driver/helper.php @@ -86,7 +86,8 @@ class helper /** * Return unique id - * @param string $extra additional entropy + * + * @param string $extra Additional entropy * * @return string Unique id */ @@ -113,6 +114,8 @@ class helper * * @param int $length Salt length * @param string $rand_seed Seed for random data (optional). For tests. + * + * @return string Random salt with specified length */ public function get_random_salt($length, $rand_seed = '/dev/urandom') { diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index 72db8d200f..5c72726422 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -122,8 +122,11 @@ class salted_md5 extends base /** * Get hash settings * - * @return array Array containing the count_log2, salt, and full hash - * settings string + * @param string $hash The hash that contains the settings + * + * @return bool|array Array containing the count_log2, salt, and full + * hash settings string or false if supplied hash is empty + * or contains incorrect settings */ public function get_hash_settings($hash) { @@ -131,6 +134,7 @@ class salted_md5 extends base { return false; } + $count_log2 = strpos($this->helper->itoa64, $hash[3]); $salt = substr($hash, 4, 8); diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 59f0bd24ef..342dae62e6 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -22,7 +22,7 @@ class helper /** * Set the passwords manager instance * - * @param phpbb\passwords\manager $manager Crypto manager object + * @param phpbb\passwords\manager $manager Passwords manager object */ public function set_manager(\phpbb\passwords\manager $manager) { @@ -35,8 +35,9 @@ class helper * @param string $hash Password hash of combined hash * * @return array An array containing the hash settings for the hash - * types in successive order as described by the comined - * password hash + * types in successive order as described by the combined + * password hash or an empty array if hash does not + * properly fit the combined hash format */ protected function get_combined_hash_settings($hash) { @@ -134,7 +135,7 @@ class helper * @param string $type Data type of the supplied value * @param string $value Value that should be put into the data array * - * @return string|none Return complete combined hash if type is neither + * @return string|null Return complete combined hash if type is neither * 'prefix' nor 'settings', nothing if it is */ protected function combine_hash_output(&$data, $type, $value) diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index e792b2bdaa..c208c59df7 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -37,7 +37,7 @@ class manager public $convert_flag = false; /** - * Crypto helper + * Passwords helper * @var phpbb\passwords\helper */ protected $helper; @@ -125,7 +125,8 @@ class manager * * @param string $prefix Password hash prefix * - * @return object The hash type object + * @return object|bool The hash type object or false if prefix is not + * supported */ protected function get_algorithm($prefix) { From 1465915830859a7c9664e477739df5f125cfcdff Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 17:56:41 +0100 Subject: [PATCH 89/94] [feature/passwords] Remove unneeded definitions of full namespace PHPBB3-11610 --- phpBB/phpbb/passwords/driver/base.php | 2 +- phpBB/phpbb/passwords/helper.php | 2 +- phpBB/phpbb/passwords/manager.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index f938bdd587..91c07a813b 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -29,7 +29,7 @@ abstract class base implements driver_interface * @param \phpbb\config\config $config phpBB config * @param \phpbb\passwords\driver\helper $helper Password driver helper */ - public function __construct(\phpbb\config\config $config, \phpbb\passwords\driver\helper $helper) + public function __construct(\phpbb\config\config $config, helper $helper) { $this->config = $config; $this->helper = $helper; diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index 342dae62e6..c7937a4c5c 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -24,7 +24,7 @@ class helper * * @param phpbb\passwords\manager $manager Passwords manager object */ - public function set_manager(\phpbb\passwords\manager $manager) + public function set_manager(manager $manager) { $this->manager = $manager; } diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index c208c59df7..539fdca954 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -57,7 +57,7 @@ class manager * @param phpbb\passwords\helper $helper Passwords helper object * @param string $defaults List of default driver types */ - public function __construct(\phpbb\config\config $config, $hashing_algorithms, \phpbb\passwords\helper $helper, $defaults) + public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults) { $this->config = $config; From 4b832cf2bd95f1af44d72dee45ff23b1eb9179ae Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 17:57:17 +0100 Subject: [PATCH 90/94] [feature/passwords] Intialize output array before usage in passwords helper PHPBB3-11610 --- phpBB/phpbb/passwords/helper.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index c7937a4c5c..fdf2b6f907 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -41,6 +41,8 @@ class helper */ protected function get_combined_hash_settings($hash) { + $output = array(); + preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match); $hash_settings = substr($hash, strpos($hash, $match[1]) + strlen($match[1]) + 1); $matches = explode('\\', $match[1]); From 85f1e8afa55356f620a8715ba9fcaaec491dff96 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 29 Dec 2013 20:52:25 +0100 Subject: [PATCH 91/94] [feature/passwords] Correct docblock of phpbb_hash() function PHPBB3-11610 --- phpBB/includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index f779bf0622..9765b10056 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -374,7 +374,7 @@ function still_on_time($extra_time = 15) * * @param string $password Password to be hashed * -* @return string Password hash or false if something went wrong during hashing +* @return string|bool Password hash or false if something went wrong during hashing */ function phpbb_hash($password) { From 292961a2771c9237197b9770b23a2a14a981c329 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 2 Feb 2014 14:09:09 +0100 Subject: [PATCH 92/94] [feature/passwords] Get rid of set_name/get_name methods for passwords drivers PHPBB3-11610 --- phpBB/config/passwords.yml | 8 -------- phpBB/phpbb/passwords/driver/base.php | 18 ----------------- .../passwords/driver/driver_interface.php | 7 ------- phpBB/phpbb/passwords/manager.php | 20 ++++++++----------- tests/auth/provider_apache_test.php | 5 ----- tests/auth/provider_db_test.php | 5 ----- tests/passwords/drivers_test.php | 5 ----- tests/passwords/manager_test.php | 5 ----- tests/security/hash_test.php | 5 ----- .../phpbb_functional_test_case.php | 5 ----- 10 files changed, 8 insertions(+), 75 deletions(-) diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index 4eeca4e34f..9e249a2c12 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -11,8 +11,6 @@ services: arguments: - @config - @passwords.driver_helper - calls: - - [set_name, [passwords.driver.bcrypt]] tags: - { name: passwords.driver } @@ -21,8 +19,6 @@ services: arguments: - @config - @passwords.driver_helper - calls: - - [set_name, [passwords.driver.bcrypt_2y]] tags: - { name: passwords.driver } @@ -31,8 +27,6 @@ services: arguments: - @config - @passwords.driver_helper - calls: - - [set_name, [passwords.driver.salted_md5]] tags: - { name: passwords.driver } @@ -41,8 +35,6 @@ services: arguments: - @config - @passwords.driver_helper - calls: - - [set_name, [passwords.driver.phpass]] tags: - { name: passwords.driver } diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index 91c07a813b..8256fd721c 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -42,22 +42,4 @@ abstract class base implements driver_interface { return true; } - - /** - * @inheritdoc - */ - public function get_name() - { - return $this->name; - } - - /** - * Set driver name - * - * @param string $name Driver name - */ - public function set_name($name) - { - $this->name = $name; - } } diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php index 53065dfb02..ebaf0626af 100644 --- a/phpBB/phpbb/passwords/driver/driver_interface.php +++ b/phpBB/phpbb/passwords/driver/driver_interface.php @@ -57,11 +57,4 @@ interface driver_interface * @return string String containing the hash settings */ public function get_settings_only($hash, $full = false); - - /** - * Get the driver name - * - * @return string Driver name - */ - public function get_name(); } diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 539fdca954..7aeb496eb5 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -79,7 +79,7 @@ class manager { if ($this->algorithms[$type]->is_supported()) { - $this->type = $type; + $this->type = $this->algorithms[$type]->get_prefix(); break; } } @@ -94,16 +94,12 @@ class manager { foreach ($hashing_algorithms as $algorithm) { - if (!isset($this->algorithms[$algorithm->get_name()])) - { - $this->algorithms[$algorithm->get_name()] = $algorithm; - } - if (!isset($this->type_map[$algorithm->get_prefix()])) { - $this->type_map[$algorithm->get_prefix()] = $algorithm->get_name(); + $this->type_map[$algorithm->get_prefix()] = $algorithm; } } + $this->algorithms = $hashing_algorithms; } /** @@ -130,9 +126,9 @@ class manager */ protected function get_algorithm($prefix) { - if (isset($this->type_map[$prefix]) && isset($this->algorithms[$this->type_map[$prefix]])) + if (isset($this->type_map[$prefix])) { - return $this->algorithms[$this->type_map[$prefix]]; + return $this->type_map[$prefix]; } else { @@ -216,9 +212,9 @@ class manager return $this->helper->combined_hash_password($password, $type); } - if (isset($this->algorithms[$type])) + if (isset($this->type_map[$type])) { - $hashing_algorithm = $this->algorithms[$type]; + $hashing_algorithm = $this->type_map[$type]; } else { @@ -260,7 +256,7 @@ class manager return $correct; } - if ($stored_hash_type->get_name() !== $this->type) + if ($stored_hash_type->get_prefix() !== $this->type) { $this->convert_flag = true; } diff --git a/tests/auth/provider_apache_test.php b/tests/auth/provider_apache_test.php index dbd98d9a66..1231c16a4c 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -34,11 +34,6 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); - foreach ($passwords_drivers as $key => $driver) - { - $driver->set_name($key); - } - $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index b18b6a1ae2..91ffcdc2a7 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -44,11 +44,6 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); - foreach ($passwords_drivers as $key => $driver) - { - $driver->set_name($key); - } - $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); diff --git a/tests/passwords/drivers_test.php b/tests/passwords/drivers_test.php index fd45c22fc1..2d26be7da5 100644 --- a/tests/passwords/drivers_test.php +++ b/tests/passwords/drivers_test.php @@ -21,11 +21,6 @@ class phpbb_passwords_helper_test extends PHPUnit_Framework_TestCase 'passwords.driver.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), ); - - foreach ($this->passwords_drivers as $key => $driver) - { - $driver->set_name($key); - } } public function data_helper_encode64() diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index e965e3a692..11efaa5afd 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -28,11 +28,6 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), ); - foreach ($this->passwords_drivers as $key => $driver) - { - $driver->set_name($key); - } - $this->helper = new \phpbb\passwords\helper; // Set up passwords manager $this->manager = new \phpbb\passwords\manager($config, $this->passwords_drivers, $this->helper, array_keys($this->passwords_drivers)); diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index 1bccc6726f..bc1bebd87a 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -25,11 +25,6 @@ class phpbb_security_hash_test extends phpbb_test_case 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); - foreach ($passwords_drivers as $key => $driver) - { - $driver->set_name($key); - } - $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager $passwords_manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); diff --git a/tests/test_framework/phpbb_functional_test_case.php b/tests/test_framework/phpbb_functional_test_case.php index b61fb25326..71d03746a9 100644 --- a/tests/test_framework/phpbb_functional_test_case.php +++ b/tests/test_framework/phpbb_functional_test_case.php @@ -1017,11 +1017,6 @@ class phpbb_functional_test_case extends phpbb_test_case 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $driver_helper), ); - foreach ($passwords_drivers as $key => $driver) - { - $driver->set_name($key); - } - $passwords_helper = new \phpbb\passwords\helper; // Set up passwords manager $manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers)); From 08a8bd8e6f2ae339fbb29e01ffb002942e7a89f3 Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 2 Feb 2014 14:11:32 +0100 Subject: [PATCH 93/94] [feature/passwords] Add support for passwords driver service name in hash() This will allow users to specify both the hash type by prefix and by its service name. PHPBB3-11610 --- phpBB/phpbb/passwords/manager.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 7aeb496eb5..7f886e3d7d 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -205,6 +205,13 @@ class manager return false; } + // Try to retrieve algorithm by service name if type doesn't + // start with dollar sign + if (!is_array($type) && strpos($type, '$') !== 0 && isset($this->algorithms[$type])) + { + $type = $this->algorithms[$type]->get_prefix(); + } + $type = ($type === '') ? $this->type : $type; if (is_array($type)) From b094c7999660703370566018bf449a9280148b8d Mon Sep 17 00:00:00 2001 From: Marc Alexander Date: Sun, 2 Feb 2014 14:57:43 +0100 Subject: [PATCH 94/94] [feature/passwords] Move combined hashing methods to manager This will get rid of the circular dependency between the passwords manager and the passwords helper. The combined_hash_password() method was also slightly changed to allow both the definitions of service names or prefixes for the hash types. PHPBB3-11610 --- phpBB/phpbb/passwords/helper.php | 96 ++---------------------------- phpBB/phpbb/passwords/manager.php | 98 +++++++++++++++++++++++++------ tests/passwords/manager_test.php | 8 +++ 3 files changed, 93 insertions(+), 109 deletions(-) diff --git a/phpBB/phpbb/passwords/helper.php b/phpBB/phpbb/passwords/helper.php index fdf2b6f907..95bad5805f 100644 --- a/phpBB/phpbb/passwords/helper.php +++ b/phpBB/phpbb/passwords/helper.php @@ -14,21 +14,6 @@ namespace phpbb\passwords; */ class helper { - /** - * @var phpbb\passwords\manager - */ - protected $manager; - - /** - * Set the passwords manager instance - * - * @param phpbb\passwords\manager $manager Passwords manager object - */ - public function set_manager(manager $manager) - { - $this->manager = $manager; - } - /** * Get hash settings from combined hash * @@ -39,7 +24,7 @@ class helper * password hash or an empty array if hash does not * properly fit the combined hash format */ - protected function get_combined_hash_settings($hash) + public function get_combined_hash_settings($hash) { $output = array(); @@ -56,79 +41,6 @@ class helper return $output; } - /** - * Create combined hash from already hashed password - * - * @param string $password_hash Complete current password hash - * @param string $type Type of the hashing algorithm the password hash - * should be combined with - * @return string|bool Combined password hash if combined hashing was - * successful, else false - */ - public function combined_hash_password($password_hash, $type) - { - $data = array( - 'prefix' => '$', - 'settings' => '$', - ); - $hash_settings = $this->get_combined_hash_settings($password_hash); - $hash = $hash_settings[0]; - - // Put settings of current hash into data array - $stored_hash_type = $this->manager->detect_algorithm($password_hash); - $this->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix()); - $this->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash)); - - // Hash current hash with the defined types - foreach ($type as $cur_type) - { - if (isset($this->manager->algorithms[$cur_type])) - { - $new_hash_type = $this->manager->algorithms[$cur_type]; - } - else - { - return false; - } - - $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash)); - $this->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix()); - $this->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0)); - $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->obtain_hash_only($new_hash)); - } - return $this->combine_hash_output($data, 'hash', $hash); - } - - /** - * Check combined password hash against the supplied password - * - * @param string $password Password entered by user - * @param array $stored_hash_type An array containing the hash types - * as described by stored password hash - * @param string $hash Stored password hash - * - * @return bool True if password is correct, false if not - */ - public function check_combined_hash($password, $stored_hash_type, $hash) - { - $i = 0; - $data = array( - 'prefix' => '$', - 'settings' => '$', - ); - $hash_settings = $this->get_combined_hash_settings($hash); - foreach ($stored_hash_type as $key => $hash_type) - { - $rebuilt_hash = $this->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]); - $this->combine_hash_output($data, 'prefix', $key); - $this->combine_hash_output($data, 'settings', $hash_settings[$i]); - $cur_hash = $hash_type->hash($password, $rebuilt_hash); - $password = str_replace($rebuilt_hash, '', $cur_hash); - $i++; - } - return ($hash === $this->combine_hash_output($data, 'hash', $password)); - } - /** * Combine hash prefixes, settings, and actual hash * @@ -140,7 +52,7 @@ class helper * @return string|null Return complete combined hash if type is neither * 'prefix' nor 'settings', nothing if it is */ - protected function combine_hash_output(&$data, $type, $value) + public function combine_hash_output(&$data, $type, $value) { if ($type == 'prefix') { @@ -167,7 +79,7 @@ class helper * * @return string Rebuilt hash for hashing functions */ - protected function rebuild_hash($prefix, $settings) + public function rebuild_hash($prefix, $settings) { $rebuilt_hash = $prefix; if (strpos($settings, '\\') !== false) @@ -184,7 +96,7 @@ class helper * @param string $hash The full password hash * @return string Actual hash (incl. settings) */ - protected function obtain_hash_only($hash) + public function obtain_hash_only($hash) { return substr($hash, strripos($hash, '$') + 1); } diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 7f886e3d7d..0ac6b05ec4 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -60,9 +60,9 @@ class manager public function __construct(\phpbb\config\config $config, $hashing_algorithms, helper $helper, $defaults) { $this->config = $config; + $this->helper = $helper; $this->fill_type_map($hashing_algorithms); - $this->load_passwords_helper($helper); $this->register_default_type($defaults); } @@ -102,20 +102,6 @@ class manager $this->algorithms = $hashing_algorithms; } - /** - * Load passwords helper class - * - * @param phpbb\passwords\helper $helper Passwords helper object - */ - protected function load_passwords_helper(\phpbb\passwords\helper $helper) - { - if ($this->helper === null) - { - $this->helper = $helper; - $this->helper->set_manager($this); - } - } - /** * Get the algorithm specified by a specific prefix * @@ -216,7 +202,7 @@ class manager if (is_array($type)) { - return $this->helper->combined_hash_password($password, $type); + return $this->combined_hash_password($password, $type); } if (isset($this->type_map[$type])) @@ -258,7 +244,7 @@ class manager // Multiple hash passes needed if (is_array($stored_hash_type)) { - $correct = $this->helper->check_combined_hash($password, $stored_hash_type, $hash); + $correct = $this->check_combined_hash($password, $stored_hash_type, $hash); $this->convert_flag = ($correct === true) ? true : false; return $correct; } @@ -274,4 +260,82 @@ class manager return $stored_hash_type->check($password, $hash); } + + /** + * Create combined hash from already hashed password + * + * @param string $password_hash Complete current password hash + * @param string $type Type of the hashing algorithm the password hash + * should be combined with + * @return string|bool Combined password hash if combined hashing was + * successful, else false + */ + public function combined_hash_password($password_hash, $type) + { + $data = array( + 'prefix' => '$', + 'settings' => '$', + ); + $hash_settings = $this->helper->get_combined_hash_settings($password_hash); + $hash = $hash_settings[0]; + + // Put settings of current hash into data array + $stored_hash_type = $this->detect_algorithm($password_hash); + $this->helper->combine_hash_output($data, 'prefix', $stored_hash_type->get_prefix()); + $this->helper->combine_hash_output($data, 'settings', $stored_hash_type->get_settings_only($password_hash)); + + // Hash current hash with the defined types + foreach ($type as $cur_type) + { + if (isset($this->algorithms[$cur_type])) + { + $new_hash_type = $this->algorithms[$cur_type]; + } + else + { + $new_hash_type = $this->get_algorithm($cur_type); + } + + if (!$new_hash_type) + { + return false; + } + + $new_hash = $new_hash_type->hash(str_replace($stored_hash_type->get_settings_only($password_hash), '', $hash)); + $this->helper->combine_hash_output($data, 'prefix', $new_hash_type->get_prefix()); + $this->helper->combine_hash_output($data, 'settings', substr(str_replace('$', '\\', $new_hash_type->get_settings_only($new_hash, true)), 0)); + $hash = str_replace($new_hash_type->get_settings_only($new_hash), '', $this->helper->obtain_hash_only($new_hash)); + } + return $this->helper->combine_hash_output($data, 'hash', $hash); + } + + /** + * Check combined password hash against the supplied password + * + * @param string $password Password entered by user + * @param array $stored_hash_type An array containing the hash types + * as described by stored password hash + * @param string $hash Stored password hash + * + * @return bool True if password is correct, false if not + */ + public function check_combined_hash($password, $stored_hash_type, $hash) + { + $i = 0; + $data = array( + 'prefix' => '$', + 'settings' => '$', + ); + $hash_settings = $this->helper->get_combined_hash_settings($hash); + foreach ($stored_hash_type as $key => $hash_type) + { + $rebuilt_hash = $this->helper->rebuild_hash($hash_type->get_prefix(), $hash_settings[$i]); + $this->helper->combine_hash_output($data, 'prefix', $key); + $this->helper->combine_hash_output($data, 'settings', $hash_settings[$i]); + $cur_hash = $hash_type->hash($password, $rebuilt_hash); + $password = str_replace($rebuilt_hash, '', $cur_hash); + $i++; + } + return ($hash === $this->helper->combine_hash_output($data, 'hash', $password)); + } } diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index 11efaa5afd..ee295ff043 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -198,6 +198,10 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase array('passwords.driver.salted_md5'), false, ), + array( + '$H$', + array('$2a$'), + ), ); } else @@ -229,6 +233,10 @@ class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase array('passwords.driver.salted_md4'), false, ), + array( + '$H$', + array('$2y$'), + ), ); } }