[gnome-keyring/dbus-api] [secret-store] Finish up textual reading code, and test.



commit e741f9810746a0980fcb5029e6dbfad9a564ffb8
Author: Stef Walter <stef memberwebs com>
Date:   Fri Aug 14 21:18:52 2009 +0000

    [secret-store] Finish up textual reading code, and test.
    
    Add tests for gck_secret_textual_read/write, and fix the problems found.

 pkcs11/secret-store/gck-secret-item.c              |    2 +
 pkcs11/secret-store/gck-secret-textual.c           |  315 ++++++++++----------
 pkcs11/secret-store/gck-secret-textual.h           |    4 +-
 pkcs11/secret-store/tests/Makefile.am              |    1 +
 .../tests/test-data/plain-bad-number.keyring       |   23 ++
 pkcs11/secret-store/tests/test-data/plain.keyring  |   55 ++++
 .../secret-store/tests/unit-test-secret-textual.c  |  220 ++++++++++++++
 7 files changed, 455 insertions(+), 165 deletions(-)
---
diff --git a/pkcs11/secret-store/gck-secret-item.c b/pkcs11/secret-store/gck-secret-item.c
index d7b4fa8..48f400d 100644
--- a/pkcs11/secret-store/gck-secret-item.c
+++ b/pkcs11/secret-store/gck-secret-item.c
@@ -317,6 +317,8 @@ GHashTable*
 gck_secret_item_get_fields (GckSecretItem *self)
 {
 	g_return_val_if_fail (GCK_IS_SECRET_ITEM (self), NULL);
+	if (self->fields == NULL)
+		self->fields = gck_secret_fields_new ();
 	return self->fields;
 }
 
diff --git a/pkcs11/secret-store/gck-secret-textual.c b/pkcs11/secret-store/gck-secret-textual.c
index 7f83937..070ac64 100644
--- a/pkcs11/secret-store/gck-secret-textual.c
+++ b/pkcs11/secret-store/gck-secret-textual.c
@@ -25,11 +25,13 @@
 
 #include "gck-secret-collection.h"
 #include "gck-secret-compat.h"
+#include "gck-secret-data.h"
 #include "gck-secret-fields.h"
 #include "gck-secret-item.h"
 #include "gck-secret-textual.h"
 
 #include "egg/egg-secure-memory.h"
+#include "egg/egg-hex.h"
 
 #include "gck/gck-secret.h"
 
@@ -71,138 +73,94 @@ key_file_get_uint64 (GKeyFile *file, const gchar *group,
 	return TRUE;
 }
 
