#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <libgen.h>
#include <kmftypes.h>
#include <kmfapiP.h>
#define DEFAULT_MAPPER_DIR KMF_PLUGIN_PATH
static void
cleanup_mapper(KMF_HANDLE_T handle)
{
KMF_MAPPER_RECORD *mapper = &handle->policy->mapper;
void (*finalize)(KMF_HANDLE_T);
if (mapper->curpathname != NULL) {
free(mapper->curpathname);
mapper->curpathname = NULL;
}
if (mapper->curoptions != NULL) {
free(mapper->curoptions);
mapper->curoptions = NULL;
}
if (mapper->dldesc != NULL) {
finalize = (void(*)())dlsym(mapper->dldesc,
MAPPER_FINISH_FUNCTION);
if (finalize != NULL)
finalize(handle);
(void) dlclose(mapper->dldesc);
mapper->dldesc = NULL;
}
}
char *
get_mapper_pathname(char *name, char *dir)
{
char *pathname = NULL;
int len;
if (name == NULL)
return (NULL);
if (dir == NULL)
dir = DEFAULT_MAPPER_DIR;
len = strlen(name) + strlen(MAPPER_NAME_TEMPLATE) + strlen(dir);
pathname = malloc(len);
if (pathname == NULL)
return (NULL);
(void) memset(pathname, 0, len);
(void) snprintf(pathname, len, "%s%s" MAPPER_NAME_TEMPLATE,
dir, dir[strlen(dir) - 1] == '/' ? "" : "/", name);
return (pathname);
}
static KMF_RETURN
open_mapper_library(KMF_MAPPER_RECORD *map)
{
KMF_RETURN ret = KMF_OK;
map->dldesc = dlopen(map->curpathname, RTLD_LAZY | RTLD_PARENT);
if (map->dldesc == NULL)
return (KMF_ERR_MAPPER_OPEN);
return (ret);
}
KMF_RETURN
kmf_cert_to_name_mapping_initialize(KMF_HANDLE_T handle, int numattr,
KMF_ATTRIBUTE *attrlist)
{
KMF_RETURN ret = KMF_OK;
KMF_RETURN (*initialize)(KMF_HANDLE_T, char *);
KMF_MAPPER_RECORD *map = NULL;
char *dir = NULL;
char *name = NULL;
char *opts = NULL;
char *path = NULL;
char *tmppath = NULL;
char *old_curpathname = NULL;
char *old_curoptions = NULL;
if (handle == NULL)
return (KMF_ERR_BAD_PARAMETER);
map = &handle->policy->mapper;
old_curpathname = map->curpathname;
old_curoptions = map->curoptions;
name = kmf_get_attr_ptr(KMF_MAPPER_NAME_ATTR, attrlist, numattr);
dir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr);
path = kmf_get_attr_ptr(KMF_MAPPER_PATH_ATTR, attrlist, numattr);
opts = kmf_get_attr_ptr(KMF_MAPPER_OPTIONS_ATTR, attrlist, numattr);
if (path != NULL) {
if (name != NULL || dir != NULL)
return (KMF_ERR_BAD_PARAMETER);
tmppath = strdup(path);
if (tmppath == NULL)
return (KMF_ERR_MEMORY);
} else if (name != NULL) {
tmppath = get_mapper_pathname(name, dir);
if (tmppath == NULL)
return (KMF_ERR_MEMORY);
} else if (dir != NULL || opts != NULL) {
return (KMF_ERR_BAD_PARAMETER);
} else if (map->pathname != NULL) {
tmppath = strdup(map->pathname);
if (tmppath == NULL)
return (KMF_ERR_MEMORY);
opts = map->options;
} else if (map->mapname != NULL) {
tmppath = get_mapper_pathname(map->mapname, map->dir);
if (tmppath == NULL)
return (KMF_ERR_MEMORY);
opts = map->options;
} else {
return (KMF_ERR_BAD_PARAMETER);
}
if (map->dldesc == NULL) {
map->curpathname = tmppath;
if (opts != NULL) {
map->curoptions = strdup(opts);
if (map->curoptions == NULL) {
free(map->curpathname);
map->curpathname = NULL;
return (KMF_ERR_MEMORY);
}
} else
map->curoptions = NULL;
if ((ret = open_mapper_library(map)) != KMF_OK) {
free(map->curpathname);
map->curpathname = NULL;
if (map->curoptions != NULL) {
free(map->curoptions);
map->curoptions = NULL;
}
return (ret);
}
goto end;
}
if (map->curpathname != NULL &&
strcmp(map->curpathname, tmppath) == 0) {
if (map->curoptions != NULL && opts == NULL) {
map->curoptions = NULL;
} else if (map->curoptions == NULL && opts != NULL) {
if ((map->curoptions = strdup(opts)) == NULL)
goto err_mem;
} else if (strcmp(map->curoptions, opts) != 0) {
if ((map->curoptions = strdup(opts)) == NULL)
goto err_mem;
} else {
old_curoptions = NULL;
}
if (old_curoptions != NULL)
free(old_curoptions);
} else {
cleanup_mapper(handle);
old_curoptions = NULL;
old_curpathname = NULL;
map->curpathname = tmppath;
if (opts != NULL) {
map->curoptions = strdup(opts);
if (map->curoptions == NULL)
goto err_mem;
}
if ((ret = open_mapper_library(map)) != KMF_OK) {
cleanup_mapper(handle);
return (ret);
}
}
end:
initialize = (KMF_RETURN(*)())dlsym(map->dldesc,
MAPPER_INIT_FUNCTION);
ret = KMF_OK;
if (initialize != NULL)
ret = initialize(handle, map->curoptions);
if (ret != KMF_OK)
cleanup_mapper(handle);
return (ret);
err_mem:
if (tmppath != NULL)
free(tmppath);
map->curoptions = old_curoptions;
map->curpathname = old_curpathname;
return (KMF_ERR_MEMORY);
}
KMF_RETURN
kmf_cert_to_name_mapping_finalize(KMF_HANDLE_T handle)
{
if (handle == NULL)
return (KMF_ERR_BAD_PARAMETER);
cleanup_mapper(handle);
return (KMF_OK);
}
KMF_RETURN
kmf_map_cert_to_name(KMF_HANDLE_T handle, KMF_DATA *cert, KMF_DATA *name)
{
KMF_MAPPER_RECORD *map = NULL;
KMF_RETURN (*cert2name)(KMF_HANDLE *, KMF_DATA *, KMF_DATA *);
if (handle == NULL)
return (KMF_ERR_BAD_PARAMETER);
map = &handle->policy->mapper;
if (map->dldesc == NULL)
return (KMF_ERR_MAPPER_NOT_FOUND);
cert2name = (KMF_RETURN(*)())dlsym(map->dldesc,
MAP_CERT_TO_NAME_FUNCTION);
if (cert2name == NULL)
return (KMF_ERR_FUNCTION_NOT_FOUND);
return (cert2name(handle, cert, name));
}
KMF_RETURN
kmf_match_cert_to_name(KMF_HANDLE_T handle, KMF_DATA *cert,
KMF_DATA *name_to_match, KMF_DATA *mapped_name)
{
KMF_MAPPER_RECORD *map = NULL;
KMF_RETURN (*cert2name)(KMF_HANDLE *, KMF_DATA *, KMF_DATA *,
KMF_DATA *);
if (handle == NULL)
return (KMF_ERR_BAD_PARAMETER);
map = &handle->policy->mapper;
if (map->curpathname == NULL || map->dldesc == NULL)
return (KMF_ERR_MAPPER_NOT_FOUND);
cert2name = (KMF_RETURN(*)())dlsym(map->dldesc,
MATCH_CERT_TO_NAME_FUNCTION);
if (cert2name == NULL)
return (KMF_ERR_FUNCTION_NOT_FOUND);
return (cert2name(handle, cert, name_to_match, mapped_name));
}
KMF_RETURN
kmf_get_mapper_error_str(KMF_HANDLE_T handle, char **errstr)
{
KMF_HANDLE *h = NULL;
KMF_MAPPER_RECORD *map = NULL;
KMF_RETURN (*err2string)(KMF_HANDLE *, char **);
if (handle == NULL || errstr == NULL)
return (KMF_ERR_BAD_PARAMETER);
h = (KMF_HANDLE *)handle;
map = &(h->policy->mapper);
if (map->curpathname == NULL || map->dldesc == NULL)
return (KMF_ERR_MAPPER_NOT_FOUND);
err2string = (KMF_RETURN(*)())dlsym(map->dldesc,
MAPPER_ERROR_STRING_FUNCTION);
if (err2string == NULL)
return (KMF_ERR_FUNCTION_NOT_FOUND);
return (err2string(h, errstr));
}
void
kmf_set_mapper_lasterror(KMF_HANDLE_T handle, uint32_t err)
{
handle->mapstate->lastmappererr = err;
}
uint32_t
kmf_get_mapper_lasterror(KMF_HANDLE_T handle)
{
return (handle->mapstate->lastmappererr);
}
void
kmf_set_mapper_options(KMF_HANDLE_T handle, void *opts)
{
handle->mapstate->options = opts;
}
void *
kmf_get_mapper_options(KMF_HANDLE_T handle)
{
return (handle->mapstate->options);
}