use an enumerator to parse RDNs, based on asn1_unwrap() function
This commit is contained in:
@@ -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.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user