mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
604 lines
17 KiB
C
604 lines
17 KiB
C
/*
|
|
* zkey-kmip - KMIP zkey KMS plugin
|
|
*
|
|
* Copyright IBM Corp. 2021
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#define _DEFAULT_SOURCE
|
|
#include <dirent.h>
|
|
#include <ctype.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <dlfcn.h>
|
|
#include <regex.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <err.h>
|
|
|
|
#include "lib/zt_common.h"
|
|
#include "lib/util_libc.h"
|
|
|
|
#include "zkey-kmip.h"
|
|
#include "../properties.h"
|
|
|
|
#define _set_error(ph, fmt...) plugin_set_error(&(ph)->pd, fmt)
|
|
|
|
/**
|
|
* Returns the profile directory. If environment variable ZKEY_KMIP_PROFILES
|
|
* is set, then its value specifies the profile directory, otherwise the
|
|
* default profile directory '/etc/zkey/kmip/profiles' is returned.
|
|
*/
|
|
static const char *get_profiles_directory(void)
|
|
{
|
|
const char *dir;
|
|
|
|
dir = secure_getenv(KMIP_PROFILES_LOCATION_ENVVAR);
|
|
|
|
return dir != NULL ? dir : KMIP_PROFILES_LOCATION;
|
|
}
|
|
|
|
static int profile_get_bool(struct plugin_handle *ph, struct properties *props,
|
|
const char *file_name, const char *prop_name,
|
|
bool default_val, bool *bool_var)
|
|
{
|
|
int rc = 0;
|
|
char *val;
|
|
|
|
val = properties_get(props, prop_name);
|
|
if (val == NULL) {
|
|
*bool_var = default_val;
|
|
goto ret;
|
|
}
|
|
|
|
if (strcasecmp(val, KMIP_PROFILES_BOOLEAN_FALSE) == 0) {
|
|
*bool_var = false;
|
|
} else if (strcasecmp(val, KMIP_PROFILES_BOOLEAN_TRUE) == 0) {
|
|
*bool_var = true;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': '%s'",
|
|
file_name, prop_name,
|
|
val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
free(val);
|
|
|
|
ret:
|
|
if (rc == 0)
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'", prop_name,
|
|
*bool_var ? "True" : "False");
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Reads a profile from a file
|
|
*
|
|
* @param ph the plugin handle
|
|
* @param profile_dir the directory containing the profiles. If NULL, then
|
|
* the default profile directory or the one specified
|
|
* by environment variable ZKEY_KMIP_PROFILES is used.
|
|
* @param profile_file name of the profile file to read
|
|
* @param profile On return: the allocated profile. The caller must
|
|
* free the profile with profile_free.
|
|
*
|
|
* @returns 0 on success, a negative errno in case of an error.
|
|
*/
|
|
int profile_read(struct plugin_handle *ph, const char *profile_dir,
|
|
const char *profile_file, struct kmip_profile **profile)
|
|
{
|
|
struct kmip_profile *prof = NULL;
|
|
struct properties *props;
|
|
char *file_name = NULL;
|
|
char *val = NULL, *tok;
|
|
int rc;
|
|
|
|
if (profile_dir == NULL)
|
|
profile_dir = get_profiles_directory();
|
|
|
|
util_asprintf(&file_name, "%s/%s", profile_dir, profile_file);
|
|
pr_verbose(&ph->pd, "Read profile from '%s'", file_name);
|
|
|
|
props = properties_new();
|
|
rc = properties_load(props, file_name, false);
|
|
if (rc != 0) {
|
|
_set_error(ph, "Failed to read profile from file '%s': %s",
|
|
file_name, strerror(-rc));
|
|
goto out;
|
|
}
|
|
|
|
prof = util_zalloc(sizeof(struct kmip_profile));
|
|
|
|
tok = strrchr(profile_file, '/');
|
|
if (tok == NULL)
|
|
tok = (char *)profile_file;
|
|
prof->name = util_strdup(tok);
|
|
tok = strchr(prof->name, '.');
|
|
if (tok != NULL)
|
|
*tok = 0;
|
|
|
|
pr_verbose(&ph->pd, "Profile name: '%s'", prof->name);
|
|
|
|
prof->server_regex = properties_get(props, KMIP_PROFILES_SERVER_REGEX);
|
|
if (prof->server_regex == NULL) {
|
|
_set_error(ph, "Profile '%s': Missing value for '%s'",
|
|
file_name, KMIP_PROFILES_SERVER_REGEX);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'", KMIP_PROFILES_SERVER_REGEX,
|
|
prof->server_regex);
|
|
|
|
val = properties_get(props, KMIP_PROFILES_KMIP_VERSION);
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_VERSION_AUTO);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'", KMIP_PROFILES_KMIP_VERSION,
|
|
val);
|
|
if (strcasecmp(val, KMIP_PROFILES_VERSION_AUTO) == 0) {
|
|
prof->kmip_version.major = 0;
|
|
prof->kmip_version.minor = 0;
|
|
} else {
|
|
if (sscanf(val, "%u.%u", &prof->kmip_version.major,
|
|
&prof->kmip_version.minor) != 2) {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': "
|
|
"'%s'", file_name,
|
|
KMIP_PROFILES_KMIP_VERSION, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
if (prof->kmip_version.major == 0) {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': "
|
|
"'%s'", file_name,
|
|
KMIP_PROFILES_KMIP_VERSION, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_TRANSPORT);
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_TRANSPORT_TLS);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'", KMIP_PROFILES_TRANSPORT,
|
|
val);
|
|
if (strcasecmp(val, KMIP_PROFILES_TRANSPORT_TLS) == 0) {
|
|
prof->transport = KMIP_TRANSPORT_PLAIN_TLS;
|
|
} else if (strcasecmp(val, KMIP_PROFILES_TRANSPORT_HTTPS) == 0) {
|
|
prof->transport = KMIP_TRANSPORT_HTTPS;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': '%s'",
|
|
file_name, KMIP_PROFILES_TRANSPORT, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_ENCODING);
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_ENCODING_TTLV);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'", KMIP_PROFILES_ENCODING,
|
|
val);
|
|
if (strcasecmp(val, KMIP_PROFILES_ENCODING_TTLV) == 0) {
|
|
prof->encoding = KMIP_ENCODING_TTLV;
|
|
} else if (strcasecmp(val, KMIP_PROFILES_ENCODING_JSON) == 0) {
|
|
if (prof->transport != KMIP_TRANSPORT_HTTPS) {
|
|
_set_error(ph, "Profile '%s': JSON encoding is only "
|
|
"possible with HTTP transport",
|
|
file_name);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
prof->encoding = KMIP_ENCODING_JSON;
|
|
} else if (strcasecmp(val, KMIP_PROFILES_ENCODING_XML) == 0) {
|
|
prof->encoding = KMIP_ENCODING_XML;
|
|
if (prof->transport != KMIP_TRANSPORT_HTTPS) {
|
|
_set_error(ph, "Profile '%s': XML encoding is only "
|
|
"possible with HTTP transport",
|
|
file_name);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': '%s'",
|
|
file_name, KMIP_PROFILES_ENCODING, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_HTTPS_URI);
|
|
switch (prof->transport) {
|
|
case KMIP_TRANSPORT_HTTPS:
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_HTTPS_URI_DEFAULT);
|
|
prof->https_uri = val;
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_HTTPS_URI, prof->https_uri);
|
|
break;
|
|
default:
|
|
if (val != NULL) {
|
|
pr_verbose(&ph->pd, "Profile: '%s': ignored '%s'",
|
|
KMIP_PROFILES_HTTPS_URI, val);
|
|
free(val);
|
|
}
|
|
break;
|
|
}
|
|
|
|
val = properties_get(props, KMIP_PROFILES_AUTH_SCHEME);
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_AUTH_TLS_CLIENT_CERT);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'", KMIP_PROFILES_AUTH_SCHEME,
|
|
val);
|
|
if (strcasecmp(val, KMIP_PROFILES_AUTH_TLS_CLIENT_CERT) == 0) {
|
|
prof->auth_scheme = KMIP_PROFILE_AUTH_TLS_CLIENT_CERT;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': '%s'",
|
|
file_name, KMIP_PROFILES_AUTH_SCHEME, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_WRAP_KEY_ALGORITHM);
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_WRAP_KEY_ALGORITHM_RSA);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_WRAP_KEY_ALGORITHM, val);
|
|
if (strcasecmp(val, KMIP_PROFILES_WRAP_KEY_ALGORITHM_RSA) == 0) {
|
|
prof->wrap_key_algo = KMIP_CRYPTO_ALGO_RSA;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': '%s'",
|
|
file_name, KMIP_PROFILES_WRAP_KEY_ALGORITHM, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_WRAP_KEY_PARAMS);
|
|
if (prof->wrap_key_algo == KMIP_CRYPTO_ALGO_RSA) {
|
|
if (val == NULL) {
|
|
_set_error(ph, "Profile '%s': Missing value for '%s'",
|
|
file_name, KMIP_PROFILES_WRAP_KEY_PARAMS);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_WRAP_KEY_PARAMS, val);
|
|
prof->wrap_key_size = atoi(val);
|
|
if (prof->wrap_key_size == 0) {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s' "
|
|
"(RSA modulus size): '%s'", file_name,
|
|
KMIP_PROFILES_WRAP_KEY_PARAMS, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
} else if (val != NULL) {
|
|
pr_verbose(&ph->pd, "Profile: '%s': ignored '%s'",
|
|
KMIP_PROFILES_WRAP_KEY_PARAMS, val);
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_WRAP_KEY_FORMAT);
|
|
switch (prof->wrap_key_algo) {
|
|
case KMIP_CRYPTO_ALGO_RSA:
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_WRAP_KEY_FORMAT_PKCS1);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_WRAP_KEY_FORMAT, val);
|
|
if (strcasecmp(val, KMIP_PROFILES_WRAP_KEY_FORMAT_PKCS1) == 0) {
|
|
prof->wrap_key_format = KMIP_KEY_FORMAT_TYPE_PKCS_1;
|
|
} else if (strcasecmp(val,
|
|
KMIP_PROFILES_WRAP_KEY_FORMAT_PKCS8) == 0) {
|
|
prof->wrap_key_format = KMIP_KEY_FORMAT_TYPE_PKCS_8;
|
|
} else if (strcasecmp(val,
|
|
KMIP_PROFILES_WRAP_KEY_FORMAT_TRANSP) == 0) {
|
|
prof->wrap_key_format =
|
|
KMIP_KEY_FORMAT_TYPE_TRANSPARENT_RSA_PUBLIC_KEY;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': "
|
|
"'%s'", file_name,
|
|
KMIP_PROFILES_WRAP_KEY_FORMAT, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
break;
|
|
default:
|
|
if (val != NULL)
|
|
pr_verbose(&ph->pd, "Profile: '%s': ignored '%s'",
|
|
KMIP_PROFILES_WRAP_KEY_FORMAT, val);
|
|
break;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_WRAP_PADDING_METHOD);
|
|
switch (prof->wrap_key_algo) {
|
|
case KMIP_CRYPTO_ALGO_RSA:
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_WRAP_PADDING_PKCS1_5);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_WRAP_PADDING_METHOD, val);
|
|
if (strcasecmp(val, KMIP_PROFILES_WRAP_PADDING_PKCS1_5) == 0) {
|
|
prof->wrap_padding_method =
|
|
KMIP_PADDING_METHOD_PKCS_1_5;
|
|
} else if (strcasecmp(val,
|
|
KMIP_PROFILES_WRAP_PADDING_OAEP) == 0) {
|
|
prof->wrap_padding_method = KMIP_PADDING_METHOD_OAEP;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': "
|
|
"'%s'", file_name,
|
|
KMIP_PROFILES_WRAP_PADDING_METHOD, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
break;
|
|
default:
|
|
if (val != NULL)
|
|
pr_verbose(&ph->pd, "Profile: '%s': ignored '%s'",
|
|
KMIP_PROFILES_WRAP_PADDING_METHOD, val);
|
|
break;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_WRAP_HASHING_ALOGRITHM);
|
|
switch (prof->wrap_padding_method) {
|
|
case KMIP_PADDING_METHOD_OAEP:
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_WRAP_HASHING_ALGO_SHA1);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_WRAP_HASHING_ALOGRITHM, val);
|
|
if (strcasecmp(val,
|
|
KMIP_PROFILES_WRAP_HASHING_ALGO_SHA1) == 0) {
|
|
prof->wrap_hashing_algo = KMIP_HASHING_ALGO_SHA_1;
|
|
} else if (strcasecmp(val,
|
|
KMIP_PROFILES_WRAP_HASHING_ALGO_SHA256) == 0) {
|
|
prof->wrap_hashing_algo = KMIP_HASHING_ALGO_SHA_256;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': "
|
|
"'%s'", file_name,
|
|
KMIP_PROFILES_WRAP_PADDING_METHOD, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
break;
|
|
default:
|
|
if (val != NULL)
|
|
pr_verbose(&ph->pd, "Profile: '%s': ignored '%s'",
|
|
KMIP_PROFILES_WRAP_HASHING_ALOGRITHM, val);
|
|
break;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
rc = profile_get_bool(ph, props, file_name,
|
|
KMIP_PROFILES_SUPPORTS_LINK_ATTR, false,
|
|
&prof->supports_link_attr);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
rc = profile_get_bool(ph, props, file_name,
|
|
KMIP_PROFILES_SUPPORTS_DESCRIPTION_ATTR, false,
|
|
&prof->supports_description_attr);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
rc = profile_get_bool(ph, props, file_name,
|
|
KMIP_PROFILES_SUPPORTS_COMMENT_ATTR, false,
|
|
&prof->supports_comment_attr);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
val = properties_get(props, KMIP_PROFILES_CUSTOM_ATTR_SCHEME);
|
|
if (val == NULL)
|
|
val = util_strdup(KMIP_PROFILES_CUST_ATTR_SCHEME_V1);
|
|
pr_verbose(&ph->pd, "Profile: '%s': '%s'",
|
|
KMIP_PROFILES_CUSTOM_ATTR_SCHEME, val);
|
|
if (strcasecmp(val, KMIP_PROFILES_CUST_ATTR_SCHEME_V1) == 0) {
|
|
prof->cust_attr_scheme = KMIP_PROFILE_CUST_ATTR_V1_STYLE;
|
|
} else if (strcasecmp(val, KMIP_PROFILES_CUST_ATTR_SCHEME_V2) == 0) {
|
|
prof->cust_attr_scheme = KMIP_PROFILE_CUST_ATTR_V2_STYLE;
|
|
} else {
|
|
_set_error(ph, "Profile '%s': Invalid value for '%s': '%s'",
|
|
file_name, KMIP_PROFILES_CUSTOM_ATTR_SCHEME, val);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
free(val);
|
|
val = NULL;
|
|
|
|
rc = profile_get_bool(ph, props, file_name,
|
|
KMIP_PROFILES_SUPPORTS_SENSITIVE_ATTR, false,
|
|
&prof->supports_sensitive_attr);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
rc = profile_get_bool(ph, props, file_name,
|
|
KMIP_PROFILES_CHECK_ALWAYS_SENS_ATTR, false,
|
|
&prof->check_always_sensitive_attr);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
out:
|
|
properties_free(props);
|
|
if (file_name != NULL)
|
|
free(file_name);
|
|
if (val != NULL)
|
|
free(val);
|
|
|
|
if (rc != 0)
|
|
profile_free(prof);
|
|
else
|
|
*profile = prof;
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Frees a profile
|
|
*
|
|
* @param profile On return: the allocated profile
|
|
*
|
|
* @returns 0 on success, a negative errno in case of an error.
|
|
*/
|
|
void profile_free(struct kmip_profile *profile)
|
|
{
|
|
if (profile == NULL)
|
|
return;
|
|
|
|
if (profile->name != NULL)
|
|
free((char *)profile->name);
|
|
if (profile->server_regex != NULL)
|
|
free((char *)profile->server_regex);
|
|
if (profile->https_uri != NULL)
|
|
free((char *)profile->https_uri);
|
|
|
|
free(profile);
|
|
}
|
|
|
|
/**
|
|
* Filters directory entries for scanfile(). Only entries that are regular
|
|
* files and who's name ends with '.info' are matched.
|
|
*/
|
|
static int profile_file_filter(const struct dirent *dirent)
|
|
{
|
|
size_t len;
|
|
|
|
if (dirent->d_type != DT_REG && dirent->d_type != DT_UNKNOWN)
|
|
return 0;
|
|
|
|
len = strlen(dirent->d_name);
|
|
if (len > KMIP_PROFILES_FILE_TYPE_LEN &&
|
|
strcmp(&dirent->d_name[len - KMIP_PROFILES_FILE_TYPE_LEN],
|
|
KMIP_PROFILES_FILE_TYPE) == 0)
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Scans the default profile directory or the one specified by environment
|
|
* variable ZKEY_KMIP_PROFILES for profiles that match the server info.
|
|
* Returns the first profile that matches, or the default profile if none
|
|
* matches.
|
|
*
|
|
* @param ph the plugin handle
|
|
* @param server_info the server info string to match the profiles against
|
|
* @param profile On return: the matched profile. The caller must free
|
|
* the profile with profile_free.
|
|
*
|
|
* @returns 0 on success, a negative errno in case of an error.
|
|
*/
|
|
int profile_find_by_server_info(struct plugin_handle *ph,
|
|
const char *server_info,
|
|
struct kmip_profile **profile)
|
|
{
|
|
struct kmip_profile *prof = NULL;
|
|
struct dirent **namelist;
|
|
const char *profile_dir;
|
|
regmatch_t pmatch[1];
|
|
char err_buf[256];
|
|
int i, n, rc = 0;
|
|
regex_t reg_buf;
|
|
|
|
profile_dir = get_profiles_directory();
|
|
pr_verbose(&ph->pd, "profile_dir: %s", profile_dir);
|
|
|
|
n = scandir(profile_dir, &namelist, profile_file_filter, alphasort);
|
|
if (n < 0) {
|
|
rc = -errno;
|
|
pr_verbose(&ph->pd, "scandir failed with: %s", strerror(-rc));
|
|
return rc;
|
|
}
|
|
|
|
for (i = 0; i < n; i++) {
|
|
if (strcmp(namelist[i]->d_name,
|
|
KMIP_PROFILES_DEFAULT_PROFILE) == 0)
|
|
continue;
|
|
|
|
pr_verbose(&ph->pd, "Found profile '%s'", namelist[i]->d_name);
|
|
|
|
rc = profile_read(ph, profile_dir, namelist[i]->d_name, &prof);
|
|
if (rc != 0) {
|
|
pr_verbose(&ph->pd, "profile_read failed with: %s",
|
|
strerror(-rc));
|
|
goto out;
|
|
}
|
|
|
|
rc = regcomp(®_buf, prof->server_regex, REG_EXTENDED);
|
|
if (rc != 0) {
|
|
regerror(rc, ®_buf, err_buf, sizeof(err_buf));
|
|
_set_error(ph, "Profile '%s': Regular expression "
|
|
"error: '%s'", namelist[i]->d_name, err_buf);
|
|
rc = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
rc = regexec(®_buf, server_info, (size_t)1, pmatch, 0);
|
|
regfree(®_buf);
|
|
if (rc == 0)
|
|
break;
|
|
|
|
profile_free(prof);
|
|
prof = NULL;
|
|
}
|
|
|
|
if (prof == NULL) {
|
|
rc = profile_read(ph, profile_dir,
|
|
KMIP_PROFILES_DEFAULT_PROFILE, &prof);
|
|
if (rc != 0) {
|
|
pr_verbose(&ph->pd, "default profile_read failed with: "
|
|
"%s", strerror(-rc));
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
*profile = prof;
|
|
|
|
out:
|
|
for (i = 0; i < n; i++)
|
|
free(namelist[i]);
|
|
free(namelist);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Reads a profile by its name. Tries to find a profile with the specified name
|
|
* in the default profile directory or the one specified by environment
|
|
* variable ZKEY_KMIP_PROFILES and loads it.
|
|
*
|
|
* @param ph the plugin handle
|
|
* @param profile_name name of the profile to read
|
|
* @param profile On return: the allocated profile. The caller must
|
|
* free the profile with profile_free.
|
|
*
|
|
* @returns 0 on success, a negative errno in case of an error.
|
|
*/
|
|
int profile_find_by_name(struct plugin_handle *ph, const char *profile_name,
|
|
struct kmip_profile **profile)
|
|
{
|
|
char *profile_file;
|
|
int rc;
|
|
|
|
util_asprintf(&profile_file, "%s%s", profile_name,
|
|
KMIP_PROFILES_FILE_TYPE);
|
|
|
|
rc = profile_read(ph, NULL, profile_file, profile);
|
|
|
|
free(profile_file);
|
|
return rc;
|
|
}
|