[gnome-keyring/dbus-api] [dbus] Implement internal interface for creating collection with pass.



commit 45285893d83f5c80e7a4672cf6cbaf3538f8c476
Author: Stef Walter <stef memberwebs com>
Date:   Sat Dec 12 18:03:51 2009 +0000

    [dbus] Implement internal interface for creating collection with pass.
    
    Add an internal compatibility interface, so we can implement
    libgnome-keyring.

 daemon/dbus/gkd-secret-create.c  |  133 +++++++++++++---
 daemon/dbus/gkd-secret-create.h  |    5 +
 daemon/dbus/gkd-secret-service.c |   45 +++++
 daemon/dbus/gkd-secret-session.c |  341 ++++++++++++++++++--------------------
 daemon/dbus/gkd-secret-session.h |    5 +
 daemon/dbus/gkd-secret-types.h   |    2 +
 daemon/dbus/gkd-secret-util.c    |    1 +
 7 files changed, 332 insertions(+), 200 deletions(-)
---
diff --git a/daemon/dbus/gkd-secret-create.c b/daemon/dbus/gkd-secret-create.c
index f2cde76..807fca6 100644
--- a/daemon/dbus/gkd-secret-create.c
+++ b/daemon/dbus/gkd-secret-create.c
@@ -24,6 +24,8 @@
 #include "gkd-secret-create.h"
 #include "gkd-secret-service.h"
 #include "gkd-secret-prompt.h"
+#include "gkd-secret-secret.h"
+#include "gkd-secret-session.h"
 #include "gkd-secret-types.h"
 #include "gkd-secret-util.h"
 
@@ -87,18 +89,49 @@ prepare_create_prompt (GkdSecretCreate *self)
 }
 
 static gboolean
-create_collection (GkdSecretCreate *self, const gchar *password)
+create_collection_with_credential (GkdSecretCreate *self, GP11Object *cred)
 {
 	GError *error = NULL;
-	GP11Session *session;
 	GP11Object *collection;
+	GP11Session *session;
+
+	g_assert (GKD_SECRET_IS_CREATE (self));
+	g_return_val_if_fail (self->pkcs11_attrs, FALSE);
+	g_return_val_if_fail (!self->result_path, FALSE);
+	g_return_val_if_fail (GP11_IS_OBJECT (cred), FALSE);
+
+	session =  gkd_secret_prompt_get_pkcs11_session (GKD_SECRET_PROMPT (self));
+	g_return_val_if_fail (session, FALSE);
+
+	/* Setup remainder of attributes on collection */
+	gp11_attributes_add_ulong (self->pkcs11_attrs, CKA_G_CREDENTIAL,
+	                           gp11_object_get_handle (cred));
+
+	collection = gp11_session_create_object_full (session, self->pkcs11_attrs, NULL, &error);
+	if (!collection) {
+		g_warning ("couldn't create collection: %s", error->message);
+		g_clear_error (&error);
+		return FALSE;
+	}
+
+	gp11_object_set_session (collection, session);
+	self->result_path = gkd_secret_util_path_for_collection (collection);
+	g_object_unref (collection);
+
+	return TRUE;
+}
+
+static gboolean
+create_collection_with_password (GkdSecretCreate *self, const gchar *password)
+{
+	GError *error = NULL;
+	GP11Session *session;
 	GP11Object *cred;
 	gsize n_password;
 	gboolean token;
+	gboolean result;
 
 	g_assert (GKD_SECRET_IS_CREATE (self));
-	g_return_val_if_fail (self->pkcs11_attrs, FALSE);
-	g_return_val_if_fail (!self->result_path, FALSE);
 
 	if (gp11_attributes_find_boolean (self->pkcs11_attrs, CKA_TOKEN, &token))
 		token = FALSE;
@@ -120,23 +153,10 @@ create_collection (GkdSecretCreate *self, const gchar *password)
 		return FALSE;
 	}
 
-	/* Setup remainder of attributes on collection */
-	gp11_attributes_add_ulong (self->pkcs11_attrs, CKA_G_CREDENTIAL,
-	                           gp11_object_get_handle (cred));
+	result = create_collection_with_credential (self, cred);
 	g_object_unref (cred);
 
