[gnome-keyring/dbus-api] [secret-store] Additional methods for GckSecretData.



commit 943b63f6ebe91ddb043ad211d7d17cd6b6219725
Author: Stef Walter <stef memberwebs com>
Date:   Sun Aug 9 17:44:48 2009 +0000

    [secret-store] Additional methods for GckSecretData.
    
    Add gck_secret_data_get_raw() to return secret directly. And
    gck_secret_data_set_transacted() to set a secret as part of
    a transaction.

 pkcs11/secret-store/gck-secret-data.c             |   98 +++++++++++++++++
 pkcs11/secret-store/gck-secret-data.h             |   11 ++-
 pkcs11/secret-store/tests/unit-test-secret-data.c |  122 +++++++++++++++++++++
 3 files changed, 230 insertions(+), 1 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-data.c b/pkcs11/secret-store/gck-secret-data.c
index b1862ed..9d677d1 100644
--- a/pkcs11/secret-store/gck-secret-data.c
+++ b/pkcs11/secret-store/gck-secret-data.c
@@ -24,6 +24,7 @@
 #include "gck-secret-data.h"
 
 #include "gck/gck-secret.h"
+#include "gck/gck-transaction.h"
 #include "gck/gck-util.h"
 
 #include "egg/egg-secure-memory.h"
@@ -39,6 +40,72 @@ struct _GckSecretData {
 G_DEFINE_TYPE (GckSecretData, gck_secret_data, G_TYPE_OBJECT);
 
 /* -----------------------------------------------------------------------------
+ * INTERNAL
+ */
+
+typedef struct _set_secret_args {
+	gchar *identifier;
+	GckSecret *old_secret;
+} set_secret_args;
+
+static gboolean
+complete_set_secret (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckSecretData *self = GCK_SECRET_DATA (obj);
+	set_secret_args *args = user_data;
+
+	/* If the transaction failed, revert */
+	if (gck_transaction_get_failed (transaction)) {
+		if (!args->old_secret) {
+			g_hash_table_remove (self->secrets, args->identifier);
+		} else {
+			g_hash_table_replace (self->secrets, args->identifier, args->old_secret);
+			args->identifier = NULL; /* hash table took ownership */
+			args->old_secret = NULL; /* ditto */
+		}
+	}
+
+	/* Free up transaction data */
+	g_free (args->identifier);
+	if (args->old_secret)
+		g_object_unref (args->old_secret);
+	g_slice_free (set_secret_args, args);
+
+	return TRUE;
+}
+
+static void
+begin_set_secret (GckSecretData *self, GckTransaction *transaction,
+                  const gchar *identifier, GckSecret *secret)
+{
+	set_secret_args *args;
+
+	g_assert (GCK_IS_SECRET_DATA (self));
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (identifier);
+	g_assert (GCK_IS_SECRET (secret));
+
+	args = g_slice_new0 (set_secret_args);
+
+	/* Take ownership of the old data, if present */
+	if (g_hash_table_lookup_extended (self->secrets, identifier,
+	                                  (gpointer*)&args->identifier,
+	                                  (gpointer*)&args->old_secret)) {
+		if (!g_hash_table_steal (self->secrets, args->identifier))
+			g_assert_not_reached ();
+	} else {
+		args->identifier = g_strdup (identifier);
+	}
+
+	/* Replace with our new data */
+	g_hash_table_replace (self->secrets, g_strdup (identifier),
+	                      g_object_ref (secret));
+
+	/* Track in the transaction */
+	gck_transaction_add (transaction, self, complete_set_secret, args);
+}
+
+/* -----------------------------------------------------------------------------
  * OBJECT
  */
 
@@ -84,6 +151,24 @@ gck_secret_data_get_secret (GckSecretData *self, const gchar *identifier)
 	return g_hash_table_lookup (self->secrets, identifier);
 }
 
