[seahorse] pkcs11: Initial support for listing (but not showing) private keys
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [seahorse] pkcs11: Initial support for listing (but not showing) private keys
- Date: Thu, 3 Nov 2011 07:03:44 +0000 (UTC)
commit a74369551cb929d7792127792c90d39bd2dc4200
Author: Stef Walter <stefw collabora co uk>
Date: Thu Nov 3 08:03:19 2011 +0100
pkcs11: Initial support for listing (but not showing) private keys
pkcs11/Makefile.am | 1 +
pkcs11/seahorse-private-key.c | 170 +++++++++++++++++++++++++++++++++++++++++
pkcs11/seahorse-private-key.h | 51 ++++++++++++
pkcs11/seahorse-token.c | 163 ++++++++++++++++++++++++++++++++--------
pkcs11/seahorse-token.h | 5 +
5 files changed, 359 insertions(+), 31 deletions(-)
---
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index 261fb94..c9ab464 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -23,6 +23,7 @@ libseahorse_pkcs11_la_SOURCES = \
seahorse-pkcs11-helpers.c seahorse-pkcs11-helpers.h \
seahorse-pkcs11-operations.c seahorse-pkcs11-operations.h \
seahorse-pkcs11.c seahorse-pkcs11.h \
+ seahorse-private-key.c seahorse-private-key.h \
seahorse-token.c seahorse-token.h
libseahorse_pkcs11_la_LIBADD = \
diff --git a/pkcs11/seahorse-private-key.c b/pkcs11/seahorse-private-key.c
new file mode 100644
index 0000000..58e0aeb
--- /dev/null
+++ b/pkcs11/seahorse-private-key.c
@@ -0,0 +1,170 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 Stefan Walter
+ * Copyright (C) 2011 Collabora Ltd.
+ *
+ * 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 "seahorse-private-key.h"
+#include "seahorse-pkcs11.h"
+#include "seahorse-pkcs11-actions.h"
+#include "seahorse-pkcs11-helpers.h"
+#include "seahorse-token.h"
+#include "seahorse-types.h"
+
+#include "seahorse-util.h"
+
+#include <gcr/gcr.h>
+#include <gck/pkcs11.h>
+
+#include <glib/gi18n-lib.h>
+
+static const gulong REQUIRED_ATTRS[] = {
+ CKA_MODULUS_BITS,
+ CKA_ID,
+ CKA_ID,
+ CKA_LABEL,
+ CKA_CLASS,
+ CKA_KEY_TYPE,
+};
+
+enum {
+ PROP_0,
+ PROP_PLACE,
+ PROP_ATTRIBUTES,
+ PROP_FLAGS,
+ PROP_ACTIONS
+};
+
+struct _SeahorsePrivateKeyPrivate {
+ SeahorseToken *token;
+ GckAttributes *attributes;
+ GtkActionGroup *actions;
+};
+
+static void seahorse_private_key_object_attributes_iface (GckObjectAttributesIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (SeahorsePrivateKey, seahorse_private_key, GCK_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GCK_TYPE_OBJECT_ATTRIBUTES, seahorse_private_key_object_attributes_iface)
+);
+
+static void
+seahorse_private_key_init (SeahorsePrivateKey *self)
+{
+ self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKeyPrivate));
+ self->pv->actions = seahorse_pkcs11_object_actions_instance ();
+}
+
+static void
+seahorse_private_key_finalize (GObject *obj)
+{
+ SeahorsePrivateKey *self = SEAHORSE_PRIVATE_KEY (obj);
+
+ g_clear_object (&self->pv->actions);
+
+ if (self->pv->attributes)
+ gck_attributes_unref (self->pv->attributes);
+
+ G_OBJECT_CLASS (seahorse_private_key_parent_class)->finalize (obj);
+}
+
+static void
+seahorse_private_key_get_property (GObject *obj,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorsePrivateKey *self = SEAHORSE_PRIVATE_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_PLACE:
+ g_value_set_object (value, self->pv->token);
+ break;
+ case PROP_ATTRIBUTES:
+ g_value_set_boxed (value, self->pv->attributes);
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, SEAHORSE_FLAG_PERSONAL);
+ break;
+ case PROP_ACTIONS:
+ g_value_set_object (value, self->pv->actions);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_private_key_set_property (GObject *obj,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorsePrivateKey *self = SEAHORSE_PRIVATE_KEY (obj);
+
+ switch (prop_id) {
+ case PROP_PLACE:
+ g_return_if_fail (self->pv->token == NULL);
+ self->pv->token = g_value_dup_object (value);
+ break;
+ case PROP_ATTRIBUTES:
+ if (self->pv->attributes)
+ gck_attributes_unref (self->pv->attributes);
+ self->pv->attributes = g_value_dup_boxed (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_private_key_class_init (SeahorsePrivateKeyClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (SeahorsePrivateKeyPrivate));
+
+ gobject_class->finalize = seahorse_private_key_finalize;
+ gobject_class->set_property = seahorse_private_key_set_property;
+ gobject_class->get_property = seahorse_private_key_get_property;
+
+ g_object_class_install_property (gobject_class, PROP_PLACE,
+ g_param_spec_object ("place", "place", "place", SEAHORSE_TYPE_TOKEN,
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_FLAGS,
+ g_param_spec_flags ("flags", "flags", "flags", SEAHORSE_TYPE_FLAGS, SEAHORSE_FLAG_NONE,
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_ACTIONS,
+ g_param_spec_object ("actions", "Actions", "Actions", GTK_TYPE_ACTION_GROUP,
+ G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
+
+ g_object_class_override_property (gobject_class, PROP_ATTRIBUTES, "attributes");
+}
+
+static void
+seahorse_private_key_object_attributes_iface (GckObjectAttributesIface *iface)
+{
+ iface->attribute_types = REQUIRED_ATTRS;
+ iface->n_attribute_types = G_N_ELEMENTS (REQUIRED_ATTRS);
+}
diff --git a/pkcs11/seahorse-private-key.h b/pkcs11/seahorse-private-key.h
new file mode 100644
index 0000000..b15d4c4
--- /dev/null
+++ b/pkcs11/seahorse-private-key.h
@@ -0,0 +1,51 @@
+/*
+ * Seahorse
+ *
+ * Copyright (C) 2008 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 __SEAHORSE_PRIVATE_KEY_H__
+#define __SEAHORSE_PRIVATE_KEY_H__
+
+#include <gck/gck.h>
+
+#include <glib-object.h>
+
+#define SEAHORSE_TYPE_PRIVATE_KEY (seahorse_private_key_get_type ())
+#define SEAHORSE_PRIVATE_KEY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKey))
+#define SEAHORSE_PRIVATE_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKeyClass))
+#define SEAHORSE_IS_PRIVATE_KEY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PRIVATE_KEY))
+#define SEAHORSE_IS_PRIVATE_KEY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PRIVATE_KEY))
+#define SEAHORSE_PRIVATE_KEY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PRIVATE_KEY, SeahorsePrivateKeyClass))
+
+typedef struct _SeahorsePrivateKey SeahorsePrivateKey;
+typedef struct _SeahorsePrivateKeyClass SeahorsePrivateKeyClass;
+typedef struct _SeahorsePrivateKeyPrivate SeahorsePrivateKeyPrivate;
+
+struct _SeahorsePrivateKey {
+ GckObject parent;
+ SeahorsePrivateKeyPrivate *pv;
+};
+
+struct _SeahorsePrivateKeyClass {
+ GckObjectClass parent_class;
+};
+
+GType seahorse_private_key_get_type (void) G_GNUC_CONST;
+
+#endif /* __SEAHORSE_PRIVATE_KEY_H__ */
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index f0e0d46..1e98d49 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -33,6 +33,7 @@
#include "seahorse-pkcs11-actions.h"
#include "seahorse-pkcs11-helpers.h"
#include "seahorse-pkcs11-operations.h"
+#include "seahorse-private-key.h"
#include "seahorse-token.h"
#include "seahorse-place.h"
@@ -50,7 +51,8 @@ enum {
PROP_ACTIONS,
PROP_INFO,
PROP_LOCKABLE,
- PROP_UNLOCKABLE
+ PROP_UNLOCKABLE,
+ PROP_SESSION
};
struct _SeahorseTokenPrivate {
@@ -79,12 +81,12 @@ typedef struct {
GCancellable *cancellable;
GHashTable *checks;
GckEnumerator *enumerator;
-} pkcs11_refresh_closure;
+} RefreshClosure;
static void
pkcs11_refresh_free (gpointer data)
{
- pkcs11_refresh_closure *closure = data;
+ RefreshClosure *closure = data;
g_object_unref (closure->token);
g_clear_object (&closure->cancellable);
g_hash_table_destroy (closure->checks);
@@ -109,7 +111,7 @@ on_refresh_next_objects (GObject *source,
gpointer user_data)
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
- pkcs11_refresh_closure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ RefreshClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
GError *error = NULL;
gulong handle;
GList *objects;
@@ -163,6 +165,71 @@ update_token_info (SeahorseToken *self)
}
}
+static void
+refresh_enumerate (GSimpleAsyncResult *res)
+{
+ RefreshClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GckSession *session;
+ GckEnumerator *enumerator;
+ GckAttributes *attrs;
+
+ session = seahorse_token_get_session (closure->token);
+
+ attrs = gck_attributes_new ();
+ gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+ gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
+ enumerator = gck_session_enumerate_objects (session, attrs);
+ gck_enumerator_set_object_type (enumerator, SEAHORSE_TYPE_CERTIFICATE);
+ closure->enumerator = enumerator;
+ gck_attributes_unref (attrs);
+
+ attrs = gck_attributes_new ();
+ gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+ gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_PRIVATE_KEY);
+ enumerator = gck_session_enumerate_objects (session, attrs);
+ gck_enumerator_set_object_type (enumerator, SEAHORSE_TYPE_PRIVATE_KEY);
+ gck_enumerator_set_chained (closure->enumerator, enumerator);
+ g_object_unref (enumerator);
+ gck_attributes_unref (attrs);
+
+ gck_enumerator_next_async (closure->enumerator, 16, closure->cancellable,
+ on_refresh_next_objects, g_object_ref (res));
+}
+
+static void
+on_refresh_session_open (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ RefreshClosure *closure = g_simple_async_result_get_op_res_gpointer (res);
+ GError *error = NULL;
+ GckSession *session;
+
+ session = gck_session_open_finish (result, &error);
+
+ if (error == NULL) {
+ seahorse_token_set_session (closure->token, session);
+ refresh_enumerate (res);
+ g_object_unref (session);
+ } else {
+ g_simple_async_result_take_error (res, error);
+ g_simple_async_result_complete (res);
+ }
+
+ g_object_unref (res);
+}
+
+static GckSessionOptions
+calculate_session_options (SeahorseToken *self)
+{
+ GckTokenInfo *info = seahorse_token_get_info (self);
+ if (info->flags & CKF_WRITE_PROTECTED)
+ return GCK_SESSION_READ_ONLY;
+ else
+ return GCK_SESSION_READ_WRITE;
+}
+
void
seahorse_token_refresh_async (SeahorseToken *self,
GCancellable *cancellable,
@@ -170,9 +237,8 @@ seahorse_token_refresh_async (SeahorseToken *self,
gpointer user_data)
{
GSimpleAsyncResult *res;
- pkcs11_refresh_closure *closure;
- GckAttributes *attrs;
- GckSlot *slot;
+ RefreshClosure *closure;
+ GckSessionOptions options;
GList *objects, *l;
gulong handle;
@@ -182,7 +248,7 @@ seahorse_token_refresh_async (SeahorseToken *self,
res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
seahorse_token_refresh_async);
- closure = g_new0 (pkcs11_refresh_closure, 1);
+ closure = g_new0 (RefreshClosure, 1);
closure->checks = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
seahorse_pkcs11_ulong_equal,
g_free, g_object_unref);
@@ -200,21 +266,13 @@ seahorse_token_refresh_async (SeahorseToken *self,
}
g_list_free (objects);
- attrs = gck_attributes_new ();
- gck_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
- gck_attributes_add_ulong (attrs, CKA_CLASS, CKO_CERTIFICATE);
-
- slot = seahorse_token_get_slot (closure->token);
- closure->enumerator = gck_slot_enumerate_objects (slot, attrs, GCK_SESSION_READ_WRITE);
- g_return_if_fail (closure->enumerator != NULL);
-
- gck_attributes_unref (attrs);
-
- /* This enumerator creates objects of type SeahorseCertificate */
- gck_enumerator_set_object_type (closure->enumerator, SEAHORSE_TYPE_CERTIFICATE);
-
- gck_enumerator_next_async (closure->enumerator, 16, closure->cancellable,
- on_refresh_next_objects, g_object_ref (res));
+ if (!self->pv->session) {
+ options = calculate_session_options (self);
+ gck_session_open_async (self->pv->slot, options, NULL, cancellable,
+ on_refresh_session_open, g_object_ref (res));
+ } else {
+ refresh_enumerate (res);
+ }
g_object_unref (res);
}
@@ -318,6 +376,9 @@ seahorse_token_get_property (GObject *object,
case PROP_UNLOCKABLE:
g_value_set_boolean (value, seahorse_token_get_unlockable (self));
break;
+ case PROP_SESSION:
+ g_value_set_object (value, seahorse_token_get_session (self));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -343,6 +404,9 @@ seahorse_token_set_property (GObject *object,
g_return_if_fail (!self->pv->info);
self->pv->info = g_value_dup_boxed (value);
break;
+ case PROP_SESSION:
+ seahorse_token_set_session (self, g_value_get_object (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -354,10 +418,8 @@ seahorse_token_dispose (GObject *obj)
{
SeahorseToken *self = SEAHORSE_TOKEN (obj);
- /* The keyring object */
- if (self->pv->slot)
- g_object_unref (self->pv->slot);
- self->pv->slot = NULL;
+ g_clear_object (&self->pv->slot);
+ g_clear_object (&self->pv->session);
G_OBJECT_CLASS (seahorse_token_parent_class)->dispose (obj);
}
@@ -413,6 +475,10 @@ seahorse_token_class_init (SeahorseTokenClass *klass)
g_object_class_install_property (gobject_class, PROP_UNLOCKABLE,
g_param_spec_boolean ("unlockable", "Unlockable", "Token can be unlocked",
FALSE, G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_SLOT,
+ g_param_spec_object ("session", "Session", "Pkcs#11 Session",
+ GCK_TYPE_SESSION, G_PARAM_READWRITE));
}
static void
@@ -476,6 +542,35 @@ seahorse_token_get_slot (SeahorseToken *self)
return self->pv->slot;
}
+GckSession *
+seahorse_token_get_session (SeahorseToken *self)
+{
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), NULL);
+ return self->pv->session;
+}
+
+void
+seahorse_token_set_session (SeahorseToken *self,
+ GckSession *session)
+{
+ GObject *obj;
+
+ g_return_if_fail (SEAHORSE_IS_TOKEN (self));
+ g_return_if_fail (session == NULL || GCK_IS_SESSION (session));
+
+ if (session)
+ g_object_ref (session);
+ g_clear_object (&self->pv->session);
+ self->pv->session = session;
+
+ obj = G_OBJECT (self);
+ g_object_freeze_notify (obj);
+ g_object_notify (obj, "session");
+ g_object_notify (obj, "lockable");
+ g_object_notify (obj, "unlockable");
+ g_object_thaw_notify (obj);
+}
+
GckTokenInfo *
seahorse_token_get_info (SeahorseToken *self)
{
@@ -676,13 +771,17 @@ on_session_login_open (GObject *source,
{
GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
SeahorseToken *self = SEAHORSE_TOKEN (g_async_result_get_source_object (user_data));
+ GckSession *session;
GError *error = NULL;
- self->pv->session = gck_session_open_finish (result, &error);
- if (error == NULL)
+ session = gck_session_open_finish (result, &error);
+ if (error == NULL) {
+ seahorse_token_set_session (self, session);
seahorse_token_refresh_async (self, NULL, NULL, NULL);
- else
+ g_object_unref (session);
+ } else {
g_simple_async_result_take_error (res, error);
+ }
g_simple_async_result_complete (res);
g_object_unref (self);
@@ -697,6 +796,7 @@ seahorse_token_unlock_async (SeahorseToken *self,
gpointer user_data)
{
GSimpleAsyncResult *res;
+ GckSessionOptions options;
g_return_if_fail (SEAHORSE_IS_TOKEN (self));
g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
@@ -713,7 +813,8 @@ seahorse_token_unlock_async (SeahorseToken *self,
interaction, NULL, on_login_interactive,
g_object_ref (res));
} else {
- gck_session_open_async (self->pv->slot, GCK_SESSION_LOGIN_USER, interaction,
+ options = calculate_session_options (self);
+ gck_session_open_async (self->pv->slot, options | GCK_SESSION_LOGIN_USER, interaction,
NULL, on_session_login_open, g_object_ref (res));
}
diff --git a/pkcs11/seahorse-token.h b/pkcs11/seahorse-token.h
index a33fe56..0bb7abe 100644
--- a/pkcs11/seahorse-token.h
+++ b/pkcs11/seahorse-token.h
@@ -53,6 +53,11 @@ GckTokenInfo * seahorse_token_get_info (SeahorseToken *self);
GckSlot * seahorse_token_get_slot (SeahorseToken *self);
+GckSession * seahorse_token_get_session (SeahorseToken *self);
+
+void seahorse_token_set_session (SeahorseToken *self,
+ GckSession *session);
+
gboolean seahorse_token_get_lockable (SeahorseToken *self);
gboolean seahorse_token_get_unlockable (SeahorseToken *self);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]