[gnome-keyring] [secrets] Implement lookup collection passwords in login keyring.



commit 9981a23971d924294055d9a142cc2a8d7b448306
Author: Stef Walter <stef memberwebs com>
Date:   Sun Jan 3 20:27:29 2010 +0000

    [secrets] Implement lookup collection passwords in login keyring.
    
    Also add support for null passwords, and automatically unlocking
    collections with null passwords.

 daemon/dbus/gkd-secret-unlock.c |  100 ++++++++++++++++++++++++++++++++++++---
 daemon/dbus/gkd-secret-unlock.h |    5 ++
 2 files changed, 98 insertions(+), 7 deletions(-)
---
diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
index a9e8a56..6fad92a 100644
--- a/daemon/dbus/gkd-secret-unlock.c
+++ b/daemon/dbus/gkd-secret-unlock.c
@@ -32,6 +32,8 @@
 
 #include "egg/egg-secure-memory.h"
 
+#include "login/gkd-login.h"
+
 #include "pkcs11/pkcs11i.h"
 
 #include <glib/gi18n.h>
@@ -53,6 +55,31 @@ G_DEFINE_TYPE (GkdSecretUnlock, gkd_secret_unlock, GKD_SECRET_TYPE_PROMPT);
  * INTERNAL
  */
 
+static gchar*
+location_string_for_collection (GP11Object *collection)
+{
+	gpointer identifier;
+	gsize n_identifier;
+	gchar *location;
+
+	/* Figure out the identifier */
+	identifier = gp11_object_get_data (collection, CKA_ID, &n_identifier, NULL);
+	if (!identifier || !g_utf8_validate (identifier, n_identifier, NULL)) {
+		g_free (identifier);
+		return NULL;
+	}
+
+	/*
+	 * COMPAT: Format it into a string. This is done this way for compatibility
+	 * with old gnome-keyring releases. In the future this may change.
+	 *
+	 * FYI: gp11_object_get_data() null terminates
+	 */
+	location = g_strdup_printf ("LOCAL:/keyrings/%s.keyring", (gchar*)identifier);
+	g_free (identifier);
+	return location;
+}
+
 static void
 prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll)
 {
@@ -323,8 +350,10 @@ gkd_secret_unlock_new (GkdSecretService *service, const gchar *caller)
 void
 gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *objpath)
 {
+	gboolean locked = TRUE;
 	GP11Object *coll;
-	gboolean locked;
+	gchar *password;
+	gchar *location;
 	gchar *path;
 
 	g_return_if_fail (GKD_SECRET_IS_UNLOCK (self));
@@ -334,14 +363,31 @@ gkd_secret_unlock_queue (GkdSecretUnlock *self, const gchar *objpath)
 	if (coll == NULL)
 		return;
 
-	if (authenticate_collection (self, coll, &locked)) {
-		path = g_strdup (objpath);
-		if (locked)
-			g_queue_push_tail (self->queued, path);
-		else
-			g_array_append_val (self->results, path);
+	/* Try to unlock with an empty password */
+	if (gkd_secret_unlock_with_password (coll, NULL, 0, NULL)) {
+		locked = FALSE;
+
+	/* Or try to use login keyring's passwords */
+	} else {
+		location = location_string_for_collection (coll);
+		if (location) {
+			password = gkd_login_lookup_secret ("keyring", location, NULL);
+			g_free (location);
+
+			if (password) {
+				if (gkd_secret_unlock_with_password (coll, (guchar*)password, strlen (password), NULL))
+					locked = FALSE;
+				egg_secure_strfree (password);
+			}
+		}
 	}
 
+	path = g_strdup (objpath);
+	if (locked)
+		g_queue_push_tail (self->queued, path);
+	else
+		g_array_append_val (self->results, path);
+
 	g_object_unref (coll);
 }
 
@@ -402,3 +448,43 @@ gkd_secret_unlock_with_secret (GP11Object *collection, GkdSecretSecret *master,
 		g_object_unref (cred);
 	return (cred != NULL);
 }
+
+gboolean
+gkd_secret_unlock_with_password (GP11Object *collection, const guchar *password,
+                                 gsize n_password, DBusError *derr)
+{
+	GError *error = NULL;
+	GP11Session *session;
+	GP11Object *cred;
+	gboolean locked;
+
+	g_return_val_if_fail (GP11_IS_OBJECT (collection), FALSE);
+
+	/* Shortcut if already unlocked */
+	if (check_locked_collection (collection, &locked) && !locked)
+		return TRUE;
+
+	session = gp11_object_get_session (collection);
+	g_return_val_if_fail (session, FALSE);
+
+	cred = gp11_session_create_object (session, &error, CKA_CLASS, GP11_ULONG, CKO_G_CREDENTIAL,
+	                                   CKA_G_OBJECT, GP11_ULONG, gp11_object_get_handle (collection),
+	                                   CKA_GNOME_TRANSIENT, GP11_BOOLEAN, TRUE,
+	                                   CKA_TOKEN, GP11_BOOLEAN, TRUE,
+	                                   CKA_VALUE, n_password, password,
+	                                   GP11_INVALID);
+
+	if (cred == NULL) {
+		if (error->code == CKR_PIN_INCORRECT) {
+			dbus_set_error_const (derr, INTERNAL_ERROR_DENIED, "The password was incorrect.");
+		} else {
+			g_message ("couldn't create credential: %s", error->message);
+			dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't use credentials");
+		}
+		g_clear_error (&error);
+		return FALSE;
+	}
+
+	g_object_unref (cred);
+	return TRUE;
+}
diff --git a/daemon/dbus/gkd-secret-unlock.h b/daemon/dbus/gkd-secret-unlock.h
index f0f351c..0f67731 100644
--- a/daemon/dbus/gkd-secret-unlock.h
+++ b/daemon/dbus/gkd-secret-unlock.h
@@ -58,4 +58,9 @@ gboolean            gkd_secret_unlock_with_secret             (GP11Object *colle
                                                                GkdSecretSecret *master,
                                                                DBusError *derr);
 
+gboolean            gkd_secret_unlock_with_password           (GP11Object *collection,
+                                                               const guchar *password,
+                                                               gsize n_password,
+                                                               DBusError *derr);
+
 #endif /* __GKD_SECRET_UNLOCK_H__ */



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