[master 1/1] Do not allow passphrases to be typed with non-ASCII keymaps (#681250)

dashea installerbot-noreply at redhat.com
Mon Aug 31 20:57:22 UTC 2015


From: David Shea <dshea at redhat.com>

Keymaps are complicated, and it's impossible to know whether a
particular passphrase will be typable at boot time, but we can be pretty
sure that anything from a non-ASCII keymap will not be typable. If the
user is attempting to use such a keymap in the passphrase dialog,
disable input and display an error message.
---
 pyanaconda/ui/gui/spokes/lib/passphrase.py | 42 ++++++++++++++++++++++++++++++
 pyanaconda/ui/gui/xkl_wrapper.py           |  4 +++
 2 files changed, 46 insertions(+)

diff --git a/pyanaconda/ui/gui/spokes/lib/passphrase.py b/pyanaconda/ui/gui/spokes/lib/passphrase.py
index 580a1d3..10e9bfd 100644
--- a/pyanaconda/ui/gui/spokes/lib/passphrase.py
+++ b/pyanaconda/ui/gui/spokes/lib/passphrase.py
@@ -25,13 +25,16 @@
 from gi.repository import Gtk
 
 import pwquality
+import langtable
 
 from pyanaconda.ui.helpers import InputCheck
 from pyanaconda.ui.gui import GUIObject
 from pyanaconda.ui.gui.helpers import GUIInputCheckHandler
+from pyanaconda.ui.helpers import InputCheckHandler
 from pyanaconda.constants import PW_ASCII_CHARS
 from pyanaconda.i18n import _, N_
 from pyanaconda.ui.gui.utils import really_hide, really_show
+from pyanaconda.ui.gui.xkl_wrapper import XklWrapper
 
 __all__ = ["PassphraseDialog"]
 
@@ -73,6 +76,18 @@ def __init__(self, data):
         self._pwq_error = None
         self.passphrase = ""
 
+        # due to the contraints of the keymap at boot time, do not allow input
+        # from non-ASCII keymaps. This check depends on the current active keymap
+        # and not any particular input, but add it as an input check so that the error
+        # message is displayed through the same mechanism. Use add_check from InputCheckHandler
+        # so that no real input object is needed and so there is no delay wrapper around the check
+        self._keymap_check = InputCheckHandler.add_check(self, None, self._checkKeymap)
+
+        # Run the keymap check on keymap changes
+        self._xkl_instance = XklWrapper.get_instance()
+        self._xkl_instance.engine.connect("X-state-changed", self.on_keymap_change)
+        self._xkl_instance.engine.connect("X-config-changed", self.on_keymap_change)
+
         # the passphrase confirmation needs to be checked whenever either of the password
         # fields change. attach to the confirm field and check changes to the
         # password field in on_passphrase_changed
@@ -80,6 +95,9 @@ def __init__(self, data):
         self._strength_check = self.add_check(self._passphrase_entry, self._checkStrength)
         self._ascii_check = self.add_check(self._passphrase_entry, self._checkASCII)
 
+        # Initialize the keymap state
+        self._keymap_check.update_check_status()
+
     def refresh(self):
         super(PassphraseDialog, self).refresh()
 
@@ -163,6 +181,14 @@ def set_status(self, inputcheck):
         # Set the warning message with the result from the first failed check
         failed_check = next(self.failed_checks_with_message, None)
 
+        # If the keymap check failed, shutdown the input
+        if failed_check == self._keymap_check:
+            self._passphrase_entry.set_sensitive(False)
+            self._confirm_entry.set_sensitive(False)
+        else:
+            self._passphrase_entry.set_sensitive(True)
+            self._confirm_entry.set_sensitive(True)
+
         if failed_check:
             result_icon, result_message = failed_check.check_status
             self._passphrase_warning_image.set_from_icon_name(result_icon, Gtk.IconSize.BUTTON)
@@ -180,6 +206,18 @@ def set_status(self, inputcheck):
         else:
             self._save_button.set_sensitive(False)
 
+    def _checkKeymap(self, inputcheck):
+        # Check whether the current keymap is ASCII-compatible. If not, it will
+        # not match the boot keymap, and it is not suitable for typing in a
+        # passphrase
+        keymap = self._xkl_instance.get_current_layout()
+        if not langtable.supports_ascii(keymap):
+            return ("dialog-error", _("The current keyboard layout does not match the keyboard layout "
+                    "that will be used to unlock the encrypted partition. Using this keyboard layout to "
+                    "input a passphrase could result in an unbootable system."))
+        else:
+            return InputCheck.CHECK_OK
+
     def _checkASCII(self, inputcheck):
         passphrase = self.get_input(inputcheck.input_obj)
 
@@ -222,3 +260,7 @@ def on_entry_activated(self, entry):
         if self._save_button.get_sensitive() and \
            entry.get_text() == self._passphrase_entry.get_text():
             self._save_button.emit("clicked")
+
+    def on_keymap_change(self, *args):
+        # Update the keymap check
+        self._keymap_check.update_check_status()
diff --git a/pyanaconda/ui/gui/xkl_wrapper.py b/pyanaconda/ui/gui/xkl_wrapper.py
index b559eae..78d7de9 100644
--- a/pyanaconda/ui/gui/xkl_wrapper.py
+++ b/pyanaconda/ui/gui/xkl_wrapper.py
@@ -393,3 +393,7 @@ def set_switching_options(self, options):
             msg = "Failed to set switching options to: %s" % ",".join(options)
             raise XklWrapperError(msg)
 
+    @property
+    def engine(self):
+        """The underlying XklEngine object"""
+        return self._engine


-- 
To view this commit on github, visit https://github.com/rhinstaller/anaconda/commit/2942db81de78a0e98acf228822529861cd0d95e9


More information about the anaconda-patches mailing list