mirror of
https://github.com/phpbb/phpbb.git
synced 2025-08-06 08:47:45 +02:00
Merge pull request #1716 from marc1706/feature/passwords
[feature/passwords] Add password hashing manager with support for newer hashing algorithms
This commit is contained in:
@@ -18,6 +18,21 @@
|
||||
<value>1</value>
|
||||
<value>foobar</value>
|
||||
<value>foobar</value>
|
||||
<value>$2y$10$4RmpyVu2y8Yf/lP3.yQBquKvE54TCUuEDEBJYY6FDDFN3LcbCGz9i</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
<value>example@example.com</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
</row>
|
||||
<row>
|
||||
<value>2</value>
|
||||
<value>foobar2</value>
|
||||
<value>foobar2</value>
|
||||
<value>$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
|
48
tests/auth/fixtures/user_533.xml
Normal file
48
tests/auth/fixtures/user_533.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<dataset>
|
||||
<table name="phpbb_users">
|
||||
<column>user_id</column>
|
||||
<column>username</column>
|
||||
<column>username_clean</column>
|
||||
<column>user_password</column>
|
||||
<column>user_passchg</column>
|
||||
<column>user_pass_convert</column>
|
||||
<column>user_email</column>
|
||||
<column>user_type</column>
|
||||
<column>user_login_attempts</column>
|
||||
<column>user_permissions</column>
|
||||
<column>user_sig</column>
|
||||
<column>user_occ</column>
|
||||
<column>user_interests</column>
|
||||
<row>
|
||||
<value>1</value>
|
||||
<value>foobar</value>
|
||||
<value>foobar</value>
|
||||
<value>$2a$10$e01Syh9PbJjUkio66eFuUu4FhCE2nRgG7QPc1JACalsPXcIuG2bbi</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
<value>example@example.com</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
</row>
|
||||
<row>
|
||||
<value>2</value>
|
||||
<value>foobar2</value>
|
||||
<value>foobar2</value>
|
||||
<value>$H$9E45lK6J8nLTSm9oJE5aNCSTFK9wqa/</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
<value>example@example.com</value>
|
||||
<value>0</value>
|
||||
<value>0</value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
<value></value>
|
||||
</row>
|
||||
</table>
|
||||
</dataset>
|
@@ -26,13 +26,40 @@ 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_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),
|
||||
);
|
||||
|
||||
$this->provider = new \phpbb\auth\provider\apache($db, $config, $this->request, $this->user, $phpbb_root_path, $phpEx);
|
||||
$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));
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +106,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' => $this->password_hash,
|
||||
'user_passchg' => '0',
|
||||
'user_email' => 'example@example.com',
|
||||
'user_type' => '0',
|
||||
@@ -115,7 +142,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' => $this->password_hash,
|
||||
'user_passchg' => '0',
|
||||
'user_pass_convert' => '0',
|
||||
'user_email' => 'example@example.com',
|
||||
|
@@ -14,7 +14,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()
|
||||
@@ -29,7 +36,27 @@ 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_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),
|
||||
);
|
||||
|
||||
$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));
|
||||
|
||||
$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,
|
||||
@@ -37,7 +64,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' => $password_hash,
|
||||
'user_passchg' => '0',
|
||||
'user_pass_convert' => '0',
|
||||
'user_email' => 'example@example.com',
|
||||
@@ -47,5 +74,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']);
|
||||
}
|
||||
}
|
||||
|
55
tests/functional/forum_password_test.php
Normal file
55
tests/functional/forum_password_test.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @package testing
|
||||
* @copyright (c) 2013 phpBB Group
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @group functional
|
||||
*/
|
||||
class phpbb_functional_forum_password_test extends phpbb_functional_test_case
|
||||
{
|
||||
public function test_setup_forum_with_password()
|
||||
{
|
||||
$this->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());
|
||||
}
|
||||
}
|
81
tests/passwords/drivers_test.php
Normal file
81
tests/passwords/drivers_test.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @package testing
|
||||
* @copyright (c) 2013 phpBB Group
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
|
||||
*
|
||||
*/
|
||||
|
||||
class phpbb_passwords_helper_test extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
// Prepare dependencies for drivers
|
||||
$config = new \phpbb\config\config(array());
|
||||
$this->driver_helper = new \phpbb\passwords\driver\helper($config);
|
||||
|
||||
$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.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper),
|
||||
'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper),
|
||||
);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
295
tests/passwords/manager_test.php
Normal file
295
tests/passwords/manager_test.php
Normal file
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* @package testing
|
||||
* @copyright (c) 2013 phpBB Group
|
||||
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
|
||||
*
|
||||
*/
|
||||
|
||||
class phpbb_passwords_manager_test extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $passwords_drivers;
|
||||
|
||||
protected $pw_characters = '0123456789abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVXYZ.,_!?/\\';
|
||||
|
||||
protected $default_pw = 'foobar';
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
// Prepare dependencies for manager and driver
|
||||
$config = new \phpbb\config\config(array());
|
||||
$this->driver_helper = new \phpbb\passwords\driver\helper($config);
|
||||
|
||||
$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.salted_md5' => new \phpbb\passwords\driver\salted_md5($config, $this->driver_helper),
|
||||
'passwords.driver.phpass' => new \phpbb\passwords\driver\phpass($config, $this->driver_helper),
|
||||
);
|
||||
|
||||
$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));
|
||||
}
|
||||
|
||||
public function hash_password_data()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.7', '<'))
|
||||
{
|
||||
return array(
|
||||
array('', '2a', 60),
|
||||
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
|
||||
{
|
||||
return array(
|
||||
array('', '2y', 60),
|
||||
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),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider hash_password_data
|
||||
*/
|
||||
public function test_hash_password($type, $prefix, $length)
|
||||
{
|
||||
$password = $this->default_pw;
|
||||
|
||||
if (!$length)
|
||||
{
|
||||
$this->assertEquals(false, $hash = $this->manager->hash($password, $type));
|
||||
return;
|
||||
}
|
||||
$time = microtime(true);
|
||||
|
||||
// Limit each test to 1 second
|
||||
while ((microtime(true) - $time) < 1)
|
||||
{
|
||||
$hash = $this->manager->hash($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()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.7', '<'))
|
||||
{
|
||||
return array(
|
||||
array('passwords.driver.bcrypt'),
|
||||
array('passwords.driver.salted_md5'),
|
||||
array('passwords.driver.phpass'),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return array(
|
||||
array('passwords.driver.bcrypt_2y'),
|
||||
array('passwords.driver.bcrypt'),
|
||||
array('passwords.driver.salted_md5'),
|
||||
array('passwords.driver.phpass'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider check_password_data
|
||||
*/
|
||||
public function test_check_password($hash_type)
|
||||
{
|
||||
$password = $this->default_pw;
|
||||
$time = microtime(true);
|
||||
// Limit each test to 1 second
|
||||
while ((microtime(true) - $time) < 1)
|
||||
{
|
||||
$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($password, $hash));
|
||||
}
|
||||
|
||||
// Check if convert_flag is correctly set
|
||||
$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);
|
||||
}
|
||||
|
||||
|
||||
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),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider check_hash_exceptions_data
|
||||
*/
|
||||
public function test_check_hash_exceptions($password, $hash, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, $this->manager->check($password, $hash));
|
||||
}
|
||||
|
||||
public function data_hash_password_length()
|
||||
{
|
||||
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'));
|
||||
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()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.7', '<'))
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.bcrypt'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.phpass',
|
||||
array('passwords.driver.salted_md5'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.phpass', 'passwords.driver.bcrypt'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.salted_md5'),
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'$H$',
|
||||
array('$2a$'),
|
||||
),
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.bcrypt_2y'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.bcrypt'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.phpass',
|
||||
array('passwords.driver.salted_md5'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.bcrypt_2y', 'passwords.driver.bcrypt'),
|
||||
),
|
||||
array(
|
||||
'passwords.driver.salted_md5',
|
||||
array('passwords.driver.salted_md5'),
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'passwords.driver.bcrypt_2y',
|
||||
array('passwords.driver.salted_md4'),
|
||||
false,
|
||||
),
|
||||
array(
|
||||
'$H$',
|
||||
array('$2y$'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider test_combined_hash_data
|
||||
*/
|
||||
public function test_combined_hash_password($first_type, $second_type, $expected = true)
|
||||
{
|
||||
$password = $this->default_pw;
|
||||
$time = microtime(true);
|
||||
// Limit each test to 1 second
|
||||
while ((microtime(true) - $time) < 1)
|
||||
{
|
||||
$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($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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
@@ -11,6 +11,31 @@ require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
|
||||
|
||||
class phpbb_security_hash_test extends phpbb_test_case
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
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_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),
|
||||
);
|
||||
|
||||
$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));
|
||||
|
||||
$phpbb_container
|
||||
->expects($this->any())
|
||||
->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'));
|
||||
|
@@ -503,6 +503,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,
|
||||
@@ -512,7 +513,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);
|
||||
}
|
||||
@@ -997,4 +998,29 @@ 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_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),
|
||||
);
|
||||
|
||||
$passwords_helper = new \phpbb\passwords\helper;
|
||||
// Set up passwords manager
|
||||
$manager = new \phpbb\passwords\manager($config, $passwords_drivers, $passwords_helper, array_keys($passwords_drivers));
|
||||
|
||||
return $manager;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user