-typedef struct _AttributesCtx {
-	GckSecretItem *item;
-	gint index;
-	GKeyFile *file;
-	const gchar *compat_uint32;
-} AttributesCtx;
-
-static gboolean
-attribute_name_in_space_string (const gchar *string, const gchar *name)
-{
-	const gchar *at;
-	gsize len = strlen (name);
-	
-	if (len == 0)
-		return FALSE;
-
-	for (;;) {
-		at = strstr (string, name);
-		if (at == NULL)
-			return FALSE;
-		
-		/* The word exists, is at beginning or end, or spaces around it */
-		if ((at == string || isspace (*(at - 1))) && 
-		    (*(at + len) == 0 || isspace (*(at + len))))
-			return TRUE;
-	
-		string = at + len;
-	}
-
-	g_assert_not_reached ();
-}
-
-static void
-generate_each_attribute (gpointer key, gpointer value, gpointer user_data)
-{
-	AttributesCtx *ctx = user_data;
-	const gchar *name = key;
-	const gchar *string = value;
-	gchar *groupname;
-	
-	groupname = g_strdup_printf ("%s:attribute%d", 
-	                             gck_secret_object_get_identifier (GCK_SECRET_OBJECT (ctx->item)),
-	                             ctx->index);
-	
-	g_key_file_set_string (ctx->file, groupname, "name", name);
-	
-	/* 
-	 * COMPATIBILITY:
-	 * 
-	 * Our new Secrets API doesn't support integer attributes. However, to have 
-	 * compatibility with old keyring code reading this file, we need to set 
-	 * the type=uint32 attribute appropriately where expected. 
-	 * 
-	 * If there's an extra compat-uint32 attribute and the name of this attribute
-	 * is contained in that list, then write as a uint32.
-	 */
-	
-	/* Determine if it's a uint32 compatible value, and store as such if it is */
-	if (attribute_name_in_space_string (ctx->compat_uint32, name))
-		g_key_file_set_string (ctx->file, groupname, "type", "uint32");
-	else
-		g_key_file_set_string (ctx->file, groupname, "type", "string");
-	
-	g_key_file_set_string (ctx->file, groupname, "value", string);
-	
-	g_free (groupname);
-	++ctx->index;
-}
-
 static void
 generate_attributes (GKeyFile *file, GckSecretItem *item)
 {
 	GHashTable *attributes;
-	AttributesCtx ctx;
-	
+	gchar *groupname;
+	GList *names, *l;
+	guint32 number;
+	gint index = 0;
+
 	attributes = gck_secret_item_get_fields (item);
-	if (!attributes)
-		return;
-	
-	ctx.item = item;
-	ctx.index = 0;
-	ctx.file = file;
-	ctx.compat_uint32 = g_hash_table_lookup (attributes, "compat-uint32");
-	if (!ctx.compat_uint32)
-		ctx.compat_uint32 = "";
-
-	g_hash_table_foreach (attributes, generate_each_attribute, &ctx);
+	g_return_if_fail (attributes);
+
+	names = gck_secret_fields_get_names (attributes);
+	for (l = names; l; l = g_list_next (l)) {
+		groupname = g_strdup_printf ("%s:attribute%d",
+		                             gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item)),
+		                             index);
+
+		g_key_file_set_string (file, groupname, "name", l->data);
+
+		/*
+		 * COMPATIBILITY:
+		 *
+		 * Our new Secrets API doesn't support integer attributes. However, to have
+		 * compatibility with old keyring code reading this file, we need to set
+		 * the type=uint32 attribute appropriately where expected.
+		 *
+		 * If there's an extra compat-uint32 attribute and the name of this attribute
+		 * is contained in that list, then write as a uint32.
+		 */
+
+		/* Determine if it's a uint32 compatible value, and store as such if it is */
+		if (gck_secret_fields_get_compat_uint32 (attributes, l->data, &number)) {
+			g_key_file_set_string (file, groupname, "type", "uint32");
+			key_file_set_uint64 (file, groupname, "value", number);
+
+		/* A normal string attribute */
+		} else {
+			g_key_file_set_string (file, groupname, "type", "string");
+			g_key_file_set_string (file, groupname, "value", gck_secret_fields_get (attributes, l->data));
+		}
+
+		g_free (groupname);
+		++index;
+	}
 }
 
 static void
 parse_attributes (GKeyFile *file, GckSecretItem *item, const gchar **groups)
 {
 	GHashTable *attributes;
-	GString *compat_uint32;
 	const gchar *identifier;
 	const gchar **g;
 	gchar *prefix;
 	gchar *name, *type;
+	guint64 number;
 	
 	/* Now do the attributes */
 	
 	identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (item));
 	prefix = g_strdup_printf ("%s:attribute", identifier);
 	attributes = gck_secret_fields_new ();
