[gnome-keyring/dbus-api] [secrets] Implement some smaller bits of secrets-store.



commit 30ebc87d02b38e470970e7b4c48eb1bb5d834038
Author: Stef Walter <stef memberwebs com>
Date:   Fri Jul 24 01:30:30 2009 +0000

    [secrets] Implement some smaller bits of secrets-store.
    
    Implement some smaller bits of the secrets-store

 configure.in                                |    1 +
 pkcs11/Makefile.am                          |    1 +
 pkcs11/gck/gck-attributes.h                 |    3 +
 pkcs11/pkcs11g.h                            |   16 +
 pkcs11/secret-store/Makefile.am             |   20 ++
 pkcs11/secret-store/gck-secret-collection.c |  141 ++++++++
 pkcs11/secret-store/gck-secret-collection.h |   45 +++
 pkcs11/secret-store/gck-secret-item.c       |  486 +++++++++++++++++++++++++++
 pkcs11/secret-store/gck-secret-item.h       |   58 ++++
 pkcs11/secret-store/gck-secret-object.c     |  338 +++++++++++++++++++
 pkcs11/secret-store/gck-secret-object.h     |   73 ++++
 11 files changed, 1182 insertions(+), 0 deletions(-)
---
diff --git a/configure.in b/configure.in
index e05fa35..553efca 100644
--- a/configure.in
+++ b/configure.in
@@ -586,6 +586,7 @@ pkcs11/plex-layer/Makefile
 pkcs11/roots-store/Makefile
 pkcs11/roots-store/tests/Makefile
 pkcs11/rpc-layer/Makefile
+pkcs11/secret-store/Makefile
 pkcs11/ssh-agent/Makefile
 pkcs11/ssh-store/Makefile
 pkcs11/ssh-store/tests/Makefile
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 976858c..e1b118d 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -15,6 +15,7 @@ SUBDIRS = . \
 	roots-store \
 	rpc-layer \
 	plex-layer \
+	secret-store \
 	ssh-agent \
 	ssh-store \
 	user-store
