use an enumerator to parse RDNs, based on asn1_unwrap() function

This commit is contained in:
Martin Willi
2009-07-06 13:15:28 +02:00
parent 5dd492efff
commit 6bdd79d86c
+145 -119
View 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.
*/