-	compat_uint32 = NULL;
 	
 	for (g = groups; *g; ++g) {
 		if (!g_str_has_prefix (*g, prefix)) 
 			continue;
 			
 		name = g_key_file_get_string (file, *g, "name", NULL);
-		if (!name || g_key_file_has_key (file, *g, "value", NULL))
+		if (!name)
 			continue;
 
 		type = g_key_file_get_string (file, *g, "type", NULL);
+
+		/* A uint32 type value */
 		if (type && g_str_equal (type, "uint32")) {
-			if (!compat_uint32)
-				compat_uint32 = g_string_new ("");
-			g_string_append (compat_uint32, name);
-			g_string_append_c (compat_uint32, ' ');
+			if (key_file_get_uint64 (file, *g, "value", &number))
+				gck_secret_fields_add_compat_uint32 (attributes, name, number);
+			g_free (name);
+
+		/* A string type value */
+		} else {
+			gck_secret_fields_take (attributes, name,
+			                        g_key_file_get_string (file, *g, "value", NULL));
 		}
 		
 		g_free (type);
-			
-		g_hash_table_replace (attributes, name, 
-		                      g_key_file_get_string (file, *g, "value", NULL));
 	}
 	
-	if (compat_uint32)
-		g_hash_table_replace (attributes, g_strdup ("compat-uint32"),
-		                      g_string_free (compat_uint32, FALSE));
-	
 	g_free (prefix);
 } 
 
@@ -301,75 +259,85 @@ parse_acl (GKeyFile *file, GckSecretItem *item, const gchar **groups)
 }
 
 static void
