diff --git a/src/bio.c b/src/bio.c index b0173d3af..5c832a674 100644 --- a/src/bio.c +++ b/src/bio.c @@ -24,6 +24,11 @@ #endif #include +#if defined(OPENSSL_EXTRA) && !defined(_WIN32) + /* turn on GNU extensions for XVASPRINTF with wolfSSL_BIO_printf */ + #undef _GNU_SOURCE + #define _GNU_SOURCE +#endif #if !defined(WOLFSSL_BIO_INCLUDED) #ifndef WOLFSSL_IGNORE_FILE_WARN diff --git a/src/conf.c b/src/conf.c new file mode 100644 index 000000000..eeace783e --- /dev/null +++ b/src/conf.c @@ -0,0 +1,1609 @@ +/* conf.c + * + * Copyright (C) 2006-2022 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 2 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 + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#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) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_push error"); + XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL); + goto error; + } + } + + failed = 0; +error: + if (failed && ret) { + XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); + ret = NULL; + } + if (buf) { + 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 sz; + 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; + + 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; + } + } + idx[-1] = '\n'; + 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) != WOLFSSL_SUCCESS) { + 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_sk_compare_cb cmp) +{ + WOLFSSL_ENTER("wolfSSL_TXT_DB_create_index"); + (void)qual; + + if (!db || !hash || !cmp || field >= db->num_fields || field < 0) { + WOLFSSL_MSG("Bad parameter"); + return WOLFSSL_FAILURE; + } + + db->hash_fn[field] = hash; + db->comp[field] = cmp; + + 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] || !db->comp[idx]) { + WOLFSSL_MSG("Missing hash or cmp functions"); + return NULL; + } + + /* If first data struct has correct hash and cmp function then + * assume others do too */ + if (db->data->hash_fn != db->hash_fn[idx] || + db->data->comp != db->comp[idx]) { + /* Set the hash and comp functions */ + WOLF_STACK_OF(WOLFSSL_STRING)* data = db->data; + while (data) { + if (data->comp != db->comp[idx] || + data->hash_fn != db->hash_fn[idx]) { + data->comp = db->comp[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; +} + +static int wolfssl_conf_value_cmp(const WOLFSSL_CONF_VALUE *a, + const WOLFSSL_CONF_VALUE *b) +{ + int cmp_val; + + if (!a || !b) { + return WOLFSSL_FATAL_ERROR; + } + + if (a->section != b->section) { + if ((cmp_val = XSTRCMP(a->section, b->section)) != 0) { + return cmp_val; + } + } + + if (a->name && b->name) { + return XSTRCMP(a->name, b->name); + } + else if (a->name == b->name) { + return 0; + } + else { + return a->name ? 1 : -1; + } +} + +/* Use SHA 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; +#ifndef NO_SHA + wc_Sha sha; + int strLen; + byte digest[WC_SHA_DIGEST_SIZE]; +#endif + WOLFSSL_ENTER("wolfSSL_LH_strhash"); + + if (!str) + return 0; + +#ifndef NO_SHA + strLen = (int)XSTRLEN(str); + + 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); + 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) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error"); + 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) != WOLFSSL_SUCCESS) { + 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 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(*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; + newRet = (char*)XREALLOC(ret, strLen + 1, NULL, + DYNAMIC_TYPE_OPENSSL); + 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: + if (ret) + 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 = 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--; + 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_MSG("wolfSSL_CONF_add_string error"); + goto cleanup; + } + } + idx = lineEnd + 1; + } + + ret = WOLFSSL_SUCCESS; +cleanup: + if (in) + wolfSSL_BIO_free(in); + if (buf) + 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) +{ + WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL; + + 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); + if (val->value) + XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL); + } + else { + /* Section so val->value is a stack */ + if (val->section) + XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL); + /* Only free the stack structures. The contained conf values + * will be freed in wolfSSL_NCONF_free */ + sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value; + while (sk) { + WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *tmp = sk->next; + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = tmp; + } + } + XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(wolf_sk_compare_cb compFunc) +{ + WOLFSSL_STACK* ret; + WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_new"); + ret = wolfSSL_sk_new_node(NULL); + if (!ret) + return NULL; + ret->comp = compFunc ? compFunc : (wolf_sk_compare_cb)wolfssl_conf_value_cmp; + ret->hash_fn = (wolf_sk_hash_cb)wolfSSL_CONF_VALUE_hash; + ret->type = STACK_TYPE_CONF_VALUE; + 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_STACK* tmp; + WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free"); + + if (sk == NULL) + return; + + /* parse through stack freeing each node */ + while (sk) { + tmp = sk->next; + wolfSSL_X509V3_conf_free(sk->data.conf); + XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); + sk = tmp; + } +} + +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"); + + if (cctx) { + 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 falg 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; + size_t cmdlen = 0; + + if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) { + 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 = 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 + * unvalid 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 SSL_CONF_TYPE_UNKNOWN; + return (int)confcmd->data_type; +} + +#endif /* OPENSSL_EXTRA */ + + +/******************************************************************************* + * END OF CONF API + ******************************************************************************/ + +#endif /* WOLFSSL_CONF_INCLUDED */ diff --git a/src/include.am b/src/include.am index 9a29d640a..6206fe5c1 100644 --- a/src/include.am +++ b/src/include.am @@ -16,6 +16,9 @@ BUILT_SOURCES+= $(FIPS_FILES) MAINTAINERCLEANFILES+= $(FIPS_FILES) +EXTRA_DIST += src/bio.c +EXTRA_DIST += src/conf.c + $(FIPS_FILES): $(AM_V_at)touch $(srcdir)/$@ diff --git a/src/ssl.c b/src/ssl.c index 57ef9e9f5..5cb109503 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -26,7 +26,7 @@ #include #if defined(OPENSSL_EXTRA) && !defined(_WIN32) - /* turn on GNU extensions for XVASPRINTF with wolfSSL_BIO_printf */ + /* turn on GNU extensions for XISASCII */ #undef _GNU_SOURCE #define _GNU_SOURCE #endif @@ -58214,1579 +58214,8 @@ void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf) * END OF BUF_MEM API ******************************************************************************/ -/******************************************************************************* - * 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) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_push error"); - XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL); - goto error; - } - } - - failed = 0; -error: - if (failed && ret) { - XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL); - ret = NULL; - } - if (buf) { - 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 sz; - 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; - - 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; - } - } - idx[-1] = '\n'; - 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) != WOLFSSL_SUCCESS) { - 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_sk_compare_cb cmp) -{ - WOLFSSL_ENTER("wolfSSL_TXT_DB_create_index"); - (void)qual; - - if (!db || !hash || !cmp || field >= db->num_fields || field < 0) { - WOLFSSL_MSG("Bad parameter"); - return WOLFSSL_FAILURE; - } - - db->hash_fn[field] = hash; - db->comp[field] = cmp; - - 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] || !db->comp[idx]) { - WOLFSSL_MSG("Missing hash or cmp functions"); - return NULL; - } - - /* If first data struct has correct hash and cmp function then - * assume others do too */ - if (db->data->hash_fn != db->hash_fn[idx] || - db->data->comp != db->comp[idx]) { - /* Set the hash and comp functions */ - WOLF_STACK_OF(WOLFSSL_STRING)* data = db->data; - while (data) { - if (data->comp != db->comp[idx] || - data->hash_fn != db->hash_fn[idx]) { - data->comp = db->comp[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; -} - -static int wolfssl_conf_value_cmp(const WOLFSSL_CONF_VALUE *a, - const WOLFSSL_CONF_VALUE *b) -{ - int cmp_val; - - if (!a || !b) { - return WOLFSSL_FATAL_ERROR; - } - - if (a->section != b->section) { - if ((cmp_val = XSTRCMP(a->section, b->section)) != 0) { - return cmp_val; - } - } - - if (a->name && b->name) { - return XSTRCMP(a->name, b->name); - } - else if (a->name == b->name) { - return 0; - } - else { - return a->name ? 1 : -1; - } -} - -/* Use SHA 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; -#ifndef NO_SHA - wc_Sha sha; - int strLen; - byte digest[WC_SHA_DIGEST_SIZE]; -#endif - WOLFSSL_ENTER("wolfSSL_LH_strhash"); - - if (!str) - return 0; - -#ifndef NO_SHA - strLen = (int)XSTRLEN(str); - - 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); - 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) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error"); - return WOLFSSL_FAILURE; - } - if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error"); - 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) != WOLFSSL_SUCCESS) { - 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 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(*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; - newRet = (char*)XREALLOC(ret, strLen + 1, NULL, - DYNAMIC_TYPE_OPENSSL); - 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: - if (ret) - 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 = 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--; - 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_MSG("wolfSSL_CONF_add_string error"); - goto cleanup; - } - } - idx = lineEnd + 1; - } - - ret = WOLFSSL_SUCCESS; -cleanup: - if (in) - wolfSSL_BIO_free(in); - if (buf) - 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) -{ - WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL; - - 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); - if (val->value) - XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL); - } - else { - /* Section so val->value is a stack */ - if (val->section) - XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL); - /* Only free the stack structures. The contained conf values - * will be freed in wolfSSL_NCONF_free */ - sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value; - while (sk) { - WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *tmp = sk->next; - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = tmp; - } - } - XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL); - } -} - -WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(wolf_sk_compare_cb compFunc) -{ - WOLFSSL_STACK* ret; - WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_new"); - ret = wolfSSL_sk_new_node(NULL); - if (!ret) - return NULL; - ret->comp = compFunc ? compFunc : (wolf_sk_compare_cb)wolfssl_conf_value_cmp; - ret->hash_fn = (wolf_sk_hash_cb)wolfSSL_CONF_VALUE_hash; - ret->type = STACK_TYPE_CONF_VALUE; - 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_STACK* tmp; - WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free"); - - if (sk == NULL) - return; - - /* parse through stack freeing each node */ - while (sk) { - tmp = sk->next; - wolfSSL_X509V3_conf_free(sk->data.conf); - XFREE(sk, NULL, DYNAMIC_TYPE_OPENSSL); - sk = tmp; - } -} - -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"); - - if (cctx) { - 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 falg 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; - size_t cmdlen = 0; - - if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) { - 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 = 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 - * unvalid 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 SSL_CONF_TYPE_UNKNOWN; - return (int)confcmd->data_type; -} - -#endif /* OPENSSL_EXTRA */ - - -/******************************************************************************* - * END OF CONF API - ******************************************************************************/ +#define WOLFSSL_CONF_INCLUDED +#include /******************************************************************************* * START OF RAND API diff --git a/wolfcrypt/src/include.am b/wolfcrypt/src/include.am index 84d7beecb..7f25d17d7 100644 --- a/wolfcrypt/src/include.am +++ b/wolfcrypt/src/include.am @@ -10,7 +10,6 @@ BUILT_SOURCES+= $(ASYNC_FILES) MAINTAINERCLEANFILES+= $(ASYNC_FILES) -EXTRA_DIST += src/bio.c EXTRA_DIST += wolfcrypt/src/misc.c EXTRA_DIST += wolfcrypt/src/evp.c EXTRA_DIST += wolfcrypt/src/asm.c