-	collection = gp11_session_create_object_full (session, self->pkcs11_attrs, NULL, &error);
-	if (!collection) {
-		g_warning ("couldn't create collection: %s", error->message);
-		g_clear_error (&error);
-		return FALSE;
-	}
-
-	gp11_object_set_session (collection, session);
-	self->result_path = gkd_secret_util_path_for_collection (collection);
-	g_object_unref (collection);
-
-	return TRUE;
+	return result;
 }
 
 /* -----------------------------------------------------------------------------
@@ -159,7 +179,7 @@ gkd_secret_create_prompt_ready (GkdSecretPrompt *base)
 	g_return_if_fail (gkd_prompt_get_response (prompt) == GKD_RESPONSE_OK);
 	password = gkd_prompt_get_password (prompt, "password");
 
-	if (create_collection (self, password))
+	if (create_collection_with_password (self, password))
 		gkd_secret_prompt_complete (GKD_SECRET_PROMPT (self));
 	else
 		gkd_secret_prompt_dismiss (GKD_SECRET_PROMPT (self));
@@ -265,3 +285,76 @@ gkd_secret_create_new (GkdSecretService *service, const gchar *caller,
 	                     "pkcs11-attributes", attrs,
 	                     NULL);
 }
+
+DBusMessage*
+gkd_secret_create_without_prompting (GkdSecretService *service, DBusMessage *message,
+                                     GP11Attributes *attrs, GkdSecretSecret *master)
+{
+	DBusError derr = DBUS_ERROR_INIT;
+	GkdSecretSession *session;
+	GP11Attributes *atts;
+	GP11Attribute *label;
+	DBusMessage *reply;
+	GP11Object *cred;
+	GP11Object *collection;
+	GP11Session *pkcs11_session;
+	GError *error = NULL;
+	gchar *path;
+
+	/* Figure out the session */
+	session = gkd_secret_service_lookup_session (service, master->path,
+	                                             dbus_message_get_sender (message));
+	if (session == NULL)
+		return dbus_message_new_error (message, SECRET_ERROR_NO_SESSION,
+		                               "No such session exists");
+
+	atts = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_G_CREDENTIAL,
+	                             CKA_GNOME_TRANSIENT, GP11_BOOLEAN, TRUE,
+	                             CKA_TOKEN, GP11_BOOLEAN, TRUE,
+	                             GP11_INVALID);
+
+	/* Create ourselves some credentials */
+	cred = gkd_secret_session_create_credential (session, atts, master, &derr);
+	gp11_attributes_unref (atts);
+
+	if (cred == NULL) {
+		reply = dbus_message_new_error (message, derr.name, derr.message);
+		dbus_error_free (&derr);
+		return reply;
+	}
+
+	/* The only thing we actually use from the properties right now is the label */
+	atts = gp11_attributes_newv (CKA_TOKEN, GP11_BOOLEAN, TRUE,
+	                             CKA_G_CREDENTIAL, GP11_ULONG, gp11_object_get_handle (cred),
+	                             CKA_CLASS, GP11_ULONG, CKO_G_COLLECTION,
+	                             GP11_INVALID);
+
+	label = gp11_attributes_find (attrs, CKA_LABEL);
+	if (label != NULL)
+		gp11_attributes_add (atts, label);
+
+	g_object_unref (cred);
+
+	pkcs11_session = gkd_secret_service_get_pkcs11_session (service, dbus_message_get_sender (message));
+	g_return_val_if_fail (pkcs11_session, NULL);
+
+	collection = gp11_session_create_object_full (pkcs11_session, atts, NULL, &error);
+	gp11_attributes_unref (atts);
+
+	if (collection == NULL) {
+		g_warning ("couldn't create collection: %s", error->message);
+		g_clear_error (&error);
+		return dbus_message_new_error (message, DBUS_ERROR_FAILED,
+		                               "Couldn't create new collection");
+	}
+
+	path = gkd_secret_util_path_for_collection (collection);
+	g_object_unref (collection);
+
+	reply = dbus_message_new_method_return (message);
+	dbus_message_append_args (reply,
+	                          DBUS_TYPE_OBJECT_PATH, &path,
+	                          DBUS_TYPE_INVALID);
+
+	return reply;
+}
diff --git a/daemon/dbus/gkd-secret-create.h b/daemon/dbus/gkd-secret-create.h
index 050deff..78e9a4b 100644
--- a/daemon/dbus/gkd-secret-create.h
+++ b/daemon/dbus/gkd-secret-create.h
@@ -48,4 +48,9 @@ GkdSecretCreate*    gkd_secret_create_new                     (GkdSecretService
                                                                const gchar *caller,
                                                                GP11Attributes *attrs);
 
