summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-08-20 18:53:59 +0200
committerAlexander Larsson <alexl@redhat.com>2012-08-20 18:53:59 +0200
commit86830605aeb46e63385e9000d9a78e1aa9c035e3 (patch)
tree322e96bef0fe2d3570c257d40a9af1c63d6f75c5
parente580cd115f61e98055c3619c24fc2d5b3eb64c68 (diff)
downloadgvfs-86830605aeb46e63385e9000d9a78e1aa9c035e3.tar.gz
Port to libsecret instead of libgnome-keyring
Based on an initial port by Stef Walter https://bugzilla.gnome.org/show_bug.cgi?id=679854
-rw-r--r--configure.ac4
-rw-r--r--daemon/gvfskeyring.c227
-rw-r--r--monitor/udisks2/gvfsudisks2volume.c100
3 files changed, 238 insertions, 93 deletions
diff --git a/configure.ac b/configure.ac
index 7adc583c..fa581f33 100644
--- a/configure.ac
+++ b/configure.ac
@@ -461,10 +461,10 @@ KEYRING_LIBS=
KEYRING_CFLAGS=
if test "x$enable_keyring" != "xno"; then
- PKG_CHECK_EXISTS(gnome-keyring-1, msg_keyring=yes)
+ PKG_CHECK_EXISTS(libsecret-unstable, msg_keyring=yes)
if test "x$msg_keyring" = "xyes"; then
- PKG_CHECK_MODULES(KEYRING, gnome-keyring-1)
+ PKG_CHECK_MODULES(KEYRING, libsecret-unstable)
AC_DEFINE(HAVE_KEYRING, 1, [Define to 1 if GNOME Keyring is available])
fi
fi
diff --git a/daemon/gvfskeyring.c b/daemon/gvfskeyring.c
index c720a573..3555ec14 100644
--- a/daemon/gvfskeyring.c
+++ b/daemon/gvfskeyring.c
@@ -22,8 +22,10 @@
#include <config.h>
+#define SECRET_API_SUBJECT_TO_CHANGE 1
+
#ifdef HAVE_KEYRING
-#include <gnome-keyring.h>
+#include <libsecret/secret.h>
#endif
#include "gvfskeyring.h"
@@ -32,12 +34,131 @@ gboolean
g_vfs_keyring_is_available (void)
{
#ifdef HAVE_KEYRING
- return gnome_keyring_is_available ();
+ return TRUE;
#else
return FALSE;
#endif
}
+#ifdef HAVE_KEYRING
+
+static void
+insert_string (const gchar *key,
+ const gchar *value,
+ GHashTable **attributes)
+{
+ if (*attributes == NULL)
+ return;
+
+ if (!g_utf8_validate (value, -1, NULL))
+ {
+ g_warning ("Non-utf8 value for key %s\n", key);
+ g_hash_table_unref (*attributes);
+ *attributes = NULL;
+ }
+
+ g_hash_table_insert (*attributes,
+ g_strdup (key),
+ g_strdup (value));
+}
+
+static void
+insert_int (const gchar *key,
+ gint value,
+ GHashTable **attributes)
+{
+ if (*attributes == NULL)
+ return;
+
+ g_hash_table_insert (*attributes,
+ g_strdup (key),
+ g_strdup_printf ("%d", value));
+}
+
+static GHashTable *
+build_network_attributes (const gchar *username,
+ const gchar *host,
+ const gchar *domain,
+ const gchar *protocol,
+ const gchar *object,
+ const gchar *authtype,
+ guint32 port)
+{
+ GHashTable *attributes;
+
+ attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ if (username)
+ insert_string ("user", username, &attributes);
+ if (host)
+ insert_string ("server", host, &attributes);
+ if (domain)
+ insert_string ("domain", domain, &attributes);
+ if (protocol)
+ insert_string ("protocol", protocol, &attributes);
+ if (object)
+ insert_string ("object", object, &attributes);
+ if (authtype)
+ insert_string ("authtype", authtype, &attributes);
+ if (port != 0)
+ insert_int ("port", (gint)port, &attributes);
+
+ return attributes;
+}
+
+static gchar *
+build_network_label (const gchar *user,
+ const gchar *server,
+ const gchar *object,
+ guint32 port)
+{
+ GString *s;
+ gchar *name;
+
+ if (server != NULL)
+ {
+ s = g_string_new (NULL);
+ if (user != NULL)
+ g_string_append_uri_escaped (s, user, G_URI_RESERVED_CHARS_ALLOWED_IN_USERINFO, TRUE);
+ g_string_append (s, "@");
+ g_string_append (s, server);
+ if (port != 0)
+ g_string_append_printf (s, ":%d", port);
+ if (object != NULL)
+ g_string_append_printf (s, "/%s", object);
+ name = g_string_free (s, FALSE);
+ }
+ else
+ {
+ name = g_strdup ("network password");
+ }
+ return name;
+}
+
+#endif /* HAVE_KEYRING */
+
+gint
+compare_specificity (gconstpointer a,
+ gconstpointer b)
+{
+ GHashTable *attributes_a, *attributes_b;
+ SecretItem *item_a, *item_b;
+ int res;
+
+ item_a = SECRET_ITEM (a);
+ attributes_a = secret_item_get_attributes (item_a);
+
+ item_b = SECRET_ITEM (b);
+ attributes_b = secret_item_get_attributes (item_b);
+
+ res = g_hash_table_size (attributes_a) - g_hash_table_size (attributes_b);
+
+ g_hash_table_unref (attributes_a);
+ g_hash_table_unref (attributes_b);
+
+ return res;
+}
+
gboolean
g_vfs_keyring_lookup_password (const gchar *username,
const gchar *host,
@@ -51,39 +172,58 @@ g_vfs_keyring_lookup_password (const gchar *username,
gchar **password_out)
{
#ifdef HAVE_KEYRING
- GnomeKeyringNetworkPasswordData *pwd_data;
- GnomeKeyringResult result;
- GList *plist;
+ GHashTable *attributes;
+ SecretItem *item;
+ SecretValue *secret;
+ GList *plist;
+ GError *error = NULL;
+
+
+ attributes = build_network_attributes (username, host, domain, protocol, object, authtype, port);
+ plist = secret_service_search_sync (NULL, SECRET_SCHEMA_COMPAT_NETWORK, attributes,
+ SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS |
+ SECRET_SEARCH_ALL,
+ NULL, &error);
+ g_hash_table_unref (attributes);
+
+ if (error != NULL)
+ {
+ g_error_free (error);
+ return FALSE;
+ }
- if (!gnome_keyring_is_available ())
+ if (plist == NULL)
return FALSE;
- result = gnome_keyring_find_network_password_sync (
- username,
- domain,
- host,
- object,
- protocol,
- authtype,
- port,
- &plist);
+ /* We want the least specific result, so we sort the return values.
+ For instance, given both items for ftp://host:port and ftp://host
+ in the keyring we always want to use the ftp://host one for
+ i.e. ftp://host/some/path. */
+
+ plist = g_list_sort (plist, compare_specificity);
- if (result != GNOME_KEYRING_RESULT_OK || plist == NULL)
- return FALSE;
+ item = SECRET_ITEM (plist->data);
+ secret = secret_item_get_secret (item);
+ attributes = secret_item_get_attributes (item);
+ g_list_free_full (plist, g_object_unref);
- /* We use the first result, which is the least specific match */
- pwd_data = (GnomeKeyringNetworkPasswordData *)plist->data;
+ if (secret == NULL)
+ {
+ if (attributes)
+ g_hash_table_unref (attributes);
+ return FALSE;
+ }
- *password_out = g_strdup (pwd_data->password);
+ *password_out = g_strdup (secret_value_get (secret, NULL));
+ secret_value_unref (secret);
if (username_out)
- *username_out = g_strdup (pwd_data->user);
-
+ *username_out = g_strdup (g_hash_table_lookup (attributes, "user"));
+
if (domain_out)
- *domain_out = g_strdup (pwd_data->domain);
-
- gnome_keyring_network_password_list_free (plist);
-
+ *domain_out = g_strdup (g_hash_table_lookup (attributes, "domain"));
+
+ g_hash_table_unref (attributes);
return TRUE;
#else
return FALSE;
@@ -102,31 +242,26 @@ g_vfs_keyring_save_password (const gchar *username,
GPasswordSave flags)
{
#ifdef HAVE_KEYRING
- GnomeKeyringResult result;
const gchar *keyring;
- guint32 item_id;
-
- if (!gnome_keyring_is_available ())
- return FALSE;
+ GHashTable *attributes;
+ gchar *label;
+ gboolean ret;
if (flags == G_PASSWORD_SAVE_NEVER)
return FALSE;
- keyring = (flags == G_PASSWORD_SAVE_FOR_SESSION) ? "session" : NULL;
-
- result = gnome_keyring_set_network_password_sync (
- keyring,
- username,
- domain,
- host,
- object,
- protocol,
- authtype,
- port,
- password,
- &item_id);
-
- return (result == GNOME_KEYRING_RESULT_OK);
+ keyring = (flags == G_PASSWORD_SAVE_FOR_SESSION) ? SECRET_COLLECTION_SESSION : SECRET_COLLECTION_DEFAULT;
+
+ label = build_network_label (username, host, object, port);
+ attributes = build_network_attributes (username, host, domain, protocol, object, authtype, port);
+
+ ret = secret_password_storev_sync (SECRET_SCHEMA_COMPAT_NETWORK, attributes,
+ keyring, label, password, NULL, NULL);
+
+ g_free (label);
+ g_hash_table_unref (attributes);
+
+ return ret;
#else
return FALSE;
#endif /* HAVE_KEYRING */
diff --git a/monitor/udisks2/gvfsudisks2volume.c b/monitor/udisks2/gvfsudisks2volume.c
index 29ba0a43..7652a4b8 100644
--- a/monitor/udisks2/gvfsudisks2volume.c
+++ b/monitor/udisks2/gvfsudisks2volume.c
@@ -32,7 +32,7 @@
#include <gio/gio.h>
#ifdef HAVE_KEYRING
-#include <gnome-keyring.h>
+#include <libsecret/secret.h>
#endif
#include "gvfsudisks2drive.h"
@@ -779,12 +779,13 @@ gvfs_udisks2_volume_get_activation_root (GVolume *_volume)
/* ---------------------------------------------------------------------------------------------------- */
#ifdef HAVE_KEYRING
-static GnomeKeyringPasswordSchema luks_passphrase_schema =
+static SecretSchema luks_passphrase_schema =
{
- GNOME_KEYRING_ITEM_GENERIC_SECRET,
+ "org.gnome.GVfs.Luks.Password",
+ SECRET_SCHEMA_DONT_MATCH_NAME,
{
- {"gvfs-luks-uuid", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING},
- {NULL, 0}
+ { "gvfs-luks-uuid", SECRET_SCHEMA_ATTRIBUTE_STRING },
+ { NULL, 0 },
}
};
#endif
@@ -833,8 +834,13 @@ mount_data_free (MountData *data)
g_object_unref (data->mount_operation);
}
+#ifdef HAVE_KEYRING
+ secret_password_free (data->passphrase);
+ secret_password_free (data->passphrase_from_keyring);
+#else
g_free (data->passphrase);
g_free (data->passphrase_from_keyring);
+#endif
g_free (data->uuid_of_encrypted_to_unlock);
g_free (data->desc_of_encrypted_to_unlock);
@@ -981,11 +987,14 @@ do_mount (MountData *data)
#ifdef HAVE_KEYRING
static void
-luks_store_passphrase_cb (GnomeKeyringResult result,
- gpointer user_data)
+luks_store_passphrase_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
MountData *data = user_data;
- if (result == GNOME_KEYRING_RESULT_OK)
+ GError *error = NULL;
+
+ if (secret_password_store_finish (result, &error))
{
/* everything is good */
do_mount (data);
@@ -996,9 +1005,10 @@ luks_store_passphrase_cb (GnomeKeyringResult result,
g_simple_async_result_set_error (data->simple,
G_IO_ERROR,
G_IO_ERROR_FAILED,
- _("Error storing passphrase in keyring (error code %d)"),
- result);
+ _("Error storing passphrase in keyring (%s)"),
+ error->message);
g_simple_async_result_complete (data->simple);
+ g_error_free (error);
mount_data_free (data);
}
}
@@ -1010,11 +1020,14 @@ static void do_unlock (MountData *data);
#ifdef HAVE_KEYRING
static void
-luks_delete_passphrase_cb (GnomeKeyringResult result,
- gpointer user_data)
+luks_delete_passphrase_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
MountData *data = user_data;
- if (result == GNOME_KEYRING_RESULT_OK)
+ GError *error = NULL;
+
+ if (secret_password_clear_finish (result, &error))
{
/* with the bad passphrase out of the way, try again */
g_free (data->passphrase);
@@ -1027,9 +1040,10 @@ luks_delete_passphrase_cb (GnomeKeyringResult result,
g_simple_async_result_set_error (data->simple,
G_IO_ERROR,
G_IO_ERROR_FAILED,
- _("Error deleting invalid passphrase from keyring (error code %d)"),
- result);
+ _("Error deleting invalid passphrase from keyring (%s)"),
+ error->message);
g_simple_async_result_complete (data->simple);
+ g_error_free (error);
mount_data_free (data);
}
}
@@ -1061,12 +1075,10 @@ unlock_cb (GObject *source_object,
g_strcmp0 (data->passphrase, data->passphrase_from_keyring) == 0)
{
/* nuke the invalid passphrase from keyring... */
- gnome_keyring_delete_password (&luks_passphrase_schema,
- luks_delete_passphrase_cb,
- data,
- NULL, /* GDestroyNotify */
- "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
- NULL); /* sentinel */
+ secret_password_clear (&luks_passphrase_schema, data->cancellable,
+ luks_delete_passphrase_cb, data,
+ "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
+ NULL); /* sentinel */
goto out;
}
#endif
@@ -1112,28 +1124,25 @@ unlock_cb (GObject *source_object,
g_assert_not_reached ();
break;
case G_PASSWORD_SAVE_FOR_SESSION:
- keyring = GNOME_KEYRING_SESSION;
+ keyring = SECRET_COLLECTION_SESSION;
break;
case G_PASSWORD_SAVE_PERMANENTLY:
- keyring = GNOME_KEYRING_DEFAULT;
+ keyring = SECRET_COLLECTION_DEFAULT;
break;
default:
- keyring = GNOME_KEYRING_DEFAULT;
+ keyring = SECRET_COLLECTION_DEFAULT;
break;
}
display_name = g_strdup_printf (_("Encryption passphrase for %s"),
data->desc_of_encrypted_to_unlock);
- gnome_keyring_store_password (&luks_passphrase_schema,
- keyring,
- display_name,
- data->passphrase,
- luks_store_passphrase_cb,
- data,
- NULL, /* GDestroyNotify */
- "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
- NULL); /* sentinel */
+ secret_password_store (&luks_passphrase_schema,
+ keyring, display_name, data->passphrase,
+ data->cancellable,
+ luks_store_passphrase_cb, data,
+ "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
+ NULL); /* sentinel */
goto out;
}
#endif
@@ -1237,19 +1246,22 @@ has_crypttab_passphrase (MountData *data)
#ifdef HAVE_KEYRING
static void
-luks_find_passphrase_cb (GnomeKeyringResult result,
- const gchar *string,
- gpointer user_data)
+luks_find_passphrase_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
{
MountData *data = user_data;
+ gchar *password;
+
+ password = secret_password_lookup_finish (result, NULL);
/* Don't fail if a keyring error occured - just continue and request
* the passphrase from the user...
*/
- if (result == GNOME_KEYRING_RESULT_OK)
+ if (password)
{
- data->passphrase = g_strdup (string);
- data->passphrase_from_keyring = g_strdup (string);
+ data->passphrase = password;
+ data->passphrase_from_keyring = g_strdup (password);
}
/* try again */
do_unlock (data);
@@ -1277,12 +1289,10 @@ do_unlock (MountData *data)
if (!data->checked_keyring)
{
data->checked_keyring = TRUE;
- gnome_keyring_find_password (&luks_passphrase_schema,
- luks_find_passphrase_cb,
- data,
- NULL, /* GDestroyNotify */
- "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
- NULL); /* sentinel */
+ secret_password_lookup (&luks_passphrase_schema, data->cancellable,
+ luks_find_passphrase_cb, data,
+ "gvfs-luks-uuid", data->uuid_of_encrypted_to_unlock,
+ NULL); /* sentinel */
goto out;
}
#endif