gnome-keyring r1619 - in trunk: . pkcs11 pkcs11/user-store



Author: nnielsen
Date: Thu Feb 26 05:40:43 2009
New Revision: 1619
URL: http://svn.gnome.org/viewvc/gnome-keyring?rev=1619&view=rev

Log:
Hash objects when storing them in user-store and validate the hashes
when loading them.

Modified:
   trunk/ChangeLog
   trunk/pkcs11/pkcs11i.h
   trunk/pkcs11/user-store/gck-user-storage.c

Modified: trunk/pkcs11/pkcs11i.h
==============================================================================
--- trunk/pkcs11/pkcs11i.h	(original)
+++ trunk/pkcs11/pkcs11i.h	Thu Feb 26 05:40:43 2009
@@ -66,4 +66,10 @@
 #define CK_GNOME_MAX_APP                            (((CK_ULONG)-1) >> 10)
 #define CK_GNOME_MAX_HANDLE                         (((CK_ULONG)-1) >> 10)
 
+/* -------------------------------------------------------------------
+ * OBJECT HASH
+ */
+
+#define CK_GNOME_INTERNAL_SHA1                      (CKA_GNOME + 1000)
+
 #endif /* PKCS11I_H */

Modified: trunk/pkcs11/user-store/gck-user-storage.c
==============================================================================
--- trunk/pkcs11/user-store/gck-user-storage.c	(original)
+++ trunk/pkcs11/user-store/gck-user-storage.c	Thu Feb 26 05:40:43 2009
@@ -35,6 +35,8 @@
 
 #include "egg/egg-hex.h"
 
+#include "pkcs11/pkcs11i.h"
+
 #include <glib/gstdio.h>
 
 #include <libtasn1.h>
@@ -421,6 +423,56 @@
 	gck_manager_register_object (self->manager, object);
 }
 
+static gboolean
+check_object_hash (GckUserStorage *self, const gchar *identifier, const guchar *data, gsize n_data)
+{
+	gconstpointer value;
+	GckDataResult res;
+	gboolean result;
+	gsize n_value;
+	gchar *digest;
+	
+	g_assert (GCK_IS_USER_STORAGE (self));
+	g_assert (identifier);
+	g_assert (data);
+	
+	digest = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, n_data);
+	g_return_val_if_fail (digest, FALSE);
+	
+	res = gck_data_file_read_value (self->file, identifier, CK_GNOME_INTERNAL_SHA1, &value, &n_value);
+	g_return_val_if_fail (res == GCK_DATA_SUCCESS, FALSE);
+	
+	result = (strlen (digest) == n_value && memcmp (digest, value, n_value) == 0);
+	g_free (digest);
+	
+	return result;
+}
+
+static void
+store_object_hash (GckUserStorage *self, GckTransaction *transaction, const gchar *identifier, 
+                   const guchar *data, gsize n_data)
+{
+	GckDataResult res;
+	gchar *digest;
+	
+	g_assert (GCK_IS_USER_STORAGE (self));
+	g_assert (GCK_IS_TRANSACTION (transaction));
+	g_assert (identifier);
+	g_assert (data);
+	
+	digest = g_compute_checksum_for_data (G_CHECKSUM_SHA1, data, n_data);
+	if (digest == NULL) {
+		gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+		g_return_if_reached ();
+	}
+	
+	res = gck_data_file_write_value (self->file, identifier, CK_GNOME_INTERNAL_SHA1, digest, strlen (digest));
+	g_free (digest);
+	
+	if (res != GCK_DATA_SUCCESS)
+		gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+}
+
 static void 
 data_file_entry_added (GckDataFile *store, const gchar *identifier, GckUserStorage *self)
 {
@@ -460,6 +512,12 @@
 		return;
 	}
 	
+	/* Make sure that the object wasn't tampered with */
+	if (!check_object_hash (self, identifier, data, n_data)) {
+		g_message ("file in user store doesn't match hash: %s", identifier);
+		return;
+	}
+	
 	/* Create a new object for this identifier */
 	object = g_object_new (type, "unique", identifier, NULL);
 	g_return_if_fail (GCK_IS_SERIALIZABLE (object));
@@ -521,7 +579,7 @@
 }
 
 static void
-relock_object (GckTransaction *transaction, const gchar *path, 
+relock_object (GckUserStorage *self, GckTransaction *transaction, const gchar *path, 
                const gchar *identifier, GckLogin *old_login, GckLogin *new_login)
 {
 	GError *error = NULL;
@@ -532,6 +590,7 @@
 	GType type;
 	CK_RV rv;
 	
+	g_assert (GCK_IS_USER_STORAGE (self));
 	g_assert (GCK_IS_TRANSACTION (transaction));
 	g_assert (identifier);
 	g_assert (path);
@@ -556,10 +615,18 @@
 	
 	/* Read in the data for the object */
 	if (!g_file_get_contents (path, (gchar**)&data, &n_data, &error)) {
-		g_message ("couldn't relock file in user store: %s: %s", identifier,
+		g_message ("couldn't load file in user store in order to relock: %s: %s", identifier,
 		           error && error->message ? error->message : "");
 		g_clear_error (&error);
 		g_object_unref (object);
+		gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
+		return;
+	}
+	
+	/* Make sure the data matches the hash */
+	if (!check_object_hash (self, identifier, data, n_data)) {
+		g_message ("file in data store doesn't match hash: %s", identifier);
+		gck_transaction_fail (transaction, CKR_GENERAL_ERROR);
 		return;
 	}
 	
@@ -619,7 +686,13 @@
 	
 	/* And write it back out to the file */
 	gck_transaction_write_file (transaction, path, data, n_data);
+	
+	/* Create and save the hash here */
+	if (!gck_transaction_get_failed (transaction))
+		store_object_hash (self, transaction, identifier, data, n_data);
+	
 	g_free (data);
+
 }
 
 typedef struct _RelockArgs {
@@ -648,7 +721,7 @@
 		return;
 
 	path = g_build_filename (args->self->directory, identifier, NULL);
-	relock_object (args->transaction, path, identifier, args->old_login, args->new_login);
+	relock_object (args->self, args->transaction, path, identifier, args->old_login, args->new_login);
 	g_free (path);
 }
 
@@ -1063,6 +1136,10 @@
 
 	path = g_build_filename (self->directory, identifier, NULL);
 	gck_transaction_write_file (transaction, path, data, n_data);
+	
+	/* Make sure we write in the object hash */
+	if (!gck_transaction_get_failed (transaction))
+		store_object_hash (self, transaction, identifier, data, n_data);
 
 	/* Now we decide to own the object */
 	if (!gck_transaction_get_failed (transaction))



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