+DBusMessage*        gkd_secret_create_without_prompting       (GkdSecretService *service,
+                                                               DBusMessage *message,
+                                                               GP11Attributes *attrs,
+                                                               GkdSecretSecret *master);
+
 #endif /* __GKD_SECRET_CREATE_H__ */
diff --git a/daemon/dbus/gkd-secret-service.c b/daemon/dbus/gkd-secret-service.c
index 7f24ab7..6a14cdd 100644
--- a/daemon/dbus/gkd-secret-service.c
+++ b/daemon/dbus/gkd-secret-service.c
@@ -26,6 +26,7 @@
 #include "gkd-secret-objects.h"
 #include "gkd-secret-prompt.h"
 #include "gkd-secret-property.h"
+#include "gkd-secret-secret.h"
 #include "gkd-secret-service.h"
 #include "gkd-secret-session.h"
 #include "gkd-secret-types.h"
@@ -451,6 +452,45 @@ service_method_create_collection (GkdSecretService *self, DBusMessage *message)
 }
 
 static DBusMessage*
+service_method_create_with_master_password (GkdSecretService *self, DBusMessage *message)
+{
+	DBusMessageIter iter, array;
+	DBusMessage *reply = NULL;
+	GkdSecretSecret *secret = NULL;
+	GP11Attributes *attrs = NULL;
+	const char *caller;
+
+	caller = dbus_message_get_sender (message);
+	g_return_val_if_fail (caller, NULL);
+
+	/* Parse the incoming message */
+	if (!dbus_message_has_signature (message, "a{sv}(oayay)"))
+		return NULL;
+	if (!dbus_message_iter_init (message, &iter))
+		g_return_val_if_reached (NULL);
+	attrs = gp11_attributes_new ();
+	dbus_message_iter_recurse (&iter, &array);
+	if (!gkd_secret_property_parse_all (&array, attrs)) {
+		gp11_attributes_unref (attrs);
+		return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
+		                               "Invalid properties argument");
+	}
+	dbus_message_iter_next (&iter);
+	secret = gkd_secret_secret_parse (&iter);
+	if (secret == NULL) {
+		gp11_attributes_unref (attrs);
+		return dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
+		                               "Invalid secret argument");
+	}
+
+	reply = gkd_secret_create_without_prompting (self, message, attrs, secret);
+	gp11_attributes_unref (attrs);
+	gkd_secret_secret_free (secret);
+
+	return reply;
+}
+
+static DBusMessage*
 service_method_unlock (GkdSecretService *self, DBusMessage *message)
 {
 	GkdSecretUnlock *unlock;
@@ -598,6 +638,10 @@ service_message_handler (GkdSecretService *self, DBusMessage *message)
 	if (dbus_message_is_method_call (message, SECRET_SERVICE_INTERFACE, "SetAlias"))
 		return service_method_set_alias (self, message);
 
+	/* org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface.CreateCollectionWithPassword */
+	if (dbus_message_is_method_call (message, INTERNAL_SERVICE_INTERFACE, "CreateWithMasterPassword"))
+		return service_method_create_with_master_password (self, message);
+
 	/* org.freedesktop.DBus.Properties.Get() */
 	if (dbus_message_is_method_call (message, PROPERTIES_INTERFACE, "Get"))
 		return service_property_get (self, message);
@@ -765,6 +809,7 @@ gkd_secret_service_filter_handler (DBusConnection *conn, DBusMessage *message, g
 			if (interface == NULL ||
 			    g_str_has_prefix (interface, SECRET_INTERFACE_PREFIX) ||
 			    g_str_equal (interface, DBUS_INTERFACE_PROPERTIES) ||
+			    g_str_equal (interface, INTERNAL_SERVICE_INTERFACE) ||
 			    g_str_equal (interface, DBUS_INTERFACE_INTROSPECTABLE)) {
 				service_dispatch_message (self, message);
 				return DBUS_HANDLER_RESULT_HANDLED;
diff --git a/daemon/dbus/gkd-secret-session.c b/daemon/dbus/gkd-secret-session.c
index 2a1c528..b237e74 100644
--- a/daemon/dbus/gkd-secret-session.c
+++ b/daemon/dbus/gkd-secret-session.c
@@ -49,6 +49,7 @@ struct _GkdSecretSession {
 	gchar *caller_exec;
 	gchar *caller;
 	GP11Object *key;
+	CK_MECHANISM_TYPE mech_type;
 };
 
 G_DEFINE_TYPE (GkdSecretSession, gkd_secret_session, G_TYPE_OBJECT);
@@ -60,15 +61,11 @@ static guint unique_session_number = 0;
  */
 
 static void
-take_session_key (GkdSecretSession *self, GP11Object *key)
+take_session_key (GkdSecretSession *self, GP11Object *key, CK_MECHANISM_TYPE mech)
 {
-	if (self->key) {
-		gp11_object_destroy (self->key, NULL);
-		g_object_unref (self->key);
-		self->key = NULL;
-	}
-
+	g_return_if_fail (!self->key);
 	self->key = key;
+	self->mech_type = mech;
 }
 
 static gboolean
@@ -183,7 +180,7 @@ aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input
 	}
 
 	gp11_object_set_session (key, session);
-	take_session_key (self, key);
+	take_session_key (self, key, CKM_AES_CBC_PAD);
 
 	reply = dbus_message_new_method_return (message);
 	dbus_message_iter_init_append (reply, &iter);
@@ -198,117 +195,32 @@ aes_negotiate (GkdSecretSession *self, DBusMessage *message, gconstpointer input
 	return reply;
 }
 
-static GkdSecretSecret*
-aes_wrap_item_secret (GkdSecretSession *self, GP11Object *item, DBusError *derr)
+static DBusMessage*
+plain_negotiate (GkdSecretSession *self, DBusMessage *message)
 {
-	GP11Mechanism *mech;
-	GP11Session *session;
-	gpointer value, iv;
-	gsize n_value, n_iv;
+	DBusMessageIter iter, variant;
 	GError *error = NULL;
-
-	g_assert (GP11_IS_OBJECT (self->key));
-
-	session = gp11_object_get_session (item);
-	g_return_val_if_fail (session, FALSE);
-
-	n_iv = 16;
-	iv = g_malloc (n_iv);
-	gcry_create_nonce (iv, n_iv);
-
-	mech = gp11_mechanism_new_with_param (CKM_AES_CBC_PAD, iv, n_iv);
-
-	value = gp11_session_wrap_key_full (session, self->key, mech, item, &n_value,
-	                                    NULL, &error);
-
-	gp11_mechanism_unref (mech);
-
-	if (value == NULL) {
-		if (error->code == CKR_USER_NOT_LOGGED_IN) {
-			dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED,
-			                      "Cannot get secret of a locked object");
-		} else {
-			g_message ("couldn't wrap item secret: %s", error->message);
-			dbus_set_error_const (derr, DBUS_ERROR_FAILED,
-			                      "Couldn't get item secret");
-		}
-		g_clear_error (&error);
-		g_free (iv);
-		return NULL;
-	}
-
-	return gkd_secret_secret_create_and_take_memory (self->object_path, iv, n_iv, value, n_value);
-}
-
-static gboolean
-aes_unwrap_item_secret (GkdSecretSession *self, GP11Object *item,
-                        GkdSecretSecret *secret, DBusError *derr)
-{
-	GP11Mechanism *mech;
-	GP11Object *object;
+	const char *output = "";
+	DBusMessage *reply;
+	GP11Object *key;
 	GP11Session *session;
-	GError *error = NULL;
-	GP11Attributes *attrs;
 
-	g_assert (GP11_IS_OBJECT (self->key));
-
-	session = gp11_object_get_session (item);
-	g_return_val_if_fail (session, FALSE);
-
-	/*
-	 * By getting these attributes, and then using them in the unwrap,
-	 * the unwrap won't generate a new object, but merely set the secret.
-	 */
-
-	attrs = gkd_secret_util_attributes_for_item (item);
-	g_return_val_if_fail (attrs, FALSE);
-
-	mech = gp11_mechanism_new_with_param (CKM_AES_CBC_PAD, secret->parameter,
-	                                      secret->n_parameter);
-
-	object = gp11_session_unwrap_key_full (session, self->key, mech, secret->value,
-	                                       secret->n_value, attrs, NULL, &error);
+	session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
+	g_return_val_if_fail (session, NULL);
 
-	gp11_mechanism_unref (mech);
-	gp11_attributes_unref (attrs);
+	key = gp11_session_create_object (session, &error,
+	                                  CKA_CLASS, GP11_ULONG, CKO_SECRET_KEY,
+	                                  CKA_KEY_TYPE, GP11_ULONG, CKK_G_NULL,
+	                                  GP11_INVALID);
 
-	if (object == NULL) {
-		if (error->code == CKR_USER_NOT_LOGGED_IN) {
-			dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED,
-			                      "Cannot set secret of a locked item");
-		} else if (error->code == CKR_WRAPPED_KEY_INVALID ||
-		           error->code == CKR_WRAPPED_KEY_LEN_RANGE ||
-		           error->code == CKR_MECHANISM_PARAM_INVALID) {
-			dbus_set_error_const (derr, DBUS_ERROR_INVALID_ARGS,
-			                      "The secret was transferred or encrypted in an invalid way.");
-		} else {
-			g_message ("couldn't unwrap item secret: %s", error->message);
-			dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret");
-		}
+	if (key == NULL) {
+		g_warning ("couldn't create null key: %s", error->message);
 		g_clear_error (&error);
-		return FALSE;
-	}
-
-	if (!gp11_object_equal (object, item)) {
-		g_warning ("unwrapped secret went to new object, instead of item");
-		dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret");
-		g_object_unref (object);
-		return FALSE;
+		return dbus_message_new_error_printf (message, DBUS_ERROR_FAILED,
+		                                      "Failed to create necessary plain keys.");
 	}
 
-	g_object_unref (object);
-	return TRUE;
-}
-
-
-static DBusMessage*
-plain_negotiate (GkdSecretSession *self, DBusMessage *message)
-{
-	DBusMessageIter iter, variant;
-	const char *output = "";
-	DBusMessage *reply;
-
-	take_session_key (self, NULL);
+	take_session_key (self, key, CKM_G_NULL);
 
 	reply = dbus_message_new_method_return (message);
 	dbus_message_iter_init_append (reply, &iter);
@@ -319,65 +231,6 @@ plain_negotiate (GkdSecretSession *self, DBusMessage *message)
 	return reply;
 }
 
-static GkdSecretSecret*
-plain_get_item_secret (GkdSecretSession *self, GP11Object *item, DBusError *derr)
-{
-	GError *error = NULL;
-	gpointer value;
-	gsize n_value;
-
-	/*
-	 * We're going to be sending this over DBus, which is going to litter it
-	 * all over memory. So we don't need to worry about using 'secure' memory.
-	 */
-
-	value = gp11_object_get_data (item, CKA_VALUE, &n_value, &error);
-	if (value == NULL) {
-		if (error->code == CKR_USER_NOT_LOGGED_IN) {
-			dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED,
-			                      "Cannot get secret of a locked object");
-		} else {
-			g_message ("couldn't get item secret: %s", error->message);
-			dbus_set_error_const (derr, DBUS_ERROR_FAILED,
-			                      "Couldn't get item secret");
-		}
-		g_clear_error (&error);
-		return NULL;
-	}
-
-	return gkd_secret_secret_create_and_take_memory (self->object_path, NULL, 0, value, n_value);
-}
-
-static gboolean
-plain_set_item_secret (GkdSecretSession *self, GP11Object *item,
-                       GkdSecretSecret *secret, DBusError *derr)
-{
-	GP11Attributes *attrs;
-	GError *error = NULL;
-	gboolean ret;
-
-	attrs = gp11_attributes_new ();
-	gp11_attributes_add_data (attrs, CKA_VALUE, secret->value, secret->n_value);
-
-	ret = gp11_object_set_full (item, attrs, NULL, &error);
-
-	gp11_attributes_unref (attrs);
-
-	if (ret == FALSE) {
-		if (error->code == CKR_USER_NOT_LOGGED_IN) {
-			dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED,
-			                      "Cannot set secret of a locked item");
-		} else {
-			g_message ("couldn't set item secret: %s", error->message);
-			dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret");
-		}
-		g_clear_error (&error);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
 /* -----------------------------------------------------------------------------
  * DBUS
  */
@@ -438,7 +291,10 @@ gkd_secret_session_dispose (GObject *obj)
 		self->service = NULL;
 	}
 