diff --git a/pkcs11/gck/gck-attributes.h b/pkcs11/gck/gck-attributes.h
index 41ae48a..80a643a 100644
--- a/pkcs11/gck/gck-attributes.h
+++ b/pkcs11/gck/gck-attributes.h
@@ -34,6 +34,9 @@ CK_RV                 gck_attribute_get_bool                           (CK_ATTRI
 CK_RV                 gck_attribute_get_time                           (CK_ATTRIBUTE_PTR attr,
                                                                         glong *value);
 
+CK_RV                 gck_attribute_get_string                         (CK_ATTRIBUTE_PTR attr,
+                                                                        gchar **value);
+
 CK_RV                 gck_attribute_set_bool                           (CK_ATTRIBUTE_PTR attr,
                                                                         CK_BBOOL value);
 
diff --git a/pkcs11/pkcs11g.h b/pkcs11/pkcs11g.h
index e71d5a5..2c0d235 100644
--- a/pkcs11/pkcs11g.h
+++ b/pkcs11/pkcs11g.h
@@ -105,4 +105,20 @@
 
 #define CKA_GNOME_USES_REMAINING                 (CKA_GNOME + 203)
 
+/* -------------------------------------------------------------------
+ * SECRETS
+ */
+
+#define CKO_G_COLLECTION                     (CKO_GNOME + 110)
+
+#define CKA_G_LOCKED                         (CKA_GNOME + 210)
+
+#define CKA_G_CREATED                        (CKA_GNOME + 211)
+
+#define CKA_G_MODIFIED                       (CKA_GNOME + 212)
+
+#define CKA_G_FIELDS                         (CKA_GNOME + 213)
+
+#define CKA_G_COLLECTION                     (CKA_GNOME + 214)
+
 #endif /* PKCS11G_H */
diff --git a/pkcs11/secret-store/Makefile.am b/pkcs11/secret-store/Makefile.am
new file mode 100644
index 0000000..208311c
--- /dev/null
+++ b/pkcs11/secret-store/Makefile.am
@@ -0,0 +1,20 @@
+
+INCLUDES = \
+	-I$(top_builddir) \
+    	-I$(top_srcdir) \
+    	-I$(top_srcdir)/pkcs11 \
+    	$(GOBJECT_CFLAGS) \
+	$(GLIB_CFLAGS)
+
+# ------------------------------------------------------------------------------
+# The roots component code
+
+noinst_LTLIBRARIES = \
+	libgck-secret-store.la
+
+libgck_secret_store_la_SOURCES = \
+	gck-secret-collection.h gck-secret-collection.c \
+	gck-secret-item.h gck-secret-item.c \
+	gck-secret-object.h gck-secret-object.c
+
+# -------------------------------------------------------------------------------
diff --git a/pkcs11/secret-store/gck-secret-collection.c b/pkcs11/secret-store/gck-secret-collection.c
new file mode 100644
index 0000000..4beee9f
--- /dev/null
+++ b/pkcs11/secret-store/gck-secret-collection.c
@@ -0,0 +1,141 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2009 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program 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
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-secret-collection.h"
+
+#include <glib/gi18n.h>
+
+enum {
+	PROP_0,
+};
+
+struct _GckSecretCollection {
+	GckSecretObject parent;
+};
+
+G_DEFINE_TYPE (GckSecretCollection, gck_secret_collection, GCK_TYPE_SECRET_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+
+/* -----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+static CK_RV
+gck_secret_collection_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE_PTR attr)
+{
+#if 0
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (base);
+	
+	switch (attr->type) {
+	}
+#endif	
+	return GCK_OBJECT_CLASS (gck_secret_collection_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_secret_collection_init (GckSecretCollection *self)
+{
+	
+}
+
+static GObject* 
+gck_secret_collection_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (G_OBJECT_CLASS (gck_secret_collection_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);
+
+	return G_OBJECT (self);
+}
+
+static void
+gck_secret_collection_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                                    GParamSpec *pspec)
+{
+#if 0
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+#endif
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_collection_get_property (GObject *obj, guint prop_id, GValue *value, 
+                                    GParamSpec *pspec)
+{
+#if 0
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+#endif
+	switch (prop_id) {
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_collection_dispose (GObject *obj)
+{
+#if 0
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+#endif
+
+	G_OBJECT_CLASS (gck_secret_collection_parent_class)->dispose (obj);
+}
+
+static void
+gck_secret_collection_finalize (GObject *obj)
+{
+#if 0
+	GckSecretCollection *self = GCK_SECRET_COLLECTION (obj);
+#endif
+
+	G_OBJECT_CLASS (gck_secret_collection_parent_class)->finalize (obj);
+}
+
+static void
+gck_secret_collection_class_init (GckSecretCollectionClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+	
+	gck_secret_collection_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->constructor = gck_secret_collection_constructor;
+	gobject_class->dispose = gck_secret_collection_dispose;
+	gobject_class->finalize = gck_secret_collection_finalize;
+	gobject_class->set_property = gck_secret_collection_set_property;
+	gobject_class->get_property = gck_secret_collection_get_property;
+
+	gck_class->get_attribute = gck_secret_collection_get_attribute;
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */
diff --git a/pkcs11/secret-store/gck-secret-collection.h b/pkcs11/secret-store/gck-secret-collection.h
new file mode 100644
index 0000000..53d9125
--- /dev/null
+++ b/pkcs11/secret-store/gck-secret-collection.h
@@ -0,0 +1,45 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2009 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program 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
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_SECRET_COLLECTION_H__
+#define __GCK_SECRET_COLLECTION_H__
+
+#include <glib-object.h>
+
+#include "gck-secret-object.h"
+
+#define GCK_TYPE_SECRET_COLLECTION               (gck_secret_collection_get_type ())
+#define GCK_SECRET_COLLECTION(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_COLLECTION, GckSecretCollection))
+#define GCK_SECRET_COLLECTION_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_COLLECTION, GckSecretCollectionClass))
+#define GCK_IS_SECRET_COLLECTION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SECRET_COLLECTION))
+#define GCK_IS_SECRET_COLLECTION_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SECRET_COLLECTION))
+#define GCK_SECRET_COLLECTION_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SECRET_COLLECTION, GckSecretCollectionClass))
+
+typedef struct _GckSecretCollection GckSecretCollection;
+typedef struct _GckSecretCollectionClass GckSecretCollectionClass;
+    
+struct _GckSecretCollectionClass {
+	GckSecretObjectClass parent_class;
+};
+
+GType                gck_secret_collection_get_type        (void);
+
+#endif /* __GCK_SECRET_COLLECTION_H__ */
diff --git a/pkcs11/secret-store/gck-secret-item.c b/pkcs11/secret-store/gck-secret-item.c
new file mode 100644
index 0000000..022809c
--- /dev/null
+++ b/pkcs11/secret-store/gck-secret-item.c
@@ -0,0 +1,486 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2009 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program 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
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-secret-item.h"
+
+#include "gck/gck-attributes.h"
+#include "gck/gck-login.h"
+#include "gck/gck-transaction.h"
+
+#include "pkcs11/pkcs11g.h"
+
+#include <glib/gi18n.h>
+
+enum {
+	PROP_0,
+	PROP_SECRET,
+	PROP_COLLECTION,
+	PROP_FIELDS
+};
+
+struct _GckSecretItem {
+	GckSecretObject parent;
+	GckLogin *secret;
+	GHashTable *fields;
+	GckSecretCollection *collection;
+};
+
+G_DEFINE_TYPE (GckSecretItem, gck_secret_item, GCK_TYPE_SECRET_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+static GType
+fields_boxed_type (void)
+{
+	static GType type = 0;
+	if (!type) 
+		type = g_boxed_type_register_static ("GHashTable_Fields", 
+		                                     (GBoxedCopyFunc)g_hash_table_ref,
+		                                     (GBoxedFreeFunc)g_hash_table_unref);
+	return type;
+}
+
+static void
+each_field_append (gpointer key, gpointer value, gpointer user_data)
+{
+	GString *result = user_data;
+	g_string_append (result, key);
+	g_string_append_c (result, '\0');
+	g_string_append (result, value);
+	g_string_append_c (result, '\0');
+}
+
+static void
+each_field_length (gpointer key, gpointer value, gpointer user_data)
+{
+	gsize *length = user_data;
+	*length += strlen (key);
+	*length += strlen (value);
+	*length += 2;
+}
+
+static CK_RV
+attribute_set_fields (CK_ATTRIBUTE_PTR attr, GHashTable *fields)
+{
+	GString *result;
+	gsize length;
+	CK_RV rv;
+	
+	g_assert (attr);
+	g_assert (fields);
+	
+	if (!attr->pValue) {
+		length = 0;
+		g_hash_table_foreach (fields, each_field_length, &length);
+		attr->ulValueLen = length;
+		return CKR_OK;
+	}
+	
+	result = g_string_sized_new (256);
+	g_hash_table_foreach (fields, each_field_append, result);
+	
+	rv = gck_attribute_set_data (attr, result->str, result->len);
+	g_string_free (result, TRUE);
+	
+	return rv;
+}
+
+static CK_RV
+attribute_get_fields (CK_ATTRIBUTE_PTR attr, GHashTable **fields)
+{
+	GHashTable *result;
+	gchar *name;
+	gsize n_name;
+	gchar *value;
+	gsize n_value;
+	gchar *ptr;
+	gchar *last;
+	
+	g_assert (attr);
+	g_assert (fields);
+
+	ptr = attr->pValue;
+	last = ptr + attr->ulValueLen;
+	
+	if (!ptr && last != ptr)
+		return CKR_ATTRIBUTE_VALUE_INVALID;
+
+	result = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+	while (ptr && ptr != last) {
+		g_assert (ptr < last);
+		
+		name = ptr;
+		ptr = memchr (ptr, 0, last - ptr);
+		
+		/* No value is present? */
+		if (!ptr) {
+			g_hash_table_unref (result);
+			return CKR_ATTRIBUTE_VALUE_INVALID;
+		}
+		
+		n_name = ptr - name;
+		value = ptr;
+		ptr = memchr (ptr, 0, last - ptr);
+		
+		/* The last value */
+		if (ptr == NULL)
+			ptr = last;
+		
+		n_value = ptr - value;
+
+		/* Validate the name and value*/
+		if (!g_utf8_validate (name, n_name, NULL) || 
+		    !g_utf8_validate (value, n_value, NULL)) {
+			g_hash_table_unref (result);
+			return CKR_ATTRIBUTE_VALUE_INVALID;
+		}
+		
+		g_hash_table_replace (result, g_strndup (name, n_name), g_strndup (value, n_value));
+	}
+	
+	*fields = result;
+	return CKR_OK;
+}
+
+static gboolean
+complete_set_secret (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (obj);
+	GckLogin *old_secret = user_data;
+	
+	if (gck_transaction_get_failed (transaction)) {
+		gck_secret_item_set_secret (self, old_secret);
+	} else {
+		gck_object_notify_attribute (GCK_OBJECT (obj), CKA_VALUE);
+		g_object_notify (G_OBJECT (obj), "secret");
+		gck_secret_object_was_modified (GCK_SECRET_OBJECT (self));
+	}
+
+	if (old_secret)
+		g_object_unref (old_secret);
+	return TRUE;
+}
+
+static void
+begin_set_secret (GckSecretItem *self, GckTransaction *transaction, GckLogin *secret)
+{
+	g_assert (GCK_IS_SECRET_OBJECT (self));
+	g_assert (!gck_transaction_get_failed (transaction));
+	
+	if (self->secret)
+		g_object_ref (self->secret);
+	gck_transaction_add (transaction, self, complete_set_secret, self->secret);
+	gck_secret_item_set_secret (self, secret);
+}
+
+
+static gboolean
+complete_set_fields (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (obj);
+	GHashTable *old_fields = user_data;
+	
+	if (gck_transaction_get_failed (transaction)) {
+		if (self->fields)
+			g_hash_table_unref (self->fields);
+		self->fields = old_fields;
+	} else {
+		gck_object_notify_attribute (GCK_OBJECT (obj), CKA_G_FIELDS);
+		g_object_notify (G_OBJECT (obj), "fields");
+		gck_secret_object_was_modified (GCK_SECRET_OBJECT (self));
+		if (old_fields)
+			g_hash_table_unref (old_fields);
+	}
+
+	return TRUE;
+}
+
+static void
+begin_set_fields (GckSecretItem *self, GckTransaction *transaction, GHashTable *fields)
+{
+	g_assert (GCK_IS_SECRET_OBJECT (self));
+	g_assert (!gck_transaction_get_failed (transaction));
+	
+	gck_transaction_add (transaction, self, complete_set_fields, self->fields);
+	self->fields = fields;
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+static CK_RV
+gck_secret_item_real_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE_PTR attr)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (base);
+	const gchar *identifier;
+	const gchar *password;
+	gsize n_password;
+	
+	switch (attr->type) {
+	case CKA_VALUE:
+		if (gck_secret_item_real_is_locked (self, session))
+			return CKR_USER_NOT_LOGGED_IN;
+		g_return_val_if_fail (self->secret, CKR_GENERAL_ERROR);
+		password = gck_login_get_password (self->secret, &n_password);
+		return gck_attribute_set_data (attr, password, n_password);
+		
+	case CKA_G_COLLECTION:
+		g_return_val_if_fail (self->collection, CKR_GENERAL_ERROR);
+		identifier = gck_secret_object_get_identifier (GCK_SECRET_OBJECT (self->collection));
+		return gck_attribute_set_string (attr, identifier);
+		
+	case CKA_G_FIELDS:
+		return attribute_set_fields (attr, self->fields);
+	}
+	
+	return GCK_OBJECT_CLASS (gck_secret_item_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_secret_item_real_set_attribute (GckObject *base, GckSession *session, 
+                                    GckTransaction *transaction, CK_ATTRIBUTE_PTR attr)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (base);
+	GHashTable *fields;
+	GckLogin *login;
+	CK_RV rv;
+	
+	/* Check that the object is not locked */
+	if (!gck_secret_item_real_is_locked (self, session)) {
+		gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
+		return;
+	}
+	
+	switch (attr->type) {
+	case CKA_VALUE:
+		login = gck_login_new (attr->pValue, attr->ulValueLen);
+		begin_set_secret (self, transaction, login);
+		break;
+		
+	case CKA_G_FIELDS:
+		rv = attribute_get_fields (attr, &fields);
+		if (rv != CKR_OK)
+			gck_transaction_fail (transaction, rv);
+		else
+			begin_set_fields (self, transaction, fields);
+		break;
+	}
+	
+	GCK_OBJECT_CLASS (gck_secret_item_parent_class)->set_attribute (base, session, transaction, attr);
+}
+
+static void
+gck_secret_item_init (GckSecretItem *self)
+{
+	
+}
+
+static GObject* 
+gck_secret_item_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (G_OBJECT_CLASS (gck_secret_item_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);
+	
+	g_return_val_if_fail (self->collection, NULL);
+
+	return G_OBJECT (self);
+}
+
+static void
+gck_secret_item_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                              GParamSpec *pspec)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (obj);
+	
+	switch (prop_id) {
+	case PROP_SECRET:
+		gck_secret_item_set_secret (self, g_value_get_object (value));
+		break;
+	case PROP_COLLECTION:
+		g_return_if_fail (!self->collection);
+		self->collection = g_value_get_object (value);
+		g_return_if_fail (self->collection);
+		g_object_add_weak_pointer (G_OBJECT (self->collection), 
+		                           (gpointer*)&(self->collection));
+		break;
+	case PROP_FIELDS:
+		gck_secret_item_set_fields (self, g_value_get_boxed (value));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_item_get_property (GObject *obj, guint prop_id, GValue *value, 
+                              GParamSpec *pspec)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (obj);
+	
+	switch (prop_id) {
+	case PROP_SECRET:
+		g_value_set_object (value, gck_secret_item_get_secret (self));
+		break;
+	case PROP_COLLECTION:
+		g_value_set_object (value, gck_secret_item_get_collection (self));
+		break;
+	case PROP_FIELDS:
+		g_value_set_boxed (value, gck_secret_item_get_fields (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_item_dispose (GObject *obj)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (obj);
+
+	if (self->collection)
+		g_object_remove_weak_pointer (G_OBJECT (self->collection),
+		                              (gpointer*)&(self->collection));
+	self->collection = NULL;
+	
+	gck_secret_item_set_secret (self, NULL);
+	
+	G_OBJECT_CLASS (gck_secret_item_parent_class)->dispose (obj);
+}
+
+static void
+gck_secret_item_finalize (GObject *obj)
+{
+	GckSecretItem *self = GCK_SECRET_ITEM (obj);
+	
+	g_assert (!self->collection);
+	g_assert (!self->secret);
+	
+	if (self->fields)
+		g_hash_table_unref (self->fields);
+	self->fields = NULL;
+
+	G_OBJECT_CLASS (gck_secret_item_parent_class)->finalize (obj);
+}
+
+static void
+gck_secret_item_class_init (GckSecretItemClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+	GckSecretObjectClass *secret_class = GCK_SECRET_OBJECT_CLASS (klass);
+	
+	gck_secret_item_parent_class = g_type_class_peek_parent (klass);
+	
+	gobject_class->constructor = gck_secret_item_constructor;
+	gobject_class->dispose = gck_secret_item_dispose;
+	gobject_class->finalize = gck_secret_item_finalize;
+	gobject_class->set_property = gck_secret_item_set_property;
+	gobject_class->get_property = gck_secret_item_get_property;
+
+	gck_class->get_attribute = gck_secret_item_real_get_attribute;
+	gck_class->set_attribute = gck_secret_item_real_set_attribute;
+	
+	secret_class->is_locked = gck_secret_item_real_is_locked;
+	secret_class->lock = gck_secret_item_real_lock;
+
+	g_object_class_install_property (gobject_class, PROP_SECRET,
+	           g_param_spec_object ("secret", "Secret", "Item's Secret", 
+	                                GCK_TYPE_LOGIN, G_PARAM_READWRITE));
+	
+	g_object_class_install_property (gobject_class, PROP_SECRET,
+	           g_param_spec_object ("collection", "Collection", "Item's Collection", 
+	                                GCK_TYPE_SECRET_COLLECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+	g_object_class_install_property (gobject_class, PROP_FIELDS,
+	           g_param_spec_boxed ("fields", "Fields", "Item's fields", 
+	                               fields_boxed_type (), G_PARAM_READWRITE));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+GckSecretCollection*
+gck_secret_item_get_collection (GckSecretItem *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_ITEM (self), NULL);
+	return self->collection;
+}
+
+GckLogin*
+gck_secret_item_get_secret (GckSecretItem *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_ITEM (self), NULL);
+	return self->secret;	
+}
+
+void
+gck_secret_item_set_secret (GckSecretItem *self, GckLogin *secret)
+{
+	g_return_if_fail (GCK_IS_SECRET_ITEM (self));
+	
+	if (secret == self->secret)
+		return;
+	
+	if (self->secret)
+		g_object_remove_weak_pointer (G_OBJECT (self->secret),
+		                              (gpointer*)&(self->secret));
+	self->secret = secret;
+	if (self->secret)
+		g_object_add_weak_pointer (G_OBJECT (self->secret),
+		                           (gpointer*)&(self->secret));
+	
+	g_object_notify (G_OBJECT (self), "secret");
+} 
+
+GHashTable*
+gck_secret_item_get_fields (GckSecretItem *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_ITEM (self), NULL);
+	return self->fields;
+}
+
+void
+gck_secret_item_set_fields (GckSecretItem *self, GHashTable *fields)
+{
+	g_return_if_fail (GCK_IS_SECRET_ITEM (self));
+	
+	if (fields == self->fields)
+		return;
+	
+	if (self->fields)
+		g_hash_table_unref (fields);
+	self->fields = fields;
+	if (self->fields)
+		g_hash_table_ref (fields);
+	
+	g_object_notify (G_OBJECT (self), "fields");
+	gck_object_notify_attribute (GCK_OBJECT (self), CKA_G_FIELDS);
+	gck_secret_object_was_modified (GCK_SECRET_OBJECT (self));
+}
diff --git a/pkcs11/secret-store/gck-secret-item.h b/pkcs11/secret-store/gck-secret-item.h
new file mode 100644
index 0000000..707e6cb
--- /dev/null
+++ b/pkcs11/secret-store/gck-secret-item.h
@@ -0,0 +1,58 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2009 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program 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
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_SECRET_ITEM_H__
+#define __GCK_SECRET_ITEM_H__
+
+#include <glib-object.h>
+
+#include "gck-secret-object.h"
+#include "gck-secret-collection.h"
+
+#define GCK_TYPE_SECRET_ITEM               (gck_secret_item_get_type ())
+#define GCK_SECRET_ITEM(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_ITEM, GckSecretItem))
+#define GCK_SECRET_ITEM_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_ITEM, GckSecretItemClass))
+#define GCK_IS_SECRET_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SECRET_ITEM))
+#define GCK_IS_SECRET_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SECRET_ITEM))
+#define GCK_SECRET_ITEM_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SECRET_ITEM, GckSecretItemClass))
+
+typedef struct _GckSecretItem GckSecretItem;
+typedef struct _GckSecretItemClass GckSecretItemClass;
+    
+struct _GckSecretItemClass {
+	GckSecretObjectClass parent_class;
+};
+
+GType                  gck_secret_item_get_type               (void);
+
+GckSecretCollection*   gck_secret_item_get_collection         (GckSecretItem *self);
+
+GckLogin*              gck_secret_item_get_secret             (GckSecretItem *self);
+
+void                   gck_secret_item_set_secret             (GckSecretItem *self,
+                                                               GckLogin *secret);
+
+GHashTable*            gck_secret_item_get_fields             (GckSecretItem *self);
+
+void                   gck_secret_item_set_fields             (GckSecretItem *self,
+                                                               GHashTable *fields);
+
+#endif /* __GCK_SECRET_ITEM_H__ */
diff --git a/pkcs11/secret-store/gck-secret-object.c b/pkcs11/secret-store/gck-secret-object.c
new file mode 100644
index 0000000..6aac774
--- /dev/null
+++ b/pkcs11/secret-store/gck-secret-object.c
@@ -0,0 +1,338 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2009 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program 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
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#include "config.h"
+
+#include "gck-secret-object.h"
+
+#include "gck/gck-attributes.h"
+#include "gck/gck-session.h"
+#include "gck/gck-transaction.h"
+
+#include "pkcs11/pkcs11g.h"
+
+#include <glib/gi18n.h>
+
+enum {
+	PROP_0,
+	PROP_LABEL,
+	PROP_IDENTIFIER,
+	PROP_CREATED,
+	PROP_MODIFIED
+};
+
+struct _GckSecretObjectPrivate {
+	gchar *identifier;
+	gchar *label;
+	glong created;
+	glong modified;
+};
+
+G_DEFINE_TYPE (GckSecretObject, gck_secret_object, GCK_TYPE_OBJECT);
+
+/* -----------------------------------------------------------------------------
+ * INTERNAL 
+ */
+
+static gboolean
+complete_lock (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
+	g_return_val_if_fail (GCK_IS_SESSION (user_data), FALSE);
+	gck_secret_object_lock (self, GCK_SESSION (user_data));
+	g_object_unref (user_data);
+	return TRUE;
+}
+
+static gboolean
+complete_set_label (GckTransaction *transaction, GObject *obj, gpointer user_data)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
+	gchar *old_label = user_data;
+	
+	if (gck_transaction_get_failed (transaction)) {
+		g_free (self->pv->label);
+		self->pv->label = old_label;
+	} else {
+		gck_object_notify_attribute (GCK_OBJECT (obj), CKA_LABEL);
+		g_object_notify (G_OBJECT (obj), "label");
+		gck_secret_object_was_modified (self);
+		g_free (old_label);
+	}
+	
+	return TRUE;
+}
+
+static void
+begin_set_label (GckSecretObject *self, GckTransaction *transaction, gchar *label)
+{
+	g_assert (GCK_IS_SECRET_OBJECT (self));
+	g_assert (!gck_transaction_get_failed (transaction));
+	
+	gck_transaction_add (transaction, self, complete_set_label, self->pv->label);
+	self->pv->label = label;
+}
+
+/* -----------------------------------------------------------------------------
+ * OBJECT 
+ */
+
+static CK_RV
+gck_secret_object_get_attribute (GckObject *base, GckSession *session, CK_ATTRIBUTE_PTR attr)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (base);
+	
+	switch (attr->type) {
+	case CKA_ID:
+		return gck_attribute_set_string (attr, gck_secret_object_get_identifier (self));
+		
+	case CKA_LABEL:
+		return gck_attribute_set_string (attr, gck_secret_object_get_label (self));
+		
+	case CKA_G_LOCKED:
+		return gck_attribute_set_bool (attr, gck_secret_object_is_locked (self, session));
+		
+	case CKA_G_CREATED:
+		return gck_attribute_set_time (attr, gck_secret_object_get_created (self));
+		
+	case CKA_G_MODIFIED:
+		return gck_attribute_set_time (attr, gck_secret_object_get_modified (self));
+	}
+	
+	return GCK_OBJECT_CLASS (gck_secret_object_parent_class)->get_attribute (base, session, attr);
+}
+
+static void
+gck_secret_object_set_attribute (GckObject *base, GckSession *session, 
+                                 GckTransaction *transaction, CK_ATTRIBUTE_PTR attr)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (base);
+	gboolean locked;
+	gchar *label;
+	CK_RV rv;
+	
+	/* Check that the object is not locked */
+	if (!gck_secret_object_is_locked (self, session)) {
+		gck_transaction_fail (transaction, CKR_USER_NOT_LOGGED_IN);
+		return;
+	}
+	
+	switch (attr->type) {
+	
+	case CKA_LABEL:
+		rv = gck_attribute_get_string (attr, &label);
+		if (rv != CKR_OK)
+			gck_transaction_fail (transaction, rv);
+		else
+			begin_set_label (self, transaction, label);
+		return;
+		
+	case CKA_G_LOCKED:
+		rv = gck_attribute_get_bool (attr, &locked);
+		if (rv != CKR_OK)
+			gck_transaction_fail (transaction, rv);
+		else if (!locked)
+			gck_transaction_fail (transaction, CKR_ATTRIBUTE_VALUE_INVALID);
+		else /* Not strictly correct, according to transaction semantics... */
+			gck_transaction_add (transaction, self, complete_lock, g_object_ref (session));
+		return;
+	}
+	
+	GCK_OBJECT_CLASS (gck_secret_object_parent_class)->set_attribute (base, session, transaction, attr);
+}
+
+static void
+gck_secret_object_init (GckSecretObject *self)
+{
+	self->pv = G_TYPE_INSTANCE_GET_PRIVATE (self, GCK_TYPE_SECRET_OBJECT, GckSecretObjectPrivate);
+}
+
+static GObject* 
+gck_secret_object_constructor (GType type, guint n_props, GObjectConstructParam *props) 
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (G_OBJECT_CLASS (gck_secret_object_parent_class)->constructor(type, n_props, props));
+	g_return_val_if_fail (self, NULL);	
+
+	return G_OBJECT (self);
+}
+
+static void
+gck_secret_object_set_property (GObject *obj, guint prop_id, const GValue *value, 
+                                GParamSpec *pspec)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
+	
+	switch (prop_id) {
+	case PROP_LABEL:
+		gck_secret_object_set_label (self, g_value_get_string (value));
+		break;
+	case PROP_IDENTIFIER:
+		g_return_if_fail (!self->pv->identifier);
+		self->pv->identifier = g_value_dup_string (value);
+		g_return_if_fail (self->pv->identifier);
+		break;
+	case PROP_CREATED:
+		g_return_if_fail (!self->pv->created);
+		self->pv->created = g_value_get_long (value);
+		g_return_if_fail (self->pv->created);
+		break;
+	case PROP_MODIFIED:
+		g_return_if_fail (!self->pv->modified);
+		self->pv->modified = g_value_get_long (value);
+		g_return_if_fail (self->pv->modified);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_object_get_property (GObject *obj, guint prop_id, GValue *value, 
+                                    GParamSpec *pspec)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
+	
+	switch (prop_id) {
+	case PROP_LABEL:
+		g_value_set_string (value, gck_secret_object_get_label (self));
+		break;
+	case PROP_IDENTIFIER:
+		g_value_set_string (value, gck_secret_object_get_identifier (self));
+		break;
+	case PROP_CREATED:
+		g_value_set_long (value, gck_secret_object_get_created (self));
+		break;
+	case PROP_MODIFIED:
+		g_value_set_long (value, gck_secret_object_get_modified (self));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+gck_secret_object_dispose (GObject *obj)
+{
+	/* GckSecretObject *self = GCK_SECRET_OBJECT (obj); */
+	G_OBJECT_CLASS (gck_secret_object_parent_class)->dispose (obj);
+}
+
+static void
+gck_secret_object_finalize (GObject *obj)
+{
+	GckSecretObject *self = GCK_SECRET_OBJECT (obj);
+
+	g_free (self->pv->identifier);
+	self->pv->identifier = NULL;
+	
+	g_free (self->pv->label);
+	self->pv->label = NULL;
+	
+	self->pv->created = 0;
+	self->pv->modified = 0;
+
+	G_OBJECT_CLASS (gck_secret_object_parent_class)->finalize (obj);
+}
+
+static void
+gck_secret_object_class_init (GckSecretObjectClass *klass)
+{
+	GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+	GckObjectClass *gck_class = GCK_OBJECT_CLASS (klass);
+
+	gck_secret_object_parent_class = g_type_class_peek_parent (klass);
+	g_type_class_add_private (klass, sizeof (GckSecretObjectPrivate));
+
+	gobject_class->constructor = gck_secret_object_constructor;
+	gobject_class->dispose = gck_secret_object_dispose;
+	gobject_class->finalize = gck_secret_object_finalize;
+	gobject_class->set_property = gck_secret_object_set_property;
+	gobject_class->get_property = gck_secret_object_get_property;
+
+	gck_class->get_attribute = gck_secret_object_get_attribute;
+	gck_class->set_attribute = gck_secret_object_set_attribute;
+	
+	g_object_class_install_property (gobject_class, PROP_IDENTIFIER,
+	           g_param_spec_string ("identifier", "Identifier", "Object Identifier", 
+	                                "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+	
+	g_object_class_install_property (gobject_class, PROP_LABEL,
+	           g_param_spec_string ("label", "Label", "Object Label", 
+	                                "", G_PARAM_READWRITE));
+	
+	g_object_class_install_property (gobject_class, PROP_CREATED,
+	           g_param_spec_long ("created", "Created", "Object Create Time",
+	                              0, G_MAXLONG, 0, G_PARAM_READABLE));
+	
+	g_object_class_install_property (gobject_class, PROP_MODIFIED,
+	           g_param_spec_long ("modified", "Modified", "Object Modify Time",
+	                              0, G_MAXLONG, 0, G_PARAM_READABLE));
+}
+
+/* -----------------------------------------------------------------------------
+ * PUBLIC 
+ */
+
+const gchar*
+gck_secret_object_get_identifier (GckSecretObject *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), NULL);
+	return self->pv->identifier;
+}
+
+const gchar*
+gck_secret_object_get_label (GckSecretObject *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), NULL);
+	return self->pv->label;	
+}
+
+glong
+gck_secret_object_get_created (GckSecretObject *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), 0);
+	return self->pv->created;		
+}
+
+glong
+gck_secret_object_get_modified (GckSecretObject *self)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), 0);
+	return self->pv->modified;
+}
+
+gboolean
+gck_secret_object_is_locked (GckSecretObject *self, GckSession *session)
+{
+	g_return_val_if_fail (GCK_IS_SECRET_OBJECT (self), TRUE);
+	g_return_val_if_fail (GCK_SECRET_OBJECT_GET_CLASS (self)->is_locked, TRUE);
+	return GCK_SECRET_OBJECT_GET_CLASS (self)->is_locked (self, session);
+}
+
+void
+gck_secret_object_lock (GckSecretObject *self, GckSession *session)
+{
+	g_return_if_fail (GCK_IS_SECRET_OBJECT (self));
+	g_return_if_fail (GCK_SECRET_OBJECT_GET_CLASS (self)->lock);
+	GCK_SECRET_OBJECT_GET_CLASS (self)->lock (self, session);	
+}
diff --git a/pkcs11/secret-store/gck-secret-object.h b/pkcs11/secret-store/gck-secret-object.h
new file mode 100644
index 0000000..9ec9a8f
--- /dev/null
+++ b/pkcs11/secret-store/gck-secret-object.h
@@ -0,0 +1,73 @@
+/* 
+ * gnome-keyring
+ * 
+ * Copyright (C) 2009 Stefan Walter
+ * 
+ * This program is free software; you can redistribute it and/or modify 
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *  
+ * This program 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
+ * Lesser General Public License for more details.
+ *  
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.  
+ */
+
+#ifndef __GCK_SECRET_OBJECT_H__
+#define __GCK_SECRET_OBJECT_H__
+
+#include <glib-object.h>
+
+#include "gck/gck-object.h"
+
+#define GCK_TYPE_SECRET_OBJECT               (gck_secret_object_get_type ())
+#define GCK_SECRET_OBJECT(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCK_TYPE_SECRET_OBJECT, GckSecretObject))
+#define GCK_SECRET_OBJECT_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GCK_TYPE_SECRET_OBJECT, GckSecretObjectClass))
+#define GCK_IS_SECRET_OBJECT(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCK_TYPE_SECRET_OBJECT))
+#define GCK_IS_SECRET_OBJECT_CLASS(klass)    (G_TYPE_CHECK_CLASS_TYPE ((klass), GCK_TYPE_SECRET_OBJECT))
+#define GCK_SECRET_OBJECT_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GCK_TYPE_SECRET_OBJECT, GckSecretObjectClass))
+
+typedef struct _GckSecretObject GckSecretObject;
+typedef struct _GckSecretObjectClass GckSecretObjectClass;
+typedef struct _GckSecretObjectPrivate GckSecretObjectPrivate;
+
+struct _GckSecretObject {
+	GckObject parent;
+	GckSecretObjectPrivate *pv;
+};
+struct _GckSecretObjectClass {
+	GckObjectClass parent_class;
+	
+	CK_RV (*lock) (GckSecretObject *self, GckSession *session);
+
+	gboolean (*is_locked) (GckSecretObject *self, GckSession *session);
+};
+
+GType                gck_secret_object_get_type        (void);
+
+const gchar*         gck_secret_object_get_identifier  (GckSecretObject *self);
+
+const gchar*         gck_secret_object_get_label       (GckSecretObject *self);
+
+void                 gck_secret_object_set_label       (GckSecretObject *self,
+                                                        const gchar *label);
+
+glong                gck_secret_object_get_created     (GckSecretObject *self);
+
+glong                gck_secret_object_get_modified    (GckSecretObject *self);
+
+void                 gck_secret_object_was_modified    (GckSecretObject *self);
+
+gboolean             gck_secret_object_is_locked       (GckSecretObject *self,
+                                                        GckSession *session);
+
+void                 gck_secret_object_lock            (GckSecretObject *self,
+                                                        GckSession *session);
+
+#endif /* __GCK_SECRET_OBJECT_H__ */



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