use an enumerator to parse RDNs, based on asn1_unwrap() function
authorMartin Willi <martin@strongswan.org>
Fri, 3 Jul 2009 14:12:17 +0000 (16:12 +0200)
committerMartin Willi <martin@strongswan.org>
Mon, 6 Jul 2009 11:15:28 +0000 (13:15 +0200)
src/libstrongswan/utils/identification.c

index 1c04c97..72b1c6a 100644 (file)
@@ -122,6 +122,151 @@ struct private_identification_t {
        id_type_t type;
 };
 
+/**
+ * Enumerator over RDNs
+ */
+typedef struct {
+       /* implements enumerator interface */
+       enumerator_t public;
+       /* RDNs left to parse */
+       chunk_t left;
+} rdn_enumerator_t;
+
+/**
+ * Implementation of rdn_enumerator_t.enumerate
+ */
+static bool rdn_enumerate(rdn_enumerator_t *this, chunk_t *oid,
+                                                 u_char *type, chunk_t *data)
+{
+       chunk_t rdn;
+       
+       /* a RDN is a SET of attribute-values, each is a SEQUENCE ... */
+       if (asn1_unwrap(&this->left, &rdn) == ASN1_SET &&
+               asn1_unwrap(&rdn, &rdn) == ASN1_SEQUENCE)
+       {
+               /* ... of an OID */
+               if (asn1_unwrap(&rdn, oid) == ASN1_OID)
+               {
+                       /* and a specific string type */
+                       *type = asn1_unwrap(&rdn, data);
+                       if (*type != ASN1_INVALID)
+                       {
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
+/**
+ * Create an enumerator over all RDNs (oid, string type, data) of a DN
+ */
+static enumerator_t* create_rdn_enumerator(chunk_t dn)
+{
+       rdn_enumerator_t *e = malloc_thing(rdn_enumerator_t);
+       
+       e->public.enumerate = (void*)rdn_enumerate;
+       e->public.destroy = (void*)free;
+       
+       /* a DN is a sequence of RDNs */
+       if (asn1_unwrap(&dn, &e->left) == ASN1_SEQUENCE)
+       {
+               return &e->public;
+       }
+       return enumerator_create_empty();
+}
+
+/**
+ * Part enumerator over RDNs
+ */
+typedef struct {
+       /* implements enumerator interface */
+       enumerator_t public;
+       /* inner RDN enumerator */
+       enumerator_t *inner;
+} rdn_part_enumerator_t;
+
+/**
+ * Implementation of rdn_part_enumerator_t.enumerate().
+ */
+static bool rdn_part_enumerate(rdn_part_enumerator_t *this,
+                                                          id_part_t *type, chunk_t *data)
+{
+       int i, known_oid, strtype;
+       chunk_t oid, inner_data;
+       static const struct {
+               int oid;
+               id_part_t type;
+       } oid2part[] = {
+               {OID_COMMON_NAME,               ID_PART_RDN_CN},
+               {OID_SURNAME,                   ID_PART_RDN_S},
+               {OID_SERIAL_NUMBER,             ID_PART_RDN_SN},
+               {OID_COUNTRY,                   ID_PART_RDN_C},
+               {OID_LOCALITY,                  ID_PART_RDN_L},
+               {OID_STATE_OR_PROVINCE, ID_PART_RDN_ST},
+               {OID_ORGANIZATION,              ID_PART_RDN_O},
+               {OID_ORGANIZATION_UNIT, ID_PART_RDN_OU},
+               {OID_TITLE,                             ID_PART_RDN_T},
+               {OID_DESCRIPTION,               ID_PART_RDN_D},
+               {OID_NAME,                              ID_PART_RDN_N},
+               {OID_GIVEN_NAME,                ID_PART_RDN_G},
+               {OID_INITIALS,                  ID_PART_RDN_I},
+               {OID_UNIQUE_IDENTIFIER, ID_PART_RDN_ID},
+               {OID_EMAIL_ADDRESS,             ID_PART_RDN_E},
+               {OID_EMPLOYEE_NUMBER,   ID_PART_RDN_EN},
+       };
+       
+       while (this->inner->enumerate(this->inner, &oid, &strtype, &inner_data))
+       {
+               known_oid = asn1_known_oid(oid);
+               for (i = 0; i < countof(oid2part); i++)
+               {
+                       if (oid2part[i].oid == known_oid)
+                       {
+                               *type = oid2part[i].type;
+                               *data = inner_data;
+                               return TRUE;
+                       }
+               }
+       }
+       return FALSE;
+}
+
+/**
+ * Implementation of rdn_part_enumerator_t.destroy().
+ */
+static void rdn_part_enumerator_destroy(rdn_part_enumerator_t *this)
+{
+       this->inner->destroy(this->inner);
+       free(this);
+}
+
+/**
+ * Implementation of identification_t.create_part_enumerator
+ */
+static enumerator_t* create_part_enumerator(private_identification_t *this)
+{
+       switch (this->type)
+       {
+               case ID_DER_ASN1_DN:
+               {
+                       rdn_part_enumerator_t *e = malloc_thing(rdn_part_enumerator_t);
+                       
+                       e->inner = create_rdn_enumerator(this->encoded);
+                       e->public.enumerate = (void*)rdn_part_enumerate;
+                       e->public.destroy = (void*)rdn_part_enumerator_destroy;
+                       
+                       return &e->public;
+               }
+               case ID_RFC822_ADDR:
+                       /* TODO */
+               case ID_FQDN:
+                       /* TODO */
+               default:
+                       return enumerator_create_empty();
+       }
+}
+
 static private_identification_t *identification_create(void);
 
 /**
@@ -917,125 +1062,6 @@ int identification_printf_hook(char *dst, size_t len, printf_hook_spec_t *spec,
        }
        return print_in_hook(dst, len, "%*s", spec->width, buf);
 }
-
-/**
- * Enumerator over RDNs
- */
-typedef struct {
-       /* implements enumerator interface */
-       enumerator_t public;
-       /* current RDN */
-       chunk_t rdn;
-       /* current attribute */
-       chunk_t attr;
-       /** have another RDN? */
-       bool next;
-} rdn_enumerator_t;
-
-/**
- * Implementation of rdn_enumerator_t.enumerate
- */
-static bool rdn_enumerate(rdn_enumerator_t *this,
-                                                 id_part_t *type, chunk_t *data)
-{
-       chunk_t oid, value;
-       asn1_t asn1_type;
-       
-       while (this->next)
-       {
-               if (!get_next_rdn(&this->rdn, &this->attr, &oid,
-                                                 &value, &asn1_type, &this->next))
-               {
-                       return FALSE;
-               }
-               switch (asn1_known_oid(oid))
-               {
-                       case OID_COMMON_NAME:
-                                *type = ID_PART_RDN_CN;
-                               break;
-                       case OID_SURNAME:
-                                *type = ID_PART_RDN_S;
-                               break;
-                       case OID_SERIAL_NUMBER:
-                                *type = ID_PART_RDN_SN;
-                               break;
-                       case OID_COUNTRY:
-                                *type = ID_PART_RDN_C;
-                               break;
-                       case OID_LOCALITY:
-                                *type = ID_PART_RDN_L;
-                               break;
-                       case OID_STATE_OR_PROVINCE:
-                                *type = ID_PART_RDN_ST;
-                               break;
-                       case OID_ORGANIZATION:
-                                *type = ID_PART_RDN_O;
-                               break;
-                       case OID_ORGANIZATION_UNIT:
-                                *type = ID_PART_RDN_OU;
-                               break;
-                       case OID_TITLE:
-                                *type = ID_PART_RDN_T;
-                               break;
-                       case OID_DESCRIPTION:
-                                *type = ID_PART_RDN_D;
-                               break;
-                       case OID_NAME:
-                                *type = ID_PART_RDN_N;
-                               break;
-                       case OID_GIVEN_NAME:
-                                *type = ID_PART_RDN_G;
-                               break;
-                       case OID_INITIALS:
-                                *type = ID_PART_RDN_I;
-                               break;
-                       case OID_UNIQUE_IDENTIFIER:
-                                *type = ID_PART_RDN_ID;
-                               break;
-                       case OID_EMAIL_ADDRESS:
-                               *type = ID_PART_RDN_E;
-                               break;
-                       case OID_EMPLOYEE_NUMBER:
-                               *type = ID_PART_RDN_EN;
-                               break;
-                       default:
-                               continue;
-               }
-               *data = value;
-               return TRUE;
-       }
-       return FALSE;
-}
-
-/**
- * Implementation of identification_t.create_part_enumerator
- */
-static enumerator_t* create_part_enumerator(private_identification_t *this)
-{
-       switch (this->type)
-       {
-               case ID_DER_ASN1_DN:
-               {
-                       rdn_enumerator_t *e = malloc_thing(rdn_enumerator_t);
-                       
-                       e->public.enumerate = (void*)rdn_enumerate;
-                       e->public.destroy = (void*)free;
-                       if (init_rdn(this->encoded, &e->rdn, &e->attr, &e->next))
-                       {
-                               return &e->public;
-                       }
-                       free(e);
-                       /* FALL */
-               }
-               case ID_RFC822_ADDR:
-                       /* TODO */
-               case ID_FQDN:
-                       /* TODO */
-               default:
-                       return enumerator_create_empty();
-       }
-}
-
 /**
  * Implementation of identification_t.clone.
  */