[gnome-keyring] gcr: Support get surrounding data block from GcrParser



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]