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;
|
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);
|
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);
|
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.
|
* Implementation of identification_t.clone.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user