+const guchar*
+gck_secret_data_get_raw (GckSecretData *self, const gchar *identifier,
+                         gsize *n_result)
+{
+	GckSecret *secret;
+
+	g_return_val_if_fail (GCK_IS_SECRET_DATA (self), NULL);
+	g_return_val_if_fail (identifier, NULL);
+	g_return_val_if_fail (n_result, NULL);
+
+	secret = gck_secret_data_get_secret (self, identifier);
+	if (secret == NULL)
+		return NULL;
+
+	return gck_secret_get (secret, n_result);
+}
+
+
 void
 gck_secret_data_set_secret (GckSecretData *self, const gchar *identifier,
                             GckSecret *secret)
@@ -96,6 +181,19 @@ gck_secret_data_set_secret (GckSecretData *self, const gchar *identifier,
 }
 
 void
+gck_secret_data_set_transacted  (GckSecretData *self, GckTransaction *transaction,
+                                 const gchar *identifier, GckSecret *secret)
+{
+	g_return_if_fail (GCK_IS_SECRET_DATA (self));
+	g_return_if_fail (GCK_IS_TRANSACTION (transaction));
+	g_return_if_fail (!gck_transaction_get_failed (transaction));
+	g_return_if_fail (identifier);
+	g_return_if_fail (GCK_IS_SECRET (secret));
+
+	begin_set_secret (self, transaction, identifier, secret);
+}
+
+void
 gck_secret_data_remove_secret (GckSecretData *self, const gchar *identifier)
 {
 	g_return_if_fail (GCK_IS_SECRET_DATA (self));
diff --git a/pkcs11/secret-store/gck-secret-data.h b/pkcs11/secret-store/gck-secret-data.h
index 48a3f0d..570a200 100644
--- a/pkcs11/secret-store/gck-secret-data.h
+++ b/pkcs11/secret-store/gck-secret-data.h
@@ -26,7 +26,7 @@
 
 #include "gck-secret-types.h"
 
-#include "gck/gck-secret.h"
+#include "gck/gck-types.h"
 
 #define GCK_TYPE_SECRET_DATA               (gck_secret_data_get_type ())
 #define GCK_SECRET_DATA(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_DATA, GckSecretData))
@@ -46,10 +46,19 @@ GType                gck_secret_data_get_type        (void);
 GckSecret*           gck_secret_data_get_secret      (GckSecretData *self,
                                                       const gchar *identifier);
 
+const guchar*        gck_secret_data_get_raw         (GckSecretData *self,
+                                                      const gchar *identifier,
+                                                      gsize *n_result);
+
 void                 gck_secret_data_set_secret      (GckSecretData *self,
                                                       const gchar *identifier,
                                                       GckSecret *secret);
 
+void                 gck_secret_data_set_transacted  (GckSecretData *self,
+                                                      GckTransaction *transaction,
+                                                      const gchar *identifier,
+                                                      GckSecret *secret);
+
 void                 gck_secret_data_remove_secret   (GckSecretData *self,
                                                       const gchar *identifier);
 
diff --git a/pkcs11/secret-store/tests/unit-test-secret-data.c b/pkcs11/secret-store/tests/unit-test-secret-data.c
index 7460b46..9ca3ff5 100644
--- a/pkcs11/secret-store/tests/unit-test-secret-data.c
+++ b/pkcs11/secret-store/tests/unit-test-secret-data.c
@@ -27,6 +27,9 @@
 
 #include "gck-secret-data.h"
 
+#include "gck/gck-secret.h"
+#include "gck/gck-transaction.h"
+
 #include <glib.h>
 
 #include <stdlib.h>
@@ -57,6 +60,27 @@ DEFINE_TEST(secret_data_get_set)
 	g_object_unref (data);
 }
 
