[gnome-disk-utility] Check keyring for LUKS passphrase and put it in passphrase entry if available



commit a1d23726503212b0f5b1ce17153dea1e11c17235
Author: David Zeuthen <davidz redhat com>
Date:   Thu Apr 26 16:17:59 2012 -0400

    Check keyring for LUKS passphrase and put it in passphrase entry if available
    
    Also show a cluebar if this is the case. See
    
     http://people.freedesktop.org/~david/disks-luks-passphrase-from-keyring.png
    
    for a screenshot and
    
     https://bugzilla.gnome.org/show_bug.cgi?id=674161
    
    for where it was decided that it was useful for GVfs to store the
    passphrase in the keyring (in addition to /etc/crypttab).
    
    Signed-off-by: David Zeuthen <davidz redhat com>

 configure.ac                     |    2 +
 data/ui/unlock-device-dialog.ui  |   40 ++++----
 src/palimpsest/Makefile.am       |    2 +
 src/palimpsest/gduunlockdialog.c |  210 +++++++++++++++++++++++++++-----------
 4 files changed, 175 insertions(+), 79 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index da614fb..5bf50fe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,10 +30,12 @@ GNOME_MAINTAINER_MODE_DEFINES
 GLIB2_REQUIRED=2.31.0
 UDISKS2_REQUIRED=1.90.0
 GTK3_REQUIRED=3.3.11
+KEYRING1_REQUIRED=3.4.0
 
 PKG_CHECK_MODULES(GLIB2, [gio-unix-2.0 >= $GLIB2_REQUIRED])
 PKG_CHECK_MODULES(UDISKS2, [udisks2 >= $UDISKS2_REQUIRED])
 PKG_CHECK_MODULES(GTK3, [gtk+-3.0 >= $GTK3_REQUIRED])
+PKG_CHECK_MODULES(KEYRING1, [gnome-keyring-1 >= $KEYRING1_REQUIRED])
 
 dnl **********************************
 dnl *** Check for libsystemd-login ***
diff --git a/data/ui/unlock-device-dialog.ui b/data/ui/unlock-device-dialog.ui
index aa4e42e..d2085b6 100644
--- a/data/ui/unlock-device-dialog.ui
+++ b/data/ui/unlock-device-dialog.ui
@@ -14,6 +14,21 @@
         <property name="orientation">vertical</property>
         <property name="spacing">12</property>
         <child>
+          <object class="GtkBox" id="infobar-vbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <placeholder/>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
           <object class="GtkLabel" id="label8">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
@@ -24,7 +39,7 @@
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">0</property>
+            <property name="position">1</property>
           </packing>
         </child>
         <child>
@@ -56,6 +71,7 @@
               <object class="GtkEntry" id="unlock-device-passphrase-entry">
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
+                <property name="hexpand">True</property>
                 <property name="visibility">False</property>
                 <property name="invisible_char">â</property>
                 <property name="activates_default">True</property>
@@ -71,6 +87,7 @@
             <child>
               <object class="GtkCheckButton" id="unlock-device-show-passphrase-check-button">
                 <property name="label" translatable="yes">Sho_w passphrase</property>
+                <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">False</property>
@@ -89,26 +106,11 @@
             <child>
               <placeholder/>
             </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
-            <child>
-              <placeholder/>
-            </child>
           </object>
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">1</property>
+            <property name="position">2</property>
           </packing>
         </child>
         <child internal-child="action_area">
@@ -118,6 +120,7 @@
             <child>
               <object class="GtkButton" id="button5">
                 <property name="label">gtk-cancel</property>
+                <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
@@ -133,6 +136,7 @@
             <child>
               <object class="GtkButton" id="button6">
                 <property name="label" translatable="yes">_Unlock</property>
+                <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="can_default">True</property>
@@ -151,7 +155,7 @@
             <property name="expand">False</property>
             <property name="fill">True</property>
             <property name="pack_type">end</property>
-            <property name="position">2</property>
+            <property name="position">3</property>
           </packing>
         </child>
       </object>
diff --git a/src/palimpsest/Makefile.am b/src/palimpsest/Makefile.am
index 69f73d5..d06f2ae 100644
--- a/src/palimpsest/Makefile.am
+++ b/src/palimpsest/Makefile.am
@@ -62,6 +62,7 @@ palimpsest_CFLAGS = 					\
 	$(GLIB2_CFLAGS)					\
 	$(UDISKS2_CFLAGS)				\
 	$(GTK3_CFLAGS)					\
+	$(KEYRING1_CFLAGS)				\
 	$(LIBSYSTEMD_LOGIN_CFLAGS)			\
 	$(WARN_CFLAGS)					\
 	-lm						\
