diff options
author | David Lehman <dlehman@redhat.com> | 2012-10-03 12:04:45 -0500 |
---|---|---|
committer | David Lehman <dlehman@redhat.com> | 2012-10-08 16:36:06 -0500 |
commit | f0114775a4dc28104421202bda6105363d60d8ae (patch) | |
tree | 77253fcda50e77fa5c453880a8129f0ac72600d5 /pyanaconda | |
parent | dcda4ed39866c648e2fb32b8c199ea4a3bfc0d6c (diff) | |
download | anaconda-f0114775a4dc28104421202bda6105363d60d8ae.tar.gz anaconda-f0114775a4dc28104421202bda6105363d60d8ae.tar.xz anaconda-f0114775a4dc28104421202bda6105363d60d8ae.zip |
Add a dialog for collecting a passphrase for newly encrypted devices.
Diffstat (limited to 'pyanaconda')
-rw-r--r-- | pyanaconda/ui/gui/spokes/lib/passphrase.glade | 236 | ||||
-rw-r--r-- | pyanaconda/ui/gui/spokes/lib/passphrase.py | 174 |
2 files changed, 410 insertions, 0 deletions
diff --git a/pyanaconda/ui/gui/spokes/lib/passphrase.glade b/pyanaconda/ui/gui/spokes/lib/passphrase.glade new file mode 100644 index 000000000..ca912f5ee --- /dev/null +++ b/pyanaconda/ui/gui/spokes/lib/passphrase.glade @@ -0,0 +1,236 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <!-- interface-requires gtk+ 3.0 --> + <object class="GtkDialog" id="passphrase_dialog"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="type_hint">dialog</property> + <property name="decorated">False</property> + <child internal-child="vbox"> + <object class="GtkBox" id="dialog-vbox3"> + <property name="can_focus">False</property> + <property name="orientation">vertical</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="passphrase_dialog_title_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="ypad">1</property> + <property name="label" translatable="yes">DISK ENCRYPTION PASSPHRASE</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child internal-child="action_area"> + <object class="GtkButtonBox" id="dialog-action_area3"> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="passphrase_cancel_button"> + <property name="label">gtk-cancel</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="halign">end</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="passphrase_save_button"> + <property name="label" translatable="yes">Save Passphrase</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_save_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="passphrase_description_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">You have chosen to encrypt some of your data. You will need to create a passphrase that you will use to access your data when you start your computer.</property> + <property name="wrap">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkGrid" id="passphrase_grid"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="halign">center</property> + <property name="row_spacing">6</property> + <property name="column_spacing">6</property> + <child> + <object class="GtkLabel" id="passphrase_entry_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Passphrase:</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="passphrase_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">●</property> + <property name="width_chars">32</property> + <signal name="changed" handler="on_passphrase_changed" swapped="no"/> + <signal name="focus-out-event" handler="on_passphrase_editing_done" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">0</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="confirm_entry_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Confirm:</property> + </object> + <packing> + <property name="left_attach">0</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkEntry" id="confirm_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="visibility">False</property> + <property name="invisible_char">●</property> + <property name="width_chars">32</property> + <signal name="changed" handler="on_confirm_changed" swapped="no"/> + <signal name="focus-out-event" handler="on_confirm_editing_done" swapped="no"/> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">2</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <object class="GtkBox" id="strength_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkLabel" id="strength_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">Weak</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="left_attach">1</property> + <property name="top_attach">1</property> + <property name="width">1</property> + <property name="height">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkBox" id="warning_box"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="stock">gtk-dialog-warning</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="passphrase_warning_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">keymap warning label</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">passphrase_cancel_button</action-widget> + <action-widget response="1">passphrase_save_button</action-widget> + </action-widgets> + </object> +</interface> diff --git a/pyanaconda/ui/gui/spokes/lib/passphrase.py b/pyanaconda/ui/gui/spokes/lib/passphrase.py new file mode 100644 index 000000000..c629cd731 --- /dev/null +++ b/pyanaconda/ui/gui/spokes/lib/passphrase.py @@ -0,0 +1,174 @@ +# Dialog for creating new encryption passphrase +# +# Copyright (C) 2012 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# the GNU General Public License v.2, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY expressed or implied, including the implied warranties of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. You should have received a copy of the +# GNU General Public License along with this program; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the +# source code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission of +# Red Hat, Inc. +# +# Red Hat Author(s): David Lehman <dlehman@redhat.com> +# + +from gi.repository import Gtk +from gi.repository import Gdk + +import gettext +import pwquality + +from pyanaconda.ui.gui import GUIObject + +from pyanaconda import keyboard + +_ = lambda x: gettext.ldgettext("anaconda", x) +P_ = lambda x, y, z: gettext.ldngettext("anaconda", x, y, z) + +__all__ = ["PassphraseDialog"] + +warning_label_template = _("Warning: Your current keyboard layout is <b>%s</b>." + "If you change your keyboard layout, you may not be " + "able to decrypt your disks after install.") + +ERROR_WEAK = _("You have provided a weak passphrase: %s") +ERROR_NOT_MATCHING = _("Passphrases do not match.") + +class PassphraseDialog(GUIObject): + builderObjects = ["passphrase_dialog"] + mainWidgetName = "passphrase_dialog" + uiFile = "spokes/lib/passphrase.glade" + + def refresh(self): + super(GUIObject, self).refresh() + self._warning_label = self.builder.get_object("passphrase_warning_label") + + # disable input methods for the passphrase Entry widgets and make sure + # the focus change mask is enabled + self._passphrase_entry = self.builder.get_object("passphrase_entry") + self._passphrase_entry.set_property("im-module", "") + self._passphrase_entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, "") + self._passphrase_entry.add_events(Gdk.EventMask.FOCUS_CHANGE_MASK) + self._confirm_entry = self.builder.get_object("confirm_entry") + self._confirm_entry.set_property("im-module", "") + self._confirm_entry.add_events(Gdk.EventMask.FOCUS_CHANGE_MASK) + + self._save_button = self.builder.get_object("passphrase_save_button") + + # add the passphrase strength meter + self._strength_bar = Gtk.LevelBar() + self._strength_bar.set_mode(Gtk.LevelBarMode.DISCRETE) + self._strength_bar.set_min_value(0) + self._strength_bar.set_max_value(4) + box = self.builder.get_object("strength_box") + box.pack_start(self._strength_bar, False, True, 0) + box.show_all() + self._strength_label = self.builder.get_object("strength_label") + + # set up passphrase quality checker + self._pwq = pwquality.PWQSettings() + self._pwq.read_config() + + # update the warning label with the currently selected keymap + xkl_wrapper = keyboard.XklWrapper.get_instance() + keymap_name = xkl_wrapper.get_current_layout_name() + warning_label_text = warning_label_template % keymap_name + self._warning_label.set_markup(warning_label_text) + + # initialize with the previously set passphrase + self.passphrase = self.data.autopart.passphrase + + self._passphrase_entry.set_text(self.passphrase) + self._confirm_entry.set_text(self.passphrase) + + self._update_passphrase_strength() + + def run(self): + self.refresh() + rc = self.window.run() + self.window.destroy() + return rc + + def _update_passphrase_strength(self): + passphrase = self._passphrase_entry.get_text() + strength = 0 + self._pwq_error = "" + try: + strength = self._pwq.check(passphrase, None, None) + except pwquality.PWQError as (e, msg): + self._pwq_error = msg + + if strength < 50: + val = 1 + text = _("Weak") + elif strength < 75: + val = 2 + text = _("Fair") + elif strength < 90: + val = 3 + text = _("Good") + else: + val = 4 + text = _("Strong") + + self._strength_bar.set_value(val) + self._strength_label.set_text(text) + + def _set_entry_icon(self, entry, icon, msg): + entry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, icon) + entry.set_icon_tooltip_text(Gtk.EntryIconPosition.SECONDARY, msg) + + def on_passphrase_changed(self, entry): + self._update_passphrase_strength() + if self._confirm_entry.get_text(): + self._confirm_entry.set_text("") + self._set_entry_icon(self._confirm_entry, "", "") + + if not self._pwq_error: + self._set_entry_icon(entry, "", "") + + self._save_button.set_sensitive(False) + self._confirm_entry.set_sensitive(False) + + def on_passphrase_editing_done(self, entry, *args): + sensitive = True + if self._pwq_error: + icon = "gtk-dialog-error" + msg = ERROR_WEAK % self._pwq_error + sensitive = False + self._set_entry_icon(entry, icon, msg) + + self._confirm_entry.set_sensitive(sensitive) + if sensitive: + self._confirm_entry.grab_focus() + + return True + + def on_confirm_changed(self, entry): + if not self._save_button.get_sensitive() and \ + entry.get_text() == self._passphrase_entry.get_text(): + self._save_button.set_sensitive(True) + self._set_entry_icon(entry, "", "") + + def on_confirm_editing_done(self, entry, *args): + passphrase = self._passphrase_entry.get_text() + confirm = self._confirm_entry.get_text() + if passphrase != confirm: + match = False + icon = "gtk-dialog-error" + msg = ERROR_NOT_MATCHING + self._set_entry_icon(entry, icon, msg) + self._save_button.set_sensitive(False) + else: + self._save_button.grab_focus() + + def on_save_clicked(self, button): + self.passphrase = self._passphrase_entry.get_text() + |