-	take_session_key (self, NULL);
+	if (self->key) {
+		g_object_unref (self->key);
+		self->key = NULL;
+	}
 
 	G_OBJECT_CLASS (gkd_secret_session_parent_class)->dispose (obj);
 }
@@ -638,25 +494,150 @@ GkdSecretSecret*
 gkd_secret_session_get_item_secret (GkdSecretSession *self, GP11Object *item,
                                     DBusError *derr)
 {
-	g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), NULL);
-	g_return_val_if_fail (GP11_IS_OBJECT (item), NULL);
+	GP11Mechanism *mech;
+	GP11Session *session;
+	gpointer value, iv;
+	gsize n_value, n_iv;
+	GError *error = NULL;
+
+	g_assert (GP11_IS_OBJECT (self->key));
+
+	session = gp11_object_get_session (item);
+	g_return_val_if_fail (session, FALSE);
+
+	if (self->mech_type == CKM_AES_CBC_PAD) {
+		n_iv = 16;
+		iv = g_malloc (n_iv);
+		gcry_create_nonce (iv, n_iv);
+		mech = gp11_mechanism_new_with_param (CKM_AES_CBC_PAD, iv, n_iv);
+		g_free (iv);
+	} else {
+		n_iv = 0;
+		iv = NULL;
+		mech = gp11_mechanism_new (self->mech_type);
+	}
 