-generate_item (GKeyFile *file, GckSecretItem *item)
+generate_item (GKeyFile *file, GckSecretItem *item, GckSecretData *sdata)
 {
 	GckSecretObject *obj;
 	GHashTable *attributes;
 	const gchar *value;
-	const gchar *groupname;
-	GckSecret *secret;
-	const gchar *password;
-	gsize n_password;
-	
+	const gchar *identifier;
+	const guchar *secret;
+	gsize n_secret;
+	gchar *hex;
+
+	g_assert (file);
+	g_assert (GCK_IS_SECRET_ITEM (item));
+	g_assert (GCK_IS_SECRET_DATA (sdata));
+
 	obj = GCK_SECRET_OBJECT (item);
-	groupname = gck_secret_object_get_identifier (obj);
+	identifier = gck_secret_object_get_identifier (obj);
 	attributes = gck_secret_item_get_fields (item);
-	
+
 	/* 
 	 * COMPATIBILITY: We no longer have the concept of an item type.
 	 * The gkr:item-type field serves that purpose.
 	 */
-	
-	value = g_hash_table_lookup (attributes, "gkr:item-type");
-	g_key_file_set_integer (file, groupname, "item-type",
+
+	value = gck_secret_fields_get (attributes, "gkr:item-type");
+	g_key_file_set_integer (file, identifier, "item-type",
 	                        gck_secret_compat_parse_item_type (value));
 
 	value = gck_secret_object_get_label (obj);
 	if (value != NULL)
-		g_key_file_set_string (file, groupname, "display-name", value);
-	
-#if 0
-	secret = gck_secret_item_get_secret (item);
-#endif
-g_assert_not_reached ();
+		g_key_file_set_string (file, identifier, "display-name", value);
+
+	secret = gck_secret_data_get_raw (sdata, identifier, &n_secret);
 	if (secret != NULL) {
-		password = gck_secret_get_password (secret, &n_password);
-		/* TODO: What about non-textual passwords? */
-		if (password != NULL) 
-			g_key_file_set_value (file, groupname, "secret", (gchar*)password);
+		/* A textual secret. Note that secrets are always null-terminated. */
+		if (g_utf8_validate ((gchar*)secret, n_secret, NULL)) {
+			g_key_file_set_value (file, identifier, "secret", (gchar*)secret);
+
+		/* A non-textual secret */
+		} else {
+			hex = egg_hex_encode (secret, n_secret);
+			g_key_file_set_value (file, identifier, "binary-secret", hex);
+			g_free (hex);
+		}
 	}
 
-	key_file_set_uint64 (file, groupname, "mtime", gck_secret_object_get_modified (obj));
-	key_file_set_uint64 (file, groupname, "ctime", gck_secret_object_get_created (obj));
-	
+	key_file_set_uint64 (file, identifier, "mtime", gck_secret_object_get_modified (obj));
+	key_file_set_uint64 (file, identifier, "ctime", gck_secret_object_get_created (obj));
+
 	generate_attributes (file, item);
 	generate_acl (file, item);
 }
 
 static void 
-parse_item (GKeyFile *file, GckSecretItem *item, const gchar **groups)
+parse_item (GKeyFile *file, GckSecretItem *item, GckSecretData *sdata,
+            const gchar **groups)
 {
 	GckSecretObject *obj;
 	GHashTable *attributes;
-	const gchar *groupname;
+	const gchar *identifier;
 	GError *err = NULL;
 	GckSecret *secret;
+	guchar *binary;
+	gsize n_binary;
 	gchar *val;
 	guint64 num;
 	gint type;
-	
+
 	/* First the main item data */
-	
+
 	obj = GCK_SECRET_OBJECT (item);
-	groupname = gck_secret_object_get_identifier (obj);
+	identifier = gck_secret_object_get_identifier (obj);
 	attributes = gck_secret_item_get_fields (item);
-	
+
 	/* 
 	 * COMPATIBILITY: We no longer have the concept of an item type.
 	 * The gkr:item-type field serves that purpose.
 	 */
 
-	type = g_key_file_get_integer (file, groupname, "item-type", &err);
+	type = g_key_file_get_integer (file, identifier, "item-type", &err);
 	if (err) {
 		g_clear_error (&err);
 		type = 0;
@@ -378,31 +346,41 @@ parse_item (GKeyFile *file, GckSecretItem *item, const gchar **groups)
 	gck_secret_fields_add (attributes, "gkr:item-type",
 	                       gck_secret_compat_format_item_type (type));
 
-	val = g_key_file_get_string (file, groupname, "display-name", NULL);
+	val = g_key_file_get_string (file, identifier, "display-name", NULL);
 	gck_secret_object_set_label (obj, val);
 	g_free (val);
 
-	val = g_key_file_get_string (file, groupname, "secret", NULL);
-	if (val == NULL) {
-#if 0
-		gck_secret_item_set_secret (item, NULL);
-#endif
-g_assert_not_reached ();
-	} else {
-		secret = gck_secret_new ((guchar*)val, strlen (val));
-#if 0
-		gck_secret_item_set_secret (item, secret);
-#endif
-g_assert_not_reached ();
-		g_object_unref (secret);
-		g_free (val);
+	if (sdata) {
+		secret = NULL;
+
+		/* A textual secret */
+		val = g_key_file_get_string (file, identifier, "secret", NULL);
+		if (val != NULL) {
+			secret = gck_secret_new_from_password (val);
+			g_free (val);
+
+		/* A binary secret */
+		} else {
+			val = g_key_file_get_string (file, identifier, "binary-secret", NULL);
+			if (val != NULL) {
+				binary = egg_hex_decode (val, -1, &n_binary);
+				secret = gck_secret_new (binary, n_binary);
+				g_free (binary);
+				g_free (val);
+			}
+		}
+
+		/* Put the secret in the right place */
+		gck_secret_data_set_secret (sdata, identifier, secret);
+		if (secret)
+			g_object_unref (secret);
 	}
 
 	num = 0;
-	if (key_file_get_uint64 (file, groupname, "mtime", &num))
+	if (key_file_get_uint64 (file, identifier, "mtime", &num))
 		gck_secret_object_set_modified (obj, num);
 	num = 0;
-	if (key_file_get_uint64 (file, groupname, "ctime", &num))
+	if (key_file_get_uint64 (file, identifier, "ctime", &num))
 		gck_secret_object_set_created (obj, num);
 
 	/* Now the other stuff */	
@@ -411,7 +389,8 @@ g_assert_not_reached ();
 }
 
 GckDataResult
-gck_secret_textual_write (GckSecretCollection *collection, guchar **result, gsize *n_result)
+gck_secret_textual_write (GckSecretCollection *collection, GckSecretData *sdata,
+                          guchar **data, gsize *n_data)
 {
 	GckSecretObject *obj;
 	GList *items, *l;
@@ -420,37 +399,40 @@ gck_secret_textual_write (GckSecretCollection *collection, guchar **result, gsiz
 	GError *err = NULL;
 	gboolean idle_lock;
 	gint idle_timeout;
-	
-	obj = GCK_SECRET_OBJECT (collection);
 
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (collection), GCK_DATA_FAILURE);
+	g_return_val_if_fail (GCK_IS_SECRET_DATA (sdata), GCK_DATA_LOCKED);
+	g_return_val_if_fail (data && n_data, GCK_DATA_FAILURE);
+
+	obj = GCK_SECRET_OBJECT (collection);
 	file = g_key_file_new ();
-	
+
 	value = gck_secret_object_get_label (obj);
 	if (value != NULL)
 		g_key_file_set_string (file, "keyring", "display-name", value);
-	
+
 	key_file_set_uint64 (file, "keyring", "ctime", gck_secret_object_get_created (obj));
 	key_file_set_uint64 (file, "keyring", "mtime", gck_secret_object_get_modified (obj));
-	
+
 	/* Not currently used :( */
 	idle_lock = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (collection), "lock-on-idle"));
 	g_key_file_set_boolean (file, "keyring", "lock-on-idle", idle_lock);
 	idle_timeout = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (collection), "lock-timeout"));
 	g_key_file_set_integer (file, "keyring", "lock-timeout", idle_timeout);
