diff options
author | Stef Walter <stefw@collabora.co.uk> | 2011-09-27 15:48:39 +0200 |
---|---|---|
committer | Stef Walter <stefw@collabora.co.uk> | 2011-09-27 15:48:39 +0200 |
commit | 61040577ebb5f6dfbb4d07a30edde91205abd7a9 (patch) | |
tree | 7ad773130474c103d580d4210e5332a76cdcdd5d | |
parent | 6cf14cf7397de26f80257dc49c741ec17f446a51 (diff) | |
download | gnome-keyring-61040577ebb5f6dfbb4d07a30edde91205abd7a9.tar.gz |
gcr: Refactor GcrParser and delay listing of importers
* PKCS#11 takes a long time to initialize with certain smart cards
(several seconds). So we can't block the UI.
* Expose the PKCS#11 initialization functions publicly.
* Refactor GcrParser so that the current parsed item can be held
around until later in the form of a GcrParsed structure.
* Queue parsed items in GcrImportButton until PKCS#11 is initialized.
-rw-r--r-- | gcr/gcr-gnupg-importer.c | 14 | ||||
-rw-r--r-- | gcr/gcr-import-button.c | 48 | ||||
-rw-r--r-- | gcr/gcr-import-button.h | 2 | ||||
-rw-r--r-- | gcr/gcr-importer.c | 40 | ||||
-rw-r--r-- | gcr/gcr-importer.h | 26 | ||||
-rw-r--r-- | gcr/gcr-internal.h | 10 | ||||
-rw-r--r-- | gcr/gcr-library.c | 18 | ||||
-rw-r--r-- | gcr/gcr-library.h | 10 | ||||
-rw-r--r-- | gcr/gcr-parser.c | 246 | ||||
-rw-r--r-- | gcr/gcr-parser.h | 22 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-certificate.c | 4 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-importer.c | 41 | ||||
-rw-r--r-- | gcr/gcr-pkcs11-importer.h | 3 | ||||
-rw-r--r-- | gcr/gcr-trust.c | 8 | ||||
-rw-r--r-- | gcr/gcr-viewer-widget.c | 9 | ||||
-rw-r--r-- | gcr/gcr-viewer-window.c | 4 | ||||
-rw-r--r-- | tool/gkr-tool-import.c | 6 |
17 files changed, 362 insertions, 149 deletions
diff --git a/gcr/gcr-gnupg-importer.c b/gcr/gcr-gnupg-importer.c index f527938c..5cd8faea 100644 --- a/gcr/gcr-gnupg-importer.c +++ b/gcr/gcr-gnupg-importer.c @@ -207,15 +207,15 @@ _gcr_gnupg_importer_class_init (GcrGnupgImporterClass *klass) } static GList * -_gcr_gnupg_importer_create_for_parsed (GcrParser *parser) +_gcr_gnupg_importer_create_for_parsed (GcrParsed *parsed) { GcrImporter *self; - if (gcr_parser_get_parsed_format (parser) != GCR_FORMAT_OPENPGP_PACKET) - return FALSE; + if (gcr_parsed_get_format (parsed) != GCR_FORMAT_OPENPGP_PACKET) + return NULL; self = _gcr_gnupg_importer_new (NULL); - if (!gcr_importer_queue_for_parsed (self, parser)) + if (!gcr_importer_queue_for_parsed (self, parsed)) g_assert_not_reached (); return g_list_append (NULL, self); @@ -223,16 +223,16 @@ _gcr_gnupg_importer_create_for_parsed (GcrParser *parser) static gboolean _gcr_gnupg_importer_queue_for_parsed (GcrImporter *importer, - GcrParser *parser) + GcrParsed *parsed) { GcrGnupgImporter *self = GCR_GNUPG_IMPORTER (importer); gconstpointer block; gsize n_block; - if (gcr_parser_get_parsed_format (parser) != GCR_FORMAT_OPENPGP_PACKET) + if (gcr_parsed_get_format (parsed) != GCR_FORMAT_OPENPGP_PACKET) return FALSE; - block = gcr_parser_get_parsed_block (parser, &n_block); + block = gcr_parsed_get_data (parsed, &n_block); g_return_val_if_fail (block, FALSE); g_memory_input_stream_add_data (self->pv->packets, g_memdup (block, n_block), diff --git a/gcr/gcr-import-button.c b/gcr/gcr-import-button.c index 253ba541..6ae289d8 100644 --- a/gcr/gcr-import-button.c +++ b/gcr/gcr-import-button.c @@ -60,7 +60,9 @@ enum { */ struct _GcrImportButtonPrivate { + GList *queued; GList *importers; + gboolean ready; gboolean created; gboolean importing; gchar *imported; @@ -96,8 +98,15 @@ update_import_button (GcrImportButton *self) gchar *message; gchar *label; + /* Initializing, set a spinner */ + if (!self->pv->ready) { + gtk_widget_show (self->pv->spinner); + gtk_widget_hide (self->pv->arrow); + gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); + gtk_widget_set_tooltip_text (GTK_WIDGET (self), _("Initializing...")); + /* Importing, set a spinner */ - if (self->pv->importing) { + } else if (self->pv->importing) { gtk_widget_show (self->pv->spinner); gtk_widget_hide (self->pv->arrow); gtk_widget_set_sensitive (GTK_WIDGET (self), FALSE); @@ -150,6 +159,25 @@ update_import_button (GcrImportButton *self) } static void +on_library_pkcs11_ready (GObject *source, + GAsyncResult *result, + gpointer user_data) +{ + GcrImportButton *self = GCR_IMPORT_BUTTON (user_data); + GList *queued, *l; + + self->pv->ready = TRUE; + + /* Process the parsed items that have been seen */ + queued = self->pv->queued; + self->pv->queued = NULL; + for (l = queued; l != NULL; l = g_list_next (l)) + gcr_import_button_add_parsed (self, l->data); + g_assert (self->pv->queued == NULL); + g_list_free_full (queued, gcr_parsed_unref); +} + +static void gcr_import_button_constructed (GObject *obj) { GcrImportButton *self = GCR_IMPORT_BUTTON (obj); @@ -175,6 +203,8 @@ gcr_import_button_constructed (GObject *obj) gtk_container_add (GTK_CONTAINER (self), grid); update_import_button (self); + + gcr_pkcs11_initialize_async (NULL, on_library_pkcs11_ready, g_object_ref (self)); } static void @@ -224,6 +254,9 @@ gcr_import_button_dispose (GObject *obj) g_cancellable_cancel (self->pv->cancellable); g_clear_object (&self->pv->menu); + g_list_free_full (self->pv->queued, gcr_parsed_unref); + self->pv->queued = NULL; + G_OBJECT_CLASS (gcr_import_button_parent_class)->dispose (obj); } @@ -463,20 +496,25 @@ gcr_import_button_new (const gchar *label) void gcr_import_button_add_parsed (GcrImportButton *self, - GcrParser *parser) + GcrParsed *parsed) { GList *importers; g_return_if_fail (GCR_IS_IMPORT_BUTTON (self)); - g_return_if_fail (GCR_IS_PARSER (parser)); + g_return_if_fail (parsed != NULL); + + if (!self->pv->ready) { + self->pv->queued = g_list_prepend (self->pv->queued, gcr_parsed_ref (parsed)); + return; + } g_free (self->pv->imported); self->pv->imported = NULL; if (self->pv->created) { - importers = gcr_importer_queue_and_filter_for_parsed (self->pv->importers, parser); + importers = gcr_importer_queue_and_filter_for_parsed (self->pv->importers, parsed); } else { - importers = gcr_importer_create_for_parsed (parser); + importers = gcr_importer_create_for_parsed (parsed); self->pv->created = TRUE; } diff --git a/gcr/gcr-import-button.h b/gcr/gcr-import-button.h index 35b116c3..3df12407 100644 --- a/gcr/gcr-import-button.h +++ b/gcr/gcr-import-button.h @@ -61,7 +61,7 @@ GType gcr_import_button_get_type (void) G_GNUC_CONST GcrImportButton * gcr_import_button_new (const gchar *label); void gcr_import_button_add_parsed (GcrImportButton *button, - GcrParser *parser); + GcrParsed *parsed); G_END_DECLS diff --git a/gcr/gcr-importer.c b/gcr/gcr-importer.c index b82b7d80..658bc324 100644 --- a/gcr/gcr-importer.c +++ b/gcr/gcr-importer.c @@ -154,19 +154,30 @@ sort_registered_by_n_attrs (gconstpointer a, gconstpointer b) return (na == nb) ? 0 : -1; } +static gboolean +check_if_seen_or_add (GHashTable *seen, + gpointer key) +{ + if (g_hash_table_lookup (seen, key)) + return TRUE; + g_hash_table_insert (seen, key, key); + return FALSE; +} + /** * gcr_importer_create_for_parsed: - * @parser: a parser with a parsed item to import + * @parsed: a parser with a parsed item to import * * Create a set of importers which can import this parsed item. * The parsed item is represented by the state of the GcrParser at the * time of calling this method. * * Returns: a list of importers which can import the parsed item, which - * should be freed with gck_list_unref_free(). + * should be freed with g_object_unref(), or %NULL if no types + * of importers can be created. */ GList * -gcr_importer_create_for_parsed (GcrParser *parser) +gcr_importer_create_for_parsed (GcrParsed *parsed) { GcrRegistered *registered; GcrImporterIface *iface; @@ -175,10 +186,11 @@ gcr_importer_create_for_parsed (GcrParser *parser) gboolean matched; gulong n_attrs; GList *results = NULL; + GHashTable *seen; gulong j; gsize i; - g_return_val_if_fail (GCR_IS_PARSER (parser), NULL); + g_return_val_if_fail (parsed != NULL, NULL); gcr_importer_register_well_known (); @@ -190,12 +202,14 @@ gcr_importer_create_for_parsed (GcrParser *parser) registered_sorted = TRUE; } - attrs = gcr_parser_get_parsed_attributes (parser); + attrs = gcr_parsed_get_attributes (parsed); if (attrs != NULL) gck_attributes_ref (attrs); else attrs = gck_attributes_new (); + seen = g_hash_table_new (g_direct_hash, g_direct_equal); + for (i = 0; i < registered_importers->len; ++i) { registered = &(g_array_index (registered_importers, GcrRegistered, i)); n_attrs = gck_attributes_count (registered->attrs); @@ -210,17 +224,21 @@ gcr_importer_create_for_parsed (GcrParser *parser) } if (matched) { + if (check_if_seen_or_add (seen, GUINT_TO_POINTER (registered->importer_type))) + continue; + instance_class = g_type_class_ref (registered->importer_type); iface = g_type_interface_peek (instance_class, GCR_TYPE_IMPORTER); g_return_val_if_fail (iface != NULL, NULL); g_return_val_if_fail (iface->create_for_parsed, NULL); - results = g_list_concat (results, (iface->create_for_parsed) (parser)); + results = g_list_concat (results, (iface->create_for_parsed) (parsed)); g_type_class_unref (instance_class); } } + g_hash_table_unref (seen); gck_attributes_unref (attrs); return results; } @@ -240,18 +258,18 @@ gcr_importer_create_for_parsed (GcrParser *parser) */ gboolean gcr_importer_queue_for_parsed (GcrImporter *importer, - GcrParser *parser) + GcrParsed *parsed) { GcrImporterIface *iface; g_return_val_if_fail (GCR_IS_IMPORTER (importer), FALSE); - g_return_val_if_fail (GCR_IS_PARSER (parser), FALSE); + g_return_val_if_fail (parsed != NULL, FALSE); iface = GCR_IMPORTER_GET_INTERFACE (importer); g_return_val_if_fail (iface != NULL, FALSE); g_return_val_if_fail (iface->queue_for_parsed != NULL, FALSE); - return (iface->queue_for_parsed) (importer, parser); + return (iface->queue_for_parsed) (importer, parsed); } /** @@ -271,13 +289,13 @@ gcr_importer_queue_for_parsed (GcrImporter *importer, */ GList * gcr_importer_queue_and_filter_for_parsed (GList *importers, - GcrParser *parser) + GcrParsed *parsed) { GList *results = NULL; GList *l; for (l = importers; l != NULL; l = g_list_next (l)) { - if (gcr_importer_queue_for_parsed (l->data, parser)) + if (gcr_importer_queue_for_parsed (l->data, parsed)) results = g_list_prepend (results, g_object_ref (l->data)); } diff --git a/gcr/gcr-importer.h b/gcr/gcr-importer.h index 37ab2d97..e93395eb 100644 --- a/gcr/gcr-importer.h +++ b/gcr/gcr-importer.h @@ -45,10 +45,10 @@ typedef struct _GcrImporterIface GcrImporterIface; struct _GcrImporterIface { GTypeInterface parent; - GList * (*create_for_parsed) (GcrParser *parser); + GList * (*create_for_parsed) (GcrParsed *parsed); gboolean (*queue_for_parsed) (GcrImporter *importer, - GcrParser *parser); + GcrParsed *parsed); gboolean (*import_sync) (GcrImporter *importer, GCancellable *cancellable, @@ -67,33 +67,33 @@ struct _GcrImporterIface { gpointer reserved[14]; }; -GType gcr_importer_get_type (void); +GType gcr_importer_get_type (void); -GList * gcr_importer_create_for_parsed (GcrParser *parser); +GList * gcr_importer_create_for_parsed (GcrParsed *parsed); -gboolean gcr_importer_queue_for_parsed (GcrImporter *importer, - GcrParser *parser); +gboolean gcr_importer_queue_for_parsed (GcrImporter *importer, + GcrParsed *parsed); -GList * gcr_importer_queue_and_filter_for_parsed (GList *importers, - GcrParser *parser); +GList * gcr_importer_queue_and_filter_for_parsed (GList *importers, + GcrParsed *parsed); -gboolean gcr_importer_import (GcrImporter *importer, +gboolean gcr_importer_import (GcrImporter *importer, GCancellable *cancellable, GError **error); -void gcr_importer_import_async (GcrImporter *importer, +void gcr_importer_import_async (GcrImporter *importer, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); -gboolean gcr_importer_import_finish (GcrImporter *importer, +gboolean gcr_importer_import_finish (GcrImporter *importer, GAsyncResult *result, GError **error); -void gcr_importer_register (GType importer_type, +void gcr_importer_register (GType importer_type, GckAttributes *attrs); -void gcr_importer_register_well_known (void); +void gcr_importer_register_well_known (void); G_END_DECLS diff --git a/gcr/gcr-internal.h b/gcr/gcr-internal.h index fdf37488..ef6153fc 100644 --- a/gcr/gcr-internal.h +++ b/gcr/gcr-internal.h @@ -32,16 +32,6 @@ void _gcr_initialize_library (void); -gboolean _gcr_initialize_pkcs11 (GCancellable *cancellable, - GError **error); - -void _gcr_initialize_pkcs11_async (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); - -gboolean _gcr_initialize_pkcs11_finish (GAsyncResult *result, - GError **error); - void _gcr_set_pkcs11_config_dir (const gchar *dir); #endif /* GCR_INTERNAL_H_ */ diff --git a/gcr/gcr-library.c b/gcr/gcr-library.c index 409f6b45..b190a94a 100644 --- a/gcr/gcr-library.c +++ b/gcr/gcr-library.c @@ -211,14 +211,14 @@ on_initialize_registered (GObject *object, } void -_gcr_initialize_pkcs11_async (GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) +gcr_pkcs11_initialize_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) { GSimpleAsyncResult *res; res = g_simple_async_result_new (NULL, callback, user_data, - _gcr_initialize_pkcs11_async); + gcr_pkcs11_initialize_async); if (initialized_modules) { _gcr_debug ("already initialized, no need to async"); @@ -234,11 +234,11 @@ _gcr_initialize_pkcs11_async (GCancellable *cancellable, } gboolean -_gcr_initialize_pkcs11_finish (GAsyncResult *result, - GError **error) +gcr_pkcs11_initialize_finish (GAsyncResult *result, + GError **error) { g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, - _gcr_initialize_pkcs11_async), FALSE); + gcr_pkcs11_initialize_async), FALSE); if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error)) return FALSE; @@ -247,8 +247,8 @@ _gcr_initialize_pkcs11_finish (GAsyncResult *result, } gboolean -_gcr_initialize_pkcs11 (GCancellable *cancellable, - GError **error) +gcr_pkcs11_initialize (GCancellable *cancellable, + GError **error) { GList *results; GError *err = NULL; diff --git a/gcr/gcr-library.h b/gcr/gcr-library.h index 88e13a3f..617a580b 100644 --- a/gcr/gcr-library.h +++ b/gcr/gcr-library.h @@ -32,6 +32,16 @@ #include <glib.h> +void gcr_pkcs11_initialize_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean gcr_pkcs11_initialize_finish (GAsyncResult *result, + GError **error); + +gboolean gcr_pkcs11_initialize (GCancellable *cancellable, + GError **error); + GList* gcr_pkcs11_get_modules (void); void gcr_pkcs11_set_modules (GList *modules); diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c index 7990633d..2e7e65f6 100644 --- a/gcr/gcr-parser.c +++ b/gcr/gcr-parser.c @@ -113,15 +113,18 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; -typedef struct _GcrParsed { +struct _GcrParsed { + gint refs; GckAttributes *attrs; const gchar *description; gchar *label; - gconstpointer block; - gsize n_block; + gpointer data; + gsize n_data; + gboolean sensitive; + GDestroyNotify destroy_func; GcrDataFormat format; struct _GcrParsed *next; -} GcrParsed; +}; struct _GcrParserPrivate { GTree *specific_formats; @@ -211,8 +214,8 @@ parsed_attribute (GcrParsed *parsed, gconstpointer data, gsize n_data) { - g_assert (parsed); - g_assert (parsed->attrs); + g_assert (parsed != NULL); + g_assert (parsed->attrs != NULL); gck_attributes_add_data (parsed->attrs, type, data, n_data); } @@ -245,8 +248,8 @@ parsed_ulong_attribute (GcrParsed *parsed, CK_ATTRIBUTE_TYPE type, gulong value) { - g_assert (parsed); - g_assert (parsed->attrs); + g_assert (parsed != NULL); + g_assert (parsed->attrs != NULL); gck_attributes_add_ulong (parsed->attrs, type, value); } @@ -255,8 +258,8 @@ parsed_boolean_attribute (GcrParsed *parsed, CK_ATTRIBUTE_TYPE type, gboolean value) { - g_assert (parsed); - g_assert (parsed->attrs); + g_assert (parsed != NULL); + g_assert (parsed->attrs != NULL); gck_attributes_add_boolean (parsed->attrs, type, value); } @@ -264,25 +267,26 @@ parsed_boolean_attribute (GcrParsed *parsed, static void parsing_block (GcrParsed *parsed, gint format, - gconstpointer block, - gsize n_block) + gconstpointer data, + gsize n_data) { - g_assert (parsed); - g_assert (block); - g_assert (n_block); + g_assert (parsed != NULL); + g_assert (data != NULL); + g_assert (n_data != 0); g_assert (format); - g_assert (!parsed->block); + g_assert (parsed->data == NULL); + g_assert (parsed->destroy_func == NULL); parsed->format = format; - parsed->block = block; - parsed->n_block = n_block; + parsed->data = (gpointer)data; + parsed->n_data = n_data; } static void parsed_description (GcrParsed *parsed, CK_OBJECT_CLASS klass) { - g_assert (parsed); + g_assert (parsed != NULL); switch (klass) { case CKO_PRIVATE_KEY: parsed->description = _("Private Key"); @@ -306,10 +310,10 @@ static void parsing_object (GcrParsed *parsed, CK_OBJECT_CLASS klass) { - g_assert (parsed); - g_assert (!parsed->attrs); + g_assert (parsed != NULL); + g_assert (parsed->attrs == NULL); - if (klass == CKO_PRIVATE_KEY) + if (parsed->sensitive) parsed->attrs = gck_attributes_new_full ((GckAllocator)egg_secure_realloc); else parsed->attrs = gck_attributes_new (); @@ -323,9 +327,9 @@ parsed_attributes (GcrParsed *parsed, { gulong klass; - g_assert (parsed); - g_assert (attrs); - g_assert (!parsed->attrs); + g_assert (parsed != NULL); + g_assert (attrs != NULL); + g_assert (parsed->attrs == NULL); parsed->attrs = gck_attributes_ref (attrs); if (gck_attributes_find_ulong (attrs, CKA_CLASS, &klass)) @@ -336,15 +340,18 @@ static void parsed_label (GcrParsed *parsed, const gchar *label) { - g_assert (parsed); - g_assert (!parsed->label); + g_assert (parsed != NULL); + g_assert (parsed->label == NULL); parsed->label = g_strdup (label); } static GcrParsed * -push_parsed (GcrParser *self) +push_parsed (GcrParser *self, + gboolean sensitive) { GcrParsed *parsed = g_new0 (GcrParsed, 1); + parsed->refs = 0; + parsed->sensitive = sensitive; parsed->next = self->pv->parsed; self->pv->parsed = parsed; return parsed; @@ -436,7 +443,7 @@ parse_der_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data) gulong version; GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, TRUE); asn = egg_asn1x_create_and_decode (pk_asn1_tab, "RSAPrivateKey", data, n_data); if (!asn) @@ -489,7 +496,7 @@ parse_der_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data) GNode *asn = NULL; GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, TRUE); asn = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivateKey", data, n_data); if (!asn) @@ -528,7 +535,7 @@ parse_der_private_key_dsa_parts (GcrParser *self, const guchar *keydata, gsize n GNode *asn_key = NULL; GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, TRUE); asn_params = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAParameters", params, n_params); asn_key = egg_asn1x_create_and_decode (pk_asn1_tab, "DSAPrivatePart", keydata, n_keydata); @@ -592,7 +599,7 @@ parse_der_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data) GNode *asn = NULL; GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, TRUE); ret = GCR_ERROR_UNRECOGNIZED; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-PrivateKeyInfo", data, n_data); @@ -667,10 +674,10 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data) const guchar *params; gsize n_crypted, n_params; const gchar *password; - gint l; GcrParsed *parsed; + gint l; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); ret = GCR_ERROR_UNRECOGNIZED; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-8-EncryptedPrivateKeyInfo", data, n_data); @@ -770,7 +777,7 @@ parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data) if (asn == NULL) return GCR_ERROR_UNRECOGNIZED; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); parsing_block (parsed, GCR_FORMAT_DER_CERTIFICATE_X509, data, n_data); parsing_object (parsed, CKO_CERTIFICATE); @@ -850,7 +857,7 @@ parse_der_pkcs7 (GcrParser *self, const guchar *data, gsize n_data) GQuark oid; GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); ret = GCR_ERROR_UNRECOGNIZED; asn = egg_asn1x_create_and_decode (pkix_asn1_tab, "pkcs-7-ContentInfo", data, n_data); @@ -1036,7 +1043,7 @@ handle_pkcs12_bag (GcrParser *self, const guchar *data, gsize n_data) if (!element) goto done; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); friendly = parse_pkcs12_bag_friendly_name (egg_asn1x_node (asn, i, "bagAttributes", NULL)); if (friendly != NULL) @@ -1353,7 +1360,7 @@ parse_der_pkcs12 (GcrParser *self, const guchar *data, gsize n_data) GQuark oid; GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); ret = GCR_ERROR_UNRECOGNIZED; asn = decode_pkcs12_asn1_accepting_invalid_crap (pkix_asn1_tab, "pkcs-12-PFX", @@ -1420,7 +1427,7 @@ on_openpgp_packet (GPtrArray *records, if (records->len == 0) return; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); /* All we can do is the packet bounds */ parsing_block (parsed, GCR_FORMAT_OPENPGP_PACKET, outer, n_outer); @@ -1616,7 +1623,7 @@ handle_pem_data (GQuark type, if (!formats_for_armor_type (type, &inner_format, &outer_format)) return; - parsed = push_parsed (args->parser); + parsed = push_parsed (args->parser, FALSE); /* Fill in information necessary for prompting */ parsing_block (parsed, outer_format, outer, n_outer); @@ -1735,7 +1742,7 @@ on_openssh_public_key_parsed (GckAttributes *attrs, GcrParser *self = GCR_PARSER (user_data); GcrParsed *parsed; - parsed = push_parsed (self); + parsed = push_parsed (self, FALSE); parsing_block (parsed, GCR_FORMAT_OPENSSH_PUBLIC, outer, n_outer); parsed_attributes (parsed, attrs); parsed_label (parsed, label); @@ -2238,6 +2245,85 @@ gcr_parser_format_supported (GcrParser *self, return parser_format_lookup (format) ? TRUE : FALSE; } +GcrParsed * +gcr_parser_get_parsed (GcrParser *self) +{ + g_return_val_if_fail (GCR_IS_PARSER (self), NULL); + return self->pv->parsed; +} + +GType +gcr_parsed_get_type (void) +{ + static volatile gsize initialized = 0; + static GType type = 0; + if (g_once_init_enter (&initialized)) { + type = g_boxed_type_register_static ("GcrParsed", + (GBoxedCopyFunc)gcr_parsed_ref, + (GBoxedFreeFunc)gcr_parsed_unref); + g_once_init_leave (&initialized, 1); + } + return type; +} + +GcrParsed * +gcr_parsed_ref (GcrParsed *parsed) +{ + GcrParsed *copy; + + g_return_val_if_fail (parsed != NULL, NULL); + + /* Already had a reference */ + if (g_atomic_int_exchange_and_add (&parsed->refs, 1) >= 1) + return parsed; + + /* If this is the first reference, flatten the stack of parsed */ + copy = g_new0 (GcrParsed, 1); + copy->refs = 1; + copy->label = g_strdup (gcr_parsed_get_label (parsed)); + copy->attrs = gcr_parsed_get_attributes (parsed); + if (copy->attrs) + gck_attributes_ref (copy->attrs); + copy->description = gcr_parsed_get_description (parsed); + copy->next = NULL; + + /* Find the block of data to copy */ + while (parsed != NULL) { + if (parsed->data != NULL) { + if (parsed->sensitive) { + copy->data = egg_secure_alloc (parsed->n_data); + memcpy (copy->data, parsed->data, parsed->n_data); + copy->destroy_func = egg_secure_free; + } else { + copy->data = g_memdup (parsed->data, parsed->n_data); + copy->destroy_func = g_free; + } + copy->n_data = parsed->n_data; + break; + } + parsed = parsed->next; + } + + return copy; +} + +void +gcr_parsed_unref (gpointer parsed) +{ + GcrParsed *par = parsed; + + g_return_if_fail (parsed != NULL); + + if (g_atomic_int_dec_and_test (&par->refs)) { + if (par->attrs) + gck_attributes_unref (par->attrs); + g_free (par->label); + if (par->destroy_func) + (par->destroy_func) (par->data); + g_free (par); + } +} + /** * gcr_parser_get_parsed_description: * @self: The parser @@ -2251,13 +2337,19 @@ gcr_parser_format_supported (GcrParser *self, const gchar* gcr_parser_get_parsed_description (GcrParser *self) { - GcrParsed *parsed; - g_return_val_if_fail (GCR_IS_PARSER (self), NULL); + g_return_val_if_fail (self->pv->parsed != NULL, NULL); + + return gcr_parsed_get_description (self->pv->parsed); +} - for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) { +const gchar* +gcr_parsed_get_description (GcrParsed *parsed) +{ + while (parsed != NULL) { if (parsed->description != NULL) return parsed->description; + parsed = parsed->next; } return NULL; @@ -2273,16 +2365,22 @@ gcr_parser_get_parsed_description (GcrParser *self) * Returns: The attributes for the current item. These are owned by the parser * and should not be freed. */ -GckAttributes* +GckAttributes * gcr_parser_get_parsed_attributes (GcrParser *self) { - GcrParsed *parsed; - g_return_val_if_fail (GCR_IS_PARSER (self), NULL); + g_return_val_if_fail (self->pv->parsed != NULL, NULL); + + return gcr_parsed_get_attributes (self->pv->parsed); +} - for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) { +GckAttributes * +gcr_parsed_get_attributes (GcrParsed *parsed) +{ + while (parsed != NULL) { if (parsed->attrs != NULL) return parsed->attrs; + parsed = parsed->next; } return NULL; @@ -2301,13 +2399,19 @@ gcr_parser_get_parsed_attributes (GcrParser *self) const gchar* gcr_parser_get_parsed_label (GcrParser *self) { - GcrParsed *parsed; - g_return_val_if_fail (GCR_IS_PARSER (self), NULL); + g_return_val_if_fail (self->pv->parsed != NULL, NULL); - for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) { + return gcr_parsed_get_label (self->pv->parsed); +} + +const gchar* +gcr_parsed_get_label (GcrParsed *parsed) +{ + while (parsed != NULL) { if (parsed->label != NULL) return parsed->label; + parsed = parsed->next; } return NULL; @@ -2328,19 +2432,28 @@ gconstpointer gcr_parser_get_parsed_block (GcrParser *self, gsize *n_block) { - GcrParsed *parsed; - g_return_val_if_fail (GCR_IS_PARSER (self), NULL); - g_return_val_if_fail (n_block, NULL); + g_return_val_if_fail (n_block != NULL, NULL); + g_return_val_if_fail (self->pv->parsed != NULL, NULL); - for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) { - if (parsed->block != NULL) { - *n_block = parsed->n_block; - return parsed->block; + return gcr_parsed_get_data (self->pv->parsed, n_block); +} + +gconstpointer +gcr_parsed_get_data (GcrParsed *parsed, + gsize *n_data) +{ + g_return_val_if_fail (n_data != NULL, NULL); + + while (parsed != NULL) { + if (parsed->data != NULL) { + *n_data = parsed->n_data; + return parsed->data; } + parsed = parsed->next; } - *n_block = 0; + *n_data = 0; return NULL; } @@ -2358,18 +2471,23 @@ gcr_parser_get_parsed_block (GcrParser *self, GcrDataFormat gcr_parser_get_parsed_format (GcrParser *self) { - GcrParsed *parsed; - g_return_val_if_fail (GCR_IS_PARSER (self), 0); + g_return_val_if_fail (self->pv->parsed != NULL, 0); + + return gcr_parsed_get_format (self->pv->parsed); +} - for (parsed = self->pv->parsed; parsed != NULL; parsed = parsed->next) { - if (parsed->block != NULL) +GcrDataFormat +gcr_parsed_get_format (GcrParsed *parsed) +{ + while (parsed != NULL) { + if (parsed->data != NULL) return parsed->format; + parsed = parsed->next; } return 0; } - /* --------------------------------------------------------------------------------- * STREAM PARSING */ diff --git a/gcr/gcr-parser.h b/gcr/gcr-parser.h index d6cb1c52..cb2676c2 100644 --- a/gcr/gcr-parser.h +++ b/gcr/gcr-parser.h @@ -43,6 +43,7 @@ G_BEGIN_DECLS typedef struct _GcrParser GcrParser; typedef struct _GcrParserClass GcrParserClass; typedef struct _GcrParserPrivate GcrParserPrivate; +typedef struct _GcrParsed GcrParsed; struct _GcrParser { GObject parent; @@ -98,6 +99,8 @@ gboolean gcr_parser_parse_stream_finish (GcrParser *self, void gcr_parser_add_password (GcrParser *self, const gchar *password); +GcrParsed * gcr_parser_get_parsed (GcrParser *self); + const gchar* gcr_parser_get_parsed_label (GcrParser *self); const gchar* gcr_parser_get_parsed_description (GcrParser *self); @@ -109,6 +112,25 @@ gconstpointer gcr_parser_get_parsed_block (GcrParser *self, GcrDataFormat gcr_parser_get_parsed_format (GcrParser *self); +#define GCR_TYPE_PARSED (gcr_parsed_get_type ()) + +GType gcr_parsed_get_type (void) G_GNUC_CONST; + +GcrParsed * gcr_parsed_ref (GcrParsed *parsed); + +void gcr_parsed_unref (gpointer parsed); + +const gchar* gcr_parsed_get_label (GcrParsed *parsed); + +const gchar* gcr_parsed_get_description (GcrParsed *parsed); + +GckAttributes* gcr_parsed_get_attributes (GcrParsed *parsed); + +gconstpointer gcr_parsed_get_data (GcrParsed *parsed, + gsize *n_data); + +GcrDataFormat gcr_parsed_get_format (GcrParsed *parsed); + G_END_DECLS #endif /* __GCR_PARSER_H__ */ diff --git a/gcr/gcr-pkcs11-certificate.c b/gcr/gcr-pkcs11-certificate.c index 81a56d56..cb8b107e 100644 --- a/gcr/gcr-pkcs11-certificate.c +++ b/gcr/gcr-pkcs11-certificate.c @@ -121,7 +121,7 @@ perform_lookup_certificate (GckAttributes *search, GckEnumerator *en; GList *modules; - if (!_gcr_initialize_pkcs11 (cancellable, error)) + if (!gcr_pkcs11_initialize (cancellable, error)) return NULL; modules = gcr_pkcs11_get_modules (); @@ -366,7 +366,7 @@ gcr_pkcs11_certificate_lookup_issuer (GcrCertificate *certificate, GCancellable g_return_val_if_fail (GCR_IS_CERTIFICATE (certificate), NULL); - if (!_gcr_initialize_pkcs11 (cancellable, error)) + if (!gcr_pkcs11_initialize (cancellable, error)) return NULL; search = prepare_lookup_certificate_issuer (certificate); diff --git a/gcr/gcr-pkcs11-importer.c b/gcr/gcr-pkcs11-importer.c index 29a29720..f2932bab 100644 --- a/gcr/gcr-pkcs11-importer.c +++ b/gcr/gcr-pkcs11-importer.c @@ -24,8 +24,10 @@ #include "config.h" +#include "gcr-base.h" #include "gcr-internal.h" #include "gcr-library.h" +#include "gcr-internal.h" #include "gcr-parser.h" #include "gcr-pkcs11-importer.h" @@ -409,19 +411,11 @@ _gcr_pkcs11_importer_class_init (GcrPkcs11ImporterClass *klass) static GList * list_all_slots (void) { - GError *error = NULL; - GList *modules, *l; - GList *results = NULL; - - if (!_gcr_initialize_pkcs11 (NULL, &error)) { - g_warning ("couldn't initialize PKCS#11 modules: %s", error->message); - g_clear_error (&error); - return NULL; - } + GList *modules; + GList *results; modules = gcr_pkcs11_get_modules (); - for (l = modules; l != NULL; l = g_list_next (l)) - results = g_list_concat (results, gck_modules_get_slots (modules, TRUE)); + results = gck_modules_get_slots (modules, TRUE); gck_list_unref_free (modules); return results; @@ -468,7 +462,7 @@ is_slot_importable (GckSlot *slot, } static GList * -_gcr_pkcs11_importer_create_for_parsed (GcrParser *parser) +_gcr_pkcs11_importer_create_for_parsed (GcrParsed *parsed) { GcrImporter *self; GList *slots, *l; @@ -484,7 +478,7 @@ _gcr_pkcs11_importer_create_for_parsed (GcrParser *parser) if (importable) { self = _gcr_pkcs11_importer_new (l->data); - if (!gcr_importer_queue_for_parsed (self, parser)) + if (!gcr_importer_queue_for_parsed (self, parsed)) g_assert_not_reached (); results = g_list_prepend (results, self); } @@ -496,13 +490,13 @@ _gcr_pkcs11_importer_create_for_parsed (GcrParser *parser) static gboolean _gcr_pkcs11_importer_queue_for_parsed (GcrImporter *importer, - GcrParser *parser) + GcrParsed *parsed) { GcrPkcs11Importer *self = GCR_PKCS11_IMPORTER (importer); GckAttributes *attrs; gboolean is_private; - attrs = gcr_parser_get_parsed_attributes (parser); + attrs = gcr_parsed_get_attributes (parsed); if (!gck_attributes_find_boolean (attrs, CKA_PRIVATE, &is_private)) is_private = FALSE; @@ -580,3 +574,20 @@ _gcr_pkcs11_importer_get_imported (GcrPkcs11Importer *self) g_return_val_if_fail (GCR_IS_PKCS11_IMPORTER (self), NULL); return self->pv->objects; } + +void +_gcr_pkcs11_importer_queue (GcrPkcs11Importer *self, + GckAttributes *attrs) +{ + gboolean is_private; + + g_return_if_fail (GCR_IS_PKCS11_IMPORTER (self)); + g_return_if_fail (attrs != NULL); + + if (!gck_attributes_find_boolean (attrs, CKA_PRIVATE, &is_private)) + is_private = FALSE; + if (is_private) + self->pv->any_private = TRUE; + + g_queue_push_tail (&self->pv->queue, gck_attributes_ref (attrs)); +} diff --git a/gcr/gcr-pkcs11-importer.h b/gcr/gcr-pkcs11-importer.h index bbf752ca..bb0a8f21 100644 --- a/gcr/gcr-pkcs11-importer.h +++ b/gcr/gcr-pkcs11-importer.h @@ -59,6 +59,9 @@ GType _gcr_pkcs11_importer_get_type (void); GcrImporter * _gcr_pkcs11_importer_new (GckSlot *slot); +void _gcr_pkcs11_importer_queue (GcrPkcs11Importer *self, + GckAttributes *attrs); + GckSlot * _gcr_pkcs11_importer_get_slot (GcrPkcs11Importer *self); GList * _gcr_pkcs11_importer_get_imported (GcrPkcs11Importer *self); diff --git a/gcr/gcr-trust.c b/gcr/gcr-trust.c index eaa98001..48006e64 100644 --- a/gcr/gcr-trust.c +++ b/gcr/gcr-trust.c @@ -161,7 +161,7 @@ perform_is_certificate_pinned (GckAttributes *search, GList *slots; GckObject *object; - if (!_gcr_initialize_pkcs11 (cancellable, error)) + if (!gcr_pkcs11_initialize (cancellable, error)) return FALSE; slots = gcr_pkcs11_get_trust_lookup_slots (); @@ -339,7 +339,7 @@ perform_add_pinned_certificate (GckAttributes *search, GckEnumerator *en; GList *slots; - if (!_gcr_initialize_pkcs11 (cancellable, error)) + if (!gcr_pkcs11_initialize (cancellable, error)) return FALSE; slots = gcr_pkcs11_get_trust_lookup_slots (); @@ -553,7 +553,7 @@ perform_remove_pinned_certificate (GckAttributes *attrs, GckEnumerator *en; GList *slots; - if (!_gcr_initialize_pkcs11 (cancellable, error)) + if (!gcr_pkcs11_initialize (cancellable, error)) return FALSE; slots = gcr_pkcs11_get_trust_lookup_slots (); @@ -735,7 +735,7 @@ perform_is_certificate_anchored (GckAttributes *attrs, GList *slots; GckObject *object; - if (!_gcr_initialize_pkcs11 (cancellable, error)) + if (!gcr_pkcs11_initialize (cancellable, error)) return FALSE; slots = gcr_pkcs11_get_trust_lookup_slots (); diff --git a/gcr/gcr-viewer-widget.c b/gcr/gcr-viewer-widget.c index 5db8b62b..b06b1f60 100644 --- a/gcr/gcr-viewer-widget.c +++ b/gcr/gcr-viewer-widget.c @@ -76,7 +76,7 @@ struct _GcrViewerWidgetClass { void (*added) (GcrViewerWidget *widget, GcrRenderer *renderer, - GcrParser *parser); + GcrParsed *parsed); }; struct _GcrViewerWidgetPrivate { @@ -138,7 +138,8 @@ on_parser_parsed (GcrParser *parser, /* Let callers know we're rendering data */ if (actual == TRUE) - g_signal_emit (self, signals[ADDED], 0, renderer, parser); + g_signal_emit (self, signals[ADDED], 0, renderer, + gcr_parser_get_parsed (parser)); g_object_unref (renderer); } @@ -277,8 +278,8 @@ gcr_viewer_widget_class_init (GcrViewerWidgetClass *klass) signals[ADDED] = g_signal_new ("added", GCR_TYPE_VIEWER_WIDGET, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GcrViewerWidgetClass, added), - NULL, NULL, _gcr_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + NULL, NULL, _gcr_marshal_VOID__OBJECT_BOXED, + G_TYPE_NONE, 2, G_TYPE_OBJECT, GCR_TYPE_PARSED); } static void diff --git a/gcr/gcr-viewer-window.c b/gcr/gcr-viewer-window.c index 63019172..e37287bd 100644 --- a/gcr/gcr-viewer-window.c +++ b/gcr/gcr-viewer-window.c @@ -41,11 +41,11 @@ G_DEFINE_TYPE (GcrViewerWindow, _gcr_viewer_window, GTK_TYPE_WINDOW); static void on_viewer_renderer_added (GcrViewerWidget *viewer, GcrRenderer *renderer, - GcrParser *parser, + GcrParsed *parsed, gpointer user_data) { GcrViewerWindow *self = GCR_VIEWER_WINDOW (user_data); - gcr_import_button_add_parsed (self->pv->import, parser); + gcr_import_button_add_parsed (self->pv->import, parsed); } static void diff --git a/tool/gkr-tool-import.c b/tool/gkr-tool-import.c index 05f26ddc..548831c5 100644 --- a/tool/gkr-tool-import.c +++ b/tool/gkr-tool-import.c @@ -146,12 +146,14 @@ on_parser_parsed (GcrParser *parser, gpointer user_data) { ImportClosure *closure = user_data; + GcrParsed *parsed; GList *filtered; + parsed = gcr_parser_get_parsed (parser); if (closure->num_parsed == 0) { - closure->importers = gcr_importer_create_for_parsed (parser); + closure->importers = gcr_importer_create_for_parsed (parsed); } else { - filtered = gcr_importer_queue_and_filter_for_parsed (closure->importers, parser); + filtered = gcr_importer_queue_and_filter_for_parsed (closure->importers, parsed); gck_list_unref_free (closure->importers); closure->importers = filtered; } |