-	if (self->key == NULL)
-		return plain_get_item_secret (self, item, derr);
-	else
-		return aes_wrap_item_secret (self, item, derr);
+	value = gp11_session_wrap_key_full (session, self->key, mech, item, &n_value,
+	                                    NULL, &error);
+	gp11_mechanism_unref (mech);
+
+	if (value == NULL) {
+		if (error->code == CKR_USER_NOT_LOGGED_IN) {
+			dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED,
+			                      "Cannot get secret of a locked object");
+		} else {
+			g_message ("couldn't wrap item secret: %s", error->message);
+			dbus_set_error_const (derr, DBUS_ERROR_FAILED,
+			                      "Couldn't get item secret");
+		}
+		g_clear_error (&error);
+		g_free (iv);
+		return NULL;
+	}
+
+	return gkd_secret_secret_create_and_take_memory (self->object_path, iv, n_iv, value, n_value);
 }
 
 gboolean
 gkd_secret_session_set_item_secret (GkdSecretSession *self, GP11Object *item,
                                     GkdSecretSecret *secret, DBusError *derr)
 {
+	GP11Mechanism *mech;
+	GP11Object *object;
+	GP11Session *session;
+	GError *error = NULL;
+	GP11Attributes *attrs;
+
 	g_return_val_if_fail (GKD_SECRET_IS_SESSION (self), FALSE);
 	g_return_val_if_fail (GP11_IS_OBJECT (item), FALSE);
 	g_return_val_if_fail (secret, FALSE);
 
-	if (self->key == NULL)
-		return plain_set_item_secret (self, item, secret, derr);
-	else
-		return aes_unwrap_item_secret (self, item, secret, derr);
+	g_assert (GP11_IS_OBJECT (self->key));
+
+	session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
+	g_return_val_if_fail (session, FALSE);
+
+	/*
+	 * By getting these attributes, and then using them in the unwrap,
+	 * the unwrap won't generate a new object, but merely set the secret.
+	 */
+
+	attrs = gkd_secret_util_attributes_for_item (item);
+	g_return_val_if_fail (attrs, FALSE);
+
+	mech = gp11_mechanism_new_with_param (self->mech_type, secret->parameter,
+	                                      secret->n_parameter);
+
+	object = gp11_session_unwrap_key_full (session, self->key, mech, secret->value,
+	                                       secret->n_value, attrs, NULL, &error);
+
+	gp11_mechanism_unref (mech);
+	gp11_attributes_unref (attrs);
+
+	if (object == NULL) {
+		if (error->code == CKR_USER_NOT_LOGGED_IN) {
+			dbus_set_error_const (derr, SECRET_ERROR_IS_LOCKED,
+			                      "Cannot set secret of a locked item");
+		} else if (error->code == CKR_WRAPPED_KEY_INVALID ||
+		           error->code == CKR_WRAPPED_KEY_LEN_RANGE ||
+		           error->code == CKR_MECHANISM_PARAM_INVALID) {
+			dbus_set_error_const (derr, DBUS_ERROR_INVALID_ARGS,
+			                      "The secret was transferred or encrypted in an invalid way.");
+		} else {
+			g_message ("couldn't unwrap item secret: %s", error->message);
+			dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret");
+		}
+		g_clear_error (&error);
+		return FALSE;
+	}
+
+	if (!gp11_object_equal (object, item)) {
+		g_warning ("unwrapped secret went to new object, instead of item");
+		dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't set item secret");
+		g_object_unref (object);
+		return FALSE;
+	}
+
+	g_object_unref (object);
+	return TRUE;
+}
+
+GP11Object*
+gkd_secret_session_create_credential (GkdSecretSession *self, GP11Attributes *attrs,
+                                      GkdSecretSecret *secret, DBusError *derr)
+{
+	GP11Mechanism *mech;
+	GP11Object *object;
+	GP11Session *session;
+	GError *error = NULL;
+
+	g_assert (GP11_IS_OBJECT (self->key));
+	g_assert (attrs);
+
+	session = gkd_secret_service_get_pkcs11_session (self->service, self->caller);
+	g_return_val_if_fail (session, NULL);
+
+	mech = gp11_mechanism_new_with_param (self->mech_type, secret->parameter,
+	                                      secret->n_parameter);
+
+	object = gp11_session_unwrap_key_full (session, self->key, mech, secret->value,
+	                                       secret->n_value, attrs, NULL, &error);
+
+	gp11_mechanism_unref (mech);
+
+	if (object == NULL) {
+		if (error->code == CKR_WRAPPED_KEY_INVALID ||
+		    error->code == CKR_WRAPPED_KEY_LEN_RANGE ||
+		    error->code == CKR_MECHANISM_PARAM_INVALID) {
+			dbus_set_error_const (derr, DBUS_ERROR_INVALID_ARGS,
+			                      "The secret was transferred or encrypted in an invalid way.");
+		} else {
+			g_message ("couldn't unwrap credential: %s", error->message);
+			dbus_set_error_const (derr, DBUS_ERROR_FAILED, "Couldn't use credentials");
+		}
+		g_clear_error (&error);
+		return NULL;
+	}
+
+	return object;
 }
