diff options
-rw-r--r-- | docs/reference/gcr/Makefile.am | 2 | ||||
-rw-r--r-- | docs/reference/gcr/gcr-sections.txt | 14 | ||||
-rw-r--r-- | gcr/gcr-base.symbols | 3 | ||||
-rw-r--r-- | gcr/gcr-fingerprint.c | 4 | ||||
-rw-r--r-- | gcr/gcr-import-interaction.c | 99 | ||||
-rw-r--r-- | gcr/gcr-import-interaction.h | 13 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-import-dialog.c | 132 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-import-dialog.h | 9 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-import-interaction.c | 86 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-importer.c | 84 |
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); |