diff --git a/phpBB/config/auth_providers.yml b/phpBB/config/auth_providers.yml index dac8b9d252..d2f22ec477 100644 --- a/phpBB/config/auth_providers.yml +++ b/phpBB/config/auth_providers.yml @@ -1,8 +1,9 @@ services: auth.provider_collection: - class: phpbb\di\service_collection + class: phpbb\auth\provider_collection arguments: - @service_container + - @config tags: - { name: service_collection, tag: auth.provider } auth.provider.db: diff --git a/phpBB/config/passwords.yml b/phpBB/config/passwords.yml index 9e249a2c12..3dc217286f 100644 --- a/phpBB/config/passwords.yml +++ b/phpBB/config/passwords.yml @@ -22,6 +22,14 @@ services: tags: - { name: passwords.driver } + passwords.driver.bcrypt_wcf2: + class: phpbb\passwords\driver\bcrypt_wcf2 + arguments: + - @passwords.driver.bcrypt + - @passwords.driver_helper + tags: + - { name: passwords.driver } + passwords.driver.salted_md5: class: phpbb\passwords\driver\salted_md5 arguments: @@ -38,6 +46,64 @@ services: tags: - { name: passwords.driver } + passwords.driver.convert_password: + class: phpbb\passwords\driver\convert_password + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.sha1_smf: + class: phpbb\passwords\driver\sha1_smf + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.sha1_wcf1: + class: phpbb\passwords\driver\sha1_wcf1 + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.sha1: + class: phpbb\passwords\driver\sha1 + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.md5_phpbb2: + class: phpbb\passwords\driver\md5_phpbb2 + arguments: + - @request + - @passwords.driver.salted_md5 + - %core.root_path% + - %core.php_ext% + tags: + - { name: passwords.driver } + + passwords.driver.md5_mybb: + class: phpbb\passwords\driver\md5_mybb + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + + passwords.driver.md5_vb: + class: phpbb\passwords\driver\md5_vb + arguments: + - @config + - @passwords.driver_helper + tags: + - { name: passwords.driver } + passwords.driver_collection: class: phpbb\di\service_collection arguments: diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 83ab88d48c..d07120a65f 100644 --- a/phpBB/includes/acp/acp_users.php +++ b/phpBB/includes/acp/acp_users.php @@ -922,7 +922,6 @@ class acp_users $sql_ary += array( 'user_password' => $passwords_manager->hash($data['new_password']), 'user_passchg' => time(), - 'user_pass_convert' => 0, ); $user->reset_login_keys($user_id); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index be032440b9..3238f66e96 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2854,7 +2854,8 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $s_hidden_fields['credential'] = $credential; } - $auth_provider = $phpbb_container->get('auth.provider.' . $config['auth_method']); + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $auth_provider = $provider_collection->get_provider(); $auth_provider_data = $auth_provider->get_login_data(); if ($auth_provider_data) diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index fafe29f957..d728ed7d78 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -184,7 +184,6 @@ function user_add($user_row, $cp_data = false) 'username' => $user_row['username'], 'username_clean' => $username_clean, 'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '', - 'user_pass_convert' => 0, 'user_email' => strtolower($user_row['user_email']), 'user_email_hash' => phpbb_email_hash($user_row['user_email']), 'group_id' => $user_row['group_id'], diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 06326e57e6..53dec89aad 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -78,7 +78,6 @@ class ucp_activate 'user_actkey' => '', 'user_password' => $user_row['user_newpasswd'], 'user_newpasswd' => '', - 'user_pass_convert' => 0, 'user_login_attempts' => 0, ); diff --git a/phpBB/install/schemas/schema.json b/phpBB/install/schemas/schema.json index f684fddc25..79f06693a6 100644 --- a/phpBB/install/schemas/schema.json +++ b/phpBB/install/schemas/schema.json @@ -3023,10 +3023,6 @@ "TIMESTAMP", 0 ], - "user_pass_convert": [ - "BOOL", - 0 - ], "user_email": [ "VCHAR_UNI:100", "" diff --git a/phpBB/phpbb/auth/provider/db.php b/phpBB/phpbb/auth/provider/db.php index 3be1d3873f..142a47247f 100644 --- a/phpBB/phpbb/auth/provider/db.php +++ b/phpBB/phpbb/auth/provider/db.php @@ -78,7 +78,7 @@ class db extends \phpbb\auth\provider\base $username_clean = utf8_clean_string($username); - $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts + $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type, user_login_attempts FROM ' . USERS_TABLE . " WHERE username_clean = '" . $this->db->sql_escape($username_clean) . "'"; $result = $this->db->sql_query($sql); @@ -170,72 +170,8 @@ class db extends \phpbb\auth\provider\base } - // If the password convert flag is set we need to convert it - if ($row['user_pass_convert']) - { - // enable super globals to get literal value - // this is needed to prevent unicode normalization - $super_globals_disabled = $this->request->super_globals_disabled(); - if ($super_globals_disabled) - { - $this->request->enable_super_globals(); - } - - // in phpBB2 passwords were used exactly as they were sent, with addslashes applied - $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : ''; - $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format; - $password_new_format = $this->request->variable('password', '', true); - - if ($super_globals_disabled) - { - $this->request->disable_super_globals(); - } - - if ($password == $password_new_format) - { - if (!function_exists('utf8_to_cp1252')) - { - include($this->phpbb_root_path . 'includes/utf/data/recode_basic.' . $this->php_ext); - } - - // 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 && ($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 = $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 . ' - SET user_password = \'' . $this->db->sql_escape($hash) . '\', - user_pass_convert = 0 - WHERE user_id = ' . $row['user_id']; - $this->db->sql_query($sql); - - $row['user_pass_convert'] = 0; - $row['user_password'] = $hash; - } - else - { - // Although we weren't able to convert this password we have to - // increase login attempt count to make sure this cannot be exploited - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_login_attempts = user_login_attempts + 1 - WHERE user_id = ' . (int) $row['user_id'] . ' - AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX; - $this->db->sql_query($sql); - - return array( - 'status' => LOGIN_ERROR_PASSWORD_CONVERT, - 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT', - 'user_row' => $row, - ); - } - } - } - // Check password ... - if (!$row['user_pass_convert'] && $this->passwords_manager->check($password, $row['user_password'])) + if ($this->passwords_manager->check($password, $row['user_password'])) { // Check for old password hash... if ($this->passwords_manager->convert_flag || strlen($row['user_password']) == 32) @@ -244,8 +180,7 @@ class db extends \phpbb\auth\provider\base // Update the password in the users table to the new format $sql = 'UPDATE ' . USERS_TABLE . " - SET user_password = '" . $this->db->sql_escape($hash) . "', - user_pass_convert = 0 + SET user_password = '" . $this->db->sql_escape($hash) . "' WHERE user_id = {$row['user_id']}"; $this->db->sql_query($sql); diff --git a/phpBB/phpbb/auth/provider/oauth/oauth.php b/phpBB/phpbb/auth/provider/oauth/oauth.php index 2230ce15d1..07430bb42a 100644 --- a/phpBB/phpbb/auth/provider/oauth/oauth.php +++ b/phpBB/phpbb/auth/provider/oauth/oauth.php @@ -215,7 +215,7 @@ class oauth extends \phpbb\auth\provider\base } // Retrieve the user's account - $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts + $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type, user_login_attempts FROM ' . $this->users_table . ' WHERE user_id = ' . (int) $row['user_id']; $result = $this->db->sql_query($sql); diff --git a/phpBB/phpbb/auth/provider_collection.php b/phpBB/phpbb/auth/provider_collection.php new file mode 100644 index 0000000000..27a3f24564 --- /dev/null +++ b/phpBB/phpbb/auth/provider_collection.php @@ -0,0 +1,65 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\auth; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** +* Collection of auth providers to be configured at container compile time. +*/ +class provider_collection extends \phpbb\di\service_collection +{ + /** @var \phpbb\config\config phpBB Config */ + protected $config; + + /** + * Constructor + * + * @param ContainerInterface $container Container object + * @param \phpbb\config\config $config phpBB config + */ + public function __construct($container, \phpbb\config\config $config) + { + $this->container = $container; + $this->config = $config; + } + + /** + * Get an auth provider. + * + * @return object Default auth provider selected in config if it + * does exist. Otherwise the standard db auth + * provider. + * @throws \RuntimeException If neither the auth provider that + * is specified by the phpBB config nor the db + * auth provider exist. The db auth provider + * should always exist in a phpBB installation. + */ + public function get_provider() + { + if ($this->offsetExists('auth.provider.' . basename(trim($this->config['auth_method'])))) + { + return $this->offsetGet('auth.provider.' . basename(trim($this->config['auth_method']))); + } + // Revert to db auth provider if selected method does not exist + elseif ($this->offsetExists('auth.provider.db')) + { + return $this->offsetGet('auth.provider.db'); + } + else + { + throw new \RuntimeException(sprintf('The authentication provider for the authentication method "%1$s" does not exist. It was not possible to recover from this by reverting to the database authentication provider.', $this->config['auth_method'])); + } + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php new file mode 100644 index 0000000000..004d94d8bd --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p1.php @@ -0,0 +1,85 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class passwords_convert_p1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\passwords_p2'); + } + + public function update_data() + { + return array( + array('custom', array(array($this, 'update_passwords'))), + ); + } + + public function update_passwords($start) + { + // Nothing to do if user_pass_convert column doesn't exist + if (!$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_pass_convert')) + { + return; + } + + $start = (int) $start; + $limit = 1000; + $converted_users = 0; + + $sql = 'SELECT user_password, user_id + FROM ' . $this->table_prefix . 'users + WHERE user_pass_convert = 1 + GROUP BY user_id + ORDER BY user_id'; + $result = $this->db->sql_query_limit($sql, $limit, $start); + + $update_users = array(); + while ($row = $this->db->sql_fetchrow($result)) + { + $converted_users++; + + $user_id = (int) $row['user_id']; + // Only prefix passwords without proper prefix + if (!isset($update_users[$user_id]) && !preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $row['user_password'])) + { + // Use $CP$ prefix for passwords that need to + // be converted and set pass convert to false. + $update_users[$user_id] = array( + 'user_password' => '$CP$' . $row['user_password'], + 'user_pass_convert' => 0, + ); + } + } + $this->db->sql_freeresult($result); + + foreach ($update_users as $user_id => $user_data) + { + $sql = 'UPDATE ' . $this->table_prefix . 'users + SET ' . $this->db->sql_build_array('UPDATE', $user_data) . ' + WHERE user_id = ' . $user_id; + $this->sql_query($sql); + } + + if ($converted_users < $limit) + { + // There are no more users to be converted + return; + } + + // There are still more users to query, return the next start value + return $start + $limit; + } +} diff --git a/phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php new file mode 100644 index 0000000000..26a99184a6 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/passwords_convert_p2.php @@ -0,0 +1,49 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v310; + +class passwords_convert_p2 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return !$this->db_tools->sql_column_exists($this->table_prefix . 'users', 'user_pass_convert'); + } + + static public function depends_on() + { + return array('\phpbb\db\migration\data\v310\passwords_convert_p1'); + } + + public function update_schema() + { + return array( + 'drop_columns' => array( + $this->table_prefix . 'users' => array( + 'user_pass_convert', + ), + ), + ); + } + + public function revert_schema() + { + return array( + 'add_columns' => array( + $this->table_prefix . 'users' => array( + 'user_pass_convert' => array('BOOL', 0, 'after' => 'user_passchg'), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/passwords/driver/base.php b/phpBB/phpbb/passwords/driver/base.php index fffc9d1461..1d47180e55 100644 --- a/phpBB/phpbb/passwords/driver/base.php +++ b/phpBB/phpbb/passwords/driver/base.php @@ -43,4 +43,20 @@ abstract class base implements driver_interface { return true; } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return false; + } + + /** + * @inheritdoc + */ + public function get_settings_only($hash, $full = false) + { + return false; + } } diff --git a/phpBB/phpbb/passwords/driver/bcrypt.php b/phpBB/phpbb/passwords/driver/bcrypt.php index 3edf7255c0..de5840c7cf 100644 --- a/phpBB/phpbb/passwords/driver/bcrypt.php +++ b/phpBB/phpbb/passwords/driver/bcrypt.php @@ -60,7 +60,7 @@ class bcrypt extends base /** * @inheritdoc */ - public function check($password, $hash) + public function check($password, $hash, $user_row = array()) { $salt = substr($hash, 0, 29); if (strlen($salt) != 29) diff --git a/phpBB/phpbb/passwords/driver/bcrypt_wcf2.php b/phpBB/phpbb/passwords/driver/bcrypt_wcf2.php new file mode 100644 index 0000000000..f706c7af69 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/bcrypt_wcf2.php @@ -0,0 +1,84 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class bcrypt_wcf2 extends base +{ + const PREFIX = '$wcf2$'; + + /** @var \phpbb\passwords\driver\bcrypt */ + protected $bcrypt; + + /** @var phpbb\passwords\driver\helper */ + protected $helper; + + /** + * Constructor of passwords driver object + * + * @param \phpbb\passwords\driver\bcrypt $bcrypt Salted md5 driver + * @param \phpbb\passwords\driver\helper $helper Password driver helper + */ + public function __construct(\phpbb\passwords\driver\bcrypt $bcrypt, helper $helper) + { + $this->bcrypt = $bcrypt; + $this->helper = $helper; + } + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + if (empty($hash) || strlen($hash) != 60) + { + return false; + } + else + { + $salt = substr($hash, 0, 29); + + if (strlen($salt) != 29) + { + return false; + } + // Works for standard WCF 2.x, i.e. WBB4 and similar + return $hash === $this->bcrypt->hash($this->bcrypt->hash($password, $salt), $salt); + } + } +} diff --git a/phpBB/phpbb/passwords/driver/convert_password.php b/phpBB/phpbb/passwords/driver/convert_password.php new file mode 100644 index 0000000000..45d84f45c0 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/convert_password.php @@ -0,0 +1,43 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class convert_password extends base +{ + const PREFIX = '$CP$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + return false; + } +} diff --git a/phpBB/phpbb/passwords/driver/driver_interface.php b/phpBB/phpbb/passwords/driver/driver_interface.php index 54c9d6500e..a257e71f23 100644 --- a/phpBB/phpbb/passwords/driver/driver_interface.php +++ b/phpBB/phpbb/passwords/driver/driver_interface.php @@ -22,6 +22,13 @@ interface driver_interface */ public function is_supported(); + /** + * Check if hash type is a legacy hash type + * + * @return bool True if it's a legacy hash type, false if not + */ + public function is_legacy(); + /** * Returns the hash prefix * @@ -44,10 +51,11 @@ interface driver_interface * * @param string $password The password to check * @param string $hash The password hash to check against + * @param string $user_row User's row in users table * * @return bool True if password is correct, else false */ - public function check($password, $hash); + public function check($password, $hash, $user_row = array()); /** * Get only the settings of the specified hash diff --git a/phpBB/phpbb/passwords/driver/md5_mybb.php b/phpBB/phpbb/passwords/driver/md5_mybb.php new file mode 100644 index 0000000000..0745bceb5e --- /dev/null +++ b/phpBB/phpbb/passwords/driver/md5_mybb.php @@ -0,0 +1,60 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class md5_mybb extends base +{ + const PREFIX = '$md5_mybb$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + if (empty($hash) || strlen($hash) != 32 || !isset($user_row['user_passwd_salt'])) + { + return false; + } + else + { + // Works for myBB 1.1.x, 1.2.x, 1.4.x, 1.6.x + return $hash === md5(md5($user_row['user_passwd_salt']) . md5($password)); + } + } +} diff --git a/phpBB/phpbb/passwords/driver/md5_phpbb2.php b/phpBB/phpbb/passwords/driver/md5_phpbb2.php new file mode 100644 index 0000000000..de1993e8a1 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/md5_phpbb2.php @@ -0,0 +1,118 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class md5_phpbb2 extends base +{ + const PREFIX = '$md5_phpbb2$'; + + /** @var \phpbb\request\request phpBB request object */ + protected $request; + + /** @var \phpbb\passwords\driver\salted_md5 */ + protected $salted_md5; + + /** @var phpBB root path */ + protected $phpbb_root_path; + + /** @var php file extension */ + protected $php_ext; + + /** + * Constructor of passwords driver object + * + * @param \phpbb\request\request $request phpBB request object + * @param \phpbb\passwords\driver\salted_md5 $salted_md5 Salted md5 driver + * @param string $phpbb_root_path phpBB root path + * @param string $php_ext PHP file extension + */ + public function __construct($request, \phpbb\passwords\driver\salted_md5 $salted_md5, $phpbb_root_path, $php_ext) + { + $this->request = $request; + $this->salted_md5 = $salted_md5; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + } + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + if (strlen($hash) != 32 && strlen($hash) != 34) + { + return false; + } + + // enable super globals to get literal value + // this is needed to prevent unicode normalization + $super_globals_disabled = $this->request->super_globals_disabled(); + if ($super_globals_disabled) + { + $this->request->enable_super_globals(); + } + + // in phpBB2 passwords were used exactly as they were sent, with addslashes applied + $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : ''; + $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format; + $password_new_format = $this->request->variable('password', '', true); + + if ($super_globals_disabled) + { + $this->request->disable_super_globals(); + } + + if ($password == $password_new_format) + { + if (!function_exists('utf8_to_cp1252')) + { + include($this->phpbb_root_path . 'includes/utf/data/recode_basic.' . $this->php_ext); + } + + if (md5($password_old_format) === $hash || md5(\utf8_to_cp1252($password_old_format)) === $hash + || $this->salted_md5->check(md5($password_old_format), $hash) === true + || $this->salted_md5->check(md5(\utf8_to_cp1252($password_old_format)), $hash) === true) + { + return true; + } + } + + return false; + } +} diff --git a/phpBB/phpbb/passwords/driver/md5_vb.php b/phpBB/phpbb/passwords/driver/md5_vb.php new file mode 100644 index 0000000000..440b9e39e9 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/md5_vb.php @@ -0,0 +1,60 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class md5_vb extends base +{ + const PREFIX = '$md5_vb$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + if (empty($hash) || strlen($hash) != 32 || !isset($user_row['user_passwd_salt'])) + { + return false; + } + else + { + // Works for vB 3.8.x, 4.x.x, 5.0.x + return $hash === md5(md5($password) . $user_row['user_passwd_salt']); + } + } +} diff --git a/phpBB/phpbb/passwords/driver/salted_md5.php b/phpBB/phpbb/passwords/driver/salted_md5.php index a9f6712751..b5f59754e1 100644 --- a/phpBB/phpbb/passwords/driver/salted_md5.php +++ b/phpBB/phpbb/passwords/driver/salted_md5.php @@ -53,6 +53,14 @@ class salted_md5 extends base return self::PREFIX; } + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + /** * @inheritdoc */ @@ -92,7 +100,7 @@ class salted_md5 extends base /** * @inheritdoc */ - public function check($password, $hash) + public function check($password, $hash, $user_row = array()) { if (strlen($hash) !== 34) { diff --git a/phpBB/phpbb/passwords/driver/sha1.php b/phpBB/phpbb/passwords/driver/sha1.php new file mode 100644 index 0000000000..5d6c93f6a8 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/sha1.php @@ -0,0 +1,52 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class sha1 extends base +{ + const PREFIX = '$sha1$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + return (strlen($hash) == 40) ? $hash === sha1($password) : false; + } +} diff --git a/phpBB/phpbb/passwords/driver/sha1_smf.php b/phpBB/phpbb/passwords/driver/sha1_smf.php new file mode 100644 index 0000000000..3e3322d77f --- /dev/null +++ b/phpBB/phpbb/passwords/driver/sha1_smf.php @@ -0,0 +1,51 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class sha1_smf extends base +{ + const PREFIX = '$smf$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + return (isset($user_row['login_name'])) ? sha1(strtolower($user_row['login_name']) . $password) : false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + return (strlen($hash) == 40) ? $hash === $this->hash($password, $user_row) : false; + } +} diff --git a/phpBB/phpbb/passwords/driver/sha1_wcf1.php b/phpBB/phpbb/passwords/driver/sha1_wcf1.php new file mode 100644 index 0000000000..04a69705e9 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/sha1_wcf1.php @@ -0,0 +1,60 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class sha1_wcf1 extends base +{ + const PREFIX = '$wcf1$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + if (empty($hash) || strlen($hash) != 40 || !isset($user_row['user_passwd_salt'])) + { + return false; + } + else + { + // Works for standard WCF 1.x, i.e. WBB3 and similar + return $hash === sha1($user_row['user_passwd_salt'] . sha1($user_row['user_passwd_salt'] . sha1($password))); + } + } +} diff --git a/phpBB/phpbb/passwords/driver/sha_xf1.php b/phpBB/phpbb/passwords/driver/sha_xf1.php new file mode 100644 index 0000000000..7ae0b90f51 --- /dev/null +++ b/phpBB/phpbb/passwords/driver/sha_xf1.php @@ -0,0 +1,68 @@ + +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\passwords\driver; + +class sha_xf1 extends base +{ + const PREFIX = '$xf1$'; + + /** + * @inheritdoc + */ + public function get_prefix() + { + return self::PREFIX; + } + + /** + * @inheritdoc + */ + public function is_legacy() + { + return true; + } + + /** + * @inheritdoc + */ + public function hash($password, $user_row = '') + { + // Do not support hashing + return false; + } + + /** + * @inheritdoc + */ + public function check($password, $hash, $user_row = array()) + { + if (empty($hash) || (strlen($hash) != 40 && strlen($hash) != 64) || !isset($user_row['user_passwd_salt'])) + { + return false; + } + else + { + // Works for xenforo 1.0, 1.1 + if ($hash === sha1(sha1($password) . $user_row['user_passwd_salt']) + || $hash === hash('sha256', hash('sha256', $password) . $user_row['user_passwd_salt'])) + { + return true; + } + else + { + return false; + } + } + } +} diff --git a/phpBB/phpbb/passwords/manager.php b/phpBB/phpbb/passwords/manager.php index 8b16cf55dd..0a349c4a14 100644 --- a/phpBB/phpbb/passwords/manager.php +++ b/phpBB/phpbb/passwords/manager.php @@ -141,7 +141,7 @@ class manager */ if (!preg_match('#^\$([a-zA-Z0-9\\\]*?)\$#', $hash, $match)) { - return $this->get_algorithm('$H$'); + return false; } // Be on the lookout for multiple hashing algorithms @@ -224,9 +224,10 @@ class manager * * @param string $password Password that should be checked * @param string $hash Stored hash + * @param array $user_row User's row in users table * @return string|bool True if password is correct, false if not */ - public function check($password, $hash) + public function check($password, $hash, $user_row = array()) { if (strlen($password) > 4096) { @@ -235,11 +236,19 @@ class manager return false; } + // Empty hashes can't be checked + if (empty($hash)) + { + 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) { - return false; + // Still check MD5 hashes as that is what the installer + // will default to for the admin user + return $this->get_algorithm('$H$')->check($password, $hash); } // Multiple hash passes needed @@ -259,6 +268,21 @@ class manager $this->convert_flag = false; } + // Check all legacy hash types if prefix is $CP$ + if ($stored_hash_type->get_prefix() === '$CP$') + { + // Remove $CP$ prefix for proper checking + $hash = substr($hash, 4); + + foreach ($this->type_map as $algorithm) + { + if ($algorithm->is_legacy() && $algorithm->check($password, $hash, $user_row) === true) + { + return true; + } + } + } + return $stored_hash_type->check($password, $hash); } diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index c2669ea6cc..59b7ec2029 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -408,9 +408,8 @@ class session $session_expired = false; // Check whether the session is still valid if we have one - $method = basename(trim($config['auth_method'])); - - $provider = $phpbb_container->get('auth.provider.' . $method); + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $provider = $provider_collection->get_provider(); if (!($provider instanceof \phpbb\auth\provider\provider_interface)) { @@ -577,9 +576,8 @@ class session } } - $method = basename(trim($config['auth_method'])); - - $provider = $phpbb_container->get('auth.provider.' . $method); + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $provider = $provider_collection->get_provider(); $this->data = $provider->autologin(); if (sizeof($this->data)) @@ -898,9 +896,8 @@ class session $db->sql_query($sql); // Allow connecting logout with external auth method logout - $method = basename(trim($config['auth_method'])); - - $provider = $phpbb_container->get('auth.provider.' . $method); + $provider_collection = $phpbb_container->get('auth.provider_collection'); + $provider = $provider_collection->get_provider(); $provider->logout($this->data, $new_session); if ($this->data['user_id'] != ANONYMOUS) diff --git a/tests/auth/fixtures/user.xml b/tests/auth/fixtures/user.xml index 77f707bab3..1e0eb6ee49 100644 --- a/tests/auth/fixtures/user.xml +++ b/tests/auth/fixtures/user.xml @@ -6,7 +6,6 @@ username_clean user_password user_passchg - user_pass_convert user_email user_type user_login_attempts @@ -18,7 +17,6 @@ foobar $2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i 0 - 0 example@example.com 0 0 @@ -31,7 +29,6 @@ foobar2 $H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/ 0 - 0 example@example.com 0 0 diff --git a/tests/auth/fixtures/user_533.xml b/tests/auth/fixtures/user_533.xml index b64f376e5b..9731e4db4a 100644 --- a/tests/auth/fixtures/user_533.xml +++ b/tests/auth/fixtures/user_533.xml @@ -6,7 +6,6 @@ username_clean user_password user_passchg - user_pass_convert user_email user_type user_login_attempts @@ -18,7 +17,6 @@ foobar $2a$10$e01Syh9PbJjUkio66eFuUu4FhCE2nRgG7QPc1JACalsPXcIuG2bbi 0 - 0 example@example.com 0 0 @@ -31,7 +29,6 @@ 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 e17040902f..2decf0f18c 100644 --- a/tests/auth/provider_apache_test.php +++ b/tests/auth/provider_apache_test.php @@ -148,7 +148,6 @@ class phpbb_auth_provider_apache_test extends phpbb_database_test_case 'username_clean' => 'foobar', 'user_password' => $this->password_hash, 'user_passchg' => '0', - 'user_pass_convert' => '0', 'user_email' => 'example@example.com', 'user_email_hash' => '0', 'user_birthday' => '', diff --git a/tests/auth/provider_db_test.php b/tests/auth/provider_db_test.php index f071709a4b..23324f87f2 100644 --- a/tests/auth/provider_db_test.php +++ b/tests/auth/provider_db_test.php @@ -70,7 +70,6 @@ class phpbb_auth_provider_db_test extends phpbb_database_test_case 'username' => 'foobar', 'user_password' => $password_hash, 'user_passchg' => '0', - 'user_pass_convert' => '0', 'user_email' => 'example@example.com', 'user_type' => '0', 'user_login_attempts' => '0', diff --git a/tests/mock/request.php b/tests/mock/request.php index 89d5321a25..304fcf0eaf 100644 --- a/tests/mock/request.php +++ b/tests/mock/request.php @@ -15,6 +15,8 @@ class phpbb_mock_request implements \phpbb\request\request_interface { protected $data; + protected $super_globals_disabled = false; + public function __construct($get = array(), $post = array(), $cookie = array(), $server = array(), $request = false, $files = array()) { $this->data[\phpbb\request\request_interface::GET] = $get; @@ -23,6 +25,8 @@ class phpbb_mock_request implements \phpbb\request\request_interface $this->data[\phpbb\request\request_interface::REQUEST] = ($request === false) ? $post + $get : $request; $this->data[\phpbb\request\request_interface::SERVER] = $server; $this->data[\phpbb\request\request_interface::FILES] = $files; + + $this->disable_super_globals(); } public function overwrite($var_name, $value, $super_global = \phpbb\request\request_interface::REQUEST) @@ -83,6 +87,21 @@ class phpbb_mock_request implements \phpbb\request\request_interface return $this->data[$super_global]; } + public function super_globals_disabled() + { + return $this->super_globals_disabled; + } + + public function disable_super_globals() + { + $this->super_globals_disabled = true; + } + + public function enable_super_globals() + { + $this->super_globals_disabled = false; + } + /* custom methods */ public function set_header($header_name, $value) diff --git a/tests/passwords/drivers_test.php b/tests/passwords/drivers_test.php index c2104b0858..ccfb05c40f 100644 --- a/tests/passwords/drivers_test.php +++ b/tests/passwords/drivers_test.php @@ -17,14 +17,26 @@ class phpbb_passwords_helper_test extends \phpbb_test_case { // Prepare dependencies for drivers $config = new \phpbb\config\config(array()); + $request = new phpbb_mock_request(array(), array(), array(), array(), array('password' => 'fööbar')); $this->driver_helper = new \phpbb\passwords\driver\helper($config); + $phpbb_root_path = dirname(__FILE__) . '/../../phpBB/'; + $php_ext = 'php'; $this->passwords_drivers = array( '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.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), + 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), + 'passwords.driver.sha1_smf' => new \phpbb\passwords\driver\sha1_smf($config, $this->driver_helper), + 'passwords.driver.sha1_wcf1' => new \phpbb\passwords\driver\sha1_wcf1($config, $this->driver_helper), + 'passwords.driver.convert_password'=> new \phpbb\passwords\driver\convert_password($config, $this->driver_helper), + 'passwords.driver.sha1' => new \phpbb\passwords\driver\sha1($config, $this->driver_helper), + 'passwords.driver.md5_mybb' => new \phpbb\passwords\driver\md5_mybb($config, $this->driver_helper), + 'passwords.driver.md5_vb' => new \phpbb\passwords\driver\md5_vb($config, $this->driver_helper), + 'passwords.driver.sha_xf1' => new \phpbb\passwords\driver\sha_xf1($config, $this->driver_helper), ); + $this->passwords_drivers['passwords.driver.md5_phpbb2'] = new \phpbb\passwords\driver\md5_phpbb2($request, $this->passwords_drivers['passwords.driver.salted_md5'], $phpbb_root_path, $php_ext); + $this->passwords_drivers['passwords.driver.bcrypt_wcf2'] = new \phpbb\passwords\driver\bcrypt_wcf2($this->passwords_drivers['passwords.driver.bcrypt'], $this->driver_helper); } public function data_helper_encode64() @@ -82,4 +94,323 @@ class phpbb_passwords_helper_test extends \phpbb_test_case ); $this->assertEquals(false, $this->passwords_drivers['passwords.driver.salted_md5']->get_hash_settings(false)); } + + public function data_hash_sha1_smf() + { + return array( + array(false, 'test', array()), + array(false, 'test', ''), + array('6f9e2a1899e1f15708fd2e554103480eb53e8b57', 'foobar', array('login_name' => 'test')), + ); + } + + /** + * @dataProvider data_hash_sha1_smf + */ + public function test_hash_sha1_smf($expected, $password, $user_row) + { + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.sha1_smf']->hash($password, $user_row)); + } + + public function data_get_settings() + { + return array( + array(false, '6f9e2a1899e1f15708fd2e554103480eb53e8b57', 'passwords.driver.sha1_smf'), + ); + } + + /** + * @dataProvider data_get_settings + */ + public function test_get_settings_only($expected, $hash, $driver) + { + $this->assertSame($expected, $this->passwords_drivers[$driver]->get_settings_only($hash)); + } + + public function data_md5_phpbb2_check() + { + return array( + array(false, 'foobar', 'ae2fc75e20ee25d4520766788fbc96ae'), + array(false, 'foobar', 'ae2fc75e20ee25d4520766788fbc96aeddsf'), + array(false, 'fööbar', 'ae2fc75e20ee25d4520766788fbc96ae'), + array(true, 'fööbar', 'ae2fc75e20ee25d4520766788fbc96ae', utf8_decode('fööbar')), + array(true, 'fööbar', '$H$966CepJh9RC3hFIm7aKywR6jEn0kpA0', utf8_decode('fööbar')), + array(true, 'fööbar', '$H$9rNjgwETtmc8befO8JL1xFMrrMw8MC.', $this->utf8_to_cp1252(utf8_decode('fööbar'))), + array(true, 'fööbar', '$H$9rNjgwETtmc8befO8JL1xFMrrMw8MC.', $this->utf8_to_cp1252('fööbar')), + ); + } + + /** + * @dataProvider data_md5_phpbb2_check + */ + public function test_md5_phpbb2_check($expected, $password, $hash, $request_password = false) + { + if (!$request_password) + { + unset($_REQUEST['password']); + } + else + { + $_REQUEST['password'] = $request_password; + } + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.md5_phpbb2']->check($password, $hash)); + } + + public function test_md5_phpbb2_hash() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.md5_phpbb2']->hash('foobar')); + } + + public function test_convert_password_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.convert_password']->hash('foobar')); + } + + public function test_sha1_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.sha1']->hash('foobar')); + } + + public function data_md5_mybb_check() + { + return array( + array(false, 'foobar', '083d11daea8675b1b4b502c7e55f8dbd'), + array(false, 'foobar', '083d11daea8675b1b4b502c7e55f8dbd', array('user_passwd_salt' => 'ae2fc75e')), + array(true, 'foobar', 'b86ee7e24008bfd2890dcfab1ed31333', array('user_passwd_salt' => 'yeOtfFO6')), + ); + } + + /** + * @dataProvider data_md5_mybb_check + */ + public function test_md5_mybb_check($expected, $password, $hash, $user_row = array()) + { + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.md5_mybb']->check($password, $hash, $user_row)); + } + + public function test_md5_mybb_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.md5_mybb']->hash('foobar')); + } + + public function data_md5_vb_check() + { + return array( + array(false, 'foobar', '083d11daea8675b1b4b502c7e55f8dbd'), + array(false, 'foobar', 'b86ee7e24008bfd2890dcfab1ed31333', array('user_passwd_salt' => 'yeOtfFO6')), + array(true, 'foobar', 'b452c54c44c588fc095d2d000935c470', array('user_passwd_salt' => '9^F')), + array(true, 'foobar', 'f23a8241bd115d270c703213e3ef7f52', array('user_passwd_salt' => 'iaU*U%`CBl;/e~>D%do2m@Xf/,KZB0')), + array(false, 'nope', 'f23a8241bd115d270c703213e3ef7f52', array('user_passwd_salt' => 'iaU*U%`CBl;/e~>D%do2m@Xf/,KZB0')), + ); + } + + /** + * @dataProvider data_md5_vb_check + */ + public function test_md5_vb_check($expected, $password, $hash, $user_row = array()) + { + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.md5_vb']->check($password, $hash, $user_row)); + } + + public function test_md5_vb_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.md5_vb']->hash('foobar')); + } + + public function data_sha1_wcf1_check() + { + return array( + array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff'), + array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', array('user_passwd_salt' => 'yeOtfFO6')), + array(true, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', array('user_passwd_salt' => '1a783e478d63f6422783a868db667aed3a857840')), + ); + } + + /** + * @dataProvider data_sha1_wcf1_check + */ + public function test_sha1_wcf1_check($expected, $password, $hash, $user_row = array()) + { + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.sha1_wcf1']->check($password, $hash, $user_row)); + } + + public function test_sha1_wcf1_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.sha1_wcf1']->hash('foobar')); + } + + public function data_bcrypt_wcf2_check() + { + return array( + array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff'), + array(true, 'foobar', '$2a$08$p8h14U0jsEiVb1Luy.s8oOTXSQ0hVWUXpcNGBoCezeYNXrQyCKHfi'), + array(false, 'foobar', ''), + ); + } + + /** + * @dataProvider data_bcrypt_wcf2_check + */ + public function test_bcrypt_wcf2_check($expected, $password, $hash) + { + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.bcrypt_wcf2']->check($password, $hash)); + } + + public function test_bcrypt_wcf2_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.bcrypt_wcf2']->hash('foobar')); + } + + public function data_sha_xf1_check() + { + return array( + array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff'), + array(false, 'foobar', 'fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', array('user_passwd_salt' => 'yeOtfFO6')), + array(true, 'foobar', '7f65d2fa8a826d232f8134772252f8b1aaef8594b1edcabd9ab65e5b0f236ff0', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')), + array(true, 'foobar', '69962ae2079420573a3948cc4dedbabd35680051', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')), + ); + } + + /** + * @dataProvider data_sha_xf1_check + */ + public function test_sha_xf1_check($expected, $password, $hash, $user_row = array()) + { + $this->assertSame($expected, $this->passwords_drivers['passwords.driver.sha_xf1']->check($password, $hash, $user_row)); + } + + public function test_sha_xf1_driver() + { + $this->assertSame(false, $this->passwords_drivers['passwords.driver.sha_xf1']->hash('foobar')); + } + + protected function utf8_to_cp1252($string) + { + static $transform = array( + "\xE2\x82\xAC" => "\x80", + "\xE2\x80\x9A" => "\x82", + "\xC6\x92" => "\x83", + "\xE2\x80\x9E" => "\x84", + "\xE2\x80\xA6" => "\x85", + "\xE2\x80\xA0" => "\x86", + "\xE2\x80\xA1" => "\x87", + "\xCB\x86" => "\x88", + "\xE2\x80\xB0" => "\x89", + "\xC5\xA0" => "\x8A", + "\xE2\x80\xB9" => "\x8B", + "\xC5\x92" => "\x8C", + "\xC5\xBD" => "\x8E", + "\xE2\x80\x98" => "\x91", + "\xE2\x80\x99" => "\x92", + "\xE2\x80\x9C" => "\x93", + "\xE2\x80\x9D" => "\x94", + "\xE2\x80\xA2" => "\x95", + "\xE2\x80\x93" => "\x96", + "\xE2\x80\x94" => "\x97", + "\xCB\x9C" => "\x98", + "\xE2\x84\xA2" => "\x99", + "\xC5\xA1" => "\x9A", + "\xE2\x80\xBA" => "\x9B", + "\xC5\x93" => "\x9C", + "\xC5\xBE" => "\x9E", + "\xC5\xB8" => "\x9F", + "\xC2\xA0" => "\xA0", + "\xC2\xA1" => "\xA1", + "\xC2\xA2" => "\xA2", + "\xC2\xA3" => "\xA3", + "\xC2\xA4" => "\xA4", + "\xC2\xA5" => "\xA5", + "\xC2\xA6" => "\xA6", + "\xC2\xA7" => "\xA7", + "\xC2\xA8" => "\xA8", + "\xC2\xA9" => "\xA9", + "\xC2\xAA" => "\xAA", + "\xC2\xAB" => "\xAB", + "\xC2\xAC" => "\xAC", + "\xC2\xAD" => "\xAD", + "\xC2\xAE" => "\xAE", + "\xC2\xAF" => "\xAF", + "\xC2\xB0" => "\xB0", + "\xC2\xB1" => "\xB1", + "\xC2\xB2" => "\xB2", + "\xC2\xB3" => "\xB3", + "\xC2\xB4" => "\xB4", + "\xC2\xB5" => "\xB5", + "\xC2\xB6" => "\xB6", + "\xC2\xB7" => "\xB7", + "\xC2\xB8" => "\xB8", + "\xC2\xB9" => "\xB9", + "\xC2\xBA" => "\xBA", + "\xC2\xBB" => "\xBB", + "\xC2\xBC" => "\xBC", + "\xC2\xBD" => "\xBD", + "\xC2\xBE" => "\xBE", + "\xC2\xBF" => "\xBF", + "\xC3\x80" => "\xC0", + "\xC3\x81" => "\xC1", + "\xC3\x82" => "\xC2", + "\xC3\x83" => "\xC3", + "\xC3\x84" => "\xC4", + "\xC3\x85" => "\xC5", + "\xC3\x86" => "\xC6", + "\xC3\x87" => "\xC7", + "\xC3\x88" => "\xC8", + "\xC3\x89" => "\xC9", + "\xC3\x8A" => "\xCA", + "\xC3\x8B" => "\xCB", + "\xC3\x8C" => "\xCC", + "\xC3\x8D" => "\xCD", + "\xC3\x8E" => "\xCE", + "\xC3\x8F" => "\xCF", + "\xC3\x90" => "\xD0", + "\xC3\x91" => "\xD1", + "\xC3\x92" => "\xD2", + "\xC3\x93" => "\xD3", + "\xC3\x94" => "\xD4", + "\xC3\x95" => "\xD5", + "\xC3\x96" => "\xD6", + "\xC3\x97" => "\xD7", + "\xC3\x98" => "\xD8", + "\xC3\x99" => "\xD9", + "\xC3\x9A" => "\xDA", + "\xC3\x9B" => "\xDB", + "\xC3\x9C" => "\xDC", + "\xC3\x9D" => "\xDD", + "\xC3\x9E" => "\xDE", + "\xC3\x9F" => "\xDF", + "\xC3\xA0" => "\xE0", + "\xC3\xA1" => "\xE1", + "\xC3\xA2" => "\xE2", + "\xC3\xA3" => "\xE3", + "\xC3\xA4" => "\xE4", + "\xC3\xA5" => "\xE5", + "\xC3\xA6" => "\xE6", + "\xC3\xA7" => "\xE7", + "\xC3\xA8" => "\xE8", + "\xC3\xA9" => "\xE9", + "\xC3\xAA" => "\xEA", + "\xC3\xAB" => "\xEB", + "\xC3\xAC" => "\xEC", + "\xC3\xAD" => "\xED", + "\xC3\xAE" => "\xEE", + "\xC3\xAF" => "\xEF", + "\xC3\xB0" => "\xF0", + "\xC3\xB1" => "\xF1", + "\xC3\xB2" => "\xF2", + "\xC3\xB3" => "\xF3", + "\xC3\xB4" => "\xF4", + "\xC3\xB5" => "\xF5", + "\xC3\xB6" => "\xF6", + "\xC3\xB7" => "\xF7", + "\xC3\xB8" => "\xF8", + "\xC3\xB9" => "\xF9", + "\xC3\xBA" => "\xFA", + "\xC3\xBB" => "\xFB", + "\xC3\xBC" => "\xFC", + "\xC3\xBD" => "\xFD", + "\xC3\xBE" => "\xFE", + "\xC3\xBF" => "\xFF" + ); + return strtr($string, $transform); + } } diff --git a/tests/passwords/manager_test.php b/tests/passwords/manager_test.php index f9244d59f2..e46cf820f2 100644 --- a/tests/passwords/manager_test.php +++ b/tests/passwords/manager_test.php @@ -24,13 +24,25 @@ class phpbb_passwords_manager_test extends \phpbb_test_case // Prepare dependencies for manager and driver $config = new \phpbb\config\config(array()); $this->driver_helper = new \phpbb\passwords\driver\helper($config); + $request = new phpbb_mock_request(array(), array(), array(), array(), array('password' => 'töst')); + $phpbb_root_path = dirname(__FILE__) . '/../../phpBB/'; + $php_ext = 'php'; $this->passwords_drivers = array( - 'passwords.driver.bcrypt_2y' => new \phpbb\passwords\driver\bcrypt_2y($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.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper), 'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper), + 'passwords.driver.convert_password' => new \phpbb\passwords\driver\convert_password($config, $this->driver_helper), + 'passwords.driver.sha1_smf' => new \phpbb\passwords\driver\sha1_smf($config, $this->driver_helper), + 'passwords.driver.sha1' => new \phpbb\passwords\driver\sha1($config, $this->driver_helper), + 'passwords.driver.sha1_wcf1' => new \phpbb\passwords\driver\sha1_wcf1($config, $this->driver_helper), + 'passwords.driver.md5_mybb' => new \phpbb\passwords\driver\md5_mybb($config, $this->driver_helper), + 'passwords.driver.md5_vb' => new \phpbb\passwords\driver\md5_vb($config, $this->driver_helper), + 'passwords.driver.sha_xf1' => new \phpbb\passwords\driver\sha_xf1($config, $this->driver_helper), ); + $this->passwords_drivers['passwords.driver.md5_phpbb2'] = new \phpbb\passwords\driver\md5_phpbb2($request, $this->passwords_drivers['passwords.driver.salted_md5'], $phpbb_root_path, $php_ext); + $this->passwords_drivers['passwords.driver.bcrypt_wcf2'] = new \phpbb\passwords\driver\bcrypt_wcf2($this->passwords_drivers['passwords.driver.bcrypt'], $this->driver_helper); $this->helper = new \phpbb\passwords\helper; // Set up passwords manager @@ -132,21 +144,39 @@ class phpbb_passwords_manager_test extends \phpbb_test_case public function check_hash_exceptions_data() { return array( - array('foobar', '3858f62230ac3c915f300c664312c63f', true), - array('foobar', '$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false), - array('foobar', '$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false), - array('foobar', '$H$kklk938d023k//k3023', false), - array('foobar', '$H$3PtYMgXb39lrIWkgoxYLWtRkZtY3AY/', false), - array('foobar', '$2a$kwiweorurlaeirw', false), + array('3858f62230ac3c915f300c664312c63f', true), + array('$CP$3858f62230ac3c915f300c664312c63f', true), // md5_phpbb2 + array('$CP$3858f62230ac3c915f300c', false), + array('$S$b57a939fa4f2c04413a4eea9734a0903647b7adb93181295', false), + array('$2a\S$kkkkaakdkdiej39023903204j2k3490234jk234j02349', false), + array('$H$kklk938d023k//k3023', false), + array('$H$3PtYMgXb39lrIWkgoxYLWtRkZtY3AY/', false), + array('$2a$kwiweorurlaeirw', false), + array('6f9e2a1899e1f15708fd2e554103480eb53e8b57', false), + array('6f9e2a1899e1f15708fd2e554103480eb53e8b57', false, 'foobar', array('login_name' => 'test')), + array('$CP$6f9e2a1899e1f15708fd2e554103480eb53e8b57', true, 'foobar', array('login_name' => 'test')), // sha1_smf + array('6f9e2a1899', false, 'foobar', array('login_name' => 'test')), + array('ae2fc75e20ee25d4520766788fbc96ae', false, 'fööbar'), + array('$CP$ae2fc75e20ee25d4520766788fbc96ae', false, 'fööbar'), + array('$CP$ae2fc75e20ee25d4520766788fbc96ae', true, utf8_decode('fööbar')), // md5_phpbb2 + array('b86ee7e24008bfd2890dcfab1ed31333', false, 'foobar', array('user_passwd_salt' => 'yeOtfFO6')), + array('$CP$b86ee7e24008bfd2890dcfab1ed31333', true, 'foobar', array('user_passwd_salt' => 'yeOtfFO6')), // md5_mybb + array('$CP$b452c54c44c588fc095d2d000935c470', true, 'foobar', array('user_passwd_salt' => '9^F')), // md5_vb + array('$CP$f23a8241bd115d270c703213e3ef7f52', true, 'foobar', array('user_passwd_salt' => 'iaU*U%`CBl;/e~>D%do2m@Xf/,KZB0')), // md5_vb + array('$CP$fc46b9d9386167ce365ea3b891bf5dc31ddcd3ff', true, 'foobar', array('user_passwd_salt' => '1a783e478d63f6422783a868db667aed3a857840')), // sha_wcf1 + array('$2a$08$p8h14U0jsEiVb1Luy.s8oOTXSQ0hVWUXpcNGBoCezeYNXrQyCKHfi', false), + array('$CP$$2a$08$p8h14U0jsEiVb1Luy.s8oOTXSQ0hVWUXpcNGBoCezeYNXrQyCKHfi', true), // bcrypt_wcf2 + array('$CP$7f65d2fa8a826d232f8134772252f8b1aaef8594b1edcabd9ab65e5b0f236ff0', true, 'foobar', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')), // sha_xf1 + array('$CP$69962ae2079420573a3948cc4dedbabd35680051', true, 'foobar', array('user_passwd_salt' => '15b6c02cedbd727f563dcca607a89b085287b448966f19c0cc78cae263b1e38c')), // sha_xf1 ); } /** * @dataProvider check_hash_exceptions_data */ - public function test_check_hash_exceptions($password, $hash, $expected) + public function test_check_hash_exceptions($hash, $expected, $password = 'foobar', $user_row = array()) { - $this->assertEquals($expected, $this->manager->check($password, $hash)); + $this->assertEquals($expected, $this->manager->check($password, $hash, $user_row)); } public function data_hash_password_length() diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php index 81724cf661..3e25286480 100644 --- a/tests/session/testable_factory.php +++ b/tests/session/testable_factory.php @@ -96,6 +96,12 @@ class phpbb_session_testable_factory 'auth.provider.db', new phpbb_mock_auth_provider() ); + $provider_collection = new \phpbb\auth\provider_collection($phpbb_container, $config); + $provider_collection->add('auth.provider.db'); + $phpbb_container->set( + 'auth.provider_collection', + $provider_collection + ); $session = new phpbb_mock_session_testable; return $session;