[gnome-keyring] gcr: Support get surrounding data block from GcrParser
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring] gcr: Support get surrounding data block from GcrParser
- Date: Thu, 1 Sep 2011 10:16:04 +0000 (UTC)
commit 37310efb89dc5d50e77e8843c6e464df38761781
Author: Stef Walter <stefw collabora co uk>
Date: Thu Aug 25 16:50:03 2011 +0200
gcr: Support get surrounding data block from GcrParser
* This is needed for importing parsed data into other places
than PKCS#11 tokens.
* Going to use this in seahorse.
docs/reference/gcr/gcr-sections.txt | 1 +
gcr/gcr-parser.c | 118 +++++++++++++++++++++++++---------
gcr/gcr-parser.h | 3 +
gcr/tests/test-parser.c | 27 ++++++++
4 files changed, 118 insertions(+), 31 deletions(-)
---
diff --git a/docs/reference/gcr/gcr-sections.txt b/docs/reference/gcr/gcr-sections.txt
index 37a62ac..c4e8937 100644
--- a/docs/reference/gcr/gcr-sections.txt
+++ b/docs/reference/gcr/gcr-sections.txt
@@ -18,6 +18,7 @@ gcr_parser_add_password
gcr_parser_get_parsed_label
gcr_parser_get_parsed_description
gcr_parser_get_parsed_attributes
+gcr_parser_get_parsed_block
<SUBSECTION Standard>
GcrParserPrivate
GCR_PARSER
diff --git a/gcr/gcr-parser.c b/gcr/gcr-parser.c
index d9500dd..2ad68ab 100644
--- a/gcr/gcr-parser.c
+++ b/gcr/gcr-parser.c
@@ -137,10 +137,12 @@ struct _GcrParserPrivate {
GTree *specific_formats;
gboolean normal_formats;
GPtrArray *passwords;
-
+
GckAttributes *parsed_attrs;
const gchar *parsed_desc;
gchar *parsed_label;
+ gconstpointer parsing_block;
+ gsize parsing_n_block;
};
G_DEFINE_TYPE (GcrParser, gcr_parser, G_TYPE_OBJECT);
@@ -233,8 +235,15 @@ parsed_asn1_attribute (GcrParser *self, GNode *asn, const guchar *data, gsize n_
}
static void
-parsed_clear (GcrParser *self, CK_OBJECT_CLASS klass)
+parsing_begin (GcrParser *self,
+ CK_OBJECT_CLASS klass,
+ gconstpointer block,
+ gsize n_block)
{
+ g_assert (GCR_IS_PARSER (self));
+ g_assert (block);
+ g_assert (n_block);
+
if (self->pv->parsed_attrs)
gck_attributes_unref (self->pv->parsed_attrs);
if (klass == CKO_PRIVATE_KEY)
@@ -260,6 +269,9 @@ parsed_clear (GcrParser *self, CK_OBJECT_CLASS klass)
self->pv->parsed_desc = NULL;
break;
}
+
+ self->pv->parsing_block = block;
+ self->pv->parsing_n_block = n_block;
}
static void
@@ -278,6 +290,20 @@ parsed_attribute (GcrParser *self, CK_ATTRIBUTE_TYPE type, gconstpointer data, g
}
static void
+parsing_end (GcrParser *self)
+{
+ g_assert (GCR_IS_PARSER (self));
+ self->pv->parsing_block = NULL;
+ self->pv->parsing_n_block = 0;
+ if (self->pv->parsed_attrs)
+ gck_attributes_unref (self->pv->parsed_attrs);
+ self->pv->parsed_attrs = NULL;
+ g_free (self->pv->parsed_label);
+ self->pv->parsed_label = NULL;
+ self->pv->parsed_desc = NULL;
+}
+
+static void
parsed_ulong (GcrParser *self, CK_ATTRIBUTE_TYPE type, gulong value)
{
g_assert (GCR_IS_PARSER (self));
@@ -364,7 +390,7 @@ parse_der_private_key_rsa (GcrParser *self, const guchar *data, gsize n_data)
if (!asn)
goto done;
- parsed_clear (self, CKO_PRIVATE_KEY);
+ parsing_begin (self, CKO_PRIVATE_KEY, data, n_data);
parsed_ulong (self, CKA_KEY_TYPE, CKK_RSA);
parsed_boolean (self, CKA_PRIVATE, CK_TRUE);
res = GCR_ERROR_FAILURE;
@@ -394,7 +420,8 @@ done:
egg_asn1x_destroy (asn);
if (res == GCR_ERROR_FAILURE)
g_message ("invalid RSA key");
-
+
+ parsing_end (self);
return res;
}
@@ -412,7 +439,7 @@ parse_der_private_key_dsa (GcrParser *self, const guchar *data, gsize n_data)
if (!asn)
goto done;
- parsed_clear (self, CKO_PRIVATE_KEY);
+ parsing_begin (self, CKO_PRIVATE_KEY, data, n_data);
parsed_ulong (self, CKA_KEY_TYPE, CKK_DSA);
parsed_boolean (self, CKA_PRIVATE, CK_TRUE);
ret = GCR_ERROR_FAILURE;
@@ -430,7 +457,8 @@ done:
egg_asn1x_destroy (asn);
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid DSA key");
-
+
+ parsing_end (self);
return ret;
}
@@ -447,7 +475,6 @@ parse_der_private_key_dsa_parts (GcrParser *self, const guchar *keydata, gsize n
if (!asn_params || !asn_key)
goto done;
- parsed_clear (self, CKO_PRIVATE_KEY);
parsed_ulong (self, CKA_KEY_TYPE, CKK_DSA);
parsed_boolean (self, CKA_PRIVATE, CK_TRUE);
ret = GCR_ERROR_FAILURE;
@@ -466,8 +493,8 @@ done:
egg_asn1x_destroy (asn_params);
if (ret == GCR_ERROR_FAILURE)
g_message ("invalid DSA key");
-
- return ret;
+
+ return ret;
}
/* -----------------------------------------------------------------------------
@@ -478,11 +505,11 @@ static gint
parse_der_private_key (GcrParser *self, const guchar *data, gsize n_data)
{
gint res;
-
+
res = parse_der_private_key_rsa (self, data, n_data);
if (res == GCR_ERROR_UNRECOGNIZED)
res = parse_der_private_key_dsa (self, data, n_data);
-
+
return res;
}
@@ -533,7 +560,7 @@ parse_der_pkcs8_plain (GcrParser *self, const guchar *data, gsize n_data)
ret = SUCCESS;
done:
- if (ret == SUCCESS) {
+ if (ret == SUCCESS) {
switch (key_type) {
case CKK_RSA:
ret = parse_der_private_key_rsa (self, keydata, n_keydata);
@@ -541,18 +568,20 @@ done:
case CKK_DSA:
/* Try the normal sane format */
ret = parse_der_private_key_dsa (self, keydata, n_keydata);
-
+
+ parsing_begin (self, CKO_PRIVATE_KEY, data, n_data);
/* Otherwise try the two part format that everyone seems to like */
if (ret == GCR_ERROR_UNRECOGNIZED && params && n_params)
ret = parse_der_private_key_dsa_parts (self, keydata, n_keydata,
params, n_params);
+ parsing_end (self);
break;
default:
g_message ("invalid or unsupported key type in PKCS#8 key");
ret = GCR_ERROR_UNRECOGNIZED;
break;
};
-
+
} else if (ret == GCR_ERROR_FAILURE) {
g_message ("invalid PKCS#8 key");
}
@@ -591,7 +620,7 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
params = egg_asn1x_get_raw_element (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), &n_params);
- parsed_clear (self, CKO_PRIVATE_KEY);
+ parsing_begin (self, CKO_PRIVATE_KEY, data, n_data);
/* Loop to try different passwords */
for (;;) {
@@ -637,7 +666,9 @@ parse_der_pkcs8_encrypted (GcrParser *self, const guchar *data, gsize n_data)
/* We assume unrecognized data, is a bad encryption key */
}
-
+
+ parsing_end (self);
+
done:
if (cih)
gcry_cipher_close (cih);
@@ -673,7 +704,8 @@ parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
if (asn == NULL)
return GCR_ERROR_UNRECOGNIZED;
- parsed_clear (self, CKO_CERTIFICATE);
+ parsing_begin (self, CKO_CERTIFICATE, data, n_data);
+
parsed_ulong (self, CKA_CERTIFICATE_TYPE, CKC_X_509);
name = egg_dn_read_part (egg_asn1x_node (asn, "tbsCertificate", "subject", "rdnSequence", NULL), "CN");
@@ -686,7 +718,8 @@ parse_der_certificate (GcrParser *self, const guchar *data, gsize n_data)
parsed_attribute (self, CKA_VALUE, data, n_data);
parsed_fire (self);
-
+
+ parsing_end (self);
return SUCCESS;
}
@@ -923,8 +956,6 @@ handle_pkcs12_encrypted_bag (GcrParser *self, const guchar *data, gsize n_data)
if (!params)
goto done;
- parsed_clear (self, 0);
-
/* Loop to try different passwords */
for (;;) {
@@ -1204,23 +1235,26 @@ handle_encrypted_pem (GcrParser *self, GQuark type, gint subformat,
}
/* Fill in information necessary for prompting */
- parsed_clear (self, pem_type_to_class (type));
-
+ parsing_begin (self, pem_type_to_class (type), data, n_data);
+
+ res = GCR_ERROR_FAILURE;
for (;;) {
res = enum_next_password (self, &pstate, &password);
if (res != SUCCESS)
- return res;
-
+ break;
+
decrypted = NULL;
n_decrypted = 0;
/* Decrypt, this will result in garble if invalid password */
ret = egg_openssl_decrypt_block (val, password, -1, data, n_data,
&decrypted, &n_decrypted);
- if (!ret)
- return GCR_ERROR_FAILURE;
-
+ if (!ret) {
+ res = GCR_ERROR_FAILURE;
+ break;
+ }
+
g_assert (decrypted);
/* Unpad the DER data */
@@ -1234,10 +1268,11 @@ handle_encrypted_pem (GcrParser *self, GQuark type, gint subformat,
/* Unrecognized is a bad password */
if (res != GCR_ERROR_UNRECOGNIZED)
- return res;
+ break;
}
-
- return GCR_ERROR_FAILURE;
+
+ parsing_end (self);
+ return res;
}
typedef struct {
@@ -1265,7 +1300,7 @@ handle_pem_data (GQuark type, const guchar *data, gsize n_data,
if (val && strcmp (val, "4,ENCRYPTED") == 0)
encrypted = TRUE;
}
-
+
if (encrypted)
res = handle_encrypted_pem (args->parser, type, args->subformat,
headers, data, n_data);
@@ -1849,6 +1884,27 @@ gcr_parser_get_parsed_label (GcrParser *self)
return self->pv->parsed_label;
}
+/**
+ * gcr_parser_get_parsed_block:
+ * @self: a parser
+ * @n_block: a location to place the size of the block
+ *
+ * Get the raw data block that represents this parsed object. This is only
+ * valid during the GcrParser::parsed signal.
+ *
+ * Returns: The raw data block of the currently parsed item. The value is
+ * owned by the parser and should not be freed.
+ */
+gconstpointer
+gcr_parser_get_parsed_block (GcrParser *self,
+ gsize *n_block)
+{
+ g_return_val_if_fail (GCR_IS_PARSER (self), NULL);
+ g_return_val_if_fail (n_block, NULL);
+ *n_block = self->pv->parsing_n_block;
+ return self->pv->parsing_block;
+}
+
/* ---------------------------------------------------------------------------------
* STREAM PARSING
*/
diff --git a/gcr/gcr-parser.h b/gcr/gcr-parser.h
index f52972a..91bd428 100644
--- a/gcr/gcr-parser.h
+++ b/gcr/gcr-parser.h
@@ -104,6 +104,9 @@ const gchar* gcr_parser_get_parsed_description (GcrParser *self);
GckAttributes* gcr_parser_get_parsed_attributes (GcrParser *self);
+gconstpointer gcr_parser_get_parsed_block (GcrParser *self,
+ gsize *n_block);
+
G_END_DECLS
#endif /* __GCR_PARSER_H__ */
diff --git a/gcr/tests/test-parser.c b/gcr/tests/test-parser.c
index b9d2ab0..7d60150 100644
--- a/gcr/tests/test-parser.c
+++ b/gcr/tests/test-parser.c
@@ -58,12 +58,37 @@ typedef struct {
} Test;
static void
+ensure_block_can_be_parsed (gconstpointer block,
+ gsize n_block)
+{
+ GcrParser *parser;
+ gboolean result;
+ GError *error = NULL;
+
+ g_assert (block);
+ g_assert (n_block);
+
+ parser = gcr_parser_new ();
+ result = gcr_parser_parse_data (parser, block, n_block, &error);
+
+ if (!result) {
+ g_critical ("The data returned from gcr_parser_get_parsed_block() "
+ "cannot be parsed: %s", error->message);
+ g_assert_not_reached ();
+ }
+
+ g_object_unref (parser);
+}
+
+static void
parsed_item (GcrParser *par, gpointer user_data)
{
GckAttributes *attrs;
const gchar *description;
const gchar *label;
Test *test = user_data;
+ gconstpointer block;
+ gsize n_block;
g_assert (GCR_IS_PARSER (par));
g_assert (par == test->parser);
@@ -73,6 +98,8 @@ parsed_item (GcrParser *par, gpointer user_data)
description = gcr_parser_get_parsed_description (test->parser);
label = gcr_parser_get_parsed_label (test->parser);
+ block = gcr_parser_get_parsed_block (test->parser, &n_block);
+ ensure_block_can_be_parsed (block, n_block);
if (g_test_verbose ())
g_print ("%s: '%s'\n", description, label);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]