diff --git a/core/modules/user/src/Tests/UserLoginTest.php b/core/modules/user/src/Tests/UserLoginTest.php index d92c1c7..57904eb 100644 --- a/core/modules/user/src/Tests/UserLoginTest.php +++ b/core/modules/user/src/Tests/UserLoginTest.php @@ -13,6 +13,49 @@ class UserLoginTest extends WebTestBase { /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('block'); + + /** + * User cases to use in tests. + * + * @var array + */ + protected $userCases; + + /** + * Implements setUp(). + */ + public function setUp() { + parent::setUp(); + + // The maximum password length is 128 characters. + $password_lengths = array( + 128 => 'valid', + 129 => 'invalid', + ); + + foreach ($password_lengths as $password_length => $password_case) { + $test_name = $this->randomMachineName(32); + $test_pass = user_password($password_length); + + // Create the base user, based on drupalCreateUser(). + $account = entity_create('user', array( + 'name' => $test_name, + 'mail' => $test_name . '@example.com', + 'pass' => $test_pass, + 'status' => 1, + )); + $account->save(); + $account->pass_raw = $test_pass; + $this->userCases[$password_case] = $account; + } + } + + /** * Tests login with destination. */ public function testLoginCacheTagsAndDestination() { @@ -29,6 +72,62 @@ public function testLoginCacheTagsAndDestination() { } /** + * Test log in with long password on user/login. + */ + public function testPasswordLengthPage() { + /** @var User $user_with_valid_password_length */ + $user_with_valid_password_length = clone $this->userCases['valid']; + $auth = array( + 'name' => $user_with_valid_password_length->getAccountName(), + 'pass' => $user_with_valid_password_length->pass_raw, + ); + + $this->drupalPostForm('user/login', $auth, t('Log in')); + $this->assertNoText(t('User login'), 'Logged in with 128 character long password.'); + $this->assertPattern('!!', 'Redirected to /user'); + $this->drupalLogout(); + + /** @var User $user_with_invalid_password_length */ + $user_with_invalid_password_length = clone $this->userCases['invalid']; + $auth = array( + 'name' => $user_with_invalid_password_length->getAccountName(), + 'pass' => $user_with_invalid_password_length->pass_raw, + ); + + $this->drupalPostForm('user/login', $auth, t('Log in')); + $this->assertTrue(strpos($this->getRawContent(), (string) t('Log in')) > 0, 'Could not log in with 129 character long password via user/login.'); + $this->assertText('Password cannot be longer than', 'Error message appeared.'); + } + + /** + * Test log in with long password on login block. + */ + public function testPasswordLengthBlock() { + /** @var User $user_with_valid_password_length */ + $user_with_valid_password_length = clone $this->userCases['valid']; + $auth = array( + 'name' => $user_with_valid_password_length->getAccountName(), + 'pass' => $user_with_valid_password_length->pass_raw, + ); + + $this->drupalPlaceBlock('user_login_block'); + $this->drupalPostForm('filter/tips', $auth, t('Log in')); + $this->assertNoText(t('User login'), 'Logged in.'); + $this->drupalLogout(); + + /** @var User $user_with_invalid_password_length */ + $user_with_invalid_password_length = clone $this->userCases['invalid']; + $auth = array( + 'name' => $user_with_invalid_password_length->getAccountName(), + 'pass' => $user_with_invalid_password_length->pass_raw, + ); + + $this->drupalPostForm('filter/tips', $auth, t('Log in')); + $this->assertTrue(strpos($this->getRawContent(), (string) t('Log in')) > 0, 'Could not log in with 129 character long password via login block.'); + $this->assertText('Password cannot be longer than', 'Error message appeared.'); + } + + /** * Test the global login flood control. */ public function testGlobalLoginFloodControl() { @@ -38,31 +137,31 @@ public function testGlobalLoginFloodControl() { ->set('user_limit', 4000) ->save(); - $user1 = $this->drupalCreateUser([]); - $incorrect_user1 = clone $user1; - $incorrect_user1->pass_raw .= 'incorrect'; + $valid_user = clone $this->userCases['valid']; + $incorrect_user = clone $valid_user; + $incorrect_user->pass_raw .= 'incorrect'; // Try 2 failed logins. for ($i = 0; $i < 2; $i++) { - $this->assertFailedLogin($incorrect_user1); + $this->assertFailedLogin($incorrect_user); } // A successful login will not reset the IP-based flood control count. - $this->drupalLogin($user1); + $this->drupalLogin($valid_user); $this->drupalLogout(); // Try 8 more failed logins, they should not trigger the flood control // mechanism. for ($i = 0; $i < 8; $i++) { - $this->assertFailedLogin($incorrect_user1); + $this->assertFailedLogin($incorrect_user); } // The next login trial should result in an IP-based flood error message. - $this->assertFailedLogin($incorrect_user1, 'ip'); + $this->assertFailedLogin($incorrect_user, 'ip'); // A login with the correct password should also result in a flood error // message. - $this->assertFailedLogin($user1, 'ip'); + $this->assertFailedLogin($valid_user, 'ip'); } /** @@ -75,34 +174,34 @@ public function testPerUserLoginFloodControl() { ->set('user_limit', 3) ->save(); - $user1 = $this->drupalCreateUser([]); - $incorrect_user1 = clone $user1; - $incorrect_user1->pass_raw .= 'incorrect'; + $valid_user1 = clone $this->userCases['valid']; + $valid_user2 = $this->drupalCreateUser(array()); - $user2 = $this->drupalCreateUser([]); + $incorrect_user = clone $valid_user1; + $incorrect_user->pass_raw .= 'incorrect'; // Try 2 failed logins. for ($i = 0; $i < 2; $i++) { - $this->assertFailedLogin($incorrect_user1); + $this->assertFailedLogin($incorrect_user); } // A successful login will reset the per-user flood control count. - $this->drupalLogin($user1); + $this->drupalLogin($valid_user1); $this->drupalLogout(); // Try 3 failed logins for user 1, they will not trigger flood control. for ($i = 0; $i < 3; $i++) { - $this->assertFailedLogin($incorrect_user1); + $this->assertFailedLogin($incorrect_user); } // Try one successful attempt for user 2, it should not trigger any // flood control. - $this->drupalLogin($user2); + $this->drupalLogin($valid_user2); $this->drupalLogout(); // Try one more attempt for user 1, it should be rejected, even if the // correct password has been used. - $this->assertFailedLogin($user1, 'user'); + $this->assertFailedLogin($valid_user1, 'user'); } /** @@ -112,15 +211,16 @@ public function testPasswordRehashOnLogin() { // Determine default log2 for phpass hashing algorithm $default_count_log2 = 16; - // Retrieve instance of password hashing algorithm + // Retrieve instance of password hashing algorithm. $password_hasher = $this->container->get('password'); // Create a new user and authenticate. - $account = $this->drupalCreateUser([]); + $account = clone $this->userCases['valid']; $password = $account->pass_raw; $this->drupalLogin($account); $this->drupalLogout(); - // Load the stored user. The password hash should reflect $default_count_log2. + // Load the stored user. The password hash should reflect + // $default_count_log2. $user_storage = $this->container->get('entity.manager')->getStorage('user'); $account = User::load($account->id()); $this->assertIdentical($password_hasher->getCountLog2($account->getPassword()), $default_count_log2);