def test_accounts_password_reuse(self):
        """
        Assert against the password reuse policy
        """
        user = self._user_factory_with_history()
        staff = self._user_factory_with_history(is_staff=True)

        # students need to user at least one different passwords before reuse
        self.assertFalse(
            PasswordHistory.is_allowable_password_reuse(user, "test"))
        self.assertTrue(
            PasswordHistory.is_allowable_password_reuse(user, "different"))
        self._change_password(user, "different")

        self.assertTrue(
            PasswordHistory.is_allowable_password_reuse(user, "test"))

        # staff needs to use at least two different passwords before reuse
        self.assertFalse(
            PasswordHistory.is_allowable_password_reuse(staff, "test"))
        self.assertTrue(
            PasswordHistory.is_allowable_password_reuse(staff, "different"))
        self._change_password(staff, "different")

        self.assertFalse(
            PasswordHistory.is_allowable_password_reuse(staff, "test"))
        self.assertFalse(
            PasswordHistory.is_allowable_password_reuse(staff, "different"))
        self.assertTrue(
            PasswordHistory.is_allowable_password_reuse(staff, "third"))
        self._change_password(staff, "third")

        self.assertTrue(
            PasswordHistory.is_allowable_password_reuse(staff, "test"))
    def test_pbkdf2_sha256_password_reuse(self):
        """
        Assert against the password reuse policy but using the normal Django PBKDF2
        """
        user = self._user_factory_with_history()
        staff = self._user_factory_with_history(is_staff=True)

        # students need to user at least one different passwords before reuse
        self.assertFalse(PasswordHistory.is_allowable_password_reuse(user, "test"))
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(user, "different"))
        self._change_password(user, "different")

        self.assertTrue(PasswordHistory.is_allowable_password_reuse(user, "test"))

        # staff needs to use at least two different passwords before reuse
        self.assertFalse(PasswordHistory.is_allowable_password_reuse(staff, "test"))
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(staff, "different"))
        self._change_password(staff, "different")

        self.assertFalse(PasswordHistory.is_allowable_password_reuse(staff, "test"))
        self.assertFalse(PasswordHistory.is_allowable_password_reuse(staff, "different"))
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(staff, "third"))
        self._change_password(staff, "third")

        self.assertTrue(PasswordHistory.is_allowable_password_reuse(staff, "test"))
    def test_disabled_feature(self):
        """
        Test that behavior is normal when this feature is not turned on
        """
        user = UserFactory()
        staff = AdminFactory()

        # if feature is disabled user can keep reusing same password
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(user, "test"))
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(staff, "test"))

        self.assertFalse(PasswordHistory.should_user_reset_password_now(user))
        self.assertFalse(PasswordHistory.should_user_reset_password_now(staff))
Example #4
0
    def test_disabled_feature(self):
        """
        Test that behavior is normal when this feature is not turned on
        """
        user = UserFactory()
        staff = AdminFactory()

        # if feature is disabled user can keep reusing same password
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(user, "test"))
        self.assertTrue(PasswordHistory.is_allowable_password_reuse(staff, "test"))

        self.assertFalse(PasswordHistory.should_user_reset_password_now(user))
        self.assertFalse(PasswordHistory.should_user_reset_password_now(staff))
def _validate_password_security(password, user):
    """
    Check password reuse and similar operational security policy considerations.
    """
    # Check reuse
    if not PasswordHistory.is_allowable_password_reuse(user, password):
        if user.is_staff:
            num_distinct = settings.ADVANCED_SECURITY_CONFIG[
                'MIN_DIFFERENT_STAFF_PASSWORDS_BEFORE_REUSE']
        else:
            num_distinct = settings.ADVANCED_SECURITY_CONFIG[
                'MIN_DIFFERENT_STUDENT_PASSWORDS_BEFORE_REUSE']
        raise SecurityPolicyError(
            ungettext(
                "You are re-using a password that you have used recently. "
                "You must have {num} distinct password before reusing a previous password.",
                "You are re-using a password that you have used recently. "
                "You must have {num} distinct passwords before reusing a previous password.",
                num_distinct).format(num=num_distinct))

    # Check reset frequency
    if PasswordHistory.is_password_reset_too_soon(user):
        num_days = settings.ADVANCED_SECURITY_CONFIG[
            'MIN_TIME_IN_DAYS_BETWEEN_ALLOWED_RESETS']
        raise SecurityPolicyError(
            ungettext(
                "You are resetting passwords too frequently. Due to security policies, "
                "{num} day must elapse between password resets.",
                "You are resetting passwords too frequently. Due to security policies, "
                "{num} days must elapse between password resets.",
                num_days).format(num=num_days))
def validate_password_security(password, user):
    """
    Check password reuse and similar operational security policy considerations.
    """
    # Check reuse
    if not PasswordHistory.is_allowable_password_reuse(user, password):
        if user.is_staff:
            num_distinct = settings.ADVANCED_SECURITY_CONFIG['MIN_DIFFERENT_STAFF_PASSWORDS_BEFORE_REUSE']
        else:
            num_distinct = settings.ADVANCED_SECURITY_CONFIG['MIN_DIFFERENT_STUDENT_PASSWORDS_BEFORE_REUSE']
        raise SecurityPolicyError(ungettext(
            "You are re-using a password that you have used recently. "
            "You must have {num} distinct password before reusing a previous password.",
            "You are re-using a password that you have used recently. "
            "You must have {num} distinct passwords before reusing a previous password.",
            num_distinct
        ).format(num=num_distinct))

    # Check reset frequency
    if PasswordHistory.is_password_reset_too_soon(user):
        num_days = settings.ADVANCED_SECURITY_CONFIG['MIN_TIME_IN_DAYS_BETWEEN_ALLOWED_RESETS']
        raise SecurityPolicyError(ungettext(
            "You are resetting passwords too frequently. Due to security policies, "
            "{num} day must elapse between password resets.",
            "You are resetting passwords too frequently. Due to security policies, "
            "{num} days must elapse between password resets.",
            num_days
        ).format(num=num_days))