'Constraints Test', 'description' => 'Assure that password constraints work.', 'group' => 'Password Policy', ); } public function setUp() { if (defined('USER_LOAD_PHPASS_PATCHED')) { parent::setUp('password_policy', 'phpass'); } else { parent::setUp('password_policy'); } } function testUppercaseConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_uppercase'); $constraint = 2; $uid = 0; $pass = 'Abc'; $result = password_policy_constraint_uppercase_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One uppercase letter in the uppercase constraint with param 2'); $pass = 'ABc'; $result = password_policy_constraint_uppercase_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Two uppercase letters in the uppercase constraint with param 2'); $pass = 'ABC'; $result = password_policy_constraint_uppercase_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Three uppercase letters in the uppercase constraint with param 2'); } function testLowercaseConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_lowercase'); $constraint = 2; $uid = 0; $pass = 'Abc'; $result = password_policy_constraint_lowercase_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One uppercase letter in the lowercase constraint with param 2'); $pass = 'ABc'; $result = password_policy_constraint_lowercase_validate($pass, $constraint, $uid); $this->assertFalse($result, 'Two uppercase letters in the lowercase constraint with param 2'); $pass = 'ABC'; $result = password_policy_constraint_lowercase_validate($pass, $constraint, $uid); $this->assertFalse($result, 'Three uppercase letters in the lowercase constraint with param 2'); } function testLetterConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_letter'); $constraint = 2; $uid = 0; $pass = 'a12'; $result = password_policy_constraint_letter_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One lowercase letter in the letter constraint with param 2'); $pass = 'aB1'; $result = password_policy_constraint_letter_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One lowercase and one uppercase letter in the letter constraint with param 2'); $pass = 'abC'; $result = password_policy_constraint_letter_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Two lowercase and one uppercase letter in the letter constraint with param 2'); } function testDigitConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_digit'); $constraint = 2; $uid = 0; $pass = '1ab'; $result = password_policy_constraint_digit_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One digit in the digit constraint with param 2'); $pass = '12a'; $result = password_policy_constraint_digit_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Two digits in the digit constraint with param 2'); $pass = '123'; $result = password_policy_constraint_digit_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Three digits in the digit constraint with param 2'); } function testLengthConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_length'); $constraint = 6; $uid = 0; $pass = 'abcde'; $result = password_policy_constraint_length_validate($pass, $constraint, $uid); $this->assertFalse($result, 'Five characters password in the length constraint with param 6'); $pass = 'abcdef'; $result = password_policy_constraint_length_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Six characters password in the length constraint with param 6'); $pass = 'abcdefg'; $result = password_policy_constraint_length_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Seven characters password in the length constraint with param 6'); } function testAlphanumericConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_alphanumeric'); $constraint = 2; $uid = 0; $pass = '1$%'; $result = password_policy_constraint_alphanumeric_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One digit and no letter in the alphanumeric constraint with param 2'); $pass = '1a#'; $result = password_policy_constraint_alphanumeric_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One digit and one letter in the alphanumeric constraint with param 2'); $pass = '1ab'; $result = password_policy_constraint_alphanumeric_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One digit ant two letters in the alphanumeric constraint with param 2'); } function testPunctuationConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_punctuation'); $constraint = 2; $uid = 0; $pass = '%1a'; $result = password_policy_constraint_punctuation_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One punctuation character in the punctuation constraint with param 2'); $pass = '%^a'; $result = password_policy_constraint_punctuation_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Two punctuation character in the punctuation constraint with param 2'); $pass = '%^&'; $result = password_policy_constraint_punctuation_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Three punctuation character in the punctuation constraint with param 2'); } function testComplexityConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_complexity'); $constraint = 2; $uid = 0; $pass = 'abc'; $result = password_policy_constraint_complexity_validate($pass, $constraint, $uid); $this->assertFalse($result, 'Three letters in the type constraint with param 2'); $pass = 'a1c'; $result = password_policy_constraint_complexity_validate($pass, $constraint, $uid); $this->assertTrue($result, 'Two letters and one digit in the type constraint with param 2'); $pass = 'a1&'; $result = password_policy_constraint_complexity_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One letter, one digit and one punctuation in the type constraint with param 2'); } function testUsernameConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_username'); $constraint = 2; $user = $this->drupalCreateUser(); $name = $this->randomName(); $result = password_policy_constraint_username_validate($name, $constraint, $user->uid); $this->assertTrue($result, 'Random string in the username constraint'); $result = password_policy_constraint_username_validate($user->name, $constraint, $user->uid); $this->assertFalse($result, 'Username in the username constraint'); $result = password_policy_constraint_username_validate('foo' . $user->name . 'bar', $constraint, $user->uid); $this->assertFalse($result, 'String containing username in the username constraint'); } function testHistoryConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_history'); // Log in $user = $this->drupalCreateUser(array('administer site configuration')); $this->drupalLogin($user); // Create a policy $policy_name = $this->randomName(); $edit = array( 'name' => $policy_name, 'constraint_history' => t('2'), 'roles[2]' => '2', ); $this->drupalPost('admin/settings/password_policy/add', $edit, t('Create')); $this->assertText('Policy ' . $policy_name . ' has been created.', 'Policy ' . $policy_name . ' has been created'); // Enable newly created policy $pid = db_result(db_query('SELECT pid FROM {password_policy} WHERE name="%s"', $policy_name)); $constraints = unserialize(db_result(db_query('SELECT policy FROM {password_policy} WHERE pid=%d', $pid))); $this->assertTrue($constraints['history'] == 2, t('Verified history constraint set.')); $edit = array( "enabled[$pid]" => $pid, ); $this->drupalPost('admin/settings/password_policy/list', $edit, t('Save changes')); $this->assertText(t('The changes have been saved.'), t('Form submitted successfully.')); $enabled = db_result(db_query('SELECT enabled FROM {password_policy} WHERE pid=%d', $pid)); $this->assertTrue($enabled == 1, t('Policy enabled.')); // Change password $pass1 = "aaaaaa"; $edit = array( 'pass[pass1]' => $pass1, 'pass[pass2]' => $pass1, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertText(t('The changes have been saved.'), t("1st password change: $pass1")); // Change password second time $pass2 = "bbbbbb"; $edit = array( 'pass[pass1]' => $pass1, 'pass[pass2]' => $pass1, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertText(t('Your password has not met the following requirement(s):'), t("2nd password change should fail: $pass1")); // Try changing password with the first one $edit = array( 'pass[pass1]' => $pass2, 'pass[pass2]' => $pass2, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertText(t('The changes have been saved.'), t("3rd password change should pass: $pass2")); // Change password again $pass3 = "cccccc"; $edit = array( 'pass[pass1]' => $pass3, 'pass[pass2]' => $pass3, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertText(t('The changes have been saved.'), t("4th password change should pass: $pass3")); // Delete test policy $this->drupalPost('admin/settings/password_policy/delete/' . $pid, array(), t('Delete')); $this->assertText('Password policy ' . $policy_name . ' was deleted.', 'Default password policy ' . $policy_name . 'was deleted'); } function testDigitPlacementConstraint() { module_load_include('inc', 'password_policy', 'constraints/constraint_digit_placement'); $constraint = 0; $uid = 0; $pass = 'ILove2Password'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 0'); $pass = 'ILovePassword2'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 0'); $constraint = 1; $pass = 'ILove2Password'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 1'); $pass = 'ILovePassword2'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 1'); $constraint = 2; $pass = 'ILove2Password'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 2'); $pass = 'ILovePassword2'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One numeric character in the digit placement constraint with param 2'); $pass = '1LovePassword'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertFalse($result, 'One numeric character in the digit placement constraint with param 2'); $pass = '1LovePassword2'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 2'); $pass = 'ILove2Password3'; $result = password_policy_constraint_digit_placement_validate($pass, $constraint, $uid); $this->assertTrue($result, 'One numeric character in the digit placement constraint with param 2'); } } class PasswordPolicyForcePasswordChangeTestCase extends DrupalWebTestCase { protected $admin_user; public static function getInfo() { return array( 'name' => 'Force password change tests', 'description' => 'Tests forced password reset for single user, role and all new users.', 'group' => 'Password Policy', ); } public function setUp() { if (defined('USER_LOAD_PHPASS_PATCHED')) { parent::setUp('password_policy', 'phpass'); } else { parent::setUp('password_policy'); } } // test permissions public function testPerms() { // no perms $user = $this->drupalCreateUser(); $this->drupalLogin($user); $this->drupalGet('admin/settings/password_policy/password_change'); $this->assertResponse('403', t('Acces should be denied.')); $this->drupalLogout(); // with perms $user = $this->drupalCreateUser(array('force password change')); $this->drupalLogin($user); $this->drupalGet('admin/settings/password_policy/password_change'); $this->assertResponse('200', t('Access should be granted.')); $this->drupalLogout(); } // test form elements public function testForms() { // test admin form $user = $this->drupalCreateUser(array('force password change', 'administer users')); $this->drupalLogin($user); $this->drupalGet('admin/settings/password_policy/password_change'); $this->assertFieldByName('password_policy_new_login_change', '', t('Found first time login change checkbox.')); $this->assertFieldByName('password_policy_force_change_roles[2]', '', t('Found roles checkboxes.')); $this->assertFieldById('edit-submit', '', t('Found submit button.')); // test user edit form with perms $this->drupalGet("user/$user->uid/edit"); $this->assertFieldByName('force_password_change', '', 'Force password change checkbox is visible to admin.'); $this->drupalLogout(); // test user edit form without perms $user = $this->drupalCreateUser(); $this->drupalLogin($user); $this->drupalGet("user/$user->uid/edit"); $this->assertNoFieldByName('force_password_change', '', 'Force password change checkbox is hidden for normal users.'); $this->drupalLogout(); } // test single user password change public function testSingleUser() { $admin = $this->drupalCreateUser(array('force password change', 'administer users')); $user = $this->drupalCreateUser(); $this->drupalLogin($admin); $edit = array( 'force_password_change' => TRUE, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertRaw(t('!user will be required to change their password the next time they log in.', array('!user' => $user->name)), t('User flagged for password change.')); $force_change = db_result(db_query('SELECT force_change FROM {password_policy_force_change} WHERE uid=%d', $user->uid)); $this->assertTrue($force_change == 1, t('Force change flag set to %d for %s.', array('%d' => $force_change, '%s' => $user->name))); //confirm admin can edit user account without changing password $edit = array( 'name' => $user->name, 'mail' => $user->mail, 'force_password_change' => TRUE, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $force_change = db_result(db_query('SELECT force_change FROM {password_policy_force_change} WHERE uid=%d', $user->uid)); $this->assertTrue($force_change == 1, t('User force change flag set in database:%s.', array('%s' => $force_change))); $this->assertNoRaw(t('An administrator has required that you change your password. You must change your password to proceed on the site.'), t('Admin can edit user account without changing password.')); $this->drupalLogout(); // verify user is forced to change password $this->drupalLogin($user); $this->assertFieldByName('mail', '', t('User redirected correctly.')); // marginal $this->assertRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('User presented with error instructing them to change their password.')); // attempt to change password $edit = array( 'mail' => $user->mail, 'pass[pass1]' => 'random_string', 'pass[pass2]' => 'random_string', ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertRaw(t('The changes have been saved.'), t('Password change successful.')); // verify user not prompted to change password a 2nd time $this->drupalGet('node'); $this->assertNoFieldByName('mail', '', t('User not forced to change password a 2nd time.')); $this->drupalLogout(); } // test role-based password change public function testRoleChange() { $admin = $this->drupalCreateUser(array('administer users', 'force password change')); $user1 = $this->drupalCreateUser(); $user2 = $this->drupalCreateUser(); $this->drupalLogin($admin); $edit = array( 'password_policy_force_change_roles[2]' => 2, ); $this->drupalPost('admin/settings/password_policy/password_change', $edit, t('Submit')); $this->assertText(t('Users in the following roles will be required to immediately change their password: authenticated user'), t('Authenticated users role selected.')); $this->assertTrue($admin->uid != 1, t("Admin uid not 1: $admin->uid")); $this->assertRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('Admin (not uid 1) correctly forced to change password.')); // test db flags for individual users $entry_1 = db_result(db_query('SELECT uid FROM {password_policy_force_change} WHERE uid=%d', $user1->uid)); $this->assertTrue($entry_1 == $user1->uid, t("Entry created in password_policy_force_change for user $user1->uid.")); $flag_1 = db_result(db_query('SELECT force_change FROM {password_policy_force_change} WHERE uid=%d', $user1->uid)); $this->assertTrue($flag_1 == 1, t("User $user1->uid flagged: $flag_1.")); $this->drupalLogout(); //test individual users $this->drupalLogin($user1); $this->drupalGet('node'); $this->assertRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('First test user forced to change password.')); $this->drupalLogout(); //test 2nd user $this->drupalLogin($user2); $this->assertRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('Second test user forced to change password.')); $this->drupalLogout(); } //test new user change public function testNewUserChange() { $admin = $this->drupalCreateUser(array('administer users', 'force password change')); $this->drupalLogin($admin); $edit = array( 'password_policy_new_login_change' => TRUE, ); $this->drupalPost('admin/settings/password_policy/password_change', $edit, t('Submit')); $this->assertRaw(t('New users will be required to change their password on first-time login.'), t('New users required to change password on 1st login.')); $this->drupalLogout(); $user = $this->drupalCreateUser(); $this->drupalLogin($user); $this->drupalGet('node'); $this->assertRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('New user forced to change password.')); } //test admin forcing their own account to reset public function testSelfChange() { $admin = $this->drupalCreateUser(array('administer users', 'force password change')); $this->drupalLogin($admin); $this->assertNoRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('Admin should not be prompted to change password yet.')); $edit = array( 'force_password_change' => TRUE, ); $this->drupalPost("user/$admin->uid/edit", $edit, t('Save')); $this->assertRaw(t('The changes have been saved.'), t('Admin has queued account for password change.')); $this->assertNoRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('Admin not initially prompted to change password.')); $this->drupalGet('node'); $this->assertRaw(t('Your password has expired. You must change your password to proceed on the site.'), t('Admin forced to change password once they try to leave account page.')); $edit = array( 'mail' => $admin->mail, 'pass[pass1]' => 'fpcR@nd0m!', 'pass[pass2]' => 'fpcR@nd0m!', ); $this->drupalPost("user/$admin->uid/edit", $edit, t('Save')); $this->assertRaw(t('The changes have been saved.'), t('Admin changed password.')); $this->drupalGet('node'); $this->assertNoRaw(t('An administrator has required that you change your password. You must change your password to proceed on the site.'), t('Not prompted to change password a 2nd time.')); } /** * Test unforcing a password change. */ public function testUnforceChange() { $admin = $this->drupalCreateUser(array('force password change', 'administer users')); $user = $this->drupalCreateUser(); $this->drupalLogin($admin); // Force a password change. $edit = array( 'force_password_change' => TRUE, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $this->assertRaw(t('!user will be required to change their password the next time they log in.', array('!user' => $user->name)), t('User flagged for password change.')); // Unforce the password change. $edit = array( 'force_password_change' => FALSE, ); $this->drupalPost("user/$user->uid/edit", $edit, t('Save')); $force_change = db_result(db_query('SELECT force_change FROM {password_policy_force_change} WHERE uid=%d', $user->uid)); $this->assertTrue($force_change == 0, t('Force change flag set to %d for %s.', array('%d' => $force_change, '%s' => $user->name))); } }