#include <kmftypes.h>
#include <kmfapi.h>
#include <fcntl.h>
#define RDN_VALUE(x, i) \
(&x.RelativeDistinguishedName[i].AttributeTypeAndValue->value)
#define RDN_OID(x, i) \
(&x.RelativeDistinguishedName[i].AttributeTypeAndValue->type)
#define RDN_NPAIRS(x, i) (x.RelativeDistinguishedName[i].numberOfPairs)
#define CN_MAPPER_CN_RDN_NOT_PRESENT 1
typedef struct cooked_opts {
int casesensitive;
} cooked_opts;
KMF_RETURN
mapper_initialize(KMF_HANDLE_T h, char *options)
{
cooked_opts *opts;
if ((opts = malloc(sizeof (cooked_opts))) == NULL)
return (KMF_ERR_MEMORY);
opts->casesensitive = B_FALSE;
if (options != NULL) {
if (strcmp(options, "casesensitive") == 0)
opts->casesensitive = B_TRUE;
}
kmf_set_mapper_options(h, opts);
return (KMF_OK);
}
void
mapper_finalize(KMF_HANDLE_T h)
{
void *opts;
if ((opts = kmf_get_mapper_options(h)) != NULL)
free(opts);
kmf_set_mapper_options(h, NULL);
}
KMF_RETURN
mapper_map_cert_to_name(KMF_HANDLE_T h, KMF_DATA *cert, KMF_DATA *name)
{
int i, j;
char *dn;
KMF_RETURN rv;
uchar_t *cn = NULL;
KMF_X509_NAME x509name;
kmf_set_mapper_lasterror(h, KMF_OK);
if ((rv = kmf_get_cert_subject_str(h, cert, &dn)) != KMF_OK)
return (rv);
if ((rv = kmf_dn_parser(dn, &x509name)) != KMF_OK)
return (rv);
for (i = 0; i < x509name.numberOfRDNs; ++i) {
for (j = 0; j < RDN_NPAIRS(x509name, i); ++j) {
KMF_OID *oid = RDN_OID(x509name, i);
KMF_DATA *data = RDN_VALUE(x509name, i);
if (oid == NULL)
continue;
if (oid->Length == KMFOID_CommonName.Length &&
memcmp(oid->Data, KMFOID_CommonName.Data,
oid->Length) == 0) {
if ((cn = malloc(data->Length + 1)) == NULL) {
kmf_free_dn(&x509name);
return (KMF_ERR_MEMORY);
}
(void) memcpy(cn, data->Data, data->Length);
cn[data->Length] = '\0';
name->Length = data->Length + 1;
name->Data = cn;
goto finished;
}
}
}
finished:
kmf_free_dn(&x509name);
if (cn != NULL)
return (KMF_OK);
else {
kmf_set_mapper_lasterror(h, CN_MAPPER_CN_RDN_NOT_PRESENT);
return (KMF_ERR_INTERNAL);
}
}
KMF_RETURN
mapper_match_cert_to_name(KMF_HANDLE_T h, KMF_DATA *cert,
KMF_DATA *name_to_match, KMF_DATA *mapped_name)
{
int ret;
KMF_RETURN rv;
KMF_DATA get_name;
cooked_opts *opts = NULL;
opts = (cooked_opts *)kmf_get_mapper_options(h);
if (mapped_name != NULL) {
mapped_name->Length = 0;
mapped_name->Data = NULL;
}
if ((rv = mapper_map_cert_to_name(h, cert, &get_name)) != KMF_OK)
return (rv);
if (name_to_match->Data[name_to_match->Length - 1] != '\0')
if (name_to_match->Length != get_name.Length - 1)
return (KMF_ERR_NAME_NOT_MATCHED);
if (opts->casesensitive == B_TRUE)
ret = strncmp((char *)name_to_match->Data,
(char *)get_name.Data, name_to_match->Length);
else
ret = strncasecmp((char *)name_to_match->Data,
(char *)get_name.Data, name_to_match->Length);
if (mapped_name != NULL) {
mapped_name->Length = get_name.Length;
mapped_name->Data = get_name.Data;
} else
kmf_free_data(&get_name);
if (ret == 0)
return (KMF_OK);
else
return (KMF_ERR_NAME_NOT_MATCHED);
}
KMF_RETURN
mapper_get_error_str(KMF_HANDLE_T h, char **errstr)
{
uint32_t lasterr;
lasterr = kmf_get_mapper_lasterror(h);
*errstr = NULL;
if (lasterr == 0)
return (KMF_ERR_MISSING_ERRCODE);
switch (lasterr) {
case CN_MAPPER_CN_RDN_NOT_PRESENT:
*errstr = (char *)strdup("CN_MAPPER_CN_RDN_NOT_PRESENT");
break;
default:
*errstr = (char *)strdup("KMF_ERR_MISSING_MAPPER_ERRCODE");
}
if (*errstr == NULL)
return (KMF_ERR_MEMORY);
return (KMF_OK);
}