diff --git a/daemon/dbus/gkd-secret-session.h b/daemon/dbus/gkd-secret-session.h
index 321cb78..b8e9031 100644
--- a/daemon/dbus/gkd-secret-session.h
+++ b/daemon/dbus/gkd-secret-session.h
@@ -59,6 +59,11 @@ gboolean            gkd_secret_session_set_item_secret         (GkdSecretSession
                                                                 GkdSecretSecret *secret,
                                                                 DBusError *derr);
 
+GP11Object*         gkd_secret_session_create_credential       (GkdSecretSession *self,
+                                                                GP11Attributes *attrs,
+                                                                GkdSecretSecret *secret,
+                                                                DBusError *derr);
+
 DBusMessage*        gkd_secret_session_handle_open             (GkdSecretSession *self,
                                                                 DBusMessage *message);
 
diff --git a/daemon/dbus/gkd-secret-types.h b/daemon/dbus/gkd-secret-types.h
index 826ffc6..4ebd0d3 100644
--- a/daemon/dbus/gkd-secret-types.h
+++ b/daemon/dbus/gkd-secret-types.h
@@ -25,6 +25,8 @@
 #define BUS_INTERFACE                  "org.freedesktop.DBus"
 #define PROPERTIES_INTERFACE           "org.freedesktop.DBus.Properties"
 
+#define INTERNAL_SERVICE_INTERFACE      "org.gnome.keyring.InternalUnsupportedGuiltRiddenInterface"
+
 #define SECRET_COLLECTION_INTERFACE    "org.freedesktop.Secret.Collection"
 #define SECRET_ITEM_INTERFACE          "org.freedesktop.Secret.Item"
 #define SECRET_PROMPT_INTERFACE        "org.freedesktop.Secret.Prompt"
diff --git a/daemon/dbus/gkd-secret-util.c b/daemon/dbus/gkd-secret-util.c
index 9d1398f..0b4a266 100644
--- a/daemon/dbus/gkd-secret-util.c
+++ b/daemon/dbus/gkd-secret-util.c
@@ -424,6 +424,7 @@ gkd_secret_util_attributes_for_item (GP11Object *item)
 		g_return_val_if_reached (NULL);
 
 	attrs = gp11_attributes_new ();
+	gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_SECRET_KEY);
 	gp11_attributes_add_string (attrs, CKA_G_COLLECTION, coll);
 	gp11_attributes_add_string (attrs, CKA_ID, identifier);
 



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