mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-27 03:22:19 +01:00
1617 lines
46 KiB
C
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 */
|