[gnome-keyring/asn1-work: 15/18] [egg] Separate real ASN nodes in the tree from options.
- From: Stefan Walter <stefw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-keyring/asn1-work: 15/18] [egg] Separate real ASN nodes in the tree from options.
- Date: Thu, 24 Jun 2010 03:39:59 +0000 (UTC)
commit 2576fec96ca7a13675288e7038c1907b75518656
Author: Stef Walter <stef memberwebs com>
Date: Sat Dec 26 20:37:03 2009 +0000
[egg] Separate real ASN nodes in the tree from options.
egg/egg-asn1x.c | 324 ++++++++++++++++++++++++++++++-------------------------
1 files changed, 179 insertions(+), 145 deletions(-)
---
diff --git a/egg/egg-asn1x.c b/egg/egg-asn1x.c
index d325fb2..e861948 100644
--- a/egg/egg-asn1x.c
+++ b/egg/egg-asn1x.c
@@ -30,12 +30,6 @@
#include <stdlib.h>
#include <string.h>
-enum {
- NO_VALUE = 0,
- DER_VALUE,
- C_VALUE
-};
-
/* From libtasn1's int.h */
enum {
TYPE_CONSTANT = 1,
@@ -100,12 +94,11 @@ typedef struct _Atlv {
typedef struct _Anode {
const ASN1_ARRAY_TYPE *def;
const ASN1_ARRAY_TYPE *join;
+ GList *opts;
Atlv *data;
gchar* failure;
} Anode;
-/* TODO: Validate: LIST SIZE */
-
/* Forward Declarations */
static gboolean anode_decode_anything (GNode*, Atlv*);
static gboolean anode_decode_anything_for_flags (GNode *, Atlv*, gint);
@@ -135,6 +128,7 @@ anode_free_func (GNode *node, gpointer unused)
{
Anode *an = node->data;
anode_clear (node);
+ g_list_free (an->opts);
g_slice_free (Anode, an);
return FALSE;
}
@@ -155,6 +149,7 @@ anode_copy_func (gconstpointer src, gpointer unused)
Anode *an = g_slice_new0 (Anode);
an->def = san->def;
an->join = san->join;
+ an->opts = g_list_copy (san->opts);
return an;
}
@@ -231,15 +226,13 @@ anode_def_value (GNode *node)
}
static gulong
-anode_def_value_as_ulong (GNode *node)
+anode_def_value_as_ulong (ASN1_ARRAY_TYPE *def)
{
- const gchar* value;
gchar *end = NULL;
gulong lval;
- value = anode_def_value (node);
- g_return_val_if_fail (value, G_MAXULONG);
- lval = strtoul (value, &end, 10);
+ g_return_val_if_fail (def->value, G_MAXULONG);
+ lval = strtoul (def->value, &end, 10);
g_return_val_if_fail (end && !end[0], G_MAXULONG);
return lval;
}
@@ -257,73 +250,47 @@ anode_child_with_name (GNode *node, const gchar *name)
return NULL;
}
-static GNode*
-anode_child_with_type (GNode *node, gint type)
-{
- GNode *child;
-
- for (child = node->children; child; child = child->next) {
- if (anode_def_type (child) == type)
- return child;
- }
-
- return NULL;
-}
-
-static GNode*
-anode_next_with_type (GNode *node, gint type)
-{
- for (node = node->next; node; node = node->next) {
- if (anode_def_type (node) == type)
- return node;
- }
- return NULL;
-}
-
-static GNode*
-anode_child_with_real_type (GNode *node)
+static void
+anode_opt_add (GNode *node, const ASN1_ARRAY_TYPE *def)
{
- GNode *child;
-
- for (child = node->children; child; child = child->next) {
- if (anode_def_type_is_real (child))
- return child;
- }
-
- return NULL;
+ Anode *an = node->data;
+ an->opts = g_list_append (an->opts, (gpointer)def);
}
-static GNode*
-anode_next_with_real_type (GNode *node)
+static ASN1_ARRAY_TYPE*
+anode_opt_lookup (GNode *node, gint type, const gchar *name)
{
- for (node = node->next; node; node = node->next) {
- if (anode_def_type_is_real (node))
- return node;
+ Anode *an = node->data;
+ ASN1_ARRAY_TYPE* def;
+ GList *l;
+
+ for (l = an->opts; l; l = g_list_next (l)) {
+ def = l->data;
+ if (name && def->name && !g_str_equal (name, def->name))
+ continue;
+ if ((def->type & 0xFF) == type)
+ return def;
}
return NULL;
}
-static gboolean
-anode_def_size_value (GNode *node, const gchar *text, gulong *value)
+static GList*
+anode_opts_lookup (GNode *node, gint type, const gchar *name)
{
- gchar *end = NULL;
-
- if (text == NULL) {
- *value = 0;
- return FALSE;
- } else if (g_str_equal (text, "MAX")) {
- *value = G_MAXULONG;
- return TRUE;
- } else if (g_ascii_isalpha (text[0])) {
- node = anode_child_with_name (node, text);
- g_return_val_if_fail (node, FALSE);
- return anode_def_size_value (node, anode_def_value (node), value);
+ Anode *an = node->data;
+ ASN1_ARRAY_TYPE* def;
+ GList *l, *res = NULL;
+
+ for (l = an->opts; l; l = g_list_next (l)) {
+ def = l->data;
+ if (name && def->name && !g_str_equal (name, def->name))
+ continue;
+ if ((def->type & 0xFF) == type)
+ res = g_list_prepend (res, def);
}
- *value = strtoul (text, &end, 10);
- g_return_val_if_fail (end && !end[0], FALSE);
- return TRUE;
+ return g_list_reverse (res);
}
static void
@@ -372,15 +339,13 @@ anode_failure_get (GNode *node)
static gulong
anode_encode_tag_for_flags (GNode *node, gint flags)
{
- GNode *child;
-
- g_return_val_if_fail (anode_def_type_is_real (node), G_MAXULONG);
+ ASN1_ARRAY_TYPE *def;
/* A context specific tag */
if (flags & FLAG_TAG) {
- child = anode_child_with_type (node, TYPE_TAG);
- g_return_val_if_fail (child, G_MAXULONG);
- return anode_def_value_as_ulong (child);
+ def = anode_opt_lookup (node, TYPE_TAG, NULL);
+ g_return_val_if_fail (def, G_MAXULONG);
+ return anode_def_value_as_ulong (def);
}
/* A tag from the universal set */
@@ -571,8 +536,7 @@ anode_decode_choice (GNode *node, Atlv *tlv)
{
GNode *child;
- for (child = anode_child_with_real_type (node);
- child; child = anode_next_with_real_type (child)) {
+ for (child = node->children; child; child = child->next) {
if (anode_decode_anything (child, tlv)) {
anode_set_tlv_data (node, tlv);
return TRUE;
@@ -633,8 +597,7 @@ anode_decode_sequence_or_set (GNode *node, Atlv *outer)
* we have are sorted.
*/
- for (child = anode_child_with_real_type (node), i = 0;
- child; child = anode_next_with_real_type (child), ++i) {
+ for (child = node->children, i = 0; child; child = child->next, ++i) {
if (!anode_decode_tlv_for_contents (outer, i == 0, &tlv))
return anode_failure (node, "invalid encoding of child");
@@ -653,15 +616,19 @@ anode_decode_sequence_or_set (GNode *node, Atlv *outer)
static gboolean
anode_decode_sequence_or_set_of (GNode *node, Atlv *outer)
{
- GNode *child, *copy;
+ GNode *child, *other;
Atlv tlv;
gint i;
outer->len = 0;
- /* The one and only child */
- child = anode_child_with_real_type (node);
- g_return_val_if_fail (child, -1);
+ /* The first child */
+ child = node->children;
+ g_return_val_if_fail (child, FALSE);
+
+ /* Remove all the other children */
+ while (child->next)
+ anode_destroy (child->next);
/* Try to dig out as many of them as possible */
for (i = 0; TRUE; ++i) {
@@ -673,9 +640,14 @@ anode_decode_sequence_or_set_of (GNode *node, Atlv *outer)
if (tlv.off == 0)
break;
- copy = anode_clone (child);
- g_node_append (node, copy);
- if (!anode_decode_anything (copy, &tlv))
+ if (i == 0) {
+ other = child;
+ } else {
+ other = anode_clone (child);
+ g_node_append (node, other);
+ }
+
+ if (!anode_decode_anything (other, &tlv))
return FALSE;
outer->len = (tlv.end - outer->buf) - outer->off;
@@ -1345,7 +1317,7 @@ egg_asn1x_node (GNode *asn, ...)
const gchar *name;
va_list va;
gint type;
- gint index, i;
+ gint index;
g_return_val_if_fail (asn, NULL);
va_start (va, asn);
@@ -1358,10 +1330,7 @@ egg_asn1x_node (GNode *asn, ...)
index = va_arg (va, gint);
if (index == 0)
return node;
- node = anode_child_with_real_type (node);
- g_return_val_if_fail (node, NULL);
- for (i = 1; node && i <= index; ++i)
- node = anode_next_with_real_type (node);
+ node = g_node_nth_child (node, index);
if (node == NULL)
return NULL;
@@ -1543,19 +1512,46 @@ egg_asn1x_get_oid_as_quark (GNode *node)
*/
static gboolean
+anode_parse_size (GNode *node, const gchar *text, gulong *value)
+{
+ ASN1_ARRAY_TYPE *def;
+ gchar *end = NULL;
+
+ if (text == NULL) {
+ *value = 0;
+ return FALSE;
+ } else if (g_str_equal (text, "MAX")) {
+ *value = G_MAXULONG;
+ return TRUE;
+ } else if (g_ascii_isalpha (text[0])) {
+ def = anode_opt_lookup (node, TYPE_INTEGER, text);
+ g_return_val_if_fail (def, FALSE);
+ return anode_parse_size (node, def->value, value);
+ }
+
+ *value = strtoul (text, &end, 10);
+ g_return_val_if_fail (end && !end[0], FALSE);
+ return TRUE;
+}
+
+
+static gboolean
anode_validate_size (GNode *node, gulong length)
{
- GNode *size;
+ ASN1_ARRAY_TYPE *size;
gulong value1 = 0;
gulong value2 = G_MAXULONG;
if (anode_def_flags (node) & FLAG_SIZE) {
- size = anode_child_with_type (node, TYPE_SIZE);
+ size = anode_opt_lookup (node, TYPE_SIZE, NULL);
+ if (size == NULL) {
+ egg_asn1x_dump (g_node_get_root (node));
+ }
g_return_val_if_fail (size, FALSE);
- if (!anode_def_size_value (size, anode_def_value (size), &value1))
+ if (!anode_parse_size (node, size->value, &value1))
g_return_val_if_reached (FALSE);
- if (anode_def_flags (size) & FLAG_MIN_MAX) {
- if (!anode_def_size_value (size, anode_def_name (size), &value2))
+ if (size->type & FLAG_MIN_MAX) {
+ if (!anode_parse_size (node, size->name, &value2))
g_return_val_if_reached (FALSE);
if (length < value1 || length >= value2)
return anode_failure (node, "content size is out of bounds");
@@ -1571,9 +1567,9 @@ anode_validate_size (GNode *node, gulong length)
static gboolean
anode_validate_integer (GNode *node, Atlv *tlv)
{
+ GList *constants, *l;
gulong value, check;
gboolean found;
- GNode *child;
gint flags;
g_assert (tlv);
@@ -1590,15 +1586,16 @@ anode_validate_integer (GNode *node, Atlv *tlv)
/* Look through the list of constants */
found = FALSE;
- for (child = anode_child_with_type (node, TYPE_CONSTANT);
- child; child = anode_next_with_type (child, TYPE_CONSTANT)) {
- check = anode_def_value_as_ulong (child);
+ constants = anode_opts_lookup (node, TYPE_CONSTANT, NULL);
+ for (l = constants; l; l = g_list_next (l)) {
+ check = anode_def_value_as_ulong (l->data);
g_return_val_if_fail (check != G_MAXULONG, FALSE);
if (check == value) {
found = TRUE;
break;
}
}
+ g_list_free (constants);
if (!found)
return anode_failure (node, "integer not part of listed set");
@@ -1692,8 +1689,7 @@ anode_validate_choice (GNode *node)
GNode *child;
/* One and only one of the children must be set */
- for (child = anode_child_with_real_type (node);
- child; child = anode_next_with_real_type (child)) {
+ for (child = node->children; child; child = child->next) {
if (anode_get_tlv_data (child)) {
if (have)
return anode_failure (node, "only one choice may be set");
@@ -1714,8 +1710,7 @@ anode_validate_sequence_or_set (GNode *node)
GNode *child;
/* All of the children must validate properly */
- for (child = anode_child_with_real_type (node);
- child; child = anode_next_with_real_type (child)) {
+ for (child = node->children; child; child = child->next) {
if (!anode_validate_anything (child))
return FALSE;
}
@@ -1730,17 +1725,15 @@ anode_validate_sequence_or_set_of (GNode *node)
Atlv *tlv;
gulong tag;
gulong count;
+ gint i;
/* The first one must be empty */
- child = anode_child_with_real_type (node);
- g_return_val_if_fail (child, FALSE);
- g_return_val_if_fail (!anode_get_tlv_data (child), FALSE);
- tag = anode_encode_tag (child);
+ /* All the children must validate properly */
+ for (child = node->children, i = 0; child; child = child->next, ++i) {
+ if (i == 0)
+ tag = anode_encode_tag (child);
- /* All of the other children must validate properly */
- for (child = anode_next_with_real_type (child);
- child; child = anode_next_with_real_type (child)) {
if (!anode_validate_anything (child))
return FALSE;
@@ -1855,14 +1848,14 @@ join_each_child (GNode *child, gpointer data)
g_node_append (node, child);
}
-static GNode*
-lookup_type_node (const ASN1_ARRAY_TYPE *defs, const gchar *identifier, gint type)
+static const ASN1_ARRAY_TYPE*
+lookup_def (const ASN1_ARRAY_TYPE *defs, const gchar *identifier, gint type)
{
/* Find the one we're interested in */
while (defs && (defs->value || defs->type || defs->name)) {
if ((defs->type & 0xFF) == type &&
defs->name && g_str_equal (identifier, defs->name))
- return anode_new (defs);
+ return defs;
++defs;
}
@@ -1873,6 +1866,7 @@ static gboolean
traverse_and_prepare (GNode *node, gpointer data)
{
const ASN1_ARRAY_TYPE *defs = data;
+ const ASN1_ARRAY_TYPE *def;
const gchar *identifier;
Anode *an, *anj;
GNode *join = NULL;
@@ -1891,35 +1885,52 @@ traverse_and_prepare (GNode *node, gpointer data)
an->join = anj->def;
}
- if (join) {
+ if (join)
g_node_children_foreach (join, G_TRAVERSE_ALL, join_each_child, node);
- egg_asn1x_destroy (join);
- }
/* Lookup the max set size */
if (anode_def_type (node) == TYPE_SIZE) {
identifier = anode_def_name (node);
if (identifier && !g_str_equal (identifier, "MAX") &&
g_ascii_isalpha (identifier[0])) {
- join = lookup_type_node (defs, identifier, TYPE_INTEGER);
- g_return_val_if_fail (join, TRUE);
- g_node_append (node, join);
+ def = lookup_def (defs, identifier, TYPE_INTEGER);
+ g_return_val_if_fail (def, TRUE);
+ anode_opt_add (node, def);
}
}
- /* Sort the children of any sets */
- if (anode_def_type (node) == TYPE_SET) {
+ /* Anything child not a real node, we put into opts */
+ if (anode_def_type_is_real (node)) {
child = node->children;
while (child) {
next = child->next;
- if (anode_def_type_is_real (child)) {
+ if (!anode_def_type_is_real (child)) {
+ an = child->data;
+ anode_opt_add (node, an->def);
+ for (l = an->opts; l; l = g_list_next (l))
+ anode_opt_add (node, l->data);
g_node_unlink (child);
- list = g_list_prepend (list, child);
+ g_node_destroy (child);
}
child = next;
}
+ }
+
+ if (join) {
+ an = join->data;
+ for (l = an->opts; l; l = g_list_next (l))
+ anode_opt_add (node, l->data);
+ egg_asn1x_destroy (join);
+ }
+
+ /* Sort the children of any sets */
+ if (anode_def_type (node) == TYPE_SET) {
+ for (child = node->children; child; child = child->next)
+ list = g_list_prepend (list, child);
list = g_list_sort (list, compare_nodes_by_tag);
for (l = list; l; l = g_list_next (l))
+ g_node_unlink (l->data);
+ for (l = list; l; l = g_list_next (l))
g_node_append (node, l->data);
g_list_free (list);
}
@@ -1992,23 +2003,9 @@ egg_asn1x_create (const ASN1_ARRAY_TYPE *defs, const gchar *identifier)
* DUMPING and MESSAGES
*/
-static gboolean
-traverse_and_dump (GNode *node, gpointer unused)
+static void
+dump_append_type (GString *output, gint type)
{
- guint i, depth;
- GString *output;
- gchar *string;
- int flags;
- int type;
-
- depth = g_node_depth (node);
- for (i = 0; i < depth - 1; ++i)
- g_printerr (" ");
-
- output = g_string_new ("");
-
- /* Figure out the type */
- type = anode_def_type (node);
#define XX(x) if (type == TYPE_##x) g_string_append (output, #x " ")
XX(CONSTANT); XX(IDENTIFIER); XX(INTEGER); XX(BOOLEAN); XX(SEQUENCE); XX(BIT_STRING);
XX(OCTET_STRING); XX(TAG); XX(DEFAULT); XX(SIZE); XX(SEQUENCE_OF); XX(OBJECT_ID); XX(ANY);
@@ -2017,20 +2014,57 @@ traverse_and_dump (GNode *node, gpointer unused)
if (output->len == 0)
g_string_printf (output, "%d ", (int)type);
#undef XX
+}
- /* Figure out the flags */
- flags = anode_def_flags (node);
+static void
+dump_append_flags (GString *output, gint flags)
+{
#define XX(x) if ((FLAG_##x & flags) == FLAG_##x) g_string_append (output, #x " ")
XX(UNIVERSAL); XX(PRIVATE); XX(APPLICATION); XX(EXPLICIT); XX(IMPLICIT); XX(TAG); XX(OPTION);
XX(DEFAULT); XX(TRUE); XX(FALSE); XX(LIST); XX(MIN_MAX); XX(1_PARAM); XX(SIZE); XX(DEFINED_BY);
XX(GENERALIZED); XX(UTC); XX(IMPORTS); XX(NOT_USED); XX(SET); XX(ASSIGN);
/* XX(DOWN); XX(RIGHT); */
#undef XX
+}
+static gboolean
+traverse_and_dump (GNode *node, gpointer unused)
+{
+ ASN1_ARRAY_TYPE *def;
+ guint i, depth;
+ GString *output;
+ gchar *string;
+ Anode *an;
+ GList *l;
+
+ depth = g_node_depth (node);
+ for (i = 0; i < depth - 1; ++i)
+ g_printerr (" ");
+
+ output = g_string_new ("");
+ dump_append_type (output, anode_def_type (node));
+ dump_append_flags (output, anode_def_flags (node));
string = g_utf8_casefold (output->str, output->len - 1);
g_string_free (output, TRUE);
- g_printerr ("%s: %s [%s]\n", anode_def_name (node), anode_def_value (node), string);
+ g_printerr ("+ %s: %s [%s]\n", anode_def_name (node), anode_def_value (node), string);
g_free (string);
+
+ /* Print out all the options */
+ an = node->data;
+ for (l = an->opts; l; l = g_list_next (l)) {
+ for (i = 0; i < depth; ++i)
+ g_printerr (" ");
+
+ def = l->data;
+ output = g_string_new ("");
+ dump_append_type (output, def->type & 0xFF);
+ dump_append_flags (output, def->type);
+ string = g_utf8_casefold (output->str, output->len - 1);
+ g_string_free (output, TRUE);
+ g_printerr ("- %s: %s [%s]\n", def->name, (const gchar*)def->value, string);
+ g_free (string);
+ }
+
return FALSE;
}
@@ -2075,13 +2109,13 @@ traverse_and_clear (GNode *node, gpointer unused)
if (type == TYPE_SET_OF || type == TYPE_SEQUENCE_OF) {
/* The first 'real' child is the template */
- child = anode_child_with_real_type (node);
+ child = node->children;
g_return_val_if_fail (child, TRUE);
/* And any others are extras */
- child = anode_next_with_real_type (child);
+ child = child->next;
while (child) {
- next = anode_next_with_real_type (child);
+ next = child->next;
anode_destroy (child);
child = next;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]