def password_empty_test(self): """Check if quality of an empty password is reported correctly.""" request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 1) # empty password is fine with emptyok policy self.assertEqual(check.result.status_text, _(constants.PasswordStatus.EMPTY.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # empty password should override password-too-short messages request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.minlen = 10 request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 1) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.EMPTY.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message)
def password_empty_ok_test(self): """Check if the empty_ok flag works correctly.""" request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.emptyok = True request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 1) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.EMPTY.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # empty_ok with password length request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.emptyok = True request.policy.minlen = 10 request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 1) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.EMPTY.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # non-empty passwords that are too short should still get a score of 0 & the "too short" message request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.emptyok = True request.policy.minlen = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 0) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.TOO_SHORT.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # also check a long-enough password, just in case request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.emptyok = True request.policy.minlen = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 1) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.WEAK.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message)
def test_password_empty_ok(self): """Check if the empty_ok flag works correctly.""" request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.allow_empty = True request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 1 assert check.result.status_text == _( constants.SecretStatus.EMPTY.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # empty_ok with password length request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.allow_empty = True request.policy.min_length = 10 request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 1 assert check.result.status_text == _( constants.SecretStatus.EMPTY.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # non-empty passwords that are too short should still get a score of 0 & the "too short" message request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.allow_empty = True request.policy.min_length = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 0 assert check.result.status_text == _( constants.SecretStatus.TOO_SHORT.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # also check a long-enough password, just in case request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.allow_empty = True request.policy.min_length = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 1 assert check.result.status_text == _(constants.SecretStatus.WEAK.value) assert check.result.password_quality == 0 assert check.result.error_message is not None
def __init__(self, data, default_passphrase=""): super().__init__(data) self._passphrase_entry = self.builder.get_object("passphrase_entry") self._confirm_entry = self.builder.get_object("confirm_pw_entry") self._save_button = self.builder.get_object("passphrase_save_button") self._strength_bar = self.builder.get_object("strength_bar") self._strength_label = self.builder.get_object("strength_label") self._passphrase_warning_image = self.builder.get_object("passphrase_warning_image") self._passphrase_warning_label = self.builder.get_object("passphrase_warning_label") # Set the offset values for the strength bar colors self._strength_bar.add_offset_value("low", 2) self._strength_bar.add_offset_value("medium", 3) self._strength_bar.add_offset_value("high", 4) # Setup the password checker for passphrase checking self._checker = input_checking.PasswordChecker( initial_password_content=self._passphrase_entry.get_text(), initial_password_confirmation_content=self._confirm_entry.get_text(), policy_name=PASSWORD_POLICY_LUKS ) # configure the checker for passphrase checking self._checker.secret_type = constants.SecretType.PASSPHRASE # connect UI updates to check results self._checker.checks_done.connect(self._set_status) self.passphrase = default_passphrase self._passphrase_good_enough = False # check that the content of the passphrase field & the conformation field are the same self._confirm_check = input_checking.PasswordConfirmationCheck() # check passphrase validity, quality and strength self._validity_check = input_checking.PasswordValidityCheck() # connect UI updates to validity check results self._validity_check.result.password_score_changed.connect(self._set_password_strength) self._validity_check.result.status_text_changed.connect(self._set_password_status_text) # check if the passphrase contains non-ascii characters self._ascii_check = input_checking.PasswordASCIICheck() # check if the passphrase is empty self._empty_check = input_checking.PasswordEmptyCheck() # register the individual checks with the checker in proper order # 1) are both entered passphrases the same ? # 2) is the passphrase valid according to the current password checking policy ? # 3) is the passphrase free of non-ASCII characters ? self._checker.add_check(self._confirm_check) self._checker.add_check(self._validity_check) self._checker.add_check(self._ascii_check) self._checker.add_check(self._empty_check) # set the visibility of the password entries # - without this the password visibility toggle icon will # not be shown set_password_visibility(self._passphrase_entry, False) set_password_visibility(self._confirm_entry, False)
def _validate_password(self, password, confirm): """Validate and process user password.""" if password != confirm: self._report( _(constants.SECRET_CONFIRM_ERROR_TUI[self._secret_type])) return None # If an empty password was provided, unset the value if not password: return "" # prepare a password validation request password_check_request = input_checking.PasswordCheckRequest() password_check_request.password = password password_check_request.password_confirmation = "" password_check_request.policy = self._policy # validate the password password_check = input_checking.PasswordValidityCheck() password_check.run(password_check_request) # if the score is equal to 0 and we have an error message set if not password_check.result.password_score and password_check.result.error_message: self._report(password_check.result.error_message) return None if password_check.result.password_quality < self._policy.min_quality: if self._policy.is_strict: done_msg = "" else: done_msg = _("\nWould you like to use it anyway?") if password_check.result.error_message: weak_prefix = _( constants.SECRET_WEAK_WITH_ERROR[self._secret_type]) error = "{} {} {}".format(weak_prefix, password_check.result.error_message, done_msg) else: weak_prefix = _(constants.SECRET_WEAK[self._secret_type]) error = "{} {}".format(weak_prefix, done_msg) if not self._policy.is_strict: question_window = YesNoDialog(error) ScreenHandler.push_screen_modal(question_window) if not question_window.answer: return None else: self._report(error) return None if any(char not in constants.PW_ASCII_CHARS for char in password): self._report(_(constants.SECRET_ASCII[self._secret_type])) return self._process_password(password)
def password_length_test(self): """Check if minimal password length is checked properly.""" # first check if the default minimal password length is checked correctly # (should be 6 characters at the moment) request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 0) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.TOO_SHORT.value)) # weak but long enough request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 1) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.WEAK.value)) # check if setting password length works correctly request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.minlen = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 0) self.assertEqual(check.result.status_text, _(constants.PasswordStatus.TOO_SHORT.value)) request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.minlen = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertGreater(check.result.password_score, 0) self.assertNotEqual(check.result.status_text, _(constants.PasswordStatus.TOO_SHORT.value))
def test_password_length(self): """Check if minimal password length is checked properly.""" # first check if the default minimal password length is checked correctly # (should be 6 characters at the moment) request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 0 assert check.result.status_text == _( constants.SecretStatus.TOO_SHORT.value) # weak but long enough request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 1 assert check.result.status_text == _(constants.SecretStatus.WEAK.value) # check if setting password length works correctly request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.min_length = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 0 assert check.result.status_text == _( constants.SecretStatus.TOO_SHORT.value) request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.min_length = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score > 0 assert check.result.status_text != _( constants.SecretStatus.TOO_SHORT.value)
def test_password_empty(self): """Check if quality of an empty password is reported correctly.""" request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 1 # empty password is fine with emptyok policy assert check.result.status_text == _( constants.SecretStatus.EMPTY.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # empty password should override password-too-short messages request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.min_length = 10 request.password = "" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 1 assert check.result.status_text == _( constants.SecretStatus.EMPTY.value) assert check.result.password_quality == 0 assert check.result.error_message is not None
def initialize(self): NormalSpoke.initialize(self) self.initialize_start() # get object references from the builders self._password_entry = self.builder.get_object("password_entry") self._password_confirmation_entry = self.builder.get_object("password_confirmation_entry") self._password_bar = self.builder.get_object("password_bar") self._password_label = self.builder.get_object("password_label") self._enable_root_radio = self.builder.get_object("enable_root_radio") self._disable_root_radio = self.builder.get_object("disable_root_radio") self._root_password_ssh_login_override = self.builder.get_object("root_password_ssh_login_override") self._revealer = self.builder.get_object("password_revealer") # Install the password checks: # - Has a password been specified? # - If a password has been specified and there is data in the confirm box, do they match? # - How strong is the password? # - Does the password contain non-ASCII characters? # Setup the password checker for password checking self._checker = input_checking.PasswordChecker( initial_password_content=self.password, initial_password_confirmation_content=self.password_confirmation, policy_name=PASSWORD_POLICY_ROOT ) # configure the checker for password checking self.checker.secret_type = constants.SecretType.PASSWORD # remove any placeholder texts if either password or confirmation field changes content from initial state self.checker.password.changed_from_initial_state.connect(self.remove_placeholder_texts) self.checker.password_confirmation.changed_from_initial_state.connect(self.remove_placeholder_texts) # connect UI updates to check results self.checker.checks_done.connect(self._checks_done) # check that the password is not empty self._empty_check = input_checking.PasswordEmptyCheck() # check that the content of the password field & the conformation field are the same self._confirm_check = input_checking.PasswordConfirmationCheck() # check password validity, quality and strength self._validity_check = input_checking.PasswordValidityCheck() # connect UI updates to validity check results self._validity_check.result.password_score_changed.connect(self.set_password_score) self._validity_check.result.status_text_changed.connect(self.set_password_status) # check if the password contains non-ascii characters self._ascii_check = input_checking.PasswordASCIICheck() # register the individual checks with the checker in proper order # 1) is the password non-empty ? # 2) are both entered passwords the same ? # 3) is the password valid according to the current password checking policy ? # 4) is the password free of non-ASCII characters ? self.checker.add_check(self._empty_check) self.checker.add_check(self._confirm_check) self.checker.add_check(self._validity_check) self.checker.add_check(self._ascii_check) # Set placeholders if the password has been set outside of the Anaconda # GUI we either don't really know anything about it if it's crypted # and still would not really want to expose it if its set in plaintext, # and thus can'treally show it in the UI in any meaningful way. if self._users_module.IsRootPasswordSet: password_set_message = _("Root password has been set.") self.password_entry.set_placeholder_text(password_set_message) self.password_confirmation_entry.set_placeholder_text(password_set_message) # Configure levels for the password bar self._password_bar.add_offset_value("low", 2) self._password_bar.add_offset_value("medium", 3) self._password_bar.add_offset_value("high", 4) # set visibility of the password entries # - without this the password visibility toggle icon will # not be shown set_password_visibility(self.password_entry, False) set_password_visibility(self.password_confirmation_entry, False) # Send ready signal to main event loop hubQ.send_ready(self.__class__.__name__) # report that we are done self.initialize_done()
def initialize(self): NormalSpoke.initialize(self) self.initialize_start() # Create a new UserData object to store this spoke's state # as well as the state of the advanced user dialog. if self.data.user.userList: self._user = copy.copy(self.data.user.userList[0]) else: self._user = self.data.UserData() # gather references to relevant GUI objects # entry fields self._fullname_entry = self.builder.get_object("fullname_entry") self._username_entry = self.builder.get_object("username_entry") self._password_entry = self.builder.get_object("password_entry") self._password_confirmation_entry = self.builder.get_object( "password_confirmation_entry") # check boxes self._admin_checkbox = self.builder.get_object("admin_checkbox") self._password_required_checkbox = self.builder.get_object( "password_required_checkbox") # advanced user configration dialog button self._advanced_button = self.builder.get_object("advanced_button") # password checking status bar & label self._password_bar = self.builder.get_object("password_bar") self._password_label = self.builder.get_object("password_label") # Install the password checks: # - Has a password been specified? # - If a password has been specified and there is data in the confirm box, do they match? # - How strong is the password? # - Does the password contain non-ASCII characters? # Setup the password checker for password checking self._checker = input_checking.PasswordChecker( initial_password_content=self.password, initial_password_confirmation_content=self.password_confirmation, policy=input_checking.get_policy(self.data, "user")) # configure the checker for password checking self.checker.username = self.username self.checker.secret_type = constants.SecretType.PASSWORD # remove any placeholder texts if either password or confirmation field changes content from initial state self.checker.password.changed_from_initial_state.connect( self.remove_placeholder_texts) self.checker.password_confirmation.changed_from_initial_state.connect( self.remove_placeholder_texts) # connect UI updates to check results self.checker.checks_done.connect(self._checks_done) # username and full name checks self._username_check = input_checking.UsernameCheck() self._fullname_check = input_checking.FullnameCheck() # empty username is considered a success so that the user can leave # the spoke without filling it in self._username_check.success_if_username_empty = True # check that the password is not empty self._empty_check = input_checking.PasswordEmptyCheck() # check that the content of the password field & the conformation field are the same self._confirm_check = input_checking.PasswordConfirmationCheck() # check password validity, quality and strength self._validity_check = input_checking.PasswordValidityCheck() # connect UI updates to validity check results self._validity_check.result.password_score_changed.connect( self.set_password_score) self._validity_check.result.status_text_changed.connect( self.set_password_status) # check if the password contains non-ascii characters self._ascii_check = input_checking.PasswordASCIICheck() # register the individual checks with the checker in proper order # 0) is the username and fullname valid ? # 1) is the password non-empty ? # 2) are both entered passwords the same ? # 3) is the password valid according to the current password checking policy ? # 4) is the password free of non-ASCII characters ? self.checker.add_check(self._username_check) self.checker.add_check(self._fullname_check) self.checker.add_check(self._empty_check) self.checker.add_check(self._confirm_check) self.checker.add_check(self._validity_check) self.checker.add_check(self._ascii_check) self.guesser = {self.username_entry: True} # Configure levels for the password bar self.password_bar.add_offset_value("low", 2) self.password_bar.add_offset_value("medium", 3) self.password_bar.add_offset_value("high", 4) # indicate when the password was set by kickstart self.password_kickstarted = self.data.user.seen # Modify the GUI based on the kickstart and policy information # This needs to happen after the input checks have been created, since # the Gtk signal handlers use the input check variables. password_set_message = _("The password was set by kickstart.") if self.password_kickstarted: self.password_required = True self.password_entry.set_placeholder_text(password_set_message) self.password_confirmation_entry.set_placeholder_text( password_set_message) elif not self.checker.policy.emptyok: # Policy is that a non-empty password is required self.password_required = True if not self.checker.policy.emptyok: # User isn't allowed to change whether password is required or not self.password_required_checkbox.set_sensitive(False) self._advanced_user_dialog = AdvancedUserDialog(self._user, self.data) self._advanced_user_dialog.initialize() # set the visibility of the password entries set_password_visibility(self.password_entry, False) set_password_visibility(self.password_confirmation_entry, False) # report that we are done self.initialize_done()
def password_quality_test(self): """Check if libpwquality gives reasonable numbers & score is assigned correctly.""" # " " should give score 0 (<6 chars) & quality 0 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertEqual(check.result.password_score, 0) self.assertEqual(check.result.status_text, _(constants.SecretStatus.TOO_SHORT.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # "anaconda" is a dictionary word request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertGreater(check.result.password_score, 0) self.assertNotEqual(check.result.status_text, _(constants.SecretStatus.EMPTY.value)) self.assertNotEqual(check.result.status_text, _(constants.SecretStatus.TOO_SHORT.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # "jelenovipivonelej" is a palindrome request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertGreater(check.result.password_score, 0) self.assertNotEqual(check.result.status_text, _(constants.SecretStatus.EMPTY.value)) self.assertNotEqual(check.result.status_text, _(constants.SecretStatus.TOO_SHORT.value)) self.assertEqual(check.result.password_quality, 0) self.assertIsNotNone(check.result.error_message) # "4naconda-" gives a quality of 27 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertIs(check.result.error_message, "") # "4naconda----" gives a quality of 52 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertIs(check.result.error_message, "") # "----4naconda----" gives a quality of 80 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) self.assertIs(check.result.error_message, "") # "?----4naconda----?" gives a quality of 100 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) # this should (hopefully) give quality 100 everywhere self.assertEqual(check.result.password_score, 4) # quality > 90 self.assertEqual(check.result.status_text, _(constants.SecretStatus.STRONG.value)) self.assertEqual(check.result.password_quality, 100) self.assertIs(check.result.error_message, "") # a long enough strong password with minlen set request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.minlen = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) # this should (hopefully) give quality 100 everywhere self.assertEqual(check.result.password_score, 4) # quality > 90 self.assertEqual(check.result.status_text, _(constants.SecretStatus.STRONG.value)) self.assertEqual(check.result.password_quality, 100) self.assertIs(check.result.error_message, "") # minimum password length overrides strong passwords for score and status request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.minlen = 30 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) # this should (hopefully) give quality 100 everywhere self.assertEqual(check.result.password_score, 0) # too short self.assertEqual(check.result.status_text, _(constants.SecretStatus.TOO_SHORT.value)) self.assertEqual(check.result.password_quality, 0) # dependent on password length self.assertIs(check.result.error_message, _(constants.SECRET_TOO_SHORT[constants.SecretType.PASSWORD]))
def initialize(self): NormalSpoke.initialize(self) self.initialize_start() # get object references from the builders self._password_entry = self.builder.get_object("password_entry") self._password_confirmation_entry = self.builder.get_object("password_confirmation_entry") self._password_bar = self.builder.get_object("password_bar") self._password_label = self.builder.get_object("password_label") # set state based on kickstart # NOTE: this will stop working once the module supports multiple kickstart commands self.password_kickstarted = self._users_module.proxy.IsRootpwKickstarted # Install the password checks: # - Has a password been specified? # - If a password has been specified and there is data in the confirm box, do they match? # - How strong is the password? # - Does the password contain non-ASCII characters? # Setup the password checker for password checking self._checker = input_checking.PasswordChecker( initial_password_content = self.password, initial_password_confirmation_content = self.password_confirmation, policy = input_checking.get_policy(self.data, "root") ) # configure the checker for password checking self.checker.secret_type = constants.SecretType.PASSWORD # remove any placeholder texts if either password or confirmation field changes content from initial state self.checker.password.changed_from_initial_state.connect(self.remove_placeholder_texts) self.checker.password_confirmation.changed_from_initial_state.connect(self.remove_placeholder_texts) # connect UI updates to check results self.checker.checks_done.connect(self._checks_done) # check that the password is not empty self._empty_check = input_checking.PasswordEmptyCheck() # check that the content of the password field & the conformation field are the same self._confirm_check = input_checking.PasswordConfirmationCheck() # check password validity, quality and strength self._validity_check = input_checking.PasswordValidityCheck() # connect UI updates to validity check results self._validity_check.result.password_score_changed.connect(self.set_password_score) self._validity_check.result.status_text_changed.connect(self.set_password_status) # check if the password contains non-ascii characters self._ascii_check = input_checking.PasswordASCIICheck() # register the individual checks with the checker in proper order # 1) is the password non-empty ? # 2) are both entered passwords the same ? # 3) is the password valid according to the current password checking policy ? # 4) is the password free of non-ASCII characters ? self.checker.add_check(self._empty_check) self.checker.add_check(self._confirm_check) self.checker.add_check(self._validity_check) self.checker.add_check(self._ascii_check) # set placeholders if the password has been kickstarted as we likely don't know # nothing about it and can't really show it in the UI in any meaningful way password_set_message = _("The password was set by kickstart.") if self.password_kickstarted: self.password_entry.set_placeholder_text(password_set_message) self.password_confirmation_entry.set_placeholder_text(password_set_message) # Configure levels for the password bar self._password_bar.add_offset_value("low", 2) self._password_bar.add_offset_value("medium", 3) self._password_bar.add_offset_value("high", 4) # Send ready signal to main event loop hubQ.send_ready(self.__class__.__name__, False) # report that we are done self.initialize_done()
def test_password_quality(self): """Check if libpwquality gives reasonable numbers & score is assigned correctly.""" # " " should give score 0 (<6 chars) & quality 0 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score == 0 assert check.result.status_text == _( constants.SecretStatus.TOO_SHORT.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # "anaconda" is a dictionary word request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score > 0 assert check.result.status_text != _( constants.SecretStatus.EMPTY.value) assert check.result.status_text != _( constants.SecretStatus.TOO_SHORT.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # "jelenovipivonelej" is a palindrome request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.password_score > 0 assert check.result.status_text != _( constants.SecretStatus.EMPTY.value) assert check.result.status_text != _( constants.SecretStatus.TOO_SHORT.value) assert check.result.password_quality == 0 assert check.result.error_message is not None # "4naconda-" gives a quality of 27 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.error_message == "" # "4naconda----" gives a quality of 52 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.error_message == "" # "----4naconda----" gives a quality of 80 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) assert check.result.error_message == "" # "?----4naconda----?" gives a quality of 100 on RHEL7 request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) # this should (hopefully) give quality 100 everywhere assert check.result.password_score == 4 # quality > 90 assert check.result.status_text == _( constants.SecretStatus.STRONG.value) assert check.result.password_quality == 100 assert check.result.error_message == "" # a long enough strong password with minlen set request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.min_length = 10 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) # this should (hopefully) give quality 100 everywhere assert check.result.password_score == 4 # quality > 90 assert check.result.status_text == _( constants.SecretStatus.STRONG.value) assert check.result.password_quality == 100 assert check.result.error_message == "" # minimum password length overrides strong passwords for score and status request = input_checking.PasswordCheckRequest() request.policy = get_policy() request.policy.min_length = 30 request.password = "******" check = input_checking.PasswordValidityCheck() check.run(request) # this should (hopefully) give quality 100 everywhere assert check.result.password_score == 0 # too short assert check.result.status_text == _( constants.SecretStatus.TOO_SHORT.value) assert check.result.password_quality == 0 # dependent on password length assert check.result.error_message == \ _(constants.SECRET_TOO_SHORT[constants.SecretType.PASSWORD])
def _validate_password(self, password, confirm): """Validate and process user password.""" if (password and not confirm) or (confirm and not password): self._report( _("You must enter your root password and confirm it by typing" " it a second time to continue.")) return None if password != confirm: self._report( _(constants.PASSWORD_CONFIRM_ERROR_TUI) % {"password_name_plural": _(constants.NAME_OF_PASSWORD_PLURAL)}) return None # If an empty password was provided, unset the value if not password: return "" # prepare a password validation request password_check_request = input_checking.PasswordCheckRequest() password_check_request.password = password password_check_request.password_confirmation = "" password_check_request.policy = self._policy # validate the password password_check = input_checking.PasswordValidityCheck() password_check.run(password_check_request) # if the score is equal to 0 and we have an error message set if not password_check.result.password_score and password_check.result.error_message: self._report(password_check.result.error_message) return None if password_check.result.password_quality < self._policy.minquality: if self._policy.strict: done_msg = "" else: done_msg = _("\nWould you like to use it anyway?") if password_check.result.error_message: error_prefix = _(constants.PASSWORD_WEAK_WITH_ERROR) % { "password_name": _(constants.NAME_OF_PASSWORD), "error_message": password_check.result.error_message } error = "{} {}".format(error_prefix, done_msg) else: weak_prefix = _(constants.PASSWORD_WEAK) % { "password_name": _(constants.NAME_OF_PASSWORD) } error = "{} {}".format(weak_prefix, done_msg) if not self._policy.strict: question_window = YesNoDialog(error) ScreenHandler.push_screen_modal(question_window) if not question_window.answer: return None else: self._report(error) return None if any(char not in constants.PW_ASCII_CHARS for char in password): self._report( _("You have provided a password containing non-ASCII characters.\n" "You may not be able to switch between keyboard layouts to login.\n" )) return cryptPassword(password)
def initialize(self): NormalSpoke.initialize(self) self.initialize_start() # We consider user creation requested if there was at least one user # in the DBus module user list at startup. # We also remember how the user was called so that we can clear it # in a reasonably safe way & if it was cleared. self._user_list = get_user_list(self._users_module, add_default=True) self._user_requested = False self._requested_user_cleared = False # if user has a name, it's an actual user that has been requested, # rather than a default user added by us if self.user.name: self._user_requested = True # gather references to relevant GUI objects # entry fields self._fullname_entry = self.builder.get_object("fullname_entry") self._username_entry = self.builder.get_object("username_entry") self._password_entry = self.builder.get_object("password_entry") self._password_confirmation_entry = self.builder.get_object("password_confirmation_entry") # check boxes self._admin_checkbox = self.builder.get_object("admin_checkbox") self._password_required_checkbox = self.builder.get_object("password_required_checkbox") # advanced user configration dialog button self._advanced_button = self.builder.get_object("advanced_button") # password checking status bar & label self._password_bar = self.builder.get_object("password_bar") self._password_label = self.builder.get_object("password_label") # Install the password checks: # - Has a password been specified? # - If a password has been specified and there is data in the confirm box, do they match? # - How strong is the password? # - Does the password contain non-ASCII characters? # Setup the password checker for password checking self._checker = input_checking.PasswordChecker( initial_password_content=self.password, initial_password_confirmation_content=self.password_confirmation, policy_name=PASSWORD_POLICY_USER ) # configure the checker for password checking self.checker.username = self.username self.checker.secret_type = constants.SecretType.PASSWORD # remove any placeholder texts if either password or confirmation field changes content from initial state self.checker.password.changed_from_initial_state.connect(self.remove_placeholder_texts) self.checker.password_confirmation.changed_from_initial_state.connect(self.remove_placeholder_texts) # connect UI updates to check results self.checker.checks_done.connect(self._checks_done) # username and full name checks self._username_check = input_checking.UsernameCheck() self._fullname_check = input_checking.FullnameCheck() # empty username is considered a success so that the user can leave # the spoke without filling it in self._username_check.success_if_username_empty = True # check that the password is not empty self._empty_check = input_checking.PasswordEmptyCheck() # check that the content of the password field & the conformation field are the same self._confirm_check = input_checking.PasswordConfirmationCheck() # check password validity, quality and strength self._validity_check = input_checking.PasswordValidityCheck() # connect UI updates to validity check results self._validity_check.result.password_score_changed.connect(self.set_password_score) self._validity_check.result.status_text_changed.connect(self.set_password_status) # check if the password contains non-ascii characters self._ascii_check = input_checking.PasswordASCIICheck() # Skip the empty and validity password checks if no username is set self._empty_check.skip = True self._validity_check.skip = True # register the individual checks with the checker in proper order # 0) is the username and fullname valid ? # 1) is the password non-empty ? # 2) are both entered passwords the same ? # 3) is the password valid according to the current password checking policy ? # 4) is the password free of non-ASCII characters ? self.checker.add_check(self._username_check) self.checker.add_check(self._fullname_check) self.checker.add_check(self._empty_check) self.checker.add_check(self._confirm_check) self.checker.add_check(self._validity_check) self.checker.add_check(self._ascii_check) self.guesser = { self.username_entry: True } # Configure levels for the password bar self.password_bar.add_offset_value("low", 2) self.password_bar.add_offset_value("medium", 3) self.password_bar.add_offset_value("high", 4) # Modify the GUI based on the kickstart and policy information # This needs to happen after the input checks have been created, since # the Gtk signal handlers use the input check variables. password_set_message = _("The password was set by kickstart.") if self.password_kickstarted: self.password_required = True self.password_entry.set_placeholder_text(password_set_message) self.password_confirmation_entry.set_placeholder_text(password_set_message) elif not self.checker.policy.allow_empty: # Policy is that a non-empty password is required self.password_required = True if not self.checker.policy.allow_empty: # User isn't allowed to change whether password is required or not self.password_required_checkbox.set_sensitive(False) self._advanced_user_dialog = AdvancedUserDialog(self) self._advanced_user_dialog.initialize() # set the visibility of the password entries # - without this the password visibility toggle icon will # not be shown set_password_visibility(self.password_entry, False) set_password_visibility(self.password_confirmation_entry, False) # report that we are done self.initialize_done()