From 5e7a6e648c85cf923093ebac6448be82ba032448 Mon Sep 17 00:00:00 2001 From: Vratislav Podzimek Date: Wed, 25 May 2016 10:58:54 +0200 Subject: [PATCH 06/13] Allow fixing root password in graphical installations If the root password from kickstart is too short we can give users a chance to enter a new (better) one in case of graphical installation. Text mode doesn't allow for this because the root password configuration happens before the SCAP content is evaluated. Resolves: rhbz#1265116 --- org_fedora_oscap/common.py | 3 ++- org_fedora_oscap/gui/spokes/oscap.py | 39 +++++++++++++++++++++++++++++++----- org_fedora_oscap/rule_handling.py | 29 ++++++++++++++++----------- 3 files changed, 53 insertions(+), 18 deletions(-) diff --git a/org_fedora_oscap/common.py b/org_fedora_oscap/common.py index d09ccbd..8b2e84f 100644 --- a/org_fedora_oscap/common.py +++ b/org_fedora_oscap/common.py @@ -82,9 +82,10 @@ MESSAGE_TYPE_WARNING = 1 MESSAGE_TYPE_INFO = 2 # namedtuple for messages returned from the rules evaluation +# origin -- class (inherited from RuleHandler) that generated the message # type -- one of the MESSAGE_TYPE_* constants defined above # text -- the actual message that should be displayed, logged, ... -RuleMessage = namedtuple("RuleMessage", ["type", "text"]) +RuleMessage = namedtuple("RuleMessage", ["origin", "type", "text"]) def get_fix_rules_pre(profile, fpath, ds_id="", xccdf_id="", tailoring=""): """ diff --git a/org_fedora_oscap/gui/spokes/oscap.py b/org_fedora_oscap/gui/spokes/oscap.py index 3b8dbd7..42fc406 100644 --- a/org_fedora_oscap/gui/spokes/oscap.py +++ b/org_fedora_oscap/gui/spokes/oscap.py @@ -200,6 +200,11 @@ class OSCAPSpoke(NormalSpoke): # leaving the spoke self._rule_data = None + # used for storing previously set root password if we need to remove it + # due to the chosen policy (so that we can put it back in case of + # revert) + self.__old_root_pw = None + # used to check if the profile was changed or not self._active_profile = None @@ -584,20 +589,43 @@ class OSCAPSpoke(NormalSpoke): # no messages from the rules, add a message informing about that if not self._active_profile: # because of no profile - message = common.RuleMessage(common.MESSAGE_TYPE_INFO, - _("No profile selected")) + message = common.RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, + _("No profile selected")) else: # because of no pre-inst rules - message = common.RuleMessage(common.MESSAGE_TYPE_INFO, - _("No rules for the pre-installation phase")) + message = common.RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, + _("No rules for the pre-installation phase")) self._add_message(message) # nothing more to be done return + self._resolve_rootpw_issues(messages, report_only) for msg in messages: self._add_message(msg) + def _resolve_rootpw_issues(self, messages, report_only): + """Mitigate root password issues (which are not fatal in GUI)""" + fatal_rootpw_msgs = [msg for msg in messages + if msg.origin == rule_handling.PasswdRules and msg.type == common.MESSAGE_TYPE_FATAL] + if fatal_rootpw_msgs: + for msg in fatal_rootpw_msgs: + # cannot just change the message type because it is a namedtuple + messages.remove(msg) + messages.append(common.RuleMessage(self.__class__, common.MESSAGE_TYPE_WARNING, msg.text)) + if not report_only: + self.__old_root_pw = self.data.rootpw.password + self.data.rootpw.password = None + self.__old_root_pw_seen = self.data.rootpw.password.seen + self.data.rootpw.password.seen = False + + def _revert_rootpw_changes(self): + if self.__old_root_pw is not None: + self.data.rootpw.password = self.__old_root_pw + self.data.rootpw.password.seen = self.__old_root_pw_seen + self.__old_root_pw = None + self.__old_root_pw_seen = None + @gtk_action_wait def _unselect_profile(self, profile_id): """Unselects the given profile.""" @@ -615,6 +643,7 @@ class OSCAPSpoke(NormalSpoke): if self._rule_data: # revert changes and clear rule_data (no longer valid) self._rule_data.revert_changes(self.data, self._storage) + self._revert_rootpw_changes() self._rule_data = None self._active_profile = None @@ -769,7 +798,7 @@ class OSCAPSpoke(NormalSpoke): # no messages in the dry-run mode self._message_store.clear() - message = common.RuleMessage(common.MESSAGE_TYPE_INFO, + message = common.RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, _("Not applying security policy")) self._add_message(message) diff --git a/org_fedora_oscap/rule_handling.py b/org_fedora_oscap/rule_handling.py index a7bed22..2d58efe 100644 --- a/org_fedora_oscap/rule_handling.py +++ b/org_fedora_oscap/rule_handling.py @@ -223,6 +223,11 @@ class RuleData(RuleHandler): if opts.passwd: self._bootloader_rules.require_password() + @property + def passwd_rules(self): + # needed for fixups in GUI + return self._passwd_rules + class PartRules(RuleHandler): """Simple class holding data from the rules affecting partitioning.""" @@ -324,7 +329,7 @@ class PartRule(RuleHandler): if self._mount_point not in storage.mountpoints: msg = _("%s must be on a separate partition or logical " "volume" % self._mount_point) - messages.append(RuleMessage(common.MESSAGE_TYPE_FATAL, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_FATAL, msg)) # mount point doesn't exist, nothing more can be found here return messages @@ -337,7 +342,7 @@ class PartRule(RuleHandler): for opt in self._added_mount_options: msg = msg_tmpl % { "mount_option": opt, "mount_point": self._mount_point } - messages.append(RuleMessage(common.MESSAGE_TYPE_INFO, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, msg)) # mount point to be created during installation target_mount_point = storage.mountpoints[self._mount_point] @@ -352,7 +357,7 @@ class PartRule(RuleHandler): "mount_point": self._mount_point } # add message for the mount option in any case - messages.append(RuleMessage(common.MESSAGE_TYPE_INFO, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, msg)) # add new options to the target mount point if not reporting only if not report_only: @@ -428,18 +433,18 @@ class PasswdRules(RuleHandler): msg = _("make sure to create password with minimal length of %d " "characters") % self._minlen - ret = [RuleMessage(common.MESSAGE_TYPE_WARNING, msg)] + ret = [RuleMessage(self.__class__, common.MESSAGE_TYPE_WARNING, msg)] else: # root password set if ksdata.rootpw.isCrypted: msg = _("cannot check root password length (password is crypted)") log.warning("cannot check root password length (password is crypted)") - return [RuleMessage(common.MESSAGE_TYPE_WARNING, msg)] + return [RuleMessage(self.__class__, common.MESSAGE_TYPE_WARNING, msg)] elif len(ksdata.rootpw.password) < self._minlen: # too short msg = _("root password is too short, a longer one with at " "least %d characters is required") % self._minlen - ret = [RuleMessage(common.MESSAGE_TYPE_FATAL, msg)] + ret = [RuleMessage(self.__class__, common.MESSAGE_TYPE_FATAL, msg)] else: ret = [] @@ -532,7 +537,7 @@ class PackageRules(RuleHandler): for pkg in self._added_pkgs: msg = _("package '%s' has been added to the list of to be installed " "packages" % pkg) - messages.append(RuleMessage(common.MESSAGE_TYPE_INFO, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, msg)) # packages, that should be added packages_to_add = (pkg for pkg in self._add_pkgs @@ -546,7 +551,7 @@ class PackageRules(RuleHandler): msg = _("package '%s' has been added to the list of to be installed " "packages" % pkg) - messages.append(RuleMessage(common.MESSAGE_TYPE_INFO, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, msg)) ### now do the same for the packages that should be excluded @@ -554,7 +559,7 @@ class PackageRules(RuleHandler): for pkg in self._removed_pkgs: msg = _("package '%s' has been added to the list of excluded " "packages" % pkg) - messages.append(RuleMessage(common.MESSAGE_TYPE_INFO, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, msg)) # packages, that should be added packages_to_remove = (pkg for pkg in self._remove_pkgs @@ -568,7 +573,7 @@ class PackageRules(RuleHandler): msg = _("package '%s' has been added to the list of excluded " "packages" % pkg) - messages.append(RuleMessage(common.MESSAGE_TYPE_INFO, msg)) + messages.append(RuleMessage(self.__class__, common.MESSAGE_TYPE_INFO, msg)) return messages @@ -618,8 +623,8 @@ class BootloaderRules(RuleHandler): # Anaconda doesn't provide a way to set bootloader password, so # users cannot do much about that --> we shouldn't stop the # installation, should we? - return [RuleMessage(common.MESSAGE_TYPE_WARNING, - "boot loader password not set up")] + return [RuleMessage(self.__class__, common.MESSAGE_TYPE_WARNING, + "boot loader password not set up")] else: return [] -- 2.5.5