|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Provides unit tests for password.inc. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Unit tests for password hashing API. |
|
10 */ |
|
11 class PasswordHashingTest extends DrupalWebTestCase { |
|
12 protected $profile = 'testing'; |
|
13 |
|
14 public static function getInfo() { |
|
15 return array( |
|
16 'name' => 'Password hashing', |
|
17 'description' => 'Password hashing unit tests.', |
|
18 'group' => 'System', |
|
19 ); |
|
20 } |
|
21 |
|
22 function setUp() { |
|
23 require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc'); |
|
24 parent::setUp(); |
|
25 } |
|
26 |
|
27 /** |
|
28 * Test password hashing. |
|
29 */ |
|
30 function testPasswordHashing() { |
|
31 // Set a log2 iteration count that is deliberately out of bounds to test |
|
32 // that it is corrected to be within bounds. |
|
33 variable_set('password_count_log2', 1); |
|
34 // Set up a fake $account with a password 'baz', hashed with md5. |
|
35 $password = 'baz'; |
|
36 $account = (object) array('name' => 'foo', 'pass' => md5($password)); |
|
37 // The md5 password should be flagged as needing an update. |
|
38 $this->assertTrue(user_needs_new_hash($account), 'User with md5 password needs a new hash.'); |
|
39 // Re-hash the password. |
|
40 $old_hash = $account->pass; |
|
41 $account->pass = user_hash_password($password); |
|
42 $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_MIN_HASH_COUNT, 'Re-hashed password has the minimum number of log2 iterations.'); |
|
43 $this->assertTrue($account->pass != $old_hash, 'Password hash changed.'); |
|
44 $this->assertTrue(user_check_password($password, $account), 'Password check succeeds.'); |
|
45 // Since the log2 setting hasn't changed and the user has a valid password, |
|
46 // user_needs_new_hash() should return FALSE. |
|
47 $this->assertFalse(user_needs_new_hash($account), 'User does not need a new hash.'); |
|
48 // Increment the log2 iteration to MIN + 1. |
|
49 variable_set('password_count_log2', DRUPAL_MIN_HASH_COUNT + 1); |
|
50 $this->assertTrue(user_needs_new_hash($account), 'User needs a new hash after incrementing the log2 count.'); |
|
51 // Re-hash the password. |
|
52 $old_hash = $account->pass; |
|
53 $account->pass = user_hash_password($password); |
|
54 $this->assertIdentical(_password_get_count_log2($account->pass), DRUPAL_MIN_HASH_COUNT + 1, 'Re-hashed password has the correct number of log2 iterations.'); |
|
55 $this->assertTrue($account->pass != $old_hash, 'Password hash changed again.'); |
|
56 // Now the hash should be OK. |
|
57 $this->assertFalse(user_needs_new_hash($account), 'Re-hashed password does not need a new hash.'); |
|
58 $this->assertTrue(user_check_password($password, $account), 'Password check succeeds with re-hashed password.'); |
|
59 } |
|
60 |
|
61 /** |
|
62 * Verifies that passwords longer than 512 bytes are not hashed. |
|
63 */ |
|
64 public function testLongPassword() { |
|
65 $password = str_repeat('x', 512); |
|
66 $result = user_hash_password($password); |
|
67 $this->assertFalse(empty($result), '512 byte long password is allowed.'); |
|
68 $password = str_repeat('x', 513); |
|
69 $result = user_hash_password($password); |
|
70 $this->assertFalse($result, '513 byte long password is not allowed.'); |
|
71 // Check a string of 3-byte UTF-8 characters. |
|
72 $password = str_repeat('€', 170); |
|
73 $result = user_hash_password($password); |
|
74 $this->assertFalse(empty($result), '510 byte long password is allowed.'); |
|
75 $password .= 'xx'; |
|
76 $this->assertFalse(empty($result), '512 byte long password is allowed.'); |
|
77 $password = str_repeat('€', 171); |
|
78 $result = user_hash_password($password); |
|
79 $this->assertFalse($result, '513 byte long password is not allowed.'); |
|
80 } |
|
81 } |