summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/reference/gcr/Makefile.am2
-rw-r--r--docs/reference/gcr/gcr-sections.txt14
-rw-r--r--gcr/gcr-base.symbols3
-rw-r--r--gcr/gcr-fingerprint.c4
-rw-r--r--gcr/gcr-import-interaction.c99
-rw-r--r--gcr/gcr-import-interaction.h13
-rw-r--r--gcr/gcr-pkcs11-import-dialog.c132
-rw-r--r--gcr/gcr-pkcs11-import-dialog.h9
-rw-r--r--gcr/gcr-pkcs11-import-interaction.c86
-rw-r--r--gcr/gcr-pkcs11-importer.c84
10 files changed, 248 insertions, 198 deletions
diff --git a/docs/reference/gcr/Makefile.am b/docs/reference/gcr/Makefile.am
index 7ad4c12d..f7554f49 100644
--- a/docs/reference/gcr/Makefile.am
+++ b/docs/reference/gcr/Makefile.am
@@ -77,6 +77,8 @@ IGNORE_HFILES= \
gcr-menu-button.h \
gcr-openpgp.h \
gcr-pkcs11-importer.h \
+ gcr-pkcs11-import-interaction.h \
+ gcr-pkcs11-import-dialog.h \
gcr-pkcs11-renderer.h \
gcr-record.h \
gcr-single-collection.h \
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index 63372f94..31558e44 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -92,6 +92,8 @@ GcrGeneralNameType
<FILE>gcr-importer</FILE>
GcrImporter
GcrImporterIface
+gcr_importer_get_interaction
+gcr_importer_set_interaction
gcr_importer_import
gcr_importer_import_async
gcr_importer_import_finish
@@ -100,13 +102,23 @@ gcr_importer_register_well_known
gcr_importer_create_for_parsed
gcr_importer_queue_for_parsed
gcr_importer_queue_and_filter_for_parsed
+gcr_import_interaction_supplement_prep
+gcr_import_interaction_supplement
+gcr_import_interaction_supplement_async
+gcr_import_interaction_supplement_finish
<SUBSECTION Standard>
GCR_IMPORTER
GCR_IS_IMPORTER
GCR_TYPE_IMPORTER
gcr_importer_get_type
GCR_IMPORTER_GET_INTERFACE
-<SUBSECTION Private>
+GCR_IMPORT_INTERACTION
+GCR_IMPORT_INTERACTION_GET_INTERFACE
+GCR_IS_IMPORT_INTERACTION
+GCR_TYPE_IMPORT_INTERACTION
+GcrImportInteraction
+GcrImportInteractionIface
+gcr_import_interaction_get_type
</SECTION>
<SECTION>
diff --git a/gcr/gcr-base.symbols b/gcr/gcr-base.symbols
index 8c251a4d..0d48bd1f 100644
--- a/gcr/gcr-base.symbols
+++ b/gcr/gcr-base.symbols
@@ -74,12 +74,11 @@ gcr_importer_set_interaction
gcr_importer_set_parser
gcr_importer_set_prompt_behavior
gcr_importer_set_slot
-gcr_import_interaction_get_importer
gcr_import_interaction_get_type
-gcr_import_interaction_set_importer
gcr_import_interaction_supplement
gcr_import_interaction_supplement_async
gcr_import_interaction_supplement_finish
+gcr_import_interaction_supplement_prep
gcr_parsed_get_attributes
gcr_parsed_get_data
gcr_parsed_get_description
diff --git a/gcr/gcr-fingerprint.c b/gcr/gcr-fingerprint.c
index 9b43dca9..39d93195 100644
--- a/gcr/gcr-fingerprint.c
+++ b/gcr/gcr-fingerprint.c
@@ -354,8 +354,8 @@ gcr_fingerprint_from_attributes (GckAttributes *attrs,
}
/**
- * gcr_fingerprint_from_attributes:
- * @attrs: attributes for key or certificate
+ * gcr_fingerprint_from_certificate_public_key:
+ * @certificate: the certificate
* @checksum_type: the type of fingerprint to create
* @n_fingerprint: the length of fingerprint returned
*
diff --git a/gcr/gcr-import-interaction.c b/gcr/gcr-import-interaction.c
index aee2048e..19d0bc01 100644
--- a/gcr/gcr-import-interaction.c
+++ b/gcr/gcr-import-interaction.c
@@ -74,77 +74,90 @@ gcr_import_interaction_default_init (GcrImportInteractionIface *iface)
static volatile gsize initialized = 0;
if (g_once_init_enter (&initialized)) {
-
- /**
- * GcrImportInteraction:importer:
- *
- * The importer being imported to
- */
- g_object_interface_install_property (iface,
- g_param_spec_object ("importer", "Importer", "The imported imported to",
- GCR_TYPE_IMPORTER, G_PARAM_READWRITE));
-
g_once_init_leave (&initialized, 1);
}
}
/**
- * gcr_import_interaction_get_importer:
+ * gcr_import_interaction_supplement_prep:
* @interaction: the interaction
+ * @attributes: attributes to supplement
*
- * Get the importer that's using this interaction.
+ * Prepare for supplementing the given attributes before import. This means
+ * prompting the user for things like labels and the like. The attributes
+ * will contain attributes for values that the importer needs, either empty
+ * or prefilled with suggested values.
*
- * Returns: (transfer full):
+ * This method does not prompt the user, but rather just prepares the
+ * interaction that these are the attributes that are needed.
*/
-GcrImporter *
-gcr_import_interaction_get_importer (GcrImportInteraction *interaction)
+void
+gcr_import_interaction_supplement_prep (GcrImportInteraction *interaction,
+ GckAttributes *attributes)
{
- GcrImporter *importer = NULL;
-
- g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), NULL);
-
- g_object_get (interaction, "importer", &importer, NULL);
+ GcrImportInteractionIface *iface;
- if (importer != NULL)
- g_object_unref (importer);
+ g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
+ g_return_if_fail (attributes != NULL);
- return importer;
+ iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
+ if (iface->supplement != NULL)
+ (iface->supplement_prep) (interaction, attributes);
}
/**
- * gcr_import_interaction_set_importer:
+ * gcr_import_interaction_supplement:
* @interaction: the interaction
- * @importer: (allow-none): the importer or %NULL
+ * @attributes: supplemented attributes
+ * @cancellable: optional cancellable object
+ * @error: location to store error on failure
+ *
+ * Supplement attributes before import. This means prompting the user for
+ * things like labels and the like. The needed attributes will have been passed
+ * to gcr_import_interaction_supplement_prep().
*
- * Set the importer that's using this interaction.
+ * This method prompts the user and fills in the attributes. If the user or
+ * cancellable cancels the operation the error should be set with %G_IO_ERROR_CANCELLED.
+ *
+ * Returns: %G_TLS_INTERACTION_HANDLED if successful or %G_TLS_INTERACTION_FAILED
*/
-void
-gcr_import_interaction_set_importer (GcrImportInteraction *interaction,
- GcrImporter *importer)
-{
- g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
- g_object_set (interaction, "importer", importer, NULL);
-}
-
GTlsInteractionResult
gcr_import_interaction_supplement (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GError **error)
{
GcrImportInteractionIface *iface;
g_return_val_if_fail (GCR_IS_IMPORT_INTERACTION (interaction), G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (attributes != NULL, G_TLS_INTERACTION_UNHANDLED);
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_TLS_INTERACTION_UNHANDLED);
g_return_val_if_fail (error == NULL || *error == NULL, G_TLS_INTERACTION_UNHANDLED);
iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
g_return_val_if_fail (iface->supplement != NULL, G_TLS_INTERACTION_UNHANDLED);
- return (iface->supplement) (interaction, cancellable, error);
+ return (iface->supplement) (interaction, attributes, cancellable, error);
}
+
+/**
+ * gcr_import_interaction_supplement_async:
+ * @interaction: the interaction
+ * @attributes: supplemented attributes
+ * @cancellable: optional cancellable object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Asynchronously supplement attributes before import. This means prompting the
+ * user for things like labels and the like. The needed attributes will have
+ * been passed to gcr_import_interaction_supplement_prep().
+ *
+ * This method prompts the user and fills in the attributes.
+ */
void
gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -152,14 +165,28 @@ gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
GcrImportInteractionIface *iface;
g_return_if_fail (GCR_IS_IMPORT_INTERACTION (interaction));
+ g_return_if_fail (attributes != NULL);
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
iface = GCR_IMPORT_INTERACTION_GET_INTERFACE (interaction);
g_return_if_fail (iface->supplement != NULL);
- (iface->supplement_async) (interaction, cancellable, callback, user_data);
+ (iface->supplement_async) (interaction, attributes, cancellable, callback, user_data);
}
+/**
+ * gcr_import_interaction_supplement_finish:
+ * @interaction: the interaction
+ * @result: the asynchronous result
+ * @error: location to place an error on failure
+ *
+ * Complete operation to asynchronously supplement attributes before import.
+ *
+ * If the user or cancellable cancels the operation the error should be set
+ * with %G_IO_ERROR_CANCELLED.
+ *
+ * Returns: %G_TLS_INTERACTION_HANDLED if successful or %G_TLS_INTERACTION_FAILED
+ */
GTlsInteractionResult
gcr_import_interaction_supplement_finish (GcrImportInteraction *interaction,
GAsyncResult *result,
diff --git a/gcr/gcr-import-interaction.h b/gcr/gcr-import-interaction.h
index 79f5970c..2793d139 100644
--- a/gcr/gcr-import-interaction.h
+++ b/gcr/gcr-import-interaction.h
@@ -47,11 +47,16 @@ typedef struct _GcrImportInteractionIface GcrImportInteractionIface;
struct _GcrImportInteractionIface {
GTypeInterface parent;
+ void (*supplement_prep) (GcrImportInteraction *interaction,
+ GckAttributes *attributes);
+
GTlsInteractionResult (*supplement) (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GError **error);
void (*supplement_async) (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
@@ -66,16 +71,16 @@ struct _GcrImportInteractionIface {
GType gcr_import_interaction_get_type (void);
-GcrImporter * gcr_import_interaction_get_importer (GcrImportInteraction *interaction);
-
-void gcr_import_interaction_set_importer (GcrImportInteraction *interaction,
- GcrImporter *importer);
+void gcr_import_interaction_supplement_prep (GcrImportInteraction *interaction,
+ GckAttributes *attributes);
GTlsInteractionResult gcr_import_interaction_supplement (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GError **error);
void gcr_import_interaction_supplement_async (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
diff --git a/gcr/gcr-pkcs11-import-dialog.c b/gcr/gcr-pkcs11-import-dialog.c
index dce5ae1f..e33d624a 100644
--- a/gcr/gcr-pkcs11-import-dialog.c
+++ b/gcr/gcr-pkcs11-import-dialog.c
@@ -44,7 +44,6 @@ enum {
struct _GcrPkcs11ImportDialog {
GtkDialog parent;
- GcrImporter *importer;
GtkBuilder *builder;
GtkWidget *password_area;
GtkLabel *token_label;
@@ -70,18 +69,6 @@ on_label_changed (GtkEditable *editable,
self->label_changed = TRUE;
}
-static GList *
-pkcs11_importer_get_queued (GcrImporter *importer)
-{
- GList *queued = NULL;
-
- /* TODO: This is ugly */
-
- g_object_get (importer, "queued", &queued, NULL);
-
- return queued;
-}
-
static void
_gcr_pkcs11_import_dialog_constructed (GObject *obj)
{
@@ -90,9 +77,6 @@ _gcr_pkcs11_import_dialog_constructed (GObject *obj)
GtkEntryBuffer *buffer;
GtkWidget *widget;
GtkBox *contents;
- GList *queued, *l;
- gchar *label = NULL;
- gchar *value;
G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->constructed (obj);
@@ -125,27 +109,6 @@ _gcr_pkcs11_import_dialog_constructed (GObject *obj)
g_signal_connect (self->label_entry, "changed", G_CALLBACK (on_label_changed), self);
gtk_entry_set_activates_default (self->label_entry, TRUE);
- queued = pkcs11_importer_get_queued (self->importer);
- for (l = queued; l != NULL; l = g_list_next (l)) {
- if (!gck_attributes_find_string (l->data, CKA_LABEL, &value))
- value = NULL;
- if (l == queued) {
- label = value;
- value = NULL;
- } else if (g_strcmp0 (label, value) != 0) {
- g_free (label);
- label = NULL;
- }
- g_free (value);
- }
- g_list_free (queued);
-
- if (label == NULL)
- gtk_entry_set_placeholder_text (self->label_entry, _("Automatically chosen"));
- else
- gtk_entry_set_text (self->label_entry, label);
- g_free (label);
-
/* Add our various buttons */
gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (self), GTK_STOCK_OK, GTK_RESPONSE_OK);
@@ -166,94 +129,65 @@ _gcr_pkcs11_import_dialog_finalize (GObject *obj)
GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
g_object_unref (self->builder);
- g_clear_object (&self->importer);
G_OBJECT_CLASS (_gcr_pkcs11_import_dialog_parent_class)->finalize (obj);
}
static void
-_gcr_pkcs11_import_dialog_set_property (GObject *obj,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
-
- switch (prop_id) {
- case PROP_IMPORTER:
- g_return_if_fail (self->importer == NULL);
- self->importer = g_value_dup_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
- break;
- }
-}
-
-static void
-_gcr_pkcs11_import_dialog_get_property (GObject *obj,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GcrPkcs11ImportDialog *self = GCR_PKCS11_IMPORT_DIALOG (obj);
-
- switch (prop_id) {
- case PROP_IMPORTER:
- g_value_set_object (value, self->importer);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
- break;
- }
-}
-
-static void
_gcr_pkcs11_import_dialog_class_init (GcrPkcs11ImportDialogClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = _gcr_pkcs11_import_dialog_constructed;
gobject_class->finalize = _gcr_pkcs11_import_dialog_finalize;
- gobject_class->set_property = _gcr_pkcs11_import_dialog_set_property;
- gobject_class->get_property = _gcr_pkcs11_import_dialog_get_property;
-
- g_object_class_install_property (gobject_class, PROP_IMPORTER,
- g_param_spec_object ("importer", "Importer", "The PKCS#11 importer",
- GCR_TYPE_IMPORTER,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
}
GcrPkcs11ImportDialog *
-_gcr_pkcs11_import_dialog_new (GcrImporter *importer,
- GtkWindow *parent)
+_gcr_pkcs11_import_dialog_new (GtkWindow *parent)
{
GcrPkcs11ImportDialog *dialog;
- g_return_val_if_fail (GCR_IS_IMPORTER (importer), NULL);
g_return_val_if_fail (parent == NULL || GTK_IS_WINDOW (parent), NULL);
dialog = g_object_new (GCR_TYPE_PKCS11_IMPORT_DIALOG,
- "importer", importer,
"transient-for", parent,
NULL);
return g_object_ref_sink (dialog);
}
-static void
-update_importer_labels (GcrPkcs11ImportDialog *self)
+void
+_gcr_pkcs11_import_dialog_get_supplements (GcrPkcs11ImportDialog *self,
+ GckAttributes *attributes)
{
const gchar *label;
- GList *queued, *l;
+
+ g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
+ g_return_if_fail (attributes != NULL);
label = gtk_entry_get_text (self->label_entry);
- if (self->label_changed && label != NULL && label[0]) {
- queued = pkcs11_importer_get_queued (self->importer);
- for (l = queued; l != NULL; l = g_list_next (l))
- gck_attributes_set_string (l->data, CKA_LABEL, label);
- g_list_free (queued);
- }
+ if (self->label_changed && label != NULL && label[0])
+ gck_attributes_set_string (attributes, CKA_LABEL, label);
+}
+
+void
+_gcr_pkcs11_import_dialog_set_supplements (GcrPkcs11ImportDialog *self,
+ GckAttributes *attributes)
+{
+ gchar *label;
+
+ g_return_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self));
+ g_return_if_fail (attributes != NULL);
+
+ if (!gck_attributes_find_string (attributes, CKA_LABEL, &label))
+ label = NULL;
+
+ if (label == NULL)
+ gtk_entry_set_placeholder_text (self->label_entry, _("Automatically chosen"));
+ gtk_entry_set_text (self->label_entry, label == NULL ? "" : label);
+ g_free (label);
+
+ self->label_changed = FALSE;
}
gboolean
@@ -264,7 +198,6 @@ _gcr_pkcs11_import_dialog_run (GcrPkcs11ImportDialog *self)
g_return_val_if_fail (GCR_IS_PKCS11_IMPORT_DIALOG (self), FALSE);
if (gtk_dialog_run (GTK_DIALOG (self)) == GTK_RESPONSE_OK) {
- update_importer_labels (self);
ret = TRUE;
}
@@ -296,12 +229,7 @@ _gcr_pkcs11_import_dialog_run_finish (GcrPkcs11ImportDialog *self,
gtk_widget_hide (GTK_WIDGET (self));
- if (response == GTK_RESPONSE_OK) {
- update_importer_labels (self);
- return TRUE;
- }
-
- return FALSE;
+ return (response == GTK_RESPONSE_OK) ? TRUE : FALSE;
}
GTlsInteractionResult
diff --git a/gcr/gcr-pkcs11-import-dialog.h b/gcr/gcr-pkcs11-import-dialog.h
index 7c207693..38a1dd4c 100644
--- a/gcr/gcr-pkcs11-import-dialog.h
+++ b/gcr/gcr-pkcs11-import-dialog.h
@@ -39,8 +39,13 @@ typedef struct _GcrPkcs11ImportDialog GcrPkcs11ImportDialog;
GType _gcr_pkcs11_import_dialog_get_type (void) G_GNUC_CONST;
-GcrPkcs11ImportDialog * _gcr_pkcs11_import_dialog_new (GcrImporter *importer,
- GtkWindow *parent);
+GcrPkcs11ImportDialog * _gcr_pkcs11_import_dialog_new (GtkWindow *parent);
+
+void _gcr_pkcs11_import_dialog_get_supplements (GcrPkcs11ImportDialog *self,
+ GckAttributes *attributes);
+
+void _gcr_pkcs11_import_dialog_set_supplements (GcrPkcs11ImportDialog *self,
+ GckAttributes *attributes);
gboolean _gcr_pkcs11_import_dialog_run (GcrPkcs11ImportDialog *self);
diff --git a/gcr/gcr-pkcs11-import-interaction.c b/gcr/gcr-pkcs11-import-interaction.c
index 3be7c94f..ee592e14 100644
--- a/gcr/gcr-pkcs11-import-interaction.c
+++ b/gcr/gcr-pkcs11-import-interaction.c
@@ -33,7 +33,6 @@
enum {
PROP_0,
- PROP_IMPORTER,
PROP_PARENT_WINDOW
};
@@ -41,8 +40,7 @@ typedef struct _GcrPkcs11ImportInteractionClass GcrPkcs11ImportInteractionClass;
struct _GcrPkcs11ImportInteraction {
GTlsInteraction parent;
- GcrImporter *importer;
- gboolean dialog_shown;
+ gboolean supplemented;
GtkWindow *parent_window;
GcrPkcs11ImportDialog *dialog;
};
@@ -59,7 +57,7 @@ G_DEFINE_TYPE_WITH_CODE(GcrPkcs11ImportInteraction, _gcr_pkcs11_import_interacti
static void
_gcr_pkcs11_import_interaction_init (GcrPkcs11ImportInteraction *self)
{
-
+ self->dialog = _gcr_pkcs11_import_dialog_new (self->parent_window);
}
static void
@@ -81,17 +79,9 @@ _gcr_pkcs11_import_interaction_set_property (GObject *obj,
GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
switch (prop_id) {
- case PROP_IMPORTER:
- g_clear_object (&self->dialog);
- g_clear_object (&self->importer);
- self->importer = g_value_dup_object (value);
- self->dialog_shown = FALSE;
- if (self->importer != NULL)
- self->dialog = _gcr_pkcs11_import_dialog_new (self->importer, self->parent_window);
- break;
case PROP_PARENT_WINDOW:
- g_clear_object (&self->parent_window);
- self->parent_window = g_value_dup_object (value);
+ gtk_window_set_transient_for (GTK_WINDOW (self->dialog),
+ g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -108,11 +98,8 @@ _gcr_pkcs11_import_interaction_get_property (GObject *obj,
GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (obj);
switch (prop_id) {
- case PROP_IMPORTER:
- g_value_set_object (value, self->importer);
- break;
case PROP_PARENT_WINDOW:
- g_value_set_object (value, self->parent_window);
+ g_value_set_object (value, gtk_window_get_transient_for (GTK_WINDOW (self->dialog)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
@@ -130,12 +117,23 @@ _gcr_pkcs11_import_interaction_ask_password (GTlsInteraction *interaction,
g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
- self->dialog_shown = TRUE;
+ self->supplemented = TRUE;
return _gcr_pkcs11_import_dialog_run_ask_password (self->dialog, password, cancellable, error);
}
+static void
+_gcr_pkcs11_import_interaction_supplement_prep (GcrImportInteraction *interaction,
+ GckAttributes *attributes)
+{
+ GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+
+ self->supplemented = FALSE;
+ _gcr_pkcs11_import_dialog_set_supplements (self->dialog, attributes);
+}
+
static GTlsInteractionResult
_gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GError **error)
{
@@ -143,11 +141,12 @@ _gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
- if (self->dialog_shown)
+ if (self->supplemented)
return G_TLS_INTERACTION_HANDLED;
- self->dialog_shown = TRUE;
+ self->supplemented = TRUE;
if (_gcr_pkcs11_import_dialog_run (self->dialog)) {
+ _gcr_pkcs11_import_dialog_get_supplements (self->dialog, attributes);
return G_TLS_INTERACTION_HANDLED;
} else {
@@ -157,7 +156,18 @@ _gcr_pkcs11_import_interaction_supplement (GcrImportInteraction *interaction,
}
static void
+on_dialog_run_async (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+ g_simple_async_result_complete (res);
+ g_object_unref (res);
+}
+
+static void
_gcr_pkcs11_import_interaction_supplement_async (GcrImportInteraction *interaction,
+ GckAttributes *attributes,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@@ -167,17 +177,22 @@ _gcr_pkcs11_import_interaction_supplement_async (GcrImportInteraction *interacti
g_return_if_fail (self->dialog != NULL);
+ res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
+ _gcr_pkcs11_import_interaction_supplement_async);
+
/* If dialog was already shown, then short circuit */
- if (self->dialog_shown) {
- res = g_simple_async_result_new (G_OBJECT (interaction), callback, user_data,
- _gcr_pkcs11_import_interaction_supplement_async);
+ if (self->supplemented) {
g_simple_async_result_complete_in_idle (res);
- g_object_unref (res);
} else {
- self->dialog_shown = TRUE;
- _gcr_pkcs11_import_dialog_run_async (self->dialog, cancellable, callback, user_data);
+ self->supplemented = TRUE;
+ g_simple_async_result_set_op_res_gpointer (res, gck_attributes_ref (attributes),
+ (GDestroyNotify)gck_attributes_unref);
+ _gcr_pkcs11_import_dialog_run_async (self->dialog, cancellable,
+ on_dialog_run_async, g_object_ref (res));
}
+
+ g_object_unref (res);
}
static GTlsInteractionResult
@@ -186,17 +201,21 @@ _gcr_pkcs11_import_interaction_supplement_finish (GcrImportInteraction *interact
GError **error)
{
GcrPkcs11ImportInteraction *self = GCR_PKCS11_IMPORT_INTERACTION (interaction);
+ GckAttributes *attributes;
g_return_val_if_fail (self->dialog != NULL, G_TLS_INTERACTION_UNHANDLED);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
+ _gcr_pkcs11_import_interaction_supplement_async), G_TLS_INTERACTION_UNHANDLED);
- /* If it was short circuited without a dialog */
- if (g_simple_async_result_is_valid (result, G_OBJECT (interaction),
- _gcr_pkcs11_import_interaction_supplement_async)) {
- return G_TLS_INTERACTION_HANDLED;
+ attributes = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
- } else if (_gcr_pkcs11_import_dialog_run_finish (self->dialog, result)) {
+ /* Didn't show the dialog */
+ if (attributes == NULL)
return G_TLS_INTERACTION_HANDLED;
+ if (_gcr_pkcs11_import_dialog_run_finish (self->dialog, result)) {
+ _gcr_pkcs11_import_dialog_get_supplements (self->dialog, attributes);
+ return G_TLS_INTERACTION_HANDLED;
} else {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, _("The user cancelled the operation"));
return G_TLS_INTERACTION_FAILED;
@@ -206,6 +225,7 @@ _gcr_pkcs11_import_interaction_supplement_finish (GcrImportInteraction *interact
static void
_gcr_pkcs11_import_interaction_iface_init (GcrImportInteractionIface *iface)
{
+ iface->supplement_prep = _gcr_pkcs11_import_interaction_supplement_prep;
iface->supplement = _gcr_pkcs11_import_interaction_supplement;
iface->supplement_async = _gcr_pkcs11_import_interaction_supplement_async;
iface->supplement_finish = _gcr_pkcs11_import_interaction_supplement_finish;
@@ -223,8 +243,6 @@ _gcr_pkcs11_import_interaction_class_init (GcrPkcs11ImportInteractionClass *klas
interaction_class->ask_password = _gcr_pkcs11_import_interaction_ask_password;
- g_object_class_override_property (gobject_class, PROP_IMPORTER, "importer");
-
g_object_class_install_property (gobject_class, PROP_PARENT_WINDOW,
g_param_spec_object ("parent-window", "Parent Window", "Prompt Parent Window",
GTK_TYPE_WINDOW, G_PARAM_READWRITE));
diff --git a/gcr/gcr-pkcs11-importer.c b/gcr/gcr-pkcs11-importer.c
index 371f76bd..15ea88fe 100644
--- a/gcr/gcr-pkcs11-importer.c
+++ b/gcr/gcr-pkcs11-importer.c
@@ -74,6 +74,7 @@ typedef struct {
GCancellable *cancellable;
gboolean prompted;
gboolean async;
+ GckAttributes *supplement;
} GcrImporterData;
/* State forward declarations */
@@ -132,13 +133,6 @@ static void
state_complete (GSimpleAsyncResult *res,
gboolean async)
{
- GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
- GcrPkcs11Importer *self = data->importer;
-
- /* Disconnect from the interaction */
- if (data->importer->interaction && GCR_IS_IMPORT_INTERACTION (self->interaction))
- gcr_import_interaction_set_importer (GCR_IMPORT_INTERACTION (self->interaction), NULL);
-
g_simple_async_result_complete (res);
}
@@ -237,6 +231,20 @@ typedef struct {
} CertificateKeyPair;
static void
+supplement_with_attributes (GckAttributes *attrs,
+ GckAttributes *supplements)
+{
+ GckAttribute *supplement;
+ gint i;
+
+ for (i = 0; i < gck_attributes_count (supplements); i++) {
+ supplement = gck_attributes_at (supplements, i);
+ if (!gck_attribute_is_invalid (supplement) && supplement->length != 0)
+ gck_attributes_add (attrs, supplement);
+ }
+}
+
+static void
supplement_id_for_data (GckAttributes *attrs,
guchar *nonce,
gsize n_once,
@@ -263,11 +271,13 @@ supplement_id_for_data (GckAttributes *attrs,
}
static void
-supplement_attributes (GcrPkcs11Importer *self)
+supplement_attributes (GcrPkcs11Importer *self,
+ GckAttributes *supplements)
{
GHashTable *pairs;
GHashTable *paired;
CertificateKeyPair *pair;
+ gboolean supplemented = FALSE;
GckAttributes *attrs;
gulong klass;
guchar *finger;
@@ -343,14 +353,21 @@ supplement_attributes (GcrPkcs11Importer *self)
* Generate a CKA_ID based on the fingerprint and nonce,
* and do the same CKA_ID for both private key and certificate.
*/
+
+ supplement_with_attributes (pair->private_key, supplements);
supplement_id_for_data (pair->private_key, nonce, sizeof (nonce),
fingerprint, strlen (fingerprint));
g_queue_push_tail (queue, pair->private_key);
g_hash_table_insert (paired, pair->private_key, "present");
+
+ supplement_with_attributes (pair->private_key, supplements);
supplement_id_for_data (pair->certificate, nonce, sizeof (nonce),
fingerprint, strlen (fingerprint));
g_queue_push_tail (queue, pair->certificate);
g_hash_table_insert (paired, pair->certificate, "present");
+
+ /* Used the suplements for the pairs, don't use for unpaired stuff */
+ supplemented = TRUE;
}
}
@@ -358,6 +375,9 @@ supplement_attributes (GcrPkcs11Importer *self)
for (l = self->queue->head; l != NULL; l = g_list_next (l)) {
attrs = l->data;
if (!g_hash_table_lookup (paired, attrs)) {
+ if (!supplemented)
+ supplement_with_attributes (attrs, supplements);
+
/*
* Generate a CKA_ID based on the location of attrs in,
* memory, since this together with the nonce should
@@ -365,6 +385,7 @@ supplement_attributes (GcrPkcs11Importer *self)
*/
supplement_id_for_data (attrs, nonce, sizeof (nonce),
&attrs, sizeof (gpointer));
+
g_queue_push_tail (queue, l->data);
}
}
@@ -384,7 +405,7 @@ complete_supplement (GSimpleAsyncResult *res,
GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
if (error == NULL) {
- supplement_attributes (data->importer);
+ supplement_attributes (data->importer, data->supplement);
next_state (res, state_create_object);
} else {
g_simple_async_result_take_error (res, error);
@@ -421,16 +442,51 @@ state_supplement (GSimpleAsyncResult *res,
} else if (async) {
gcr_import_interaction_supplement_async (GCR_IMPORT_INTERACTION (self->interaction),
- data->cancellable, on_supplement_done,
- g_object_ref (res));
+ data->supplement, data->cancellable,
+ on_supplement_done, g_object_ref (res));
} else {
gcr_import_interaction_supplement (GCR_IMPORT_INTERACTION (self->interaction),
- data->cancellable, &error);
+ data->supplement, data->cancellable, &error);
complete_supplement (res, error);
}
}
+static void
+supplement_prep (GSimpleAsyncResult *res)
+{
+ GcrImporterData *data = g_simple_async_result_get_op_res_gpointer (res);
+ GcrPkcs11Importer *self = data->importer;
+ GckAttribute *the_label = NULL;
+ GckAttribute *attr;
+ gboolean first = TRUE;
+ GList *l;
+
+ if (data->supplement)
+ gck_attributes_unref (data->supplement);
+ data->supplement = gck_attributes_new ();
+
+ /* Do we have a consistent label across all objects? */
+ for (l = self->queue->head; l != NULL; l = g_list_next (l)) {
+ attr = gck_attributes_find (l->data, CKA_LABEL);
+ if (first)
+ the_label = attr;
+ else if (!gck_attribute_equal (the_label, attr))
+ the_label = NULL;
+ first = FALSE;
+ }
+
+ /* If consistent label, set that in supplement data */
+ if (the_label != NULL)
+ gck_attributes_add (data->supplement, the_label);
+ else
+ gck_attributes_add_empty (data->supplement, CKA_LABEL);
+
+ if (GCR_IS_IMPORT_INTERACTION (self->interaction))
+ gcr_import_interaction_supplement_prep (GCR_IMPORT_INTERACTION (self->interaction),
+ data->supplement);
+}
+
/* ---------------------------------------------------------------------------------
* OPEN SESSION
*/
@@ -770,9 +826,7 @@ _gcr_pkcs11_importer_import_async (GcrImporter *importer,
data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
g_simple_async_result_set_op_res_gpointer (res, data, gcr_importer_data_free);
- if (GCR_IS_IMPORT_INTERACTION (self->interaction))
- gcr_import_interaction_set_importer (GCR_IMPORT_INTERACTION (self->interaction),
- GCR_IMPORTER (self));
+ supplement_prep (res);
gck_slot_set_interaction (self->slot, self->interaction);
next_state (res, state_open_session);