[gnome-keyring/dbus-api] [secrets] Implement some smaller bits of secrets-store.
- From: Stefan Walter <stefw src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-keyring/dbus-api] [secrets] Implement some smaller bits of secrets-store.
- Date: Mon, 27 Jul 2009 15:13:35 +0000 (UTC)
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]