+DEFINE_TEST(secret_data_get_raw)
+{
+	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	GckSecret *secret = gck_secret_new_from_password ("barn");
+	const guchar *raw;
+	gsize n_raw;
+
+	gck_secret_data_set_secret (data, "my-identifier", secret);
+	g_object_unref (secret);
+
+	raw = gck_secret_data_get_raw (data, "my-identifier", &n_raw);
+	g_assert (raw);
+	g_assert_cmpuint (n_raw, ==, 4);
+	g_assert (memcmp (raw, "barn", 4) == 0);
+
+	raw = gck_secret_data_get_raw (data, "not-identifier", &n_raw);
+	g_assert (raw == NULL);
+
+	g_object_unref (data);
+}
+
 DEFINE_TEST(secret_data_remove)
 {
 	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
@@ -75,6 +99,104 @@ DEFINE_TEST(secret_data_remove)
 	g_object_unref (data);
 }
 
+DEFINE_TEST(secret_data_set_transacted)
+{
+	GckTransaction *transaction = gck_transaction_new ();
+	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	GckSecret *secret = gck_secret_new_from_password ("barn");
+
+	/* Transaction, but not complete */
+	gck_secret_data_set_transacted (data, transaction, "my-identifier", secret);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == secret);
+
+	/* Transaction complete */
+	gck_transaction_complete (transaction);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == secret);
+
+	g_object_unref (data);
+	g_object_unref (secret);
+	g_object_unref (transaction);
+}
+
+DEFINE_TEST(secret_data_set_transacted_replace)
+{
+	GckTransaction *transaction = gck_transaction_new ();
+	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	GckSecret *old = gck_secret_new_from_password ("old");
+	GckSecret *secret = gck_secret_new_from_password ("secret");
+
+	/* The old secret */
+	gck_secret_data_set_secret (data, "my-identifier", old);
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == old);
+
+	/* Transaction, but not complete */
+	gck_secret_data_set_transacted (data, transaction, "my-identifier", secret);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == secret);
+
+	/* Transaction complete */
+	gck_transaction_complete (transaction);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == secret);
+
+	g_object_unref (old);
+	g_object_unref (data);
+	g_object_unref (secret);
+	g_object_unref (transaction);
+}
+
+DEFINE_TEST(secret_data_set_transacted_fail)
+{
+	GckTransaction *transaction = gck_transaction_new ();
+	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	GckSecret *secret = gck_secret_new_from_password ("barn");
+
+	/* Transaction, but not complete */
+	gck_secret_data_set_transacted (data, transaction, "my-identifier", secret);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == secret);
+
+	/* Transaction fails here */
+	gck_transaction_fail (transaction, CKR_CANCEL);
+	gck_transaction_complete (transaction);
+	g_assert (gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == NULL);
+
+	g_object_unref (data);
+	g_object_unref (secret);
+	g_object_unref (transaction);
+}
+
+DEFINE_TEST(secret_data_set_transacted_fail_revert)
+{
+	GckTransaction *transaction = gck_transaction_new ();
+	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+	GckSecret *old = gck_secret_new_from_password ("old");
+	GckSecret *secret = gck_secret_new_from_password ("secret");
+
+	/* The old secret */
+	gck_secret_data_set_secret (data, "my-identifier", old);
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == old);
+
+	/* Transaction, but not complete */
+	gck_secret_data_set_transacted (data, transaction, "my-identifier", secret);
+	g_assert (!gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == secret);
+
+	/* Transaction fails here */
+	gck_transaction_fail (transaction, CKR_CANCEL);
+	gck_transaction_complete (transaction);
+	g_assert (gck_transaction_get_failed (transaction));
+	g_assert (gck_secret_data_get_secret (data, "my-identifier") == old);
+
+	g_object_unref (old);
+	g_object_unref (data);
+	g_object_unref (secret);
+	g_object_unref (transaction);
+}
+
 DEFINE_TEST(secret_data_get_set_master)
 {
 	GckSecretData *data = g_object_new (GCK_TYPE_SECRET_DATA, NULL);



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