Files
wolfssl/src/conf.c
2025-07-10 16:11:36 -06:00

1617 lines
46 KiB
C

/* conf.c
*
* Copyright (C) 2006-2025 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
#if !defined(WOLFSSL_CONF_INCLUDED)
#ifndef WOLFSSL_IGNORE_FILE_WARN
#warning conf.c does not need to be compiled separately from ssl.c
#endif
#else
/*******************************************************************************
* START OF TXT_DB API
******************************************************************************/
#if defined(OPENSSL_ALL) && !defined(NO_BIO)
/**
* This function reads a tab delimetered CSV input and returns
* a populated WOLFSSL_TXT_DB structure.
* @param in Tab delimetered CSV input
* @param num Number of fields in each row.
* @return
*/
WOLFSSL_TXT_DB *wolfSSL_TXT_DB_read(WOLFSSL_BIO *in, int num)
{
WOLFSSL_TXT_DB *ret = NULL;
char *buf = NULL;
char *bufEnd = NULL;
char *idx = NULL;
char* lineEnd = NULL;
int bufSz;
int failed = 1;
/* Space in front of str reserved for field pointers + \0 */
int fieldsSz = (num + 1) * sizeof(char *);
WOLFSSL_ENTER("wolfSSL_TXT_DB_read");
if (!in || num <= 0 || num > WOLFSSL_TXT_DB_MAX_FIELDS) {
WOLFSSL_MSG("Bad parameter or too many fields");
return NULL;
}
if (!(ret = (WOLFSSL_TXT_DB*)XMALLOC(sizeof(WOLFSSL_TXT_DB), NULL,
DYNAMIC_TYPE_OPENSSL))) {
WOLFSSL_MSG("malloc error");
goto error;
}
XMEMSET (ret, 0, sizeof(WOLFSSL_TXT_DB));
ret->num_fields = num;
if (!(ret->data = wolfSSL_sk_WOLFSSL_STRING_new())) {
WOLFSSL_MSG("wolfSSL_sk_WOLFSSL_STRING_new error");
goto error;
}
bufSz = wolfSSL_BIO_get_len(in);
if (bufSz <= 0 ||
!(buf = (char*)XMALLOC(bufSz+1, NULL,
DYNAMIC_TYPE_TMP_BUFFER))) {
WOLFSSL_MSG("malloc error or no data in BIO");
goto error;
}
if (wolfSSL_BIO_read(in, buf, bufSz) != bufSz) {
WOLFSSL_MSG("malloc error or no data in BIO");
goto error;
}
buf[bufSz] = '\0';
idx = buf;
for (bufEnd = buf + bufSz; idx < bufEnd; idx = lineEnd + 1) {
char* strBuf = NULL;
char** fieldPtr = NULL;
int fieldPtrIdx = 0;
char* fieldCheckIdx = NULL;
lineEnd = XSTRNSTR(idx, "\n", (unsigned int)(bufEnd - idx));
if (!lineEnd)
lineEnd = bufEnd;
if (idx == lineEnd) /* empty line */
continue;
if (*idx == '#')
continue;
*lineEnd = '\0';
strBuf = (char*)XMALLOC(fieldsSz + lineEnd - idx + 1, NULL,
DYNAMIC_TYPE_OPENSSL);
if (!strBuf) {
WOLFSSL_MSG("malloc error");
goto error;
}
XMEMCPY(strBuf + fieldsSz, idx, lineEnd - idx + 1); /* + 1 for NULL */
XMEMSET(strBuf, 0, fieldsSz);
/* Check for appropriate number of fields */
fieldPtr = (char**)strBuf;
fieldCheckIdx = strBuf + fieldsSz;
fieldPtr[fieldPtrIdx++] = fieldCheckIdx;
while (*fieldCheckIdx != '\0') {
/* Handle escaped tabs */
if (*fieldCheckIdx == '\t' && fieldCheckIdx[-1] != '\\') {
fieldPtr[fieldPtrIdx++] = fieldCheckIdx + 1;
*fieldCheckIdx = '\0';
if (fieldPtrIdx > num) {
WOLFSSL_MSG("too many fields");
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
goto error;
}
}
fieldCheckIdx++;
}
if (fieldPtrIdx != num) {
WOLFSSL_MSG("wrong number of fields");
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
goto error;
}
if (wolfSSL_sk_push(ret->data, strBuf) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_push error");
XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
goto error;
}
}
failed = 0;
error:
if (failed && ret) {
wolfSSL_TXT_DB_free(ret);
ret = NULL;
}
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
long wolfSSL_TXT_DB_write(WOLFSSL_BIO *out, WOLFSSL_TXT_DB *db)
{
const WOLF_STACK_OF(WOLFSSL_STRING)* data;
long totalLen = 0;
char buf[512]; /* Should be more than enough for a single row */
char* bufEnd = buf + sizeof(buf);
int i;
WOLFSSL_ENTER("wolfSSL_TXT_DB_write");
if (!out || !db || !db->num_fields) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
data = db->data;
while (data) {
char** fields = (char**)data->data.string;
char* idx = buf;
int sz;
if (!fields) {
WOLFSSL_MSG("Missing row");
return WOLFSSL_FAILURE;
}
for (i = 0; i < db->num_fields; i++) {
const char* fieldValue = fields[i];
if (!fieldValue) {
fieldValue = "";
}
/* Copy over field escaping tabs */
while (*fieldValue != '\0') {
if (idx+1 < bufEnd) {
if (*fieldValue == '\t')
*idx++ = '\\';
*idx++ = *fieldValue++;
}
else {
WOLFSSL_MSG("Data row is too big");
return WOLFSSL_FAILURE;
}
}
if (idx < bufEnd) {
*idx++ = '\t';
}
else {
WOLFSSL_MSG("Data row is too big");
return WOLFSSL_FAILURE;
}
}
if (idx > buf)
idx[-1] = '\n';
else
return WOLFSSL_FAILURE;
sz = (int)(idx - buf);
if (wolfSSL_BIO_write(out, buf, sz) != sz) {
WOLFSSL_MSG("wolfSSL_BIO_write error");
return WOLFSSL_FAILURE;
}
totalLen += sz;
data = data->next;
}
return totalLen;
}
int wolfSSL_TXT_DB_insert(WOLFSSL_TXT_DB *db, WOLFSSL_STRING *row)
{
WOLFSSL_ENTER("wolfSSL_TXT_DB_insert");
if (!db || !row || !db->data) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
if (wolfSSL_sk_push(db->data, row) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_push error");
return WOLFSSL_FAILURE;
}
return WOLFSSL_SUCCESS;
}
void wolfSSL_TXT_DB_free(WOLFSSL_TXT_DB *db)
{
WOLFSSL_ENTER("wolfSSL_TXT_DB_free");
if (db) {
if (db->data) {
wolfSSL_sk_pop_free(db->data, NULL);
}
XFREE(db, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
int wolfSSL_TXT_DB_create_index(WOLFSSL_TXT_DB *db, int field,
void* qual, wolf_sk_hash_cb hash, wolf_lh_compare_cb cmp)
{
WOLFSSL_ENTER("wolfSSL_TXT_DB_create_index");
(void)qual;
(void)cmp;
if (!db || !hash || !cmp || field >= db->num_fields || field < 0) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
db->hash_fn[field] = hash;
return WOLFSSL_SUCCESS;
}
WOLFSSL_STRING *wolfSSL_TXT_DB_get_by_index(WOLFSSL_TXT_DB *db, int idx,
WOLFSSL_STRING *value)
{
WOLFSSL_ENTER("wolfSSL_TXT_DB_get_by_index");
if (!db || !db->data || idx < 0 || idx >= db->num_fields) {
WOLFSSL_MSG("Bad parameter");
return NULL;
}
if (!db->hash_fn[idx]) {
WOLFSSL_MSG("Missing hash functions");
return NULL;
}
/* If first data struct has correct hash function
* then assume others do too */
if (db->data->hash_fn != db->hash_fn[idx]) {
/* Set the hash and comp functions */
WOLF_STACK_OF(WOLFSSL_STRING)* data = db->data;
while (data) {
if (data->hash_fn != db->hash_fn[idx]) {
data->hash_fn = db->hash_fn[idx];
data->hash = 0;
}
data= data->next;
}
}
return (WOLFSSL_STRING*) wolfSSL_lh_retrieve(db->data, value);
}
#endif /* OPENSSL_ALL && !NO_BIO */
/*******************************************************************************
* END OF TXT_DB API
******************************************************************************/
/*******************************************************************************
* START OF CONF API
******************************************************************************/
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
|| defined(HAVE_STUNNEL)
#ifndef NO_WOLFSSL_STUB
void wolfSSL_OPENSSL_config(char *config_name)
{
(void)config_name;
WOLFSSL_STUB("OPENSSL_config");
}
#endif /* !NO_WOLFSSL_STUB */
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_STUNNEL*/
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL)
/**
* This is the same hashing algo for WOLFSSL_CONF_VALUE as OpenSSL
*/
static unsigned long wolfSSL_CONF_VALUE_hash(const WOLFSSL_CONF_VALUE *val)
{
if (val)
return (wolfSSL_LH_strhash(val->section) << 2) ^
wolfSSL_LH_strhash(val->name);
else
return 0;
}
/* Use SHA[256] for hashing as OpenSSL uses a hash algorithm that is
* "not as good as MD5, but still good" so using SHA should be more
* than good enough for this application. The produced hashes don't
* need to line up between OpenSSL and wolfSSL. The hashes are for
* internal indexing only */
unsigned long wolfSSL_LH_strhash(const char *str)
{
unsigned long ret = 0;
int strLen;
#if !defined(NO_SHA)
wc_Sha sha;
byte digest[WC_SHA_DIGEST_SIZE];
#elif !defined(NO_SHA256)
wc_Sha256 sha;
byte digest[WC_SHA256_DIGEST_SIZE];
#endif
WOLFSSL_ENTER("wolfSSL_LH_strhash");
if (!str)
return 0;
strLen = (int)XSTRLEN(str);
#if !defined(NO_SHA)
if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
WOLFSSL_MSG("SHA1 Init failed");
return 0;
}
ret = wc_ShaUpdate(&sha, (const byte *)str, (word32)strLen);
if (ret != 0) {
WOLFSSL_MSG("SHA1 Update failed");
} else {
ret = wc_ShaFinal(&sha, digest);
if (ret != 0) {
WOLFSSL_MSG("SHA1 Final failed");
}
}
wc_ShaFree(&sha);
#elif !defined(NO_SHA256)
if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
WOLFSSL_MSG("SHA256 Init failed");
return 0;
}
ret = wc_Sha256Update(&sha, (const byte *)str, (word32)strLen);
if (ret != 0) {
WOLFSSL_MSG("SHA256 Update failed");
} else {
ret = wc_Sha256Final(&sha, digest);
if (ret != 0) {
WOLFSSL_MSG("SHA256 Final failed");
}
}
wc_Sha256Free(&sha);
#endif
#if !defined(NO_SHA) || !defined(NO_SHA256)
if (ret != 0)
return 0;
/* Take first 4 bytes in small endian as unsigned long */
ret = (unsigned int)digest[0];
ret |= ((unsigned int)digest[1] << 8 );
ret |= ((unsigned int)digest[2] << 16);
ret |= ((unsigned int)digest[3] << 24);
#else
WOLFSSL_MSG("No SHA available for wolfSSL_LH_strhash");
#endif
return ret;
}
WOLFSSL_CONF_VALUE *wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(
WOLF_LHASH_OF(WOLFSSL_CONF_VALUE) *sk, WOLFSSL_CONF_VALUE *data)
{
WOLFSSL_ENTER("wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve");
if (!sk || !data) {
WOLFSSL_MSG("Bad parameter");
return NULL;
}
return (WOLFSSL_CONF_VALUE*)wolfSSL_lh_retrieve(sk, data);
}
int wolfSSL_CONF_modules_load(const WOLFSSL_CONF *cnf, const char *appname,
unsigned long flags)
{
WOLFSSL_ENTER("wolfSSL_CONF_modules_load");
WOLFSSL_MSG("All wolfSSL modules are already compiled in. "
"wolfSSL_CONF_modules_load doesn't load anything new.");
(void)cnf;
(void)appname;
(void)flags;
return WOLFSSL_SUCCESS;
}
WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new(void)
{
WOLFSSL_CONF_VALUE* ret;
WOLFSSL_ENTER("wolfSSL_CONF_new");
ret = (WOLFSSL_CONF_VALUE*)XMALLOC(sizeof(WOLFSSL_CONF_VALUE),
NULL, DYNAMIC_TYPE_OPENSSL);
if (ret)
XMEMSET(ret, 0, sizeof(WOLFSSL_CONF_VALUE));
return ret;
}
int wolfSSL_CONF_add_string(WOLFSSL_CONF *conf,
WOLFSSL_CONF_VALUE *section, WOLFSSL_CONF_VALUE *value)
{
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
if (!conf || !section || !value) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *)section->value;
value->section = section->section;
if (wolfSSL_sk_CONF_VALUE_push(sk, value) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
return WOLFSSL_FAILURE;
}
if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
wolfssl_sk_pop_type(sk, STACK_TYPE_CONF_VALUE);
return WOLFSSL_FAILURE;
}
return WOLFSSL_SUCCESS;
}
WOLFSSL_CONF_VALUE *wolfSSL_CONF_new_section(WOLFSSL_CONF *conf,
const char *section)
{
WOLFSSL_CONF_VALUE* ret = NULL;
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
int slen;
WOLFSSL_ENTER("wolfSSL_CONF_new_section");
if (!conf || !section) {
WOLFSSL_MSG("Bad parameter");
return NULL;
}
slen = (int)XSTRLEN(section);
if (!(ret = wolfSSL_CONF_VALUE_new())) {
WOLFSSL_MSG("wolfSSL_CONF_new error");
goto error;
}
if (!(ret->section = (char*)XMALLOC(slen+1, NULL, DYNAMIC_TYPE_OPENSSL))) {
WOLFSSL_MSG("section malloc error");
goto error;
}
XMEMCPY(ret->section, section, slen+1);
if (!(sk = wolfSSL_sk_CONF_VALUE_new(NULL))) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_new error");
goto error;
}
ret->value = (char*)sk;
if (wolfSSL_sk_CONF_VALUE_push(conf->data, ret) <= 0) {
WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
goto error;
}
return ret;
error:
if (ret) {
/* NULL so that wolfSSL_X509V3_conf_free doesn't attempt to free it */
ret->value = NULL;
wolfSSL_X509V3_conf_free(ret);
}
if (sk) {
wolfSSL_sk_CONF_VALUE_free(sk);
}
return NULL;
}
WOLFSSL_CONF_VALUE *wolfSSL_CONF_get_section(WOLFSSL_CONF *conf,
const char *section)
{
WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
WOLFSSL_ENTER("wolfSSL_CONF_get_section");
if (!conf || !section) {
WOLFSSL_MSG("Bad parameter");
return NULL;
}
sk = conf->data;
while (sk) {
WOLFSSL_CONF_VALUE* val = sk->data.conf;
if (val) {
if (!val->name && XSTRCMP(section, val->section) == 0) {
return val;
}
}
sk = sk->next;
}
return NULL;
}
WOLFSSL_CONF *wolfSSL_NCONF_new(void *meth)
{
WOLFSSL_CONF* ret;
WOLFSSL_ENTER("wolfSSL_NCONF_new");
if (meth) {
WOLFSSL_MSG("wolfSSL does not support CONF_METHOD");
}
ret = (WOLFSSL_CONF*)XMALLOC(sizeof(WOLFSSL_CONF), NULL, DYNAMIC_TYPE_OPENSSL);
if (ret) {
XMEMSET(ret, 0, sizeof(WOLFSSL_CONF));
ret->data = wolfSSL_sk_CONF_VALUE_new(NULL);
if (!ret->data) {
wolfSSL_NCONF_free(ret);
return NULL;
}
}
return ret;
}
char *wolfSSL_NCONF_get_string(const WOLFSSL_CONF *conf,
const char *group, const char *name)
{
WOLFSSL_CONF_VALUE find_val;
WOLFSSL_CONF_VALUE *val;
WOLFSSL_ENTER("wolfSSL_NCONF_get_string");
if (!conf) {
#ifdef HAVE_SECURE_GETENV
return secure_getenv(name);
#else
WOLFSSL_MSG("Missing secure_getenv");
return NULL;
#endif
}
find_val.name = (char *)name;
if (group) {
find_val.section = (char *)group;
val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
if (val)
return val->value;
if (XSTRCMP(group, "ENV") == 0) {
#ifdef HAVE_SECURE_GETENV
return secure_getenv(name);
#else
WOLFSSL_MSG("Missing secure_getenv");
return NULL;
#endif
}
}
find_val.section = (char *)"default";
val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
if (val)
return val->value;
else
return NULL;
}
int wolfSSL_NCONF_get_number(const WOLFSSL_CONF *conf, const char *group,
const char *name, long *result)
{
char *str;
WOLFSSL_ENTER("wolfSSL_NCONF_get_number");
if (!conf || !name || !result) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
if (!(str = wolfSSL_NCONF_get_string(conf, group, name))) {
WOLFSSL_MSG("wolfSSL_NCONF_get_string error");
return WOLFSSL_FAILURE;
}
*result = atol(str);
return WOLFSSL_SUCCESS;
}
/**
* The WOLFSSL_CONF->value member is treated as a
* WOLFSSL_STACK_OF(WOLFSSL_CONF_VALUE) which becomes
* the return value.
* @param conf
* @param section
* @return WOLFSSL_STACK_OF(WOLFSSL_CONF_VALUE)
*/
WOLFSSL_STACK *wolfSSL_NCONF_get_section(
const WOLFSSL_CONF *conf, const char *section)
{
WOLFSSL_CONF_VALUE *val;
WOLFSSL_CONF_VALUE find_val;
WOLFSSL_ENTER("wolfSSL_NCONF_get_section");
if (!conf || !section) {
WOLFSSL_MSG("Bad parameter");
return NULL;
}
find_val.name = NULL;
find_val.section = (char*)section;
val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
if (val)
return (WOLFSSL_STACK*)val->value;
else
return NULL;
}
#if !defined(NO_BIO)
static WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new_values(char* section,
char* name, char* value)
{
WOLFSSL_CONF_VALUE* ret;
int len;
WOLFSSL_ENTER("wolfSSL_CONF_VALUE_new_values");
if (!(ret = wolfSSL_CONF_VALUE_new())) {
WOLFSSL_MSG("wolfSSL_CONF_VALUE_new error");
return NULL;
}
if (section) {
len = (int)XSTRLEN(section);
ret->section = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
if (!ret->section) {
WOLFSSL_MSG("malloc error");
wolfSSL_X509V3_conf_free(ret);
return NULL;
}
XMEMCPY(ret->section, section, len+1);
}
if (name) {
len = (int)XSTRLEN(name);
ret->name = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
if (!ret->name) {
WOLFSSL_MSG("malloc error");
wolfSSL_X509V3_conf_free(ret);
return NULL;
}
XMEMCPY(ret->name, name, len+1);
}
if (value) {
len = (int)XSTRLEN(value);
ret->value = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
if (!ret->value) {
WOLFSSL_MSG("malloc error");
wolfSSL_X509V3_conf_free(ret);
return NULL;
}
XMEMCPY(ret->value, value, len+1);
}
return ret;
}
static char* expandValue(WOLFSSL_CONF *conf, const char* section,
char *str)
{
int strLen = (int)XSTRLEN(str);
char* ret = NULL;
/* Check to see if there is anything to expand */
if (XSTRNSTR(str, "$", strLen)) {
int idx = 0;
char* strIdx = str;
ret = (char*)XMALLOC(strLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
if (!ret) {
WOLFSSL_MSG("malloc error");
return str;
}
while (*strIdx) {
if (*strIdx == '$') {
/* Expand variable */
char* startIdx = ++strIdx;
char* endIdx;
const char* s = section;
const char* value;
char prevValue;
if (*startIdx == '{') {
/* First read the section.
* format: ${section_name::var_name} */
s = ++startIdx;
while (*strIdx && *strIdx != ':') strIdx++;
if (!*strIdx || s == strIdx || strIdx[1] != ':') {
WOLFSSL_MSG("invalid section name in "
"variable expansion");
goto expand_cleanup;
}
*strIdx = '\0';
strIdx += 2;
startIdx = strIdx;
}
while (*strIdx && (XISALNUM((unsigned char)*strIdx) || *strIdx == '_'))
strIdx++;
endIdx = strIdx;
if (startIdx == endIdx) {
WOLFSSL_MSG("invalid variable name in config");
goto expand_cleanup;
}
if (s != section) {
/* We are expecting a trailing '}' */
if (*strIdx != '}') {
WOLFSSL_MSG("Missing '}' in variable");
goto expand_cleanup;
}
strIdx++;
}
/* Save char value at the end of the name so that we can place
* a null char there. */
prevValue = *endIdx;
*endIdx = '\0';
value = wolfSSL_NCONF_get_string(conf, s, startIdx);
*endIdx = prevValue;
/* Skip copy if no value or zero-length value */
if (value && *value) {
int valueLen = (int)XSTRLEN(value);
char* newRet;
/* This will allocate slightly more memory than necessary
* but better be safe */
strLen += valueLen;
#ifdef WOLFSSL_NO_REALLOC
newRet = (char*)XMALLOC(strLen + 1, NULL,
DYNAMIC_TYPE_OPENSSL);
if (newRet != NULL && ret != NULL) {
XMEMCPY(newRet, ret, (strLen - valueLen) + 1);
XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
ret = NULL;
}
#else
newRet = (char*)XREALLOC(ret, strLen + 1, NULL,
DYNAMIC_TYPE_OPENSSL);
#endif
if (!newRet) {
WOLFSSL_MSG("realloc error");
goto expand_cleanup;
}
ret = newRet;
XMEMCPY(ret + idx, value, valueLen);
idx += valueLen;
}
}
else {
ret[idx++] = *strIdx++;
}
}
ret[idx] = '\0';
}
return ret ? ret : str;
expand_cleanup:
XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
#define SKIP_WHITESPACE(idx, max_idx) \
while ((idx) < (max_idx) && (*(idx) == ' ' || *(idx) == '\t')) \
{(idx)++;}
int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
{
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
WOLFSSL_BIO *in = NULL;
char* buf = NULL;
char* idx = NULL;
char* bufEnd = NULL;
CONF_VALUE* section = NULL;
long line = 0;
int bufLen = 0;
if (!conf || !file) {
WOLFSSL_MSG("Bad parameter");
return WOLFSSL_FAILURE;
}
/* Open file */
if (!(in = wolfSSL_BIO_new_file(file, "rb"))) {
WOLFSSL_MSG("wolfSSL_BIO_new_file error");
return WOLFSSL_FAILURE;
}
/* Read file */
bufLen = wolfSSL_BIO_get_len(in);
if (bufLen <= 0) {
WOLFSSL_MSG("wolfSSL_BIO_get_len error");
goto cleanup;
}
if (!(buf = (char*)XMALLOC(bufLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
WOLFSSL_MSG("malloc error");
goto cleanup;
}
if (wolfSSL_BIO_read(in, buf, bufLen) != bufLen) {
WOLFSSL_MSG("wolfSSL_BIO_read error");
goto cleanup;
}
if (!(section = wolfSSL_CONF_new_section(conf, "default"))) {
WOLFSSL_MSG("wolfSSL_CONF_new_section error");
goto cleanup;
}
/* LETS START READING SOME CONFIGS */
idx = buf;
bufEnd = buf + bufLen;
while (idx < bufEnd) {
char* lineEnd = XSTRNSTR(idx, "\n", (unsigned int)(bufEnd - idx));
char* maxIdx;
if (!lineEnd)
lineEnd = bufEnd; /* Last line in file */
maxIdx = XSTRNSTR(idx, "#", (unsigned int)(lineEnd - idx));
if (!maxIdx)
maxIdx = lineEnd;
line++;
SKIP_WHITESPACE(idx, maxIdx);
if (idx == maxIdx) {
/* Empty line */
idx = lineEnd + 1;
continue;
}
if (*idx == '[') {
/* New section. Spaces not allowed in section name. */
char* sectionName;
int sectionNameLen;
if (idx < maxIdx)
idx++;
else {
WOLFSSL_MSG("Invalid section definition.");
goto cleanup;
}
SKIP_WHITESPACE(idx, maxIdx);
sectionName = idx;
/* Find end of section name */
while (idx < maxIdx && *idx != ' ' && *idx != ']')
idx++;
sectionNameLen = (int)(idx - sectionName);
SKIP_WHITESPACE(idx, maxIdx);
if (*idx != ']') {
WOLFSSL_MSG("Section definition error. "
"Closing brace not found.");
goto cleanup;
}
sectionName[sectionNameLen] = '\0';
if (!(section = wolfSSL_CONF_get_section(conf, sectionName))) {
section = wolfSSL_CONF_new_section(conf, sectionName);
if (!section)
goto cleanup;
}
}
else {
char* name;
int nameLen;
char* value;
char* exValue; /* expanded value */
int valueLen;
WOLFSSL_CONF_VALUE* newVal = NULL;
SKIP_WHITESPACE(idx, maxIdx);
name = idx;
/* Find end of name */
while (idx < maxIdx && *idx != ' ' && *idx != '=')
idx++;
nameLen = (int)(idx - name);
SKIP_WHITESPACE(idx, maxIdx);
if (*idx != '=') {
WOLFSSL_MSG("Missing equals sign");
goto cleanup;
}
idx++;
SKIP_WHITESPACE(idx, maxIdx);
value = idx;
/* Find end of value */
idx = maxIdx-1;
while (idx >= value && (*idx == ' ' || *idx == '\t' || *idx == '\r'))
idx--;
valueLen = (int)(idx - value + 1);
/* Sanity checks */
if (nameLen <= 0 || valueLen <= 0) {
WOLFSSL_MSG("Sanity checks failed");
goto cleanup;
}
name[nameLen] = '\0';
value[valueLen] = '\0';
if (!(exValue = expandValue(conf, section->section, value))) {
WOLFSSL_MSG("Variable expansion failed");
goto cleanup;
}
if (!(newVal = wolfSSL_CONF_VALUE_new_values(NULL,
name, exValue))) {
WOLFSSL_MSG("wolfSSL_CONF_VALUE_new_values error");
if (exValue != value)
XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
goto cleanup;
}
if (exValue != value)
XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
if (wolfSSL_CONF_add_string(conf, section, newVal) !=
WOLFSSL_SUCCESS) {
wolfSSL_X509V3_conf_free(newVal);
WOLFSSL_MSG("wolfSSL_CONF_add_string error");
goto cleanup;
}
}
idx = lineEnd + 1;
}
ret = WOLFSSL_SUCCESS;
cleanup:
if (in)
wolfSSL_BIO_free(in);
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (eline)
*eline = line;
return ret;
}
#endif /* !NO_BIO */
void wolfSSL_NCONF_free(WOLFSSL_CONF *conf)
{
WOLFSSL_ENTER("wolfSSL_NCONF_free");
if (conf) {
wolfSSL_sk_CONF_VALUE_free(conf->data);
XFREE(conf, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
void wolfSSL_X509V3_conf_free(WOLFSSL_CONF_VALUE *val)
{
if (val) {
if (val->name) {
/* Not a section. Don't free section as it is a shared pointer. */
XFREE(val->name, NULL, DYNAMIC_TYPE_OPENSSL);
XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL);
}
else {
/* Section so val->value is a stack */
XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL);
/* Only free the stack structures. The contained conf values
* will be freed in wolfSSL_NCONF_free */
wolfSSL_sk_free((WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value);
}
XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
}
}
WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(
WOLF_SK_COMPARE_CB(WOLFSSL_CONF_VALUE, compFunc))
{
WOLFSSL_STACK* ret;
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_new");
ret = wolfSSL_sk_new_node(NULL);
if (!ret)
return NULL;
ret->hash_fn = (wolf_sk_hash_cb)wolfSSL_CONF_VALUE_hash;
ret->type = STACK_TYPE_CONF_VALUE;
(void)compFunc;
return ret;
}
/* Free the structure for WOLFSSL_CONF_VALUE stack
*
* sk stack to free nodes in
*/
void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk)
{
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free");
wolfSSL_sk_pop_free(sk, NULL);
}
int wolfSSL_sk_CONF_VALUE_num(const WOLFSSL_STACK *sk)
{
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_num");
if (sk)
return wolfSSL_sk_num(sk);
return 0;
}
WOLFSSL_CONF_VALUE *wolfSSL_sk_CONF_VALUE_value(const WOLFSSL_STACK *sk, int i)
{
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_value");
if (sk)
return (WOLFSSL_CONF_VALUE*)wolfSSL_sk_value(sk, i);
return NULL;
}
/* return 1 on success 0 on fail */
int wolfSSL_sk_CONF_VALUE_push(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk,
WOLFSSL_CONF_VALUE* val)
{
WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_push");
if (sk == NULL || val == NULL) {
return WOLFSSL_FAILURE;
}
return wolfSSL_sk_push(sk, val);
}
#endif /* !NO_CERTS && OPENSSL_EXTRA && OPENSSL_ALL */
#ifdef OPENSSL_EXTRA
#ifndef NO_WOLFSSL_STUB
/* Returns default file name and path of config file. However
a wolfssl.cnf file is not currently supported */
char* wolfSSL_CONF_get1_default_config_file(void)
{
WOLFSSL_ENTER("wolfSSL_CONF_get1_default_config_file");
WOLFSSL_STUB("CONF_get1_default_config_file");
return NULL;
}
#endif
/**
* Allocate WOLFSSL_CONF_CTX instance
* @return pointer to WOLFSSL_CONF_CTX structure on success and NULL on fail
*/
WOLFSSL_CONF_CTX* wolfSSL_CONF_CTX_new(void)
{
WOLFSSL_CONF_CTX* cctx;
WOLFSSL_ENTER("wolfSSL_CONF_CTX_new");
cctx = (WOLFSSL_CONF_CTX*)XMALLOC(sizeof(WOLFSSL_CONF_CTX), NULL,
DYNAMIC_TYPE_OPENSSL);
if (!cctx) {
WOLFSSL_MSG("malloc error");
return NULL;
}
XMEMSET(cctx, 0, sizeof(WOLFSSL_CONF_CTX));
return cctx;
}
/**
* Release WOLFSSL_CONF_CTX instance
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to be freed
*/
void wolfSSL_CONF_CTX_free(WOLFSSL_CONF_CTX* cctx)
{
WOLFSSL_ENTER("wolfSSL_CONF_CTX_free");
XFREE(cctx, NULL, DYNAMIC_TYPE_OPENSSL);
WOLFSSL_LEAVE("wolfSSL_CONF_CTX_free", 1);
}
/**
* Set WOLFSSL_CTX instance to WOLFSSL_CONF_CTX
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to set a WOLFSSL_CTX
* pointer to its ctx
* @param ctx a pointer to WOLFSSL_CTX structure to be set
*/
void wolfSSL_CONF_CTX_set_ssl_ctx(WOLFSSL_CONF_CTX* cctx, WOLFSSL_CTX *ctx)
{
WOLFSSL_ENTER("wolfSSL_CONF_CTX_set_ssl_ctx");
/* sanity check */
if (cctx == NULL) {
WOLFSSL_MSG("cctx is null");
return;
}
cctx->ctx = ctx;
WOLFSSL_LEAVE("wolfSSL_CONF_CTX_set_ssl_ctx", 1);
}
/**
* set flag value into WOLFSSL_CONF_CTX
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to be set
* @param flags flag value to be OR'd
* @return OR'd flag value, otherwise 0
*/
unsigned int wolfSSL_CONF_CTX_set_flags(WOLFSSL_CONF_CTX* cctx,
unsigned int flags)
{
/* sanity check */
if (cctx == NULL)
return 0;
cctx->flags |= flags;
return cctx->flags;
}
/**
* finish configuration command operation
* @param cctx a pointer to WOLFSSL_CONF_CTX structure to be set
* @return WOLFSSL_SUCCESS on success
*/
int wolfSSL_CONF_CTX_finish(WOLFSSL_CONF_CTX* cctx)
{
(void)cctx;
return WOLFSSL_SUCCESS;
}
/*
* The following definitions and static functions are used for
* wolfSSL_CONF_cmd() to handle command.
*
* Definitions below are a part of conf_cmds_tbl[] contents.
* WOLFSSL_CONF_FILE_CMDx represents command name in configuration file
* WOLFSSL_CONF_CMDL_CMDx represents command name on command line
*
* The static functions after the definition section process
* those FILE or CMDL which are defined in the conf_cmds_tbl.
*
* To add a new command handling:
* 1. Add new #define to a section of WOLFSSL_CONF_FILE_CMD* and
* WOLFSSL_CONF_CMDL_CMD*
* 2. Add new static function after #define section, before
* "typedef struct conf_cmd_tbl {" line
* 3. Add new entry to conf_cmds_tbl[] by following other command entries
*/
#define WOLFSSL_CONF_FILE_CMD1 "Curves"
#define WOLFSSL_CONF_FILE_CMD2 "Certificate"
#define WOLFSSL_CONF_FILE_CMD3 "PrivateKey"
#define WOLFSSL_CONF_FILE_CMD4 "Protocol"
#define WOLFSSL_CONF_FILE_CMD5 "Options"
#define WOLFSSL_CONF_FILE_CMD6 "ServerInfoFile"
#define WOLFSSL_CONF_FILE_CMD7 "SignatureAlgorithms"
#define WOLFSSL_CONF_FILE_CMD8 "ClientSignatureAlgorithms"
#define WOLFSSL_CONF_FILE_CMD9 "CipherString"
#define WOLFSSL_CONF_CMDL_CMD1 "curves"
#define WOLFSSL_CONF_CMDL_CMD2 "cert"
#define WOLFSSL_CONF_CMDL_CMD3 "key"
#define WOLFSSL_CONF_CMDL_CMD4 NULL
#define WOLFSSL_CONF_CMDL_CMD5 NULL
#define WOLFSSL_CONF_CMDL_CMD6 NULL
#define WOLFSSL_CONF_CMDL_CMD7 "sigalgs"
#define WOLFSSL_CONF_CMDL_CMD8 "client_sigalgs"
#define WOLFSSL_CONF_CMDL_CMD9 "cipher"
#if !defined(NO_DH) && !defined(NO_BIO)
#define WOLFSSL_CONF_FILE_CMD10 "DHParameters"
#define WOLFSSL_CONF_CMDL_CMD10 "dhparam"
#endif
#ifdef HAVE_ECC
#define WOLFSSL_CONF_FILE_CMD11 "ECDHParameters"
#define WOLFSSL_CONF_CMDL_CMD11 "named_curves"
#endif
/**
* process Cipher String command
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param value arguments for cmd
* @return WOLFSSL_SUCCESS on success,
* otherwise WOLFSSL_FAILURE or
* -3 if value is null or
* negative value on other failure
*/
static int cmdfunc_cipherstring(WOLFSSL_CONF_CTX* cctx, const char* value)
{
int ret = -3;
WOLFSSL_ENTER("cmdfunc_cipherstring");
/* sanity check */
if (cctx == NULL)
return WOLFSSL_FAILURE;
if (value == NULL) {
WOLFSSL_MSG("bad arguments");
return ret;
}
if (cctx->ctx) {
ret = wolfSSL_CTX_set_cipher_list(cctx->ctx, value);
}
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
(!cctx->ctx && ret == -3)) &&
cctx->ssl) {
ret = wolfSSL_set_cipher_list(cctx->ssl, value);
}
WOLFSSL_LEAVE("cmdfunc_cipherstring", ret);
return ret;
}
/**
* process curves command
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param value arguments for cmd
* @return WOLFSSL_SUCCESS on success,
* otherwise WOLFSSL_FAILURE or
* -3 if value is null or
* negative value on other failure
*/
#if defined(HAVE_ECC)
static int cmdfunc_curves(WOLFSSL_CONF_CTX* cctx, const char* value)
{
int ret = -3;
WOLFSSL_ENTER("cmdfunc_curves");
/* sanity check */
if (cctx == NULL)
return WOLFSSL_FAILURE;
if (value == NULL) {
WOLFSSL_MSG("bad arguments");
return ret;
}
if (cctx->ctx) {
ret = wolfSSL_CTX_set1_curves_list(cctx->ctx, value);
}
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
(!cctx->ctx && ret == -3)) &&
cctx->ssl) {
ret = wolfSSL_set1_curves_list(cctx->ssl, value);
}
WOLFSSL_LEAVE("cmdfunc_curves", ret);
return ret;
}
#endif
#ifndef NO_FILESYSTEM
/**
* process cert command
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param value arguments for cmd
* @return WOLFSSL_SUCCESS on success,
* otherwise WOLFSSL_FAILURE or
* -3 if value is null or
* negative value on other failure
*/
static int cmdfunc_cert(WOLFSSL_CONF_CTX* cctx, const char* value)
{
int ret = -3;
WOLFSSL_ENTER("cmdfunc_cert");
/* sanity check */
if (cctx == NULL)
return WOLFSSL_FAILURE;
if (value == NULL) {
WOLFSSL_MSG("bad arguments");
return ret;
}
if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) {
WOLFSSL_MSG("certificate flag is not set");
return -2;
}
if (cctx->ctx) {
ret = wolfSSL_CTX_use_certificate_chain_file(cctx->ctx, value);
}
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
(!cctx->ctx && ret == -3)) &&
cctx->ssl) {
ret = wolfSSL_use_certificate_file(cctx->ssl, value,
WOLFSSL_FILETYPE_PEM);
}
WOLFSSL_LEAVE("cmdfunc_cert", ret);
return ret;
}
/**
* process key command
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param value arguments for cmd
* @return WOLFSSL_SUCCESS on success,
* otherwise WOLFSSL_FAILURE or
* -3 if value is null or
* negative value on other failure
*/
static int cmdfunc_key(WOLFSSL_CONF_CTX* cctx, const char* value)
{
int ret = -3;
WOLFSSL_ENTER("cmdfunc_key");
/* sanity check */
if (cctx == NULL)
return WOLFSSL_FAILURE;
if (value == NULL) {
WOLFSSL_MSG("bad arguments");
return ret;
}
if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) {
WOLFSSL_MSG("certificate flag is not set");
return -2;
}
if (cctx->ctx) {
ret = wolfSSL_CTX_use_PrivateKey_file(cctx->ctx, value,
WOLFSSL_FILETYPE_PEM);
}
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
(!cctx->ctx && ret == -3)) &&
cctx->ssl) {
ret = wolfSSL_use_PrivateKey_file(cctx->ssl, value,
WOLFSSL_FILETYPE_PEM);
}
WOLFSSL_LEAVE("cmdfunc_key", ret);
return ret;
}
#endif /* NO_FILESYSTEM */
/**
* process DH parameter command
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param value arguments for cmd
* @return WOLFSSL_SUCCESS on success,
* otherwise WOLFSSL_FAILURE or
* -3 if value is null or
* negative value on other failure
*/
#if !defined(NO_DH) && !defined(NO_BIO)
static int cmdfunc_dhparam(WOLFSSL_CONF_CTX* cctx, const char* value)
{
int ret = -3;
WOLFSSL_DH* dh = NULL;
WOLFSSL_BIO* bio = NULL;
WOLFSSL_MSG("cmdfunc_dhparam");
/* sanity check */
if (cctx == NULL)
return WOLFSSL_FAILURE;
if (value == NULL) {
WOLFSSL_MSG("bad arguments");
return ret;
}
if (cctx->ctx || cctx->ssl) {
bio = wolfSSL_BIO_new_file(value, "rb");
if (!bio) {
WOLFSSL_MSG("bio new file failed");
return WOLFSSL_FAILURE;
}
dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
if (!dh) {
wolfSSL_BIO_free(bio);
WOLFSSL_MSG("PEM read bio failed");
return WOLFSSL_FAILURE;
}
} else {
return 1;
}
if (cctx->ctx) {
ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ctx, dh);
}
if (((cctx->ctx && ret == WOLFSSL_SUCCESS) ||
(!cctx->ctx && ret == -3)) &&
cctx->ssl) {
ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ssl->ctx, dh);
}
if (dh)
wolfSSL_DH_free(dh);
if (bio)
wolfSSL_BIO_free(bio);
WOLFSSL_LEAVE("cmdfunc_dhparam", ret);
return ret;
}
#endif /* !NO_DH && !NO_BIO */
/**
* command table
*/
typedef struct conf_cmd_tbl {
const char* file_cmd;
const char* cmdline_cmd;
word32 data_type;
int (*cmdfunc)(WOLFSSL_CONF_CTX* cctx, const char* value);
}conf_cmd_tbl;
static const conf_cmd_tbl conf_cmds_tbl[] = {
#if defined(HAVE_ECC)
/* cmd Curves */
{WOLFSSL_CONF_FILE_CMD1, WOLFSSL_CONF_CMDL_CMD1,
WOLFSSL_CONF_TYPE_STRING, cmdfunc_curves},
#endif
#if !defined(NO_FILESYSTEM)
/* cmd Certificate */
{WOLFSSL_CONF_FILE_CMD2, WOLFSSL_CONF_CMDL_CMD2,
WOLFSSL_CONF_TYPE_FILE, cmdfunc_cert},
/* cmd PrivateKey */
{WOLFSSL_CONF_FILE_CMD3, WOLFSSL_CONF_CMDL_CMD3,
WOLFSSL_CONF_TYPE_FILE, cmdfunc_key},
#endif
/* cmd Protocol */
{WOLFSSL_CONF_FILE_CMD4, WOLFSSL_CONF_CMDL_CMD4,
WOLFSSL_CONF_TYPE_STRING, NULL},
/* cmd Options */
{WOLFSSL_CONF_FILE_CMD5, WOLFSSL_CONF_CMDL_CMD5,
WOLFSSL_CONF_TYPE_STRING, NULL},
/* cmd ServerInfoFile */
{WOLFSSL_CONF_FILE_CMD6, WOLFSSL_CONF_CMDL_CMD6,
WOLFSSL_CONF_TYPE_FILE, NULL},
/* cmd SignatureAlgorithms */
{WOLFSSL_CONF_FILE_CMD7, WOLFSSL_CONF_CMDL_CMD7,
WOLFSSL_CONF_TYPE_STRING, NULL},
/* cmd ClientSignatureAlgorithms */
{WOLFSSL_CONF_FILE_CMD8, WOLFSSL_CONF_CMDL_CMD8,
WOLFSSL_CONF_TYPE_STRING, NULL},
/* cmd CipherString */
{WOLFSSL_CONF_FILE_CMD9, WOLFSSL_CONF_CMDL_CMD9,
WOLFSSL_CONF_TYPE_STRING, cmdfunc_cipherstring},
#if !defined(NO_DH) && !defined(NO_BIO)
/* cmd DHParameters */
{WOLFSSL_CONF_FILE_CMD10, WOLFSSL_CONF_CMDL_CMD10,
WOLFSSL_CONF_TYPE_FILE, cmdfunc_dhparam},
#endif
#ifdef HAVE_ECC
/* cmd ECHDParameters */
{WOLFSSL_CONF_FILE_CMD11, WOLFSSL_CONF_CMDL_CMD11,
WOLFSSL_CONF_TYPE_STRING, NULL},
#endif
};
/* size of command table */
static const size_t size_of_cmd_tbls = sizeof(conf_cmds_tbl)
/ sizeof(conf_cmd_tbl);
static const conf_cmd_tbl* wolfssl_conf_find_cmd(WOLFSSL_CONF_CTX* cctx,
const char* cmd)
{
size_t i = 0;
if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) {
size_t cmdlen = XSTRLEN(cmd);
if (cmdlen < 2) {
WOLFSSL_MSG("bad cmdline command");
return NULL;
}
/* skip "-" prefix */
++cmd;
}
for (i = 0; i < size_of_cmd_tbls; i++) {
/* check if the cmd is valid */
if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) {
if (conf_cmds_tbl[i].cmdline_cmd != NULL &&
XSTRCMP(cmd, conf_cmds_tbl[i].cmdline_cmd) == 0) {
return &conf_cmds_tbl[i];
}
}
if (cctx->flags & WOLFSSL_CONF_FLAG_FILE) {
if (conf_cmds_tbl[i].file_cmd != NULL &&
XSTRCMP(cmd, conf_cmds_tbl[i].file_cmd) == 0) {
return &conf_cmds_tbl[i];
}
}
}
return NULL;
}
/**
* send configuration command
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param cmd configuration command
* @param value arguments for cmd
* @return 1 when cmd is recognised, but value is not used
* 2 both cmd and value are used
* otherwise WOLFSSL_FAILURE
* -2 if cmd is not recognised
* -3 if value is NULL, but cmd is recognized
*/
int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
{
int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
const conf_cmd_tbl* confcmd = NULL;
WOLFSSL_ENTER("wolfSSL_CONF_cmd");
/* sanity check */
if (cctx == NULL || cmd == NULL) {
WOLFSSL_MSG("bad arguments");
return ret;
}
confcmd = wolfssl_conf_find_cmd(cctx, cmd);
if (confcmd == NULL)
return -2;
if (confcmd->cmdfunc == NULL) {
WOLFSSL_MSG("cmd not yet implemented");
return -2;
}
ret = confcmd->cmdfunc(cctx, value);
/* return code compliant with OpenSSL */
if (ret < -3)
ret = 0;
WOLFSSL_LEAVE("wolfSSL_CONF_cmd", ret);
return ret;
}
/**
*
* @param cctx a pointer to WOLFSSL_CONF_CTX structure
* @param cmd configuration command
* @return The SSL_CONF_TYPE_* type or SSL_CONF_TYPE_UNKNOWN if an
* invalid command
*/
int wolfSSL_CONF_cmd_value_type(WOLFSSL_CONF_CTX *cctx, const char *cmd)
{
const conf_cmd_tbl* confcmd = NULL;
WOLFSSL_ENTER("wolfSSL_CONF_cmd_value_type");
confcmd = wolfssl_conf_find_cmd(cctx, cmd);
if (confcmd == NULL)
return WOLFSSL_CONF_TYPE_UNKNOWN;
return (int)confcmd->data_type;
}
#endif /* OPENSSL_EXTRA */
/*******************************************************************************
* END OF CONF API
******************************************************************************/
#if defined(OPENSSL_EXTRA)
WOLFSSL_INIT_SETTINGS* wolfSSL_OPENSSL_INIT_new(void)
{
WOLFSSL_INIT_SETTINGS* init = (WOLFSSL_INIT_SETTINGS*)XMALLOC(
sizeof(WOLFSSL_INIT_SETTINGS), NULL, DYNAMIC_TYPE_OPENSSL);
return init;
}
void wolfSSL_OPENSSL_INIT_free(WOLFSSL_INIT_SETTINGS* init)
{
XFREE(init, NULL, DYNAMIC_TYPE_OPENSSL);
}
#ifndef NO_WOLFSSL_STUB
int wolfSSL_OPENSSL_INIT_set_config_appname(WOLFSSL_INIT_SETTINGS* init,
char* appname)
{
(void)init;
(void)appname;
WOLFSSL_STUB("OPENSSL_INIT_set_config_appname");
return WOLFSSL_SUCCESS;
}
#endif
#endif /* OPENSSL_EXTRA */
#endif /* WOLFSSL_CONF_INCLUDED */