@@ -71,6 +72,7 @@ palimpsest_LDADD = 					\
 	$(GLIB2_LIBS)					\
 	$(UDISKS2_LIBS)					\
 	$(GTK3_LIBS)					\
+	$(KEYRING1_LIBS)				\
 	$(LIBSYSTEMD_LOGIN_LIBS)			\
 	$(NULL)
 
diff --git a/src/palimpsest/gduunlockdialog.c b/src/palimpsest/gduunlockdialog.c
index f1e7fa9..01b73b9 100644
--- a/src/palimpsest/gduunlockdialog.c
+++ b/src/palimpsest/gduunlockdialog.c
@@ -23,6 +23,7 @@
 #include "config.h"
 
 #include <glib/gi18n.h>
+#include <gnome-keyring.h>
 
 #include "gduapplication.h"
 #include "gduwindow.h"
@@ -30,6 +31,54 @@
 #include "gduvolumegrid.h"
 #include "gduutils.h"
 
+/* From GVfs's monitor/udisks2/gvfsudisks2volume.c */
+static GnomeKeyringPasswordSchema luks_passphrase_schema =
+{
+  GNOME_KEYRING_ITEM_GENERIC_SECRET,
+  {
+    {"gvfs-luks-uuid", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING},
+    {NULL, 0}
+  }
+};
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  UDisksObject *object;
+  UDisksBlock *block;
+  UDisksEncrypted *encrypted;
+
+  GduWindow *window;
+  GtkBuilder *builder;
+
+  GtkWidget *dialog;
+  GtkWidget *infobar_vbox;
+  GtkWidget *entry;
+  GtkWidget *show_passphrase_check_button;
+
+  gchar *passphrase;
+} DialogData;
+
+static void
+dialog_data_free (DialogData *data)
+{
+  if (data->dialog != NULL)
+    {
+      gtk_widget_hide (data->dialog);
+      gtk_widget_destroy (data->dialog);
+    }
+  if (data->object != NULL)
+    g_object_unref (data->object);
+  if (data->window != NULL)
+    g_object_unref (data->window);
+  if (data->builder != NULL)
+    g_object_unref (data->builder);
+
+  g_free (data->passphrase);
+  g_free (data);
+}
+
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
@@ -37,7 +86,7 @@ unlock_cb (UDisksEncrypted *encrypted,
            GAsyncResult    *res,
            gpointer         user_data)
 {
-  GduWindow *window = GDU_WINDOW (user_data);
+  DialogData *data = user_data;
   GError *error;
 
   error = NULL;
@@ -46,83 +95,122 @@ unlock_cb (UDisksEncrypted *encrypted,
                                             res,
                                             &error))
     {
-      gdu_window_show_error (window,
+      gdu_window_show_error (data->window,
                              _("Error unlocking encrypted device"),
                              error);
       g_error_free (error);
     }
-  g_object_unref (window);
+  dialog_data_free (data);
 }
 
-void
-gdu_unlock_dialog_show (GduWindow    *window,
-                        UDisksObject *object)
+static void
+do_unlock (DialogData *data)
 {
-  gint response;
-  GtkBuilder *builder;
-  GtkWidget *dialog;
-  GtkWidget *entry;
-  GtkWidget *show_passphrase_check_button;
-  UDisksBlock *block;
-  UDisksEncrypted *encrypted;
-  const gchar *passphrase;
-  gboolean has_passphrase;
-
-  dialog = NULL;
-  builder = NULL;
-
-  /* TODO: look up passphrase from gnome-keyring? */
+  udisks_encrypted_call_unlock (data->encrypted,
+                                data->passphrase,
+                                g_variant_new ("a{sv}", NULL), /* options */
+                                NULL, /* cancellable */
+                                (GAsyncReadyCallback) unlock_cb,
+                                data);
+}
 
-  block = udisks_object_peek_block (object);
-  encrypted = udisks_object_peek_encrypted (object);
+static void
+show_dialog (DialogData *data)
+{
+  gint response;
 
-  passphrase = "";
-  has_passphrase = FALSE;
-  if (gdu_utils_has_configuration (block, "crypttab", &has_passphrase) && has_passphrase)
-    goto do_call;
+  gtk_widget_show_all (data->dialog);
+  gtk_widget_grab_focus (data->entry);
 
-  dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
-                                                   "unlock-device-dialog.ui",
-                                                   "unlock-device-dialog",
-                                                   &builder));
-  entry = GTK_WIDGET (gtk_builder_get_object (builder, "unlock-device-passphrase-entry"));
-  show_passphrase_check_button = GTK_WIDGET (gtk_builder_get_object (builder, "unlock-device-show-passphrase-check-button"));
+  response = gtk_dialog_run (GTK_DIALOG (data->dialog));
+  if (response == GTK_RESPONSE_OK)
+    {
+      gtk_widget_hide (data->dialog);
+      data->passphrase = g_strdup (gtk_entry_get_text (GTK_ENTRY (data->entry)));
+      do_unlock (data);
+    }
+  else
+    {
+      /* otherwise, we are done */
+      dialog_data_free (data);
+    }
+}
 