-	
+
 	items = gck_secret_collection_get_items (collection);
 	for (l = items; l; l = g_list_next (l)) 
-		generate_item (file, l->data);
+		generate_item (file, l->data, sdata);
 	g_list_free (items);
 
-	*result = (guchar*)g_key_file_to_data (file, n_result, &err);
+	*data = (guchar*)g_key_file_to_data (file, n_data, &err);
 	g_key_file_free (file);
-	
-	if (!*result) {
+
+	if (!*data) {
 		g_warning ("couldn't generate textual keyring file: %s", err->message);
 		return GCK_DATA_FAILURE;
 	}
-	
+
 	return GCK_DATA_SUCCESS;
 }
 
@@ -470,7 +452,8 @@ remove_unavailable_item (gpointer key, gpointer dummy, gpointer user_data)
 }
 
 GckDataResult
-gck_secret_textual_read (GckSecretCollection *collection, const guchar *data, gsize n_data) 
+gck_secret_textual_read (GckSecretCollection *collection, GckSecretData *sdata,
+                         const guchar *data, gsize n_data)
 {
 	GckSecretObject *obj;
 	GckSecretItem *item;
@@ -487,7 +470,10 @@ gck_secret_textual_read (GckSecretCollection *collection, const guchar *data, gs
 	gchar *value;
 	guint64 num;
 	gchar **g;
-	
+
+	g_return_val_if_fail (GCK_IS_SECRET_COLLECTION (collection), GCK_DATA_FAILURE);
+	g_return_val_if_fail (!sdata || GCK_IS_SECRET_DATA (sdata), GCK_DATA_FAILURE);
+
 	file = g_key_file_new ();
 	obj = GCK_SECRET_OBJECT (collection);
 	
@@ -528,11 +514,12 @@ gck_secret_textual_read (GckSecretCollection *collection, const guchar *data, gs
 		identifier = gck_secret_object_get_identifier (l->data);
 		g_hash_table_replace (checks, g_strdup (identifier), "unused");
 	}
-	
+	g_list_free (items);
+
 	groups = g_key_file_get_groups (file, NULL);
 	for (g = groups; *g; ++g) {
 		identifier = *g;
-		if (g_str_equal (identifier, "keyring"))
+		if (g_str_equal (identifier, "keyring") || strchr (identifier, ':'))
 			continue;
 
 		/* We've seen this id */
@@ -541,12 +528,12 @@ gck_secret_textual_read (GckSecretCollection *collection, const guchar *data, gs
 		item = gck_secret_collection_get_item (collection, identifier);
 		if (item == NULL)
 			item = gck_secret_collection_create_item (collection, identifier);
-		parse_item (file, item, (const gchar**)groups);
+		parse_item (file, item, sdata, (const gchar**)groups);
 	}
-	
+
 	g_hash_table_foreach (checks, (GHFunc)remove_unavailable_item, collection);
 	res = GCK_DATA_SUCCESS;
-	
+
 done:
 	if (checks)
 		g_hash_table_destroy (checks);
@@ -556,5 +543,5 @@ done:
 	g_free (start);
 	g_clear_error (&err);
 
-	return res;	
+	return res;
 }
diff --git a/pkcs11/secret-store/gck-secret-textual.h b/pkcs11/secret-store/gck-secret-textual.h
index 6dc66cd..0a59f4a 100644
--- a/pkcs11/secret-store/gck-secret-textual.h
+++ b/pkcs11/secret-store/gck-secret-textual.h
@@ -27,10 +27,12 @@
 #include "gck/gck-data-types.h"
 
 GckDataResult          gck_secret_textual_read       (GckSecretCollection *collection, 
+                                                      GckSecretData *sdata,
                                                       const guchar *data,
                                                       gsize n_data);
 
-GckDataResult          gck_secret_textual_write      (GckSecretCollection *collection, 
+GckDataResult          gck_secret_textual_write      (GckSecretCollection *collection,
+                                                      GckSecretData *sdata,
                                                       guchar **data,
                                                       gsize *n_data);
 
diff --git a/pkcs11/secret-store/tests/Makefile.am b/pkcs11/secret-store/tests/Makefile.am
index 4a491bf..8f277a2 100644
--- a/pkcs11/secret-store/tests/Makefile.am
+++ b/pkcs11/secret-store/tests/Makefile.am
@@ -5,6 +5,7 @@ UNIT_AUTO = \
 	unit-test-secret-fields.c \
 	unit-test-secret-item.c \
 	unit-test-secret-object.c \
+	unit-test-secret-textual.c \
 	test-secret-module.c test-secret-module.h
 
 UNIT_PROMPT = 
diff --git a/pkcs11/secret-store/tests/test-data/plain-bad-number.keyring b/pkcs11/secret-store/tests/test-data/plain-bad-number.keyring
new file mode 100644
index 0000000..e5ff5ac
--- /dev/null
+++ b/pkcs11/secret-store/tests/test-data/plain-bad-number.keyring
@@ -0,0 +1,23 @@
+
+[keyring]
+display-name=plain-bad-number
+ctime=1198027852
+mtime=1198027852
+lock-on-idle=false
+lock-timeout=0
+
+[1]
+item-type=0
+display-name=Bad Number
+secret=secret
+mtime=1198027852
+ctime=1198027852
+
+[1:attribute0]
+name=bad-number
+type=uint32
+value=not-a-number
+
+[1:attribute1]
+name=missing-number
+type=uint32
diff --git a/pkcs11/secret-store/tests/test-data/plain.keyring b/pkcs11/secret-store/tests/test-data/plain.keyring
new file mode 100644
index 0000000..c048aa1
--- /dev/null
+++ b/pkcs11/secret-store/tests/test-data/plain.keyring
@@ -0,0 +1,55 @@
+
+[keyring]
+display-name=unit-test-keyring
+ctime=1198027852
+mtime=1198027852
+lock-on-idle=false
+lock-timeout=0
+
+[2]
+item-type=0
+display-name=Another display name
+secret=item-secret
+mtime=1198027852
+ctime=1198027852
+
+[2:acl0]
+display-name=run-auto-test
+path=/data/projects/gnome-keyring/library/tests/.libs/run-auto-test
+read-access=true
+write-access=true
+remove-access=true
+
+[3]
+item-type=0
+display-name=Barnyard
+secret=item-secret
+mtime=1198027852
+ctime=1198027852
+
+[3:attribute0]
+name=dog
+type=string
+value=woof
+
+[3:attribute1]
+name=bird
+type=string
+value=cheep
+
+[3:attribute2]
+name=iguana
+type=string
+value=
+
+[3:attribute3]
+name=num
+type=uint32
+value=3
+
+[3:acl0]
+display-name=run-auto-test
+path=/data/projects/gnome-keyring/library/tests/.libs/run-auto-test
+read-access=true
+write-access=true
+remove-access=true
diff --git a/pkcs11/secret-store/tests/unit-test-secret-textual.c b/pkcs11/secret-store/tests/unit-test-secret-textual.c
new file mode 100644
index 0000000..0736673
--- /dev/null
+++ b/pkcs11/secret-store/tests/unit-test-secret-textual.c
@@ -0,0 +1,220 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
+/* unit-test-secret-textual.c: Test textual keyring read and write
+
+   Copyright (C) 2009 Stefan Walter
+
+   The Gnome Keyring Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The Gnome Keyring Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the Gnome Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+
+   Author: Stef Walter <stef memberwebs com>
+*/
+
+#include "config.h"
+
+#include "run-auto-test.h"
+#include "test-secret-module.h"
+
+#include "gck-secret-collection.h"
+#include "gck-secret-data.h"
+#include "gck-secret-fields.h"
+#include "gck-secret-item.h"
+#include "gck-secret-textual.h"
+
+#include "gck/gck-secret.h"
+
+#include "pkcs11/pkcs11i.h"
+
+#include <glib.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static GckModule *module = NULL;
+static GckSession *session = NULL;
+static GckSecretCollection *collection = NULL;
+static GckSecretData *sdata = NULL;
+
+DEFINE_SETUP(textual)
+{
+	module = test_secret_module_initialize_and_enter ();
+	session = test_secret_module_open_session (TRUE);
+
+	collection = g_object_new (GCK_TYPE_SECRET_COLLECTION,
+	                           "module", module,
+	                           "identifier", "test",
+	                           "label", "brigadooooooooooooon",
+	                           NULL);
+	
+	sdata = g_object_new (GCK_TYPE_SECRET_DATA, NULL);
+
+	g_assert (GCK_IS_SECRET_COLLECTION (collection));
+	
+}
+
+DEFINE_TEARDOWN(textual)
+{
+	if (collection)
+		g_object_unref (collection);
+	collection = NULL;
+
+	if (sdata)
+		g_object_unref (sdata);
+	sdata = NULL;
+
+	test_secret_module_leave_and_finalize ();
+	module = NULL;
+	session = NULL;
+}
+
+static void
+fill_in_collection (void)
+{
+	GckSecretItem *item;
+	GHashTable *fields;
+	GckSecret *secret;
+
+	item = gck_secret_collection_create_item (collection, "4");
+	gck_secret_object_set_label (GCK_SECRET_OBJECT (item), "Noises");
+	secret = gck_secret_new_from_password ("4's secret");
+	gck_secret_data_set_secret (sdata, "4", secret);
+	g_object_unref (secret);
+	fields = gck_secret_item_get_fields (item);
+	gck_secret_fields_add (fields, "doggy", "fart");
+	gck_secret_fields_add (fields, "pig", "grunt");
+	gck_secret_fields_add_compat_uint32 (fields, "how-many", 292929);
+
+	item = gck_secret_collection_create_item (collection, "5");
+	gck_secret_object_set_label (GCK_SECRET_OBJECT (item), "Colors");
+	secret = gck_secret_new_from_password ("5's secret");
+	gck_secret_data_set_secret (sdata, "5", secret);
+	g_object_unref (secret);
+	fields = gck_secret_item_get_fields (item);
+	gck_secret_fields_add (fields, "barney", "purple");
+	gck_secret_fields_add (fields, "piglet", "pink");
+	gck_secret_fields_add_compat_uint32 (fields, "number", 8);
+
+	item = gck_secret_collection_create_item (collection, "6");
+	gck_secret_object_set_label (GCK_SECRET_OBJECT (item), "Binary Secret");
+	secret = gck_secret_new ((guchar*)"binary\0secret", 13);
+	gck_secret_data_set_secret (sdata, "6", secret);
+	g_object_unref (secret);
+	fields = gck_secret_item_get_fields (item);
+	gck_secret_fields_add (fields, "train", "zoom");
+	gck_secret_fields_add (fields, "hummer", NULL);
+	gck_secret_fields_add_compat_uint32 (fields, "number", 2);
+}
+
+DEFINE_TEST(textual_read)
+{
+	GckDataResult res;
+	guchar *data;
+	gsize n_data;
+
+	data = test_read_testdata ("plain.keyring", &n_data);
+	res = gck_secret_textual_read (collection, sdata, data, n_data);
+	g_free (data);
+
+	g_assert (res == GCK_DATA_SUCCESS);
+}
+
+DEFINE_TEST(textual_read_wrong_format)
+{
+	GckDataResult res;
+	guchar *data;
+	gsize n_data;
+
+	data = test_read_testdata ("encrypted.keyring", &n_data);
+	res = gck_secret_textual_read (collection, sdata, data, n_data);
+	g_free (data);
+
+	g_assert (res == GCK_DATA_UNRECOGNIZED);
+}
+
+DEFINE_TEST(textual_read_bad_number)
+{
+	GckSecretItem *item;
+	GckDataResult res;
+	const gchar *value;
+	guchar *data;
+	gsize n_data;
+
+	data = test_read_testdata ("plain-bad-number.keyring", &n_data);
+	res = gck_secret_textual_read (collection, sdata, data, n_data);
+	g_free (data);
+
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	item = gck_secret_collection_get_item (collection, "1");
+	g_assert (GCK_IS_SECRET_ITEM (item));
+	value = gck_secret_fields_get (gck_secret_item_get_fields (item), "bad-number");
+	g_assert (value == NULL);
+	value = gck_secret_fields_get (gck_secret_item_get_fields (item), "missing-number");
+	g_assert (value == NULL);
+}
+
+DEFINE_TEST(textual_write)
+{
+	GckDataResult res;
+	guchar *data;
+	gsize n_data;
+
+	fill_in_collection ();
+
+	res = gck_secret_textual_write (collection, sdata, &data, &n_data);
+	g_assert (res == GCK_DATA_SUCCESS);
+	g_assert (data);
+	g_assert (n_data);
+
+	/* Try parsing it again */
+	res = gck_secret_textual_read (collection, sdata, data, n_data);
+	g_assert (res == GCK_DATA_SUCCESS);
+}
+
+DEFINE_TEST(textual_remove_unavailable)
+{
+	GckDataResult res;
+	GList *items;
+	guchar *data;
+	gsize n_data;
+
+	data = test_read_testdata ("plain.keyring", &n_data);
+	res = gck_secret_textual_read (collection, sdata, data, n_data);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* Two items from the file */
+	items = gck_secret_collection_get_items (collection);
+	g_assert_cmpint (g_list_length (items), ==, 2);
+	g_list_free (items);
+
+	/* Fill in some more data */
+	fill_in_collection ();
+
+	/* Should have added three more */
+	items = gck_secret_collection_get_items (collection);
+	g_assert_cmpint (g_list_length (items), ==, 5);
+	g_list_free (items);
+
+	/* Re-read the keyring */
+	res = gck_secret_textual_read (collection, sdata, data, n_data);
+	g_assert (res == GCK_DATA_SUCCESS);
+
+	/* And we're back to two */
+	items = gck_secret_collection_get_items (collection);
+	g_assert_cmpint (g_list_length (items), ==, 2);
+	g_list_free (items);
+
+	g_free (data);
+}



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