[seahorse] pkcs11: Implement locking and unlocking of tokens
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [seahorse] pkcs11: Implement locking and unlocking of tokens
- Date: Wed, 2 Nov 2011 09:06:38 +0000 (UTC)
commit 9993a5fa795e92c9be244d2bfc6baca850702ef6
Author: Stef Walter <stefw collabora co uk>
Date: Tue Oct 25 13:08:02 2011 +0200
pkcs11: Implement locking and unlocking of tokens
libseahorse/seahorse-passphrase.c | 6 +-
libseahorse/seahorse-passphrase.h | 2 +-
pgp/seahorse-gpgme-keyring.c | 2 +-
pkcs11/Makefile.am | 1 +
pkcs11/seahorse-certificate.c | 2 +-
pkcs11/seahorse-interaction.c | 194 ++++++++++++++++++++++++
pkcs11/seahorse-interaction.h | 59 ++++++++
pkcs11/seahorse-pkcs11-actions.c | 174 +++++++++++++++++++---
pkcs11/seahorse-pkcs11-actions.h | 4 +-
pkcs11/seahorse-token.c | 295 +++++++++++++++++++++++++++++++++++--
pkcs11/seahorse-token.h | 26 ++++
11 files changed, 728 insertions(+), 37 deletions(-)
---
diff --git a/libseahorse/seahorse-passphrase.c b/libseahorse/seahorse-passphrase.c
index 69fd44f..965ff3b 100644
--- a/libseahorse/seahorse-passphrase.c
+++ b/libseahorse/seahorse-passphrase.c
@@ -178,13 +178,10 @@ seahorse_passphrase_prompt_show (const gchar *title,
GtkWidget *chbox;
gchar *msg;
- if (!title)
- title = _("Passphrase");
-
if (!prompt)
prompt = _("Password:");
- widget = gtk_dialog_new_with_buttons (title, NULL, 0, NULL);
+ widget = gtk_dialog_new_with_buttons (title, NULL, GTK_DIALOG_MODAL, NULL);
gtk_window_set_icon_name (GTK_WINDOW (widget), GTK_STOCK_DIALOG_AUTHENTICATION);
dialog = GTK_DIALOG (widget);
@@ -285,7 +282,6 @@ seahorse_passphrase_prompt_show (const gchar *title,
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
- gtk_window_set_type_hint (GTK_WINDOW (dialog), GDK_WINDOW_TYPE_HINT_NORMAL);
gtk_window_set_keep_above (GTK_WINDOW (dialog), TRUE);
gtk_widget_show_all (GTK_WIDGET (dialog));
gdk_window_focus (gtk_widget_get_window (GTK_WIDGET (dialog)), GDK_CURRENT_TIME);
diff --git a/libseahorse/seahorse-passphrase.h b/libseahorse/seahorse-passphrase.h
index e394a77..34ad050 100644
--- a/libseahorse/seahorse-passphrase.h
+++ b/libseahorse/seahorse-passphrase.h
@@ -32,7 +32,7 @@ GtkDialog* seahorse_passphrase_prompt_show (const gchar *title,
const gchar *prompt,
const gchar *check,
gboolean confirm);
-
+
const gchar* seahorse_passphrase_prompt_get (GtkDialog *dialog);
gboolean seahorse_passphrase_prompt_checked (GtkDialog *dialog);
diff --git a/pgp/seahorse-gpgme-keyring.c b/pgp/seahorse-gpgme-keyring.c
index 11b2524..1f5de02 100644
--- a/pgp/seahorse-gpgme-keyring.c
+++ b/pgp/seahorse-gpgme-keyring.c
@@ -103,7 +103,7 @@ passphrase_get (gconstpointer dummy, const gchar *passphrase_hint,
g_strfreev (split_uid);
- dialog = seahorse_passphrase_prompt_show (NULL, errmsg ? errmsg : label,
+ dialog = seahorse_passphrase_prompt_show (_("Passphrase"), errmsg ? errmsg : label,
NULL, NULL, confirm);
g_free (label);
g_free (errmsg);
diff --git a/pkcs11/Makefile.am b/pkcs11/Makefile.am
index c37f4f9..261fb94 100644
--- a/pkcs11/Makefile.am
+++ b/pkcs11/Makefile.am
@@ -16,6 +16,7 @@ noinst_LTLIBRARIES = libseahorse-pkcs11.la
libseahorse_pkcs11_la_SOURCES = \
seahorse-certificate.c seahorse-certificate.h \
+ seahorse-interaction.c seahorse-interaction.h \
seahorse-pkcs11-actions.c seahorse-pkcs11-actions.h \
seahorse-pkcs11-backend.c seahorse-pkcs11-backend.h \
seahorse-pkcs11-certificate-props.c seahorse-pkcs11-certificate-props.h \
diff --git a/pkcs11/seahorse-certificate.c b/pkcs11/seahorse-certificate.c
index f0a7883..664daaa 100644
--- a/pkcs11/seahorse-certificate.c
+++ b/pkcs11/seahorse-certificate.c
@@ -72,7 +72,7 @@ static void
seahorse_certificate_init (SeahorseCertificate *self)
{
self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_CERTIFICATE, SeahorseCertificatePrivate));
- self->pv->actions = seahorse_pkcs11_actions_instance ();
+ self->pv->actions = seahorse_pkcs11_object_actions_instance ();
gck_attribute_init_invalid (&self->pv->der_value, CKA_VALUE);
}
diff --git a/pkcs11/seahorse-interaction.c b/pkcs11/seahorse-interaction.c
new file mode 100644
index 0000000..be8cb58
--- /dev/null
+++ b/pkcs11/seahorse-interaction.c
@@ -0,0 +1,194 @@
+/*
+ * 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-interaction.h"
+#include "seahorse-passphrase.h"
+
+#include <gnome-keyring-memory.h>
+
+#include <glib/gi18n.h>
+
+enum {
+ PROP_0,
+ PROP_PARENT
+};
+
+struct _SeahorseInteractionPrivate {
+ GtkWindow *parent;
+};
+
+G_DEFINE_TYPE (SeahorseInteraction, seahorse_interaction, G_TYPE_TLS_INTERACTION);
+
+static void
+seahorse_interaction_init (SeahorseInteraction *self)
+{
+ self->pv = (G_TYPE_INSTANCE_GET_PRIVATE (self, SEAHORSE_TYPE_INTERACTION,
+ SeahorseInteractionPrivate));
+}
+
+static void
+seahorse_interaction_set_property (GObject *obj,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseInteraction *self = SEAHORSE_INTERACTION (obj);
+
+ switch (prop_id) {
+ case PROP_PARENT:
+ seahorse_interaction_set_parent (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_interaction_get_property (GObject *obj,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SeahorseInteraction *self = SEAHORSE_INTERACTION (obj);
+
+ switch (prop_id) {
+ case PROP_PARENT:
+ g_value_set_object (value, seahorse_interaction_get_parent (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+seahorse_interaction_dispose (GObject *obj)
+{
+ SeahorseInteraction *self = SEAHORSE_INTERACTION (obj);
+
+ seahorse_interaction_set_parent (self, NULL);
+
+ G_OBJECT_CLASS (seahorse_interaction_parent_class)->dispose (obj);
+}
+
+static gchar *
+calc_description (GTlsPassword *password)
+{
+ const gchar *description = g_tls_password_get_description (password);
+ return g_strdup_printf (_("Enter PIN or password for: %s"), description);
+}
+
+static GTlsInteractionResult
+seahorse_interaction_ask_password (GTlsInteraction *interaction,
+ GTlsPassword *password,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SeahorseInteraction *self = SEAHORSE_INTERACTION (interaction);
+ GTlsInteractionResult res;
+ GtkDialog *dialog;
+ gchar *description;
+ const gchar *pass;
+ gsize length;
+
+ description = calc_description (password);
+
+ dialog = seahorse_passphrase_prompt_show (NULL, description, NULL, NULL, FALSE);
+
+ g_free (description);
+
+ if (self->pv->parent)
+ gtk_window_set_transient_for (GTK_WINDOW (dialog), self->pv->parent);
+
+ switch (gtk_dialog_run (dialog)) {
+ case GTK_RESPONSE_ACCEPT:
+ pass = seahorse_passphrase_prompt_get (dialog);
+ length = strlen (pass);
+ g_tls_password_set_value_full (password,
+ (guchar *)gnome_keyring_memory_strdup (pass),
+ length, gnome_keyring_memory_free);
+ res = G_TLS_INTERACTION_HANDLED;
+ break;
+ default:
+ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
+ "The password request was cancelled by the user");
+ res = G_TLS_INTERACTION_FAILED;
+ break;
+ };
+
+ gtk_widget_destroy (GTK_WIDGET (dialog));
+ return res;
+}
+
+static void
+seahorse_interaction_class_init (SeahorseInteractionClass *klass)
+{
+ GTlsInteractionClass *interaction_class = G_TLS_INTERACTION_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = seahorse_interaction_get_property;
+ object_class->set_property = seahorse_interaction_set_property;
+ object_class->dispose = seahorse_interaction_dispose;
+
+ interaction_class->ask_password = seahorse_interaction_ask_password;
+
+ g_object_class_install_property (object_class, PROP_PARENT,
+ g_param_spec_object ("parent", "Parent", "Parent window",
+ GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_type_class_add_private (klass, sizeof (SeahorseInteractionPrivate));
+}
+
+GTlsInteraction *
+seahorse_interaction_new (GtkWindow *parent)
+{
+ return g_object_new (SEAHORSE_TYPE_INTERACTION,
+ "parent", parent,
+ NULL);
+}
+
+GtkWindow *
+seahorse_interaction_get_parent (SeahorseInteraction *self)
+{
+ g_return_val_if_fail (SEAHORSE_IS_INTERACTION (self), NULL);
+ return self->pv->parent;
+}
+
+void
+seahorse_interaction_set_parent (SeahorseInteraction *self,
+ GtkWindow *parent)
+{
+ g_return_if_fail (SEAHORSE_IS_INTERACTION (self));
+ g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
+
+ if (self->pv->parent)
+ g_object_remove_weak_pointer (G_OBJECT (self->pv->parent),
+ (gpointer *)&self->pv->parent);
+ self->pv->parent = parent;
+ if (self->pv->parent)
+ g_object_add_weak_pointer (G_OBJECT (self->pv->parent),
+ (gpointer *)&self->pv->parent);
+ g_object_notify (G_OBJECT (self), "parent");
+}
diff --git a/pkcs11/seahorse-interaction.h b/pkcs11/seahorse-interaction.h
new file mode 100644
index 0000000..54209ee
--- /dev/null
+++ b/pkcs11/seahorse-interaction.h
@@ -0,0 +1,59 @@
+/*
+ * Seahorse
+ *
+ * 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.
+ */
+
+#ifndef __SEAHORSE_INTERACTION_H__
+#define __SEAHORSE_INTERACTION_H__
+
+#include <gtk/gtk.h>
+
+#include "seahorse-object.h"
+#include "seahorse-viewer.h"
+
+#define SEAHORSE_TYPE_INTERACTION (seahorse_interaction_get_type ())
+#define SEAHORSE_INTERACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_INTERACTION, SeahorseInteraction))
+#define SEAHORSE_INTERACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_INTERACTION, SeahorseInteractionClass))
+#define SEAHORSE_IS_INTERACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_INTERACTION))
+#define SEAHORSE_IS_INTERACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_INTERACTION))
+#define SEAHORSE_INTERACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_INTERACTION, SeahorseInteractionClass))
+
+typedef struct _SeahorseInteraction SeahorseInteraction;
+typedef struct _SeahorseInteractionClass SeahorseInteractionClass;
+typedef struct _SeahorseInteractionPrivate SeahorseInteractionPrivate;
+
+struct _SeahorseInteraction {
+ GTlsInteraction parent_instance;
+ SeahorseInteractionPrivate *pv;
+};
+
+struct _SeahorseInteractionClass {
+ GTlsInteractionClass parent_class;
+};
+
+GType seahorse_interaction_get_type (void);
+
+GTlsInteraction * seahorse_interaction_new (GtkWindow *parent);
+
+GtkWindow * seahorse_interaction_get_parent (SeahorseInteraction *self);
+
+void seahorse_interaction_set_parent (SeahorseInteraction *self,
+ GtkWindow *parent);
+
+#endif
diff --git a/pkcs11/seahorse-pkcs11-actions.c b/pkcs11/seahorse-pkcs11-actions.c
index 160080f..a5a0bec 100644
--- a/pkcs11/seahorse-pkcs11-actions.c
+++ b/pkcs11/seahorse-pkcs11-actions.c
@@ -25,9 +25,11 @@
#include "seahorse-pkcs11-actions.h"
#include "seahorse-certificate.h"
+#include "seahorse-interaction.h"
#include "seahorse-pkcs11.h"
#include "seahorse-pkcs11-certificate-props.h"
#include "seahorse-pkcs11-operations.h"
+#include "seahorse-token.h"
#include "seahorse-action.h"
#include "seahorse-actions.h"
@@ -36,25 +38,161 @@
#include "seahorse-registry.h"
#include "seahorse-util.h"
-GType seahorse_pkcs11_actions_get_type (void) G_GNUC_CONST;
-#define SEAHORSE_TYPE_PKCS11_ACTIONS (seahorse_pkcs11_actions_get_type ())
-#define SEAHORSE_PKCS11_ACTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_ACTIONS, SeahorsePkcs11Actions))
-#define SEAHORSE_PKCS11_ACTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SEAHORSE_TYPE_PKCS11_ACTIONS, SeahorsePkcs11ActionsClass))
-#define SEAHORSE_PKCS11_IS_ACTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_ACTIONS))
-#define SEAHORSE_PKCS11_IS_ACTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SEAHORSE_TYPE_PKCS11_ACTIONS))
-#define SEAHORSE_PKCS11_ACTIONS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SEAHORSE_TYPE_PKCS11_ACTIONS, SeahorsePkcs11ActionsClass))
+GType seahorse_pkcs11_token_actions_get_type (void) G_GNUC_CONST;
+#define SEAHORSE_TYPE_PKCS11_TOKEN_ACTIONS (seahorse_pkcs11_token_actions_get_type ())
+#define SEAHORSE_PKCS11_TOKEN_ACTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_TOKEN_ACTIONS, SeahorsePkcs11TokenActions))
+#define SEAHORSE_PKCS11_IS_ACTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_TOKEN_ACTIONS))
typedef struct {
SeahorseActions parent;
-} SeahorsePkcs11Actions;
+} SeahorsePkcs11TokenActions;
typedef struct {
SeahorseActionsClass parent_class;
-} SeahorsePkcs11ActionsClass;
+} SeahorsePkcs11TokenActionsClass;
+
+G_DEFINE_TYPE (SeahorsePkcs11TokenActions, seahorse_pkcs11_token_actions, SEAHORSE_TYPE_ACTIONS);
+
+static void
+on_token_locked (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ seahorse_token_lock_finish (SEAHORSE_TOKEN (source), result, &error);
+ if (error != NULL) {
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("couldn't unlock token: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+on_token_lock (GtkAction *action,
+ gpointer user_data)
+{
+ GTlsInteraction *interaction;
+
+ interaction = seahorse_interaction_new (seahorse_action_get_window (action));
+ seahorse_token_lock_async (SEAHORSE_TOKEN (user_data), interaction, NULL,
+ on_token_locked, NULL);
+ g_object_unref (interaction);
+}
+
+
+static void
+on_token_unlocked (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ seahorse_token_unlock_finish (SEAHORSE_TOKEN (source), result, &error);
+ if (error != NULL) {
+ if (!g_error_matches (error, GCK_ERROR, CKR_FUNCTION_CANCELED))
+ g_warning ("couldn't unlock token: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+on_token_unlock (GtkAction *action,
+ gpointer user_data)
+{
+ GTlsInteraction *interaction;
+ GtkWindow *window;
+
+ window = seahorse_action_get_window (action);
+ interaction = seahorse_interaction_new (window);
+
+ seahorse_token_unlock_async (SEAHORSE_TOKEN (user_data), interaction, NULL,
+ on_token_unlocked, NULL);
+
+ g_object_unref (interaction);
+}
+
+static const GtkActionEntry TOKEN_ACTIONS[] = {
+ { "lock", NULL, NULL, NULL,
+ N_("Lock this token"), G_CALLBACK (on_token_lock) },
+ { "unlock", NULL, NULL, NULL,
+ N_("Unlock this token"), G_CALLBACK (on_token_unlock) },
+};
+
+static void
+seahorse_pkcs11_token_actions_init (SeahorsePkcs11TokenActions *self)
+{
+
+}
+
+static GtkActionGroup *
+seahorse_pkcs11_token_actions_clone_for_objects (SeahorseActions *actions,
+ GList *objects)
+{
+ GtkActionGroup *cloned;
+
+ g_return_val_if_fail (objects != NULL, NULL);
+
+ cloned = gtk_action_group_new ("Pkcs11Token");
+
+ if (!objects->next) {
+ gtk_action_group_add_actions_full (cloned, TOKEN_ACTIONS,
+ G_N_ELEMENTS (TOKEN_ACTIONS),
+ g_object_ref (objects->data),
+ g_object_unref);
+
+ g_object_bind_property (objects->data, "lockable",
+ gtk_action_group_get_action (cloned, "lock"), "sensitive",
+ G_BINDING_SYNC_CREATE);
+ g_object_bind_property (objects->data, "unlockable",
+ gtk_action_group_get_action (cloned, "unlock"), "sensitive",
+ G_BINDING_SYNC_CREATE);
+ }
+
+ return cloned;
+}
+
+static void
+seahorse_pkcs11_token_actions_class_init (SeahorsePkcs11TokenActionsClass *klass)
+{
+ SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
+ actions_class->clone_for_objects = seahorse_pkcs11_token_actions_clone_for_objects;
+}
+
+GtkActionGroup *
+seahorse_pkcs11_token_actions_instance (void)
+{
+ static GtkActionGroup *actions = NULL;
+
+ if (actions == NULL) {
+ actions = g_object_new (SEAHORSE_TYPE_PKCS11_TOKEN_ACTIONS,
+ "name", "Pkcs11Token",
+ NULL);
+ g_object_add_weak_pointer (G_OBJECT (actions),
+ (gpointer *)&actions);
+ } else {
+ g_object_ref (actions);
+ }
+
+ return actions;
+}
+
+GType seahorse_pkcs11_object_actions_get_type (void) G_GNUC_CONST;
+#define SEAHORSE_TYPE_PKCS11_OBJECT_ACTIONS (seahorse_pkcs11_object_actions_get_type ())
+#define SEAHORSE_PKCS11_OBJECT_ACTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SEAHORSE_TYPE_PKCS11_OBJECT_ACTIONS, SeahorsePkcs11ObjectActions))
+#define SEAHORSE_PKCS11_IS_OBJECT_ACTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SEAHORSE_TYPE_PKCS11_OBJECT_ACTIONS))
+
+typedef struct {
+ SeahorseActions parent;
+} SeahorsePkcs11ObjectActions;
+
+typedef struct {
+ SeahorseActionsClass parent_class;
+} SeahorsePkcs11ObjectActionsClass;
static GQuark QUARK_WINDOW = 0;
-G_DEFINE_TYPE (SeahorsePkcs11Actions, seahorse_pkcs11_actions, SEAHORSE_TYPE_ACTIONS);
+G_DEFINE_TYPE (SeahorsePkcs11ObjectActions, seahorse_pkcs11_object_actions, SEAHORSE_TYPE_ACTIONS);
static void
properties_response (GtkDialog *dialog, gint response_id, gpointer user_data)
@@ -157,20 +295,20 @@ static const GtkActionEntry CERTIFICATES_ACTIONS[] = {
};
static void
-seahorse_pkcs11_actions_init (SeahorsePkcs11Actions *self)
+seahorse_pkcs11_object_actions_init (SeahorsePkcs11ObjectActions *self)
{
}
static GtkActionGroup *
-seahorse_pkcs11_actions_clone_for_objects (SeahorseActions *actions,
+seahorse_pkcs11_object_actions_clone_for_objects (SeahorseActions *actions,
GList *objects)
{
GtkActionGroup *cloned;
g_return_val_if_fail (objects != NULL, NULL);
- cloned = gtk_action_group_new ("Certificate");
+ cloned = gtk_action_group_new ("Pkcs11Object");
gtk_action_group_set_translation_domain (cloned, GETTEXT_PACKAGE);
gtk_action_group_add_actions_full (cloned, CERTIFICATES_ACTIONS,
G_N_ELEMENTS (CERTIFICATES_ACTIONS),
@@ -188,21 +326,21 @@ seahorse_pkcs11_actions_clone_for_objects (SeahorseActions *actions,
}
static void
-seahorse_pkcs11_actions_class_init (SeahorsePkcs11ActionsClass *klass)
+seahorse_pkcs11_object_actions_class_init (SeahorsePkcs11ObjectActionsClass *klass)
{
SeahorseActionsClass *actions_class = SEAHORSE_ACTIONS_CLASS (klass);
QUARK_WINDOW = g_quark_from_static_string ("seahorse-pkcs11-actions-window");
- actions_class->clone_for_objects = seahorse_pkcs11_actions_clone_for_objects;
+ actions_class->clone_for_objects = seahorse_pkcs11_object_actions_clone_for_objects;
}
GtkActionGroup *
-seahorse_pkcs11_actions_instance (void)
+seahorse_pkcs11_object_actions_instance (void)
{
static GtkActionGroup *actions = NULL;
if (actions == NULL) {
- actions = g_object_new (SEAHORSE_TYPE_PKCS11_ACTIONS,
- "name", "Certificate",
+ actions = g_object_new (SEAHORSE_TYPE_PKCS11_OBJECT_ACTIONS,
+ "name", "Pkcs11Object",
NULL);
g_object_add_weak_pointer (G_OBJECT (actions),
(gpointer *)&actions);
diff --git a/pkcs11/seahorse-pkcs11-actions.h b/pkcs11/seahorse-pkcs11-actions.h
index fd50dc3..9f94e16 100644
--- a/pkcs11/seahorse-pkcs11-actions.h
+++ b/pkcs11/seahorse-pkcs11-actions.h
@@ -24,6 +24,8 @@
#include <gtk/gtk.h>
-GtkActionGroup * seahorse_pkcs11_actions_instance (void);
+GtkActionGroup * seahorse_pkcs11_token_actions_instance (void);
+
+GtkActionGroup * seahorse_pkcs11_object_actions_instance (void);
#endif /* __SEAHORSE_PKCS11_ACTIONS_H__ */
diff --git a/pkcs11/seahorse-token.c b/pkcs11/seahorse-token.c
index 9a1f4de..f0e0d46 100644
--- a/pkcs11/seahorse-token.c
+++ b/pkcs11/seahorse-token.c
@@ -30,6 +30,7 @@
#include "seahorse-certificate.h"
#include "seahorse-pkcs11.h"
+#include "seahorse-pkcs11-actions.h"
#include "seahorse-pkcs11-helpers.h"
#include "seahorse-pkcs11-operations.h"
#include "seahorse-token.h"
@@ -46,13 +47,19 @@ enum {
PROP_SLOT,
PROP_FLAGS,
PROP_URI,
- PROP_ACTIONS
+ PROP_ACTIONS,
+ PROP_INFO,
+ PROP_LOCKABLE,
+ PROP_UNLOCKABLE
};
struct _SeahorseTokenPrivate {
GckSlot *slot;
gchar *uri;
GHashTable *objects;
+ GckTokenInfo *info;
+ GckSession *session;
+ GtkActionGroup *actions;
};
static void receive_object (SeahorseToken *self,
@@ -67,7 +74,6 @@ G_DEFINE_TYPE_EXTENDED (SeahorseToken, seahorse_token, G_TYPE_OBJECT, 0,
G_IMPLEMENT_INTERFACE (SEAHORSE_TYPE_PLACE, seahorse_token_place_iface);
);
-
typedef struct {
SeahorseToken *token;
GCancellable *cancellable;
@@ -139,8 +145,26 @@ on_refresh_next_objects (GObject *source,
g_object_unref (res);
}
+static void
+update_token_info (SeahorseToken *self)
+{
+ GckTokenInfo *info;
+ GObject *obj;
+
+ info = gck_slot_get_token_info (self->pv->slot);
+ if (info != NULL) {
+ gck_token_info_free (self->pv->info);
+ self->pv->info = info;
+
+ obj = G_OBJECT (self);
+ g_object_notify (obj, "info");
+ g_object_notify (obj, "lockable");
+ g_object_notify (obj, "unlockable");
+ }
+}
+
void
-seahorse_token_refresh_async (SeahorseToken *token,
+seahorse_token_refresh_async (SeahorseToken *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -152,18 +176,22 @@ seahorse_token_refresh_async (SeahorseToken *token,
GList *objects, *l;
gulong handle;
- res = g_simple_async_result_new (G_OBJECT (token), callback, user_data,
+ g_return_if_fail (SEAHORSE_IS_TOKEN (self));
+
+ update_token_info (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->checks = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
seahorse_pkcs11_ulong_equal,
g_free, g_object_unref);
- closure->token = g_object_ref (token);
+ closure->token = g_object_ref (self);
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, closure, pkcs11_refresh_free);
/* Make note of all the objects that were there */
- objects = gcr_collection_get_objects (GCR_COLLECTION (token));
+ objects = gcr_collection_get_objects (GCR_COLLECTION (self));
for (l = objects; l; l = g_list_next (l)) {
handle = gck_object_get_handle (l->data);
g_hash_table_insert (closure->checks,
@@ -213,6 +241,7 @@ seahorse_token_init (SeahorseToken *self)
self->pv->objects = g_hash_table_new_full (seahorse_pkcs11_ulong_hash,
seahorse_pkcs11_ulong_equal,
g_free, g_object_unref);
+ self->pv->actions = seahorse_pkcs11_token_actions_instance ();
}
static void
@@ -225,12 +254,13 @@ seahorse_token_constructed (GObject *obj)
g_return_if_fail (self->pv->slot != NULL);
+ seahorse_token_refresh_async (self, NULL, NULL, NULL);
+
data = gck_uri_data_new ();
- data->token_info = gck_slot_get_token_info (self->pv->slot);
+ data->token_info = seahorse_token_get_info (self);
self->pv->uri = gck_uri_build (data, GCK_URI_FOR_TOKEN);
+ data->token_info = NULL;
gck_uri_data_free (data);
-
- seahorse_token_refresh_async (self, NULL, NULL, NULL);
}
static void
@@ -277,7 +307,16 @@ seahorse_token_get_property (GObject *object,
g_value_set_string (value, self->pv->uri);
break;
case PROP_ACTIONS:
- g_value_set_object (value, NULL);
+ g_value_set_object (value, self->pv->actions);
+ break;
+ case PROP_INFO:
+ g_value_set_boxed (value, self->pv->info);
+ break;
+ case PROP_LOCKABLE:
+ g_value_set_boolean (value, seahorse_token_get_lockable (self));
+ break;
+ case PROP_UNLOCKABLE:
+ g_value_set_boolean (value, seahorse_token_get_unlockable (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -300,6 +339,13 @@ seahorse_token_set_property (GObject *object,
g_return_if_fail (self->pv->slot);
g_object_ref (self->pv->slot);
break;
+ case PROP_INFO:
+ g_return_if_fail (!self->pv->info);
+ self->pv->info = g_value_dup_boxed (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
};
}
@@ -323,6 +369,7 @@ seahorse_token_finalize (GObject *obj)
g_hash_table_destroy (self->pv->objects);
g_assert (self->pv->slot == NULL);
+ g_clear_object (&self->pv->actions);
g_free (self->pv->uri);
G_OBJECT_CLASS (seahorse_token_parent_class)->finalize (obj);
@@ -354,6 +401,18 @@ seahorse_token_class_init (SeahorseTokenClass *klass)
g_object_class_install_property (gobject_class, PROP_FLAGS,
g_param_spec_uint ("flags", "Flags", "Object Token flags.",
0, G_MAXUINT, 0, G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_INFO,
+ g_param_spec_boxed ("info", "Info", "Token info",
+ GCK_TYPE_TOKEN_INFO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (gobject_class, PROP_LOCKABLE,
+ g_param_spec_boolean ("lockable", "Lockable", "Token can be locked",
+ FALSE, G_PARAM_READABLE));
+
+ g_object_class_install_property (gobject_class, PROP_UNLOCKABLE,
+ g_param_spec_boolean ("unlockable", "Unlockable", "Token can be unlocked",
+ FALSE, G_PARAM_READABLE));
}
static void
@@ -417,6 +476,74 @@ seahorse_token_get_slot (SeahorseToken *self)
return self->pv->slot;
}
+GckTokenInfo *
+seahorse_token_get_info (SeahorseToken *self)
+{
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), NULL);
+
+ if (self->pv->info == NULL)
+ update_token_info (self);
+
+ return self->pv->info;
+}
+
+static gboolean
+is_session_logged_in (GckSession *session)
+{
+ GckSessionInfo *info;
+ gboolean logged_in;
+
+ if (session == NULL)
+ return FALSE;
+
+ info = gck_session_get_info (session);
+ logged_in = (info != NULL) &&
+ (info->state == CKS_RW_USER_FUNCTIONS ||
+ info->state == CKS_RO_USER_FUNCTIONS ||
+ info->state == CKS_RW_SO_FUNCTIONS);
+ gck_session_info_free (info);
+
+ return logged_in;
+}
+
+gboolean
+seahorse_token_get_lockable (SeahorseToken *self)
+{
+ GckTokenInfo *info;
+
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), FALSE);
+
+ info = seahorse_token_get_info (self);
+
+ if ((info->flags & CKF_LOGIN_REQUIRED) == 0)
+ return FALSE;
+
+ if ((info->flags & CKF_USER_PIN_INITIALIZED) == 0)
+ return FALSE;
+
+ return is_session_logged_in (self->pv->session);
+
+}
+
+gboolean
+seahorse_token_get_unlockable (SeahorseToken *self)
+{
+ GckTokenInfo *info;
+
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), FALSE);
+
+ info = seahorse_token_get_info (self);
+
+ if ((info->flags & CKF_LOGIN_REQUIRED) == 0)
+ return FALSE;
+
+ if ((info->flags & CKF_USER_PIN_INITIALIZED) == 0)
+ return FALSE;
+
+ return !is_session_logged_in (self->pv->session);
+
+}
+
static void
receive_object (SeahorseToken *self,
GckObject *obj)
@@ -460,3 +587,151 @@ seahorse_token_remove_object (SeahorseToken *self,
g_object_unref (object);
}
+
+static void
+on_session_logout (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ SeahorseToken *self = SEAHORSE_TOKEN (g_async_result_get_source_object (user_data));
+ GError *error = NULL;
+
+ gck_session_logout_finish (GCK_SESSION (source), result, &error);
+ if (error == NULL)
+ seahorse_token_refresh_async (self, NULL, NULL, NULL);
+ else
+ g_simple_async_result_take_error (res, error);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (self);
+ g_object_unref (res);
+}
+
+void
+seahorse_token_lock_async (SeahorseToken *self,
+ GTlsInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (SEAHORSE_IS_TOKEN (self));
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ seahorse_token_lock_async);
+
+ if (is_session_logged_in (self->pv->session))
+ gck_session_logout_async (self->pv->session, cancellable,
+ on_session_logout, g_object_ref (res));
+ else
+ g_simple_async_result_complete_in_idle (res);
+
+ g_object_unref (res);
+}
+
+gboolean
+seahorse_token_lock_finish (SeahorseToken *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ seahorse_token_lock_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+on_login_interactive (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ SeahorseToken *self = SEAHORSE_TOKEN (g_async_result_get_source_object (user_data));
+ GError *error = NULL;
+
+ gck_session_logout_finish (GCK_SESSION (source), result, &error);
+ if (error == NULL)
+ seahorse_token_refresh_async (self, NULL, NULL, NULL);
+ else
+ g_simple_async_result_take_error (res, error);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (self);
+ g_object_unref (res);
+}
+
+static void
+on_session_login_open (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ SeahorseToken *self = SEAHORSE_TOKEN (g_async_result_get_source_object (user_data));
+ GError *error = NULL;
+
+ self->pv->session = gck_session_open_finish (result, &error);
+ if (error == NULL)
+ seahorse_token_refresh_async (self, NULL, NULL, NULL);
+ else
+ g_simple_async_result_take_error (res, error);
+
+ g_simple_async_result_complete (res);
+ g_object_unref (self);
+ g_object_unref (res);
+}
+
+void
+seahorse_token_unlock_async (SeahorseToken *self,
+ GTlsInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res;
+
+ g_return_if_fail (SEAHORSE_IS_TOKEN (self));
+ g_return_if_fail (interaction == NULL || G_IS_TLS_INTERACTION (interaction));
+ g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+ res = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ seahorse_token_unlock_async);
+
+ if (is_session_logged_in (self->pv->session)) {
+ g_simple_async_result_complete_in_idle (res);
+
+ } else if (self->pv->session) {
+ gck_session_login_interactive_async (self->pv->session, CKU_USER,
+ interaction, NULL, on_login_interactive,
+ g_object_ref (res));
+ } else {
+ gck_session_open_async (self->pv->slot, GCK_SESSION_LOGIN_USER, interaction,
+ NULL, on_session_login_open, g_object_ref (res));
+ }
+
+ g_object_unref (res);
+}
+
+gboolean
+seahorse_token_unlock_finish (SeahorseToken *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (SEAHORSE_IS_TOKEN (self), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
+ seahorse_token_unlock_async), FALSE);
+
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error))
+ return FALSE;
+
+ return TRUE;
+}
diff --git a/pkcs11/seahorse-token.h b/pkcs11/seahorse-token.h
index cf2ff55..a33fe56 100644
--- a/pkcs11/seahorse-token.h
+++ b/pkcs11/seahorse-token.h
@@ -49,11 +49,37 @@ GType seahorse_token_get_type (void);
SeahorseToken * seahorse_token_new (GckSlot *slot);
+GckTokenInfo * seahorse_token_get_info (SeahorseToken *self);
+
GckSlot * seahorse_token_get_slot (SeahorseToken *self);
+gboolean seahorse_token_get_lockable (SeahorseToken *self);
+
+gboolean seahorse_token_get_unlockable (SeahorseToken *self);
+
void seahorse_token_remove_object (SeahorseToken *self,
GckObject *object);
+void seahorse_token_lock_async (SeahorseToken *self,
+ GTlsInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean seahorse_token_lock_finish (SeahorseToken *self,
+ GAsyncResult *result,
+ GError **error);
+
+void seahorse_token_unlock_async (SeahorseToken *self,
+ GTlsInteraction *interaction,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean seahorse_token_unlock_finish (SeahorseToken *self,
+ GAsyncResult *result,
+ GError **error);
+
void seahorse_token_refresh_async (SeahorseToken *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]