-  gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window));
-  gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+static void
+luks_find_passphrase_cb (GnomeKeyringResult result,
+                         const gchar       *string,
+                         gpointer           user_data)
+{
+  DialogData *data = user_data;
 
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (show_passphrase_check_button), FALSE);
-  gtk_entry_set_text (GTK_ENTRY (entry), "");
+  /* Don't fail if a keyring error occured... but if we do find a
+   * passphrase then put it into the entry field and show a
+   * cluebar
+   */
+  if (result == GNOME_KEYRING_RESULT_OK)
+    {
+      GtkWidget *infobar;
+      infobar = gdu_utils_create_info_bar (GTK_MESSAGE_INFO,
+                                           _("The encryption passphrase was retrieved from the keyring"),
+                                           NULL);
+      gtk_box_pack_start (GTK_BOX (data->infobar_vbox), infobar, TRUE, TRUE, 0);
+      gtk_entry_set_text (GTK_ENTRY (data->entry), string);
+    }
+  else
+    {
+      gtk_widget_hide (data->infobar_vbox);
+      gtk_widget_set_no_show_all (data->infobar_vbox, TRUE);
+    }
+  show_dialog (data);
+}
 
-  g_object_bind_property (show_passphrase_check_button,
+void
+gdu_unlock_dialog_show (GduWindow    *window,
+                        UDisksObject *object)
+{
+  gboolean has_passphrase_in_crypttab = FALSE;
+  DialogData *data;
+
+  data = g_new0 (DialogData, 1);
+  data->object = g_object_ref (object);
+  data->block = udisks_object_peek_block (object);
+  data->encrypted = udisks_object_peek_encrypted (object);
+  data->window = g_object_ref (window);
+
+  data->dialog = GTK_WIDGET (gdu_application_new_widget (gdu_window_get_application (window),
+                                                         "unlock-device-dialog.ui",
+                                                         "unlock-device-dialog",
+                                                         &data->builder));
+  data->infobar_vbox = GTK_WIDGET (gtk_builder_get_object (data->builder, "infobar-vbox"));
+  data->entry = GTK_WIDGET (gtk_builder_get_object (data->builder, "unlock-device-passphrase-entry"));
+  data->show_passphrase_check_button = GTK_WIDGET (gtk_builder_get_object (data->builder, "unlock-device-show-passphrase-check-button"));
+
+  gtk_window_set_transient_for (GTK_WINDOW (data->dialog), GTK_WINDOW (data->window));
+  gtk_dialog_set_default_response (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK);
+
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->show_passphrase_check_button), FALSE);
+  gtk_entry_set_text (GTK_ENTRY (data->entry), "");
+
+  g_object_bind_property (data->show_passphrase_check_button,
                           "active",
-                          entry,
+                          data->entry,
                           "visibility",
                           G_BINDING_SYNC_CREATE);
 
-  gtk_widget_show_all (dialog);
-  gtk_widget_grab_focus (entry);
-
-  response = gtk_dialog_run (GTK_DIALOG (dialog));
-  if (response != GTK_RESPONSE_OK)
-    goto out;
-
-  passphrase = gtk_entry_get_text (GTK_ENTRY (entry));
-
- do_call:
-  udisks_encrypted_call_unlock (encrypted,
-                                passphrase,
-                                g_variant_new ("a{sv}", NULL), /* options */
-                                NULL, /* cancellable */
-                                (GAsyncReadyCallback) unlock_cb,
-                                g_object_ref (window));
-
- out:
-  if (dialog != NULL)
+  if (gdu_utils_has_configuration (data->block, "crypttab", &has_passphrase_in_crypttab) &&
+      has_passphrase_in_crypttab)
+    {
+      data->passphrase = g_strdup ("");
+      do_unlock (data);
+    }
+  else
     {
-      gtk_widget_hide (dialog);
-      gtk_widget_destroy (dialog);
+      /* see if there's a passphrase in the keyring */
+      gnome_keyring_find_password (&luks_passphrase_schema,
+                                   luks_find_passphrase_cb,
+                                   data,
+                                   NULL, /* GDestroyNotify */
+                                   "gvfs-luks-uuid", udisks_block_get_id_uuid (data->block),
+                                   NULL); /* sentinel */
     }
-  if (builder != NULL)
-    g_object_unref (builder);
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]