1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* Part of the code in here was originally in conf.c, which is now removed */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <stdio.h> 13e1051a39Sopenharmony_ci#include <string.h> 14e1051a39Sopenharmony_ci#include "e_os.h" /* struct stat */ 15e1051a39Sopenharmony_ci#ifdef __TANDEM 16e1051a39Sopenharmony_ci# include <sys/types.h> /* needed for stat.h */ 17e1051a39Sopenharmony_ci# include <sys/stat.h> /* struct stat */ 18e1051a39Sopenharmony_ci#endif 19e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 20e1051a39Sopenharmony_ci#include "internal/o_dir.h" 21e1051a39Sopenharmony_ci#include <openssl/lhash.h> 22e1051a39Sopenharmony_ci#include <openssl/conf.h> 23e1051a39Sopenharmony_ci#include <openssl/conf_api.h> 24e1051a39Sopenharmony_ci#include "conf_local.h" 25e1051a39Sopenharmony_ci#include "conf_def.h" 26e1051a39Sopenharmony_ci#include <openssl/buffer.h> 27e1051a39Sopenharmony_ci#include <openssl/err.h> 28e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 29e1051a39Sopenharmony_ci# include <sys/stat.h> 30e1051a39Sopenharmony_ci# ifdef _WIN32 31e1051a39Sopenharmony_ci# define stat _stat 32e1051a39Sopenharmony_ci# endif 33e1051a39Sopenharmony_ci#endif 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci#ifndef S_ISDIR 36e1051a39Sopenharmony_ci# define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 37e1051a39Sopenharmony_ci#endif 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci/* 40e1051a39Sopenharmony_ci * The maximum length we can grow a value to after variable expansion. 64k 41e1051a39Sopenharmony_ci * should be more than enough for all reasonable uses. 42e1051a39Sopenharmony_ci */ 43e1051a39Sopenharmony_ci#define MAX_CONF_VALUE_LENGTH 65536 44e1051a39Sopenharmony_ci 45e1051a39Sopenharmony_cistatic int is_keytype(const CONF *conf, char c, unsigned short type); 46e1051a39Sopenharmony_cistatic char *eat_ws(CONF *conf, char *p); 47e1051a39Sopenharmony_cistatic void trim_ws(CONF *conf, char *start); 48e1051a39Sopenharmony_cistatic char *eat_alpha_numeric(CONF *conf, char *p); 49e1051a39Sopenharmony_cistatic void clear_comments(CONF *conf, char *p); 50e1051a39Sopenharmony_cistatic int str_copy(CONF *conf, char *section, char **to, char *from); 51e1051a39Sopenharmony_cistatic char *scan_quote(CONF *conf, char *p); 52e1051a39Sopenharmony_cistatic char *scan_dquote(CONF *conf, char *p); 53e1051a39Sopenharmony_ci#define scan_esc(conf,p) (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2))) 54e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 55e1051a39Sopenharmony_cistatic BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx, 56e1051a39Sopenharmony_ci char **dirpath); 57e1051a39Sopenharmony_cistatic BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx); 58e1051a39Sopenharmony_ci#endif 59e1051a39Sopenharmony_ci 60e1051a39Sopenharmony_cistatic CONF *def_create(CONF_METHOD *meth); 61e1051a39Sopenharmony_cistatic int def_init_default(CONF *conf); 62e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 63e1051a39Sopenharmony_cistatic int def_init_WIN32(CONF *conf); 64e1051a39Sopenharmony_ci#endif 65e1051a39Sopenharmony_cistatic int def_destroy(CONF *conf); 66e1051a39Sopenharmony_cistatic int def_destroy_data(CONF *conf); 67e1051a39Sopenharmony_cistatic int def_load(CONF *conf, const char *name, long *eline); 68e1051a39Sopenharmony_cistatic int def_load_bio(CONF *conf, BIO *bp, long *eline); 69e1051a39Sopenharmony_cistatic int def_dump(const CONF *conf, BIO *bp); 70e1051a39Sopenharmony_cistatic int def_is_number(const CONF *conf, char c); 71e1051a39Sopenharmony_cistatic int def_to_int(const CONF *conf, char c); 72e1051a39Sopenharmony_ci 73e1051a39Sopenharmony_cistatic CONF_METHOD default_method = { 74e1051a39Sopenharmony_ci "OpenSSL default", 75e1051a39Sopenharmony_ci def_create, 76e1051a39Sopenharmony_ci def_init_default, 77e1051a39Sopenharmony_ci def_destroy, 78e1051a39Sopenharmony_ci def_destroy_data, 79e1051a39Sopenharmony_ci def_load_bio, 80e1051a39Sopenharmony_ci def_dump, 81e1051a39Sopenharmony_ci def_is_number, 82e1051a39Sopenharmony_ci def_to_int, 83e1051a39Sopenharmony_ci def_load 84e1051a39Sopenharmony_ci}; 85e1051a39Sopenharmony_ci 86e1051a39Sopenharmony_ciCONF_METHOD *NCONF_default(void) 87e1051a39Sopenharmony_ci{ 88e1051a39Sopenharmony_ci return &default_method; 89e1051a39Sopenharmony_ci} 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 92e1051a39Sopenharmony_cistatic CONF_METHOD WIN32_method = { 93e1051a39Sopenharmony_ci "WIN32", 94e1051a39Sopenharmony_ci def_create, 95e1051a39Sopenharmony_ci def_init_WIN32, 96e1051a39Sopenharmony_ci def_destroy, 97e1051a39Sopenharmony_ci def_destroy_data, 98e1051a39Sopenharmony_ci def_load_bio, 99e1051a39Sopenharmony_ci def_dump, 100e1051a39Sopenharmony_ci def_is_number, 101e1051a39Sopenharmony_ci def_to_int, 102e1051a39Sopenharmony_ci def_load 103e1051a39Sopenharmony_ci}; 104e1051a39Sopenharmony_ci 105e1051a39Sopenharmony_ciCONF_METHOD *NCONF_WIN32(void) 106e1051a39Sopenharmony_ci{ 107e1051a39Sopenharmony_ci return &WIN32_method; 108e1051a39Sopenharmony_ci} 109e1051a39Sopenharmony_ci#endif 110e1051a39Sopenharmony_ci 111e1051a39Sopenharmony_cistatic CONF *def_create(CONF_METHOD *meth) 112e1051a39Sopenharmony_ci{ 113e1051a39Sopenharmony_ci CONF *ret; 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci ret = OPENSSL_malloc(sizeof(*ret)); 116e1051a39Sopenharmony_ci if (ret != NULL) 117e1051a39Sopenharmony_ci if (meth->init(ret) == 0) { 118e1051a39Sopenharmony_ci OPENSSL_free(ret); 119e1051a39Sopenharmony_ci ret = NULL; 120e1051a39Sopenharmony_ci } 121e1051a39Sopenharmony_ci return ret; 122e1051a39Sopenharmony_ci} 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_cistatic int def_init_default(CONF *conf) 125e1051a39Sopenharmony_ci{ 126e1051a39Sopenharmony_ci if (conf == NULL) 127e1051a39Sopenharmony_ci return 0; 128e1051a39Sopenharmony_ci 129e1051a39Sopenharmony_ci memset(conf, 0, sizeof(*conf)); 130e1051a39Sopenharmony_ci conf->meth = &default_method; 131e1051a39Sopenharmony_ci conf->meth_data = (void *)CONF_type_default; 132e1051a39Sopenharmony_ci 133e1051a39Sopenharmony_ci return 1; 134e1051a39Sopenharmony_ci} 135e1051a39Sopenharmony_ci 136e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0 137e1051a39Sopenharmony_cistatic int def_init_WIN32(CONF *conf) 138e1051a39Sopenharmony_ci{ 139e1051a39Sopenharmony_ci if (conf == NULL) 140e1051a39Sopenharmony_ci return 0; 141e1051a39Sopenharmony_ci 142e1051a39Sopenharmony_ci memset(conf, 0, sizeof(*conf)); 143e1051a39Sopenharmony_ci conf->meth = &WIN32_method; 144e1051a39Sopenharmony_ci conf->meth_data = (void *)CONF_type_win32; 145e1051a39Sopenharmony_ci 146e1051a39Sopenharmony_ci return 1; 147e1051a39Sopenharmony_ci} 148e1051a39Sopenharmony_ci#endif 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_cistatic int def_destroy(CONF *conf) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci if (def_destroy_data(conf)) { 153e1051a39Sopenharmony_ci OPENSSL_free(conf); 154e1051a39Sopenharmony_ci return 1; 155e1051a39Sopenharmony_ci } 156e1051a39Sopenharmony_ci return 0; 157e1051a39Sopenharmony_ci} 158e1051a39Sopenharmony_ci 159e1051a39Sopenharmony_cistatic int def_destroy_data(CONF *conf) 160e1051a39Sopenharmony_ci{ 161e1051a39Sopenharmony_ci if (conf == NULL) 162e1051a39Sopenharmony_ci return 0; 163e1051a39Sopenharmony_ci _CONF_free_data(conf); 164e1051a39Sopenharmony_ci return 1; 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_cistatic int def_load(CONF *conf, const char *name, long *line) 168e1051a39Sopenharmony_ci{ 169e1051a39Sopenharmony_ci int ret; 170e1051a39Sopenharmony_ci BIO *in = NULL; 171e1051a39Sopenharmony_ci 172e1051a39Sopenharmony_ci#ifdef OPENSSL_SYS_VMS 173e1051a39Sopenharmony_ci in = BIO_new_file(name, "r"); 174e1051a39Sopenharmony_ci#else 175e1051a39Sopenharmony_ci in = BIO_new_file(name, "rb"); 176e1051a39Sopenharmony_ci#endif 177e1051a39Sopenharmony_ci if (in == NULL) { 178e1051a39Sopenharmony_ci if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE) 179e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_NO_SUCH_FILE); 180e1051a39Sopenharmony_ci else 181e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_SYS_LIB); 182e1051a39Sopenharmony_ci return 0; 183e1051a39Sopenharmony_ci } 184e1051a39Sopenharmony_ci 185e1051a39Sopenharmony_ci ret = def_load_bio(conf, in, line); 186e1051a39Sopenharmony_ci BIO_free(in); 187e1051a39Sopenharmony_ci 188e1051a39Sopenharmony_ci return ret; 189e1051a39Sopenharmony_ci} 190e1051a39Sopenharmony_ci 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci/* Parse a boolean value and fill in *flag. Return 0 on error. */ 193e1051a39Sopenharmony_cistatic int parsebool(const char *pval, int *flag) 194e1051a39Sopenharmony_ci{ 195e1051a39Sopenharmony_ci if (OPENSSL_strcasecmp(pval, "on") == 0 196e1051a39Sopenharmony_ci || OPENSSL_strcasecmp(pval, "true") == 0) { 197e1051a39Sopenharmony_ci *flag = 1; 198e1051a39Sopenharmony_ci } else if (OPENSSL_strcasecmp(pval, "off") == 0 199e1051a39Sopenharmony_ci || OPENSSL_strcasecmp(pval, "false") == 0) { 200e1051a39Sopenharmony_ci *flag = 0; 201e1051a39Sopenharmony_ci } else { 202e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA); 203e1051a39Sopenharmony_ci return 0; 204e1051a39Sopenharmony_ci } 205e1051a39Sopenharmony_ci return 1; 206e1051a39Sopenharmony_ci} 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_cistatic int def_load_bio(CONF *conf, BIO *in, long *line) 209e1051a39Sopenharmony_ci{ 210e1051a39Sopenharmony_ci/* The macro BUFSIZE conflicts with a system macro in VxWorks */ 211e1051a39Sopenharmony_ci#define CONFBUFSIZE 512 212e1051a39Sopenharmony_ci int bufnum = 0, i, ii; 213e1051a39Sopenharmony_ci BUF_MEM *buff = NULL; 214e1051a39Sopenharmony_ci char *s, *p, *end; 215e1051a39Sopenharmony_ci int again; 216e1051a39Sopenharmony_ci int first_call = 1; 217e1051a39Sopenharmony_ci long eline = 0; 218e1051a39Sopenharmony_ci char btmp[DECIMAL_SIZE(eline) + 1]; 219e1051a39Sopenharmony_ci CONF_VALUE *v = NULL, *tv; 220e1051a39Sopenharmony_ci CONF_VALUE *sv = NULL; 221e1051a39Sopenharmony_ci char *section = NULL, *buf; 222e1051a39Sopenharmony_ci char *start, *psection, *pname; 223e1051a39Sopenharmony_ci void *h = (void *)(conf->data); 224e1051a39Sopenharmony_ci STACK_OF(BIO) *biosk = NULL; 225e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 226e1051a39Sopenharmony_ci char *dirpath = NULL; 227e1051a39Sopenharmony_ci OPENSSL_DIR_CTX *dirctx = NULL; 228e1051a39Sopenharmony_ci#endif 229e1051a39Sopenharmony_ci#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 230e1051a39Sopenharmony_ci int numincludes = 0; 231e1051a39Sopenharmony_ci#endif 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci if ((buff = BUF_MEM_new()) == NULL) { 234e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB); 235e1051a39Sopenharmony_ci goto err; 236e1051a39Sopenharmony_ci } 237e1051a39Sopenharmony_ci 238e1051a39Sopenharmony_ci section = OPENSSL_strdup("default"); 239e1051a39Sopenharmony_ci if (section == NULL) { 240e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 241e1051a39Sopenharmony_ci goto err; 242e1051a39Sopenharmony_ci } 243e1051a39Sopenharmony_ci 244e1051a39Sopenharmony_ci if (_CONF_new_data(conf) == 0) { 245e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 246e1051a39Sopenharmony_ci goto err; 247e1051a39Sopenharmony_ci } 248e1051a39Sopenharmony_ci 249e1051a39Sopenharmony_ci sv = _CONF_new_section(conf, section); 250e1051a39Sopenharmony_ci if (sv == NULL) { 251e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 252e1051a39Sopenharmony_ci goto err; 253e1051a39Sopenharmony_ci } 254e1051a39Sopenharmony_ci 255e1051a39Sopenharmony_ci bufnum = 0; 256e1051a39Sopenharmony_ci again = 0; 257e1051a39Sopenharmony_ci for (;;) { 258e1051a39Sopenharmony_ci if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) { 259e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_BUF_LIB); 260e1051a39Sopenharmony_ci goto err; 261e1051a39Sopenharmony_ci } 262e1051a39Sopenharmony_ci p = &(buff->data[bufnum]); 263e1051a39Sopenharmony_ci *p = '\0'; 264e1051a39Sopenharmony_ci read_retry: 265e1051a39Sopenharmony_ci if (in != NULL && BIO_gets(in, p, CONFBUFSIZE - 1) < 0) 266e1051a39Sopenharmony_ci goto err; 267e1051a39Sopenharmony_ci p[CONFBUFSIZE - 1] = '\0'; 268e1051a39Sopenharmony_ci ii = i = strlen(p); 269e1051a39Sopenharmony_ci if (first_call) { 270e1051a39Sopenharmony_ci /* Other BOMs imply unsupported multibyte encoding, 271e1051a39Sopenharmony_ci * so don't strip them and let the error raise */ 272e1051a39Sopenharmony_ci const unsigned char utf8_bom[3] = {0xEF, 0xBB, 0xBF}; 273e1051a39Sopenharmony_ci 274e1051a39Sopenharmony_ci if (i >= 3 && memcmp(p, utf8_bom, 3) == 0) { 275e1051a39Sopenharmony_ci memmove(p, p + 3, i - 3); 276e1051a39Sopenharmony_ci p[i - 3] = 0; 277e1051a39Sopenharmony_ci i -= 3; 278e1051a39Sopenharmony_ci ii -= 3; 279e1051a39Sopenharmony_ci } 280e1051a39Sopenharmony_ci first_call = 0; 281e1051a39Sopenharmony_ci } 282e1051a39Sopenharmony_ci if (i == 0 && !again) { 283e1051a39Sopenharmony_ci /* the currently processed BIO is NULL or at EOF */ 284e1051a39Sopenharmony_ci BIO *parent; 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 287e1051a39Sopenharmony_ci /* continue processing with the next file from directory */ 288e1051a39Sopenharmony_ci if (dirctx != NULL) { 289e1051a39Sopenharmony_ci BIO *next; 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_ci if ((next = get_next_file(dirpath, &dirctx)) != NULL) { 292e1051a39Sopenharmony_ci BIO_vfree(in); 293e1051a39Sopenharmony_ci in = next; 294e1051a39Sopenharmony_ci goto read_retry; 295e1051a39Sopenharmony_ci } else { 296e1051a39Sopenharmony_ci OPENSSL_free(dirpath); 297e1051a39Sopenharmony_ci dirpath = NULL; 298e1051a39Sopenharmony_ci } 299e1051a39Sopenharmony_ci } 300e1051a39Sopenharmony_ci#endif 301e1051a39Sopenharmony_ci /* no more files in directory, continue with processing parent */ 302e1051a39Sopenharmony_ci if ((parent = sk_BIO_pop(biosk)) == NULL) { 303e1051a39Sopenharmony_ci /* everything processed get out of the loop */ 304e1051a39Sopenharmony_ci break; 305e1051a39Sopenharmony_ci } else { 306e1051a39Sopenharmony_ci BIO_vfree(in); 307e1051a39Sopenharmony_ci in = parent; 308e1051a39Sopenharmony_ci goto read_retry; 309e1051a39Sopenharmony_ci } 310e1051a39Sopenharmony_ci } 311e1051a39Sopenharmony_ci again = 0; 312e1051a39Sopenharmony_ci while (i > 0) { 313e1051a39Sopenharmony_ci if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) 314e1051a39Sopenharmony_ci break; 315e1051a39Sopenharmony_ci else 316e1051a39Sopenharmony_ci i--; 317e1051a39Sopenharmony_ci } 318e1051a39Sopenharmony_ci /* 319e1051a39Sopenharmony_ci * we removed some trailing stuff so there is a new line on the end. 320e1051a39Sopenharmony_ci */ 321e1051a39Sopenharmony_ci if (ii && i == ii) 322e1051a39Sopenharmony_ci again = 1; /* long line */ 323e1051a39Sopenharmony_ci else { 324e1051a39Sopenharmony_ci p[i] = '\0'; 325e1051a39Sopenharmony_ci eline++; /* another input line */ 326e1051a39Sopenharmony_ci } 327e1051a39Sopenharmony_ci 328e1051a39Sopenharmony_ci /* we now have a line with trailing \r\n removed */ 329e1051a39Sopenharmony_ci 330e1051a39Sopenharmony_ci /* i is the number of bytes */ 331e1051a39Sopenharmony_ci bufnum += i; 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_ci v = NULL; 334e1051a39Sopenharmony_ci /* check for line continuation */ 335e1051a39Sopenharmony_ci if (bufnum >= 1) { 336e1051a39Sopenharmony_ci /* 337e1051a39Sopenharmony_ci * If we have bytes and the last char '\\' and second last char 338e1051a39Sopenharmony_ci * is not '\\' 339e1051a39Sopenharmony_ci */ 340e1051a39Sopenharmony_ci p = &(buff->data[bufnum - 1]); 341e1051a39Sopenharmony_ci if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) { 342e1051a39Sopenharmony_ci bufnum--; 343e1051a39Sopenharmony_ci again = 1; 344e1051a39Sopenharmony_ci } 345e1051a39Sopenharmony_ci } 346e1051a39Sopenharmony_ci if (again) 347e1051a39Sopenharmony_ci continue; 348e1051a39Sopenharmony_ci bufnum = 0; 349e1051a39Sopenharmony_ci buf = buff->data; 350e1051a39Sopenharmony_ci 351e1051a39Sopenharmony_ci clear_comments(conf, buf); 352e1051a39Sopenharmony_ci s = eat_ws(conf, buf); 353e1051a39Sopenharmony_ci if (IS_EOF(conf, *s)) 354e1051a39Sopenharmony_ci continue; /* blank line */ 355e1051a39Sopenharmony_ci if (*s == '[') { 356e1051a39Sopenharmony_ci char *ss; 357e1051a39Sopenharmony_ci 358e1051a39Sopenharmony_ci s++; 359e1051a39Sopenharmony_ci start = eat_ws(conf, s); 360e1051a39Sopenharmony_ci ss = start; 361e1051a39Sopenharmony_ci again: 362e1051a39Sopenharmony_ci end = eat_alpha_numeric(conf, ss); 363e1051a39Sopenharmony_ci p = eat_ws(conf, end); 364e1051a39Sopenharmony_ci if (*p != ']') { 365e1051a39Sopenharmony_ci if (*p != '\0' && ss != p) { 366e1051a39Sopenharmony_ci ss = p; 367e1051a39Sopenharmony_ci goto again; 368e1051a39Sopenharmony_ci } 369e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET); 370e1051a39Sopenharmony_ci goto err; 371e1051a39Sopenharmony_ci } 372e1051a39Sopenharmony_ci *end = '\0'; 373e1051a39Sopenharmony_ci if (!str_copy(conf, NULL, §ion, start)) 374e1051a39Sopenharmony_ci goto err; 375e1051a39Sopenharmony_ci if ((sv = _CONF_get_section(conf, section)) == NULL) 376e1051a39Sopenharmony_ci sv = _CONF_new_section(conf, section); 377e1051a39Sopenharmony_ci if (sv == NULL) { 378e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 379e1051a39Sopenharmony_ci goto err; 380e1051a39Sopenharmony_ci } 381e1051a39Sopenharmony_ci continue; 382e1051a39Sopenharmony_ci } else { 383e1051a39Sopenharmony_ci pname = s; 384e1051a39Sopenharmony_ci end = eat_alpha_numeric(conf, s); 385e1051a39Sopenharmony_ci if ((end[0] == ':') && (end[1] == ':')) { 386e1051a39Sopenharmony_ci *end = '\0'; 387e1051a39Sopenharmony_ci end += 2; 388e1051a39Sopenharmony_ci psection = pname; 389e1051a39Sopenharmony_ci pname = end; 390e1051a39Sopenharmony_ci end = eat_alpha_numeric(conf, end); 391e1051a39Sopenharmony_ci } else { 392e1051a39Sopenharmony_ci psection = section; 393e1051a39Sopenharmony_ci } 394e1051a39Sopenharmony_ci p = eat_ws(conf, end); 395e1051a39Sopenharmony_ci if (strncmp(pname, ".pragma", 7) == 0 396e1051a39Sopenharmony_ci && (p != pname + 7 || *p == '=')) { 397e1051a39Sopenharmony_ci char *pval; 398e1051a39Sopenharmony_ci 399e1051a39Sopenharmony_ci if (*p == '=') { 400e1051a39Sopenharmony_ci p++; 401e1051a39Sopenharmony_ci p = eat_ws(conf, p); 402e1051a39Sopenharmony_ci } 403e1051a39Sopenharmony_ci trim_ws(conf, p); 404e1051a39Sopenharmony_ci 405e1051a39Sopenharmony_ci /* Pragma values take the form keyword:value */ 406e1051a39Sopenharmony_ci pval = strchr(p, ':'); 407e1051a39Sopenharmony_ci if (pval == NULL || pval == p || pval[1] == '\0') { 408e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_INVALID_PRAGMA); 409e1051a39Sopenharmony_ci goto err; 410e1051a39Sopenharmony_ci } 411e1051a39Sopenharmony_ci 412e1051a39Sopenharmony_ci *pval++ = '\0'; 413e1051a39Sopenharmony_ci trim_ws(conf, p); 414e1051a39Sopenharmony_ci pval = eat_ws(conf, pval); 415e1051a39Sopenharmony_ci 416e1051a39Sopenharmony_ci /* 417e1051a39Sopenharmony_ci * Known pragmas: 418e1051a39Sopenharmony_ci * 419e1051a39Sopenharmony_ci * dollarid takes "on", "true or "off", "false" 420e1051a39Sopenharmony_ci * abspath takes "on", "true or "off", "false" 421e1051a39Sopenharmony_ci * includedir directory prefix 422e1051a39Sopenharmony_ci */ 423e1051a39Sopenharmony_ci if (strcmp(p, "dollarid") == 0) { 424e1051a39Sopenharmony_ci if (!parsebool(pval, &conf->flag_dollarid)) 425e1051a39Sopenharmony_ci goto err; 426e1051a39Sopenharmony_ci } else if (strcmp(p, "abspath") == 0) { 427e1051a39Sopenharmony_ci if (!parsebool(pval, &conf->flag_abspath)) 428e1051a39Sopenharmony_ci goto err; 429e1051a39Sopenharmony_ci } else if (strcmp(p, "includedir") == 0) { 430e1051a39Sopenharmony_ci OPENSSL_free(conf->includedir); 431e1051a39Sopenharmony_ci if ((conf->includedir = OPENSSL_strdup(pval)) == NULL) { 432e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 433e1051a39Sopenharmony_ci goto err; 434e1051a39Sopenharmony_ci } 435e1051a39Sopenharmony_ci } 436e1051a39Sopenharmony_ci 437e1051a39Sopenharmony_ci /* 438e1051a39Sopenharmony_ci * We *ignore* any unknown pragma. 439e1051a39Sopenharmony_ci */ 440e1051a39Sopenharmony_ci continue; 441e1051a39Sopenharmony_ci } else if (strncmp(pname, ".include", 8) == 0 442e1051a39Sopenharmony_ci && (p != pname + 8 || *p == '=')) { 443e1051a39Sopenharmony_ci char *include = NULL; 444e1051a39Sopenharmony_ci BIO *next; 445e1051a39Sopenharmony_ci const char *include_dir = ossl_safe_getenv("OPENSSL_CONF_INCLUDE"); 446e1051a39Sopenharmony_ci char *include_path = NULL; 447e1051a39Sopenharmony_ci 448e1051a39Sopenharmony_ci#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 449e1051a39Sopenharmony_ci /* 450e1051a39Sopenharmony_ci * The include processing below can cause the "conf" fuzzer to 451e1051a39Sopenharmony_ci * timeout due to the fuzzer inserting large and complicated 452e1051a39Sopenharmony_ci * includes - with a large amount of time spent in 453e1051a39Sopenharmony_ci * OPENSSL_strlcat/OPENSSL_strcpy. This is not a security 454e1051a39Sopenharmony_ci * concern because config files should never come from untrusted 455e1051a39Sopenharmony_ci * sources. We just set an arbitrary limit on the allowed 456e1051a39Sopenharmony_ci * number of includes when fuzzing to prevent this timeout. 457e1051a39Sopenharmony_ci */ 458e1051a39Sopenharmony_ci if (numincludes++ > 10) 459e1051a39Sopenharmony_ci goto err; 460e1051a39Sopenharmony_ci#endif 461e1051a39Sopenharmony_ci 462e1051a39Sopenharmony_ci if (include_dir == NULL) 463e1051a39Sopenharmony_ci include_dir = conf->includedir; 464e1051a39Sopenharmony_ci 465e1051a39Sopenharmony_ci if (*p == '=') { 466e1051a39Sopenharmony_ci p++; 467e1051a39Sopenharmony_ci p = eat_ws(conf, p); 468e1051a39Sopenharmony_ci } 469e1051a39Sopenharmony_ci trim_ws(conf, p); 470e1051a39Sopenharmony_ci if (!str_copy(conf, psection, &include, p)) 471e1051a39Sopenharmony_ci goto err; 472e1051a39Sopenharmony_ci 473e1051a39Sopenharmony_ci if (include_dir != NULL && !ossl_is_absolute_path(include)) { 474e1051a39Sopenharmony_ci size_t newlen = strlen(include_dir) + strlen(include) + 2; 475e1051a39Sopenharmony_ci 476e1051a39Sopenharmony_ci include_path = OPENSSL_malloc(newlen); 477e1051a39Sopenharmony_ci if (include_path == NULL) { 478e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 479e1051a39Sopenharmony_ci OPENSSL_free(include); 480e1051a39Sopenharmony_ci goto err; 481e1051a39Sopenharmony_ci } 482e1051a39Sopenharmony_ci 483e1051a39Sopenharmony_ci OPENSSL_strlcpy(include_path, include_dir, newlen); 484e1051a39Sopenharmony_ci if (!ossl_ends_with_dirsep(include_path)) 485e1051a39Sopenharmony_ci OPENSSL_strlcat(include_path, "/", newlen); 486e1051a39Sopenharmony_ci OPENSSL_strlcat(include_path, include, newlen); 487e1051a39Sopenharmony_ci OPENSSL_free(include); 488e1051a39Sopenharmony_ci } else { 489e1051a39Sopenharmony_ci include_path = include; 490e1051a39Sopenharmony_ci } 491e1051a39Sopenharmony_ci 492e1051a39Sopenharmony_ci if (conf->flag_abspath 493e1051a39Sopenharmony_ci && !ossl_is_absolute_path(include_path)) { 494e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_RELATIVE_PATH); 495e1051a39Sopenharmony_ci OPENSSL_free(include_path); 496e1051a39Sopenharmony_ci goto err; 497e1051a39Sopenharmony_ci } 498e1051a39Sopenharmony_ci 499e1051a39Sopenharmony_ci /* get the BIO of the included file */ 500e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 501e1051a39Sopenharmony_ci next = process_include(include_path, &dirctx, &dirpath); 502e1051a39Sopenharmony_ci if (include_path != dirpath) { 503e1051a39Sopenharmony_ci /* dirpath will contain include in case of a directory */ 504e1051a39Sopenharmony_ci OPENSSL_free(include_path); 505e1051a39Sopenharmony_ci } 506e1051a39Sopenharmony_ci#else 507e1051a39Sopenharmony_ci next = BIO_new_file(include_path, "r"); 508e1051a39Sopenharmony_ci OPENSSL_free(include_path); 509e1051a39Sopenharmony_ci#endif 510e1051a39Sopenharmony_ci 511e1051a39Sopenharmony_ci if (next != NULL) { 512e1051a39Sopenharmony_ci /* push the currently processing BIO onto stack */ 513e1051a39Sopenharmony_ci if (biosk == NULL) { 514e1051a39Sopenharmony_ci if ((biosk = sk_BIO_new_null()) == NULL) { 515e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 516e1051a39Sopenharmony_ci BIO_free(next); 517e1051a39Sopenharmony_ci goto err; 518e1051a39Sopenharmony_ci } 519e1051a39Sopenharmony_ci } 520e1051a39Sopenharmony_ci if (!sk_BIO_push(biosk, in)) { 521e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 522e1051a39Sopenharmony_ci BIO_free(next); 523e1051a39Sopenharmony_ci goto err; 524e1051a39Sopenharmony_ci } 525e1051a39Sopenharmony_ci /* continue with reading from the included BIO */ 526e1051a39Sopenharmony_ci in = next; 527e1051a39Sopenharmony_ci } 528e1051a39Sopenharmony_ci continue; 529e1051a39Sopenharmony_ci } else if (*p != '=') { 530e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CONF, CONF_R_MISSING_EQUAL_SIGN, 531e1051a39Sopenharmony_ci "HERE-->%s", p); 532e1051a39Sopenharmony_ci goto err; 533e1051a39Sopenharmony_ci } 534e1051a39Sopenharmony_ci *end = '\0'; 535e1051a39Sopenharmony_ci p++; 536e1051a39Sopenharmony_ci start = eat_ws(conf, p); 537e1051a39Sopenharmony_ci trim_ws(conf, start); 538e1051a39Sopenharmony_ci 539e1051a39Sopenharmony_ci if ((v = OPENSSL_malloc(sizeof(*v))) == NULL) { 540e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 541e1051a39Sopenharmony_ci goto err; 542e1051a39Sopenharmony_ci } 543e1051a39Sopenharmony_ci v->name = OPENSSL_strdup(pname); 544e1051a39Sopenharmony_ci v->value = NULL; 545e1051a39Sopenharmony_ci if (v->name == NULL) { 546e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 547e1051a39Sopenharmony_ci goto err; 548e1051a39Sopenharmony_ci } 549e1051a39Sopenharmony_ci if (!str_copy(conf, psection, &(v->value), start)) 550e1051a39Sopenharmony_ci goto err; 551e1051a39Sopenharmony_ci 552e1051a39Sopenharmony_ci if (strcmp(psection, section) != 0) { 553e1051a39Sopenharmony_ci if ((tv = _CONF_get_section(conf, psection)) 554e1051a39Sopenharmony_ci == NULL) 555e1051a39Sopenharmony_ci tv = _CONF_new_section(conf, psection); 556e1051a39Sopenharmony_ci if (tv == NULL) { 557e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, 558e1051a39Sopenharmony_ci CONF_R_UNABLE_TO_CREATE_NEW_SECTION); 559e1051a39Sopenharmony_ci goto err; 560e1051a39Sopenharmony_ci } 561e1051a39Sopenharmony_ci } else 562e1051a39Sopenharmony_ci tv = sv; 563e1051a39Sopenharmony_ci if (_CONF_add_string(conf, tv, v) == 0) { 564e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 565e1051a39Sopenharmony_ci goto err; 566e1051a39Sopenharmony_ci } 567e1051a39Sopenharmony_ci v = NULL; 568e1051a39Sopenharmony_ci } 569e1051a39Sopenharmony_ci } 570e1051a39Sopenharmony_ci BUF_MEM_free(buff); 571e1051a39Sopenharmony_ci OPENSSL_free(section); 572e1051a39Sopenharmony_ci /* 573e1051a39Sopenharmony_ci * No need to pop, since we only get here if the stack is empty. 574e1051a39Sopenharmony_ci * If this causes a BIO leak, THE ISSUE IS SOMEWHERE ELSE! 575e1051a39Sopenharmony_ci */ 576e1051a39Sopenharmony_ci sk_BIO_free(biosk); 577e1051a39Sopenharmony_ci return 1; 578e1051a39Sopenharmony_ci 579e1051a39Sopenharmony_ci err: 580e1051a39Sopenharmony_ci BUF_MEM_free(buff); 581e1051a39Sopenharmony_ci OPENSSL_free(section); 582e1051a39Sopenharmony_ci /* 583e1051a39Sopenharmony_ci * Since |in| is the first element of the stack and should NOT be freed 584e1051a39Sopenharmony_ci * here, we cannot use sk_BIO_pop_free(). Instead, we pop and free one 585e1051a39Sopenharmony_ci * BIO at a time, making sure that the last one popped isn't. 586e1051a39Sopenharmony_ci */ 587e1051a39Sopenharmony_ci while (sk_BIO_num(biosk) > 0) { 588e1051a39Sopenharmony_ci BIO *popped = sk_BIO_pop(biosk); 589e1051a39Sopenharmony_ci BIO_vfree(in); 590e1051a39Sopenharmony_ci in = popped; 591e1051a39Sopenharmony_ci } 592e1051a39Sopenharmony_ci sk_BIO_free(biosk); 593e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 594e1051a39Sopenharmony_ci OPENSSL_free(dirpath); 595e1051a39Sopenharmony_ci if (dirctx != NULL) 596e1051a39Sopenharmony_ci OPENSSL_DIR_end(&dirctx); 597e1051a39Sopenharmony_ci#endif 598e1051a39Sopenharmony_ci if (line != NULL) 599e1051a39Sopenharmony_ci *line = eline; 600e1051a39Sopenharmony_ci BIO_snprintf(btmp, sizeof(btmp), "%ld", eline); 601e1051a39Sopenharmony_ci ERR_add_error_data(2, "line ", btmp); 602e1051a39Sopenharmony_ci if (h != conf->data) { 603e1051a39Sopenharmony_ci CONF_free(conf->data); 604e1051a39Sopenharmony_ci conf->data = NULL; 605e1051a39Sopenharmony_ci } 606e1051a39Sopenharmony_ci if (v != NULL) { 607e1051a39Sopenharmony_ci OPENSSL_free(v->name); 608e1051a39Sopenharmony_ci OPENSSL_free(v->value); 609e1051a39Sopenharmony_ci OPENSSL_free(v); 610e1051a39Sopenharmony_ci } 611e1051a39Sopenharmony_ci return 0; 612e1051a39Sopenharmony_ci} 613e1051a39Sopenharmony_ci 614e1051a39Sopenharmony_cistatic void clear_comments(CONF *conf, char *p) 615e1051a39Sopenharmony_ci{ 616e1051a39Sopenharmony_ci for (;;) { 617e1051a39Sopenharmony_ci if (IS_FCOMMENT(conf, *p)) { 618e1051a39Sopenharmony_ci *p = '\0'; 619e1051a39Sopenharmony_ci return; 620e1051a39Sopenharmony_ci } 621e1051a39Sopenharmony_ci if (!IS_WS(conf, *p)) { 622e1051a39Sopenharmony_ci break; 623e1051a39Sopenharmony_ci } 624e1051a39Sopenharmony_ci p++; 625e1051a39Sopenharmony_ci } 626e1051a39Sopenharmony_ci 627e1051a39Sopenharmony_ci for (;;) { 628e1051a39Sopenharmony_ci if (IS_COMMENT(conf, *p)) { 629e1051a39Sopenharmony_ci *p = '\0'; 630e1051a39Sopenharmony_ci return; 631e1051a39Sopenharmony_ci } 632e1051a39Sopenharmony_ci if (IS_DQUOTE(conf, *p)) { 633e1051a39Sopenharmony_ci p = scan_dquote(conf, p); 634e1051a39Sopenharmony_ci continue; 635e1051a39Sopenharmony_ci } 636e1051a39Sopenharmony_ci if (IS_QUOTE(conf, *p)) { 637e1051a39Sopenharmony_ci p = scan_quote(conf, p); 638e1051a39Sopenharmony_ci continue; 639e1051a39Sopenharmony_ci } 640e1051a39Sopenharmony_ci if (IS_ESC(conf, *p)) { 641e1051a39Sopenharmony_ci p = scan_esc(conf, p); 642e1051a39Sopenharmony_ci continue; 643e1051a39Sopenharmony_ci } 644e1051a39Sopenharmony_ci if (IS_EOF(conf, *p)) 645e1051a39Sopenharmony_ci return; 646e1051a39Sopenharmony_ci else 647e1051a39Sopenharmony_ci p++; 648e1051a39Sopenharmony_ci } 649e1051a39Sopenharmony_ci} 650e1051a39Sopenharmony_ci 651e1051a39Sopenharmony_cistatic int str_copy(CONF *conf, char *section, char **pto, char *from) 652e1051a39Sopenharmony_ci{ 653e1051a39Sopenharmony_ci int q, r, rr = 0, to = 0, len = 0; 654e1051a39Sopenharmony_ci char *s, *e, *rp, *p, *rrp, *np, *cp, v; 655e1051a39Sopenharmony_ci BUF_MEM *buf; 656e1051a39Sopenharmony_ci 657e1051a39Sopenharmony_ci if ((buf = BUF_MEM_new()) == NULL) 658e1051a39Sopenharmony_ci return 0; 659e1051a39Sopenharmony_ci 660e1051a39Sopenharmony_ci len = strlen(from) + 1; 661e1051a39Sopenharmony_ci if (!BUF_MEM_grow(buf, len)) 662e1051a39Sopenharmony_ci goto err; 663e1051a39Sopenharmony_ci 664e1051a39Sopenharmony_ci for (;;) { 665e1051a39Sopenharmony_ci if (IS_QUOTE(conf, *from)) { 666e1051a39Sopenharmony_ci q = *from; 667e1051a39Sopenharmony_ci from++; 668e1051a39Sopenharmony_ci while (!IS_EOF(conf, *from) && (*from != q)) { 669e1051a39Sopenharmony_ci if (IS_ESC(conf, *from)) { 670e1051a39Sopenharmony_ci from++; 671e1051a39Sopenharmony_ci if (IS_EOF(conf, *from)) 672e1051a39Sopenharmony_ci break; 673e1051a39Sopenharmony_ci } 674e1051a39Sopenharmony_ci buf->data[to++] = *(from++); 675e1051a39Sopenharmony_ci } 676e1051a39Sopenharmony_ci if (*from == q) 677e1051a39Sopenharmony_ci from++; 678e1051a39Sopenharmony_ci } else if (IS_DQUOTE(conf, *from)) { 679e1051a39Sopenharmony_ci q = *from; 680e1051a39Sopenharmony_ci from++; 681e1051a39Sopenharmony_ci while (!IS_EOF(conf, *from)) { 682e1051a39Sopenharmony_ci if (*from == q) { 683e1051a39Sopenharmony_ci if (*(from + 1) == q) { 684e1051a39Sopenharmony_ci from++; 685e1051a39Sopenharmony_ci } else { 686e1051a39Sopenharmony_ci break; 687e1051a39Sopenharmony_ci } 688e1051a39Sopenharmony_ci } 689e1051a39Sopenharmony_ci buf->data[to++] = *(from++); 690e1051a39Sopenharmony_ci } 691e1051a39Sopenharmony_ci if (*from == q) 692e1051a39Sopenharmony_ci from++; 693e1051a39Sopenharmony_ci } else if (IS_ESC(conf, *from)) { 694e1051a39Sopenharmony_ci from++; 695e1051a39Sopenharmony_ci v = *(from++); 696e1051a39Sopenharmony_ci if (IS_EOF(conf, v)) 697e1051a39Sopenharmony_ci break; 698e1051a39Sopenharmony_ci else if (v == 'r') 699e1051a39Sopenharmony_ci v = '\r'; 700e1051a39Sopenharmony_ci else if (v == 'n') 701e1051a39Sopenharmony_ci v = '\n'; 702e1051a39Sopenharmony_ci else if (v == 'b') 703e1051a39Sopenharmony_ci v = '\b'; 704e1051a39Sopenharmony_ci else if (v == 't') 705e1051a39Sopenharmony_ci v = '\t'; 706e1051a39Sopenharmony_ci buf->data[to++] = v; 707e1051a39Sopenharmony_ci } else if (IS_EOF(conf, *from)) 708e1051a39Sopenharmony_ci break; 709e1051a39Sopenharmony_ci else if (*from == '$' 710e1051a39Sopenharmony_ci && (!conf->flag_dollarid 711e1051a39Sopenharmony_ci || from[1] == '{' 712e1051a39Sopenharmony_ci || from[1] == '(')) { 713e1051a39Sopenharmony_ci size_t newsize; 714e1051a39Sopenharmony_ci 715e1051a39Sopenharmony_ci /* try to expand it */ 716e1051a39Sopenharmony_ci rrp = NULL; 717e1051a39Sopenharmony_ci s = &(from[1]); 718e1051a39Sopenharmony_ci if (*s == '{') 719e1051a39Sopenharmony_ci q = '}'; 720e1051a39Sopenharmony_ci else if (*s == '(') 721e1051a39Sopenharmony_ci q = ')'; 722e1051a39Sopenharmony_ci else 723e1051a39Sopenharmony_ci q = 0; 724e1051a39Sopenharmony_ci 725e1051a39Sopenharmony_ci if (q) 726e1051a39Sopenharmony_ci s++; 727e1051a39Sopenharmony_ci cp = section; 728e1051a39Sopenharmony_ci e = np = s; 729e1051a39Sopenharmony_ci while (IS_ALNUM(conf, *e) 730e1051a39Sopenharmony_ci || (conf->flag_dollarid && IS_DOLLAR(conf, *e))) 731e1051a39Sopenharmony_ci e++; 732e1051a39Sopenharmony_ci if ((e[0] == ':') && (e[1] == ':')) { 733e1051a39Sopenharmony_ci cp = np; 734e1051a39Sopenharmony_ci rrp = e; 735e1051a39Sopenharmony_ci rr = *e; 736e1051a39Sopenharmony_ci *rrp = '\0'; 737e1051a39Sopenharmony_ci e += 2; 738e1051a39Sopenharmony_ci np = e; 739e1051a39Sopenharmony_ci while (IS_ALNUM(conf, *e) 740e1051a39Sopenharmony_ci || (conf->flag_dollarid && IS_DOLLAR(conf, *e))) 741e1051a39Sopenharmony_ci e++; 742e1051a39Sopenharmony_ci } 743e1051a39Sopenharmony_ci r = *e; 744e1051a39Sopenharmony_ci *e = '\0'; 745e1051a39Sopenharmony_ci rp = e; 746e1051a39Sopenharmony_ci if (q) { 747e1051a39Sopenharmony_ci if (r != q) { 748e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_NO_CLOSE_BRACE); 749e1051a39Sopenharmony_ci goto err; 750e1051a39Sopenharmony_ci } 751e1051a39Sopenharmony_ci e++; 752e1051a39Sopenharmony_ci } 753e1051a39Sopenharmony_ci /*- 754e1051a39Sopenharmony_ci * So at this point we have 755e1051a39Sopenharmony_ci * np which is the start of the name string which is 756e1051a39Sopenharmony_ci * '\0' terminated. 757e1051a39Sopenharmony_ci * cp which is the start of the section string which is 758e1051a39Sopenharmony_ci * '\0' terminated. 759e1051a39Sopenharmony_ci * e is the 'next point after'. 760e1051a39Sopenharmony_ci * r and rr are the chars replaced by the '\0' 761e1051a39Sopenharmony_ci * rp and rrp is where 'r' and 'rr' came from. 762e1051a39Sopenharmony_ci */ 763e1051a39Sopenharmony_ci p = _CONF_get_string(conf, cp, np); 764e1051a39Sopenharmony_ci if (rrp != NULL) 765e1051a39Sopenharmony_ci *rrp = rr; 766e1051a39Sopenharmony_ci *rp = r; 767e1051a39Sopenharmony_ci if (p == NULL) { 768e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_VARIABLE_HAS_NO_VALUE); 769e1051a39Sopenharmony_ci goto err; 770e1051a39Sopenharmony_ci } 771e1051a39Sopenharmony_ci newsize = strlen(p) + buf->length - (e - from); 772e1051a39Sopenharmony_ci if (newsize > MAX_CONF_VALUE_LENGTH) { 773e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG); 774e1051a39Sopenharmony_ci goto err; 775e1051a39Sopenharmony_ci } 776e1051a39Sopenharmony_ci if (!BUF_MEM_grow_clean(buf, newsize)) { 777e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 778e1051a39Sopenharmony_ci goto err; 779e1051a39Sopenharmony_ci } 780e1051a39Sopenharmony_ci while (*p) 781e1051a39Sopenharmony_ci buf->data[to++] = *(p++); 782e1051a39Sopenharmony_ci 783e1051a39Sopenharmony_ci /* 784e1051a39Sopenharmony_ci * Since we change the pointer 'from', we also have to change the 785e1051a39Sopenharmony_ci * perceived length of the string it points at. /RL 786e1051a39Sopenharmony_ci */ 787e1051a39Sopenharmony_ci len -= e - from; 788e1051a39Sopenharmony_ci from = e; 789e1051a39Sopenharmony_ci 790e1051a39Sopenharmony_ci /* 791e1051a39Sopenharmony_ci * In case there were no braces or parenthesis around the 792e1051a39Sopenharmony_ci * variable reference, we have to put back the character that was 793e1051a39Sopenharmony_ci * replaced with a '\0'. /RL 794e1051a39Sopenharmony_ci */ 795e1051a39Sopenharmony_ci *rp = r; 796e1051a39Sopenharmony_ci } else 797e1051a39Sopenharmony_ci buf->data[to++] = *(from++); 798e1051a39Sopenharmony_ci } 799e1051a39Sopenharmony_ci buf->data[to] = '\0'; 800e1051a39Sopenharmony_ci OPENSSL_free(*pto); 801e1051a39Sopenharmony_ci *pto = buf->data; 802e1051a39Sopenharmony_ci OPENSSL_free(buf); 803e1051a39Sopenharmony_ci return 1; 804e1051a39Sopenharmony_ci err: 805e1051a39Sopenharmony_ci BUF_MEM_free(buf); 806e1051a39Sopenharmony_ci return 0; 807e1051a39Sopenharmony_ci} 808e1051a39Sopenharmony_ci 809e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_POSIX_IO 810e1051a39Sopenharmony_ci/* 811e1051a39Sopenharmony_ci * Check whether included path is a directory. 812e1051a39Sopenharmony_ci * Returns next BIO to process and in case of a directory 813e1051a39Sopenharmony_ci * also an opened directory context and the include path. 814e1051a39Sopenharmony_ci */ 815e1051a39Sopenharmony_cistatic BIO *process_include(char *include, OPENSSL_DIR_CTX **dirctx, 816e1051a39Sopenharmony_ci char **dirpath) 817e1051a39Sopenharmony_ci{ 818e1051a39Sopenharmony_ci struct stat st; 819e1051a39Sopenharmony_ci BIO *next; 820e1051a39Sopenharmony_ci 821e1051a39Sopenharmony_ci if (stat(include, &st) < 0) { 822e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_SYS, errno, "calling stat(%s)", include); 823e1051a39Sopenharmony_ci /* missing include file is not fatal error */ 824e1051a39Sopenharmony_ci return NULL; 825e1051a39Sopenharmony_ci } 826e1051a39Sopenharmony_ci 827e1051a39Sopenharmony_ci if (S_ISDIR(st.st_mode)) { 828e1051a39Sopenharmony_ci if (*dirctx != NULL) { 829e1051a39Sopenharmony_ci ERR_raise_data(ERR_LIB_CONF, CONF_R_RECURSIVE_DIRECTORY_INCLUDE, 830e1051a39Sopenharmony_ci "%s", include); 831e1051a39Sopenharmony_ci return NULL; 832e1051a39Sopenharmony_ci } 833e1051a39Sopenharmony_ci /* a directory, load its contents */ 834e1051a39Sopenharmony_ci if ((next = get_next_file(include, dirctx)) != NULL) 835e1051a39Sopenharmony_ci *dirpath = include; 836e1051a39Sopenharmony_ci return next; 837e1051a39Sopenharmony_ci } 838e1051a39Sopenharmony_ci 839e1051a39Sopenharmony_ci next = BIO_new_file(include, "r"); 840e1051a39Sopenharmony_ci return next; 841e1051a39Sopenharmony_ci} 842e1051a39Sopenharmony_ci 843e1051a39Sopenharmony_ci/* 844e1051a39Sopenharmony_ci * Get next file from the directory path. 845e1051a39Sopenharmony_ci * Returns BIO of the next file to read and updates dirctx. 846e1051a39Sopenharmony_ci */ 847e1051a39Sopenharmony_cistatic BIO *get_next_file(const char *path, OPENSSL_DIR_CTX **dirctx) 848e1051a39Sopenharmony_ci{ 849e1051a39Sopenharmony_ci const char *filename; 850e1051a39Sopenharmony_ci size_t pathlen; 851e1051a39Sopenharmony_ci 852e1051a39Sopenharmony_ci pathlen = strlen(path); 853e1051a39Sopenharmony_ci while ((filename = OPENSSL_DIR_read(dirctx, path)) != NULL) { 854e1051a39Sopenharmony_ci size_t namelen; 855e1051a39Sopenharmony_ci 856e1051a39Sopenharmony_ci namelen = strlen(filename); 857e1051a39Sopenharmony_ci 858e1051a39Sopenharmony_ci 859e1051a39Sopenharmony_ci if ((namelen > 5 860e1051a39Sopenharmony_ci && OPENSSL_strcasecmp(filename + namelen - 5, ".conf") == 0) 861e1051a39Sopenharmony_ci || (namelen > 4 862e1051a39Sopenharmony_ci && OPENSSL_strcasecmp(filename + namelen - 4, ".cnf") == 0)) { 863e1051a39Sopenharmony_ci size_t newlen; 864e1051a39Sopenharmony_ci char *newpath; 865e1051a39Sopenharmony_ci BIO *bio; 866e1051a39Sopenharmony_ci 867e1051a39Sopenharmony_ci newlen = pathlen + namelen + 2; 868e1051a39Sopenharmony_ci newpath = OPENSSL_zalloc(newlen); 869e1051a39Sopenharmony_ci if (newpath == NULL) { 870e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE); 871e1051a39Sopenharmony_ci break; 872e1051a39Sopenharmony_ci } 873e1051a39Sopenharmony_ci#ifdef OPENSSL_SYS_VMS 874e1051a39Sopenharmony_ci /* 875e1051a39Sopenharmony_ci * If the given path isn't clear VMS syntax, 876e1051a39Sopenharmony_ci * we treat it as on Unix. 877e1051a39Sopenharmony_ci */ 878e1051a39Sopenharmony_ci if (path[pathlen - 1] == ']' 879e1051a39Sopenharmony_ci || path[pathlen - 1] == '>' 880e1051a39Sopenharmony_ci || path[pathlen - 1] == ':') { 881e1051a39Sopenharmony_ci /* Clear VMS directory syntax, just copy as is */ 882e1051a39Sopenharmony_ci OPENSSL_strlcpy(newpath, path, newlen); 883e1051a39Sopenharmony_ci } 884e1051a39Sopenharmony_ci#endif 885e1051a39Sopenharmony_ci if (newpath[0] == '\0') { 886e1051a39Sopenharmony_ci OPENSSL_strlcpy(newpath, path, newlen); 887e1051a39Sopenharmony_ci OPENSSL_strlcat(newpath, "/", newlen); 888e1051a39Sopenharmony_ci } 889e1051a39Sopenharmony_ci OPENSSL_strlcat(newpath, filename, newlen); 890e1051a39Sopenharmony_ci 891e1051a39Sopenharmony_ci bio = BIO_new_file(newpath, "r"); 892e1051a39Sopenharmony_ci OPENSSL_free(newpath); 893e1051a39Sopenharmony_ci /* Errors when opening files are non-fatal. */ 894e1051a39Sopenharmony_ci if (bio != NULL) 895e1051a39Sopenharmony_ci return bio; 896e1051a39Sopenharmony_ci } 897e1051a39Sopenharmony_ci } 898e1051a39Sopenharmony_ci OPENSSL_DIR_end(dirctx); 899e1051a39Sopenharmony_ci *dirctx = NULL; 900e1051a39Sopenharmony_ci return NULL; 901e1051a39Sopenharmony_ci} 902e1051a39Sopenharmony_ci#endif 903e1051a39Sopenharmony_ci 904e1051a39Sopenharmony_cistatic int is_keytype(const CONF *conf, char c, unsigned short type) 905e1051a39Sopenharmony_ci{ 906e1051a39Sopenharmony_ci const unsigned short * keytypes = (const unsigned short *) conf->meth_data; 907e1051a39Sopenharmony_ci unsigned char key = (unsigned char)c; 908e1051a39Sopenharmony_ci 909e1051a39Sopenharmony_ci#ifdef CHARSET_EBCDIC 910e1051a39Sopenharmony_ci# if CHAR_BIT > 8 911e1051a39Sopenharmony_ci if (key > 255) { 912e1051a39Sopenharmony_ci /* key is out of range for os_toascii table */ 913e1051a39Sopenharmony_ci return 0; 914e1051a39Sopenharmony_ci } 915e1051a39Sopenharmony_ci# endif 916e1051a39Sopenharmony_ci /* convert key from ebcdic to ascii */ 917e1051a39Sopenharmony_ci key = os_toascii[key]; 918e1051a39Sopenharmony_ci#endif 919e1051a39Sopenharmony_ci 920e1051a39Sopenharmony_ci if (key > 127) { 921e1051a39Sopenharmony_ci /* key is not a seven bit ascii character */ 922e1051a39Sopenharmony_ci return 0; 923e1051a39Sopenharmony_ci } 924e1051a39Sopenharmony_ci 925e1051a39Sopenharmony_ci return (keytypes[key] & type) ? 1 : 0; 926e1051a39Sopenharmony_ci} 927e1051a39Sopenharmony_ci 928e1051a39Sopenharmony_cistatic char *eat_ws(CONF *conf, char *p) 929e1051a39Sopenharmony_ci{ 930e1051a39Sopenharmony_ci while (IS_WS(conf, *p) && (!IS_EOF(conf, *p))) 931e1051a39Sopenharmony_ci p++; 932e1051a39Sopenharmony_ci return p; 933e1051a39Sopenharmony_ci} 934e1051a39Sopenharmony_ci 935e1051a39Sopenharmony_cistatic void trim_ws(CONF *conf, char *start) 936e1051a39Sopenharmony_ci{ 937e1051a39Sopenharmony_ci char *p = start; 938e1051a39Sopenharmony_ci 939e1051a39Sopenharmony_ci while (!IS_EOF(conf, *p)) 940e1051a39Sopenharmony_ci p++; 941e1051a39Sopenharmony_ci p--; 942e1051a39Sopenharmony_ci while ((p >= start) && IS_WS(conf, *p)) 943e1051a39Sopenharmony_ci p--; 944e1051a39Sopenharmony_ci p++; 945e1051a39Sopenharmony_ci *p = '\0'; 946e1051a39Sopenharmony_ci} 947e1051a39Sopenharmony_ci 948e1051a39Sopenharmony_cistatic char *eat_alpha_numeric(CONF *conf, char *p) 949e1051a39Sopenharmony_ci{ 950e1051a39Sopenharmony_ci for (;;) { 951e1051a39Sopenharmony_ci if (IS_ESC(conf, *p)) { 952e1051a39Sopenharmony_ci p = scan_esc(conf, p); 953e1051a39Sopenharmony_ci continue; 954e1051a39Sopenharmony_ci } 955e1051a39Sopenharmony_ci if (!(IS_ALNUM_PUNCT(conf, *p) 956e1051a39Sopenharmony_ci || (conf->flag_dollarid && IS_DOLLAR(conf, *p)))) 957e1051a39Sopenharmony_ci return p; 958e1051a39Sopenharmony_ci p++; 959e1051a39Sopenharmony_ci } 960e1051a39Sopenharmony_ci} 961e1051a39Sopenharmony_ci 962e1051a39Sopenharmony_cistatic char *scan_quote(CONF *conf, char *p) 963e1051a39Sopenharmony_ci{ 964e1051a39Sopenharmony_ci int q = *p; 965e1051a39Sopenharmony_ci 966e1051a39Sopenharmony_ci p++; 967e1051a39Sopenharmony_ci while (!(IS_EOF(conf, *p)) && (*p != q)) { 968e1051a39Sopenharmony_ci if (IS_ESC(conf, *p)) { 969e1051a39Sopenharmony_ci p++; 970e1051a39Sopenharmony_ci if (IS_EOF(conf, *p)) 971e1051a39Sopenharmony_ci return p; 972e1051a39Sopenharmony_ci } 973e1051a39Sopenharmony_ci p++; 974e1051a39Sopenharmony_ci } 975e1051a39Sopenharmony_ci if (*p == q) 976e1051a39Sopenharmony_ci p++; 977e1051a39Sopenharmony_ci return p; 978e1051a39Sopenharmony_ci} 979e1051a39Sopenharmony_ci 980e1051a39Sopenharmony_cistatic char *scan_dquote(CONF *conf, char *p) 981e1051a39Sopenharmony_ci{ 982e1051a39Sopenharmony_ci int q = *p; 983e1051a39Sopenharmony_ci 984e1051a39Sopenharmony_ci p++; 985e1051a39Sopenharmony_ci while (!(IS_EOF(conf, *p))) { 986e1051a39Sopenharmony_ci if (*p == q) { 987e1051a39Sopenharmony_ci if (*(p + 1) == q) { 988e1051a39Sopenharmony_ci p++; 989e1051a39Sopenharmony_ci } else { 990e1051a39Sopenharmony_ci break; 991e1051a39Sopenharmony_ci } 992e1051a39Sopenharmony_ci } 993e1051a39Sopenharmony_ci p++; 994e1051a39Sopenharmony_ci } 995e1051a39Sopenharmony_ci if (*p == q) 996e1051a39Sopenharmony_ci p++; 997e1051a39Sopenharmony_ci return p; 998e1051a39Sopenharmony_ci} 999e1051a39Sopenharmony_ci 1000e1051a39Sopenharmony_cistatic void dump_value_doall_arg(const CONF_VALUE *a, BIO *out) 1001e1051a39Sopenharmony_ci{ 1002e1051a39Sopenharmony_ci if (a->name) 1003e1051a39Sopenharmony_ci BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value); 1004e1051a39Sopenharmony_ci else 1005e1051a39Sopenharmony_ci BIO_printf(out, "[[%s]]\n", a->section); 1006e1051a39Sopenharmony_ci} 1007e1051a39Sopenharmony_ci 1008e1051a39Sopenharmony_ciIMPLEMENT_LHASH_DOALL_ARG_CONST(CONF_VALUE, BIO); 1009e1051a39Sopenharmony_ci 1010e1051a39Sopenharmony_cistatic int def_dump(const CONF *conf, BIO *out) 1011e1051a39Sopenharmony_ci{ 1012e1051a39Sopenharmony_ci lh_CONF_VALUE_doall_BIO(conf->data, dump_value_doall_arg, out); 1013e1051a39Sopenharmony_ci return 1; 1014e1051a39Sopenharmony_ci} 1015e1051a39Sopenharmony_ci 1016e1051a39Sopenharmony_cistatic int def_is_number(const CONF *conf, char c) 1017e1051a39Sopenharmony_ci{ 1018e1051a39Sopenharmony_ci return IS_NUMBER(conf, c); 1019e1051a39Sopenharmony_ci} 1020e1051a39Sopenharmony_ci 1021e1051a39Sopenharmony_cistatic int def_to_int(const CONF *conf, char c) 1022e1051a39Sopenharmony_ci{ 1023e1051a39Sopenharmony_ci return c - '0'; 1024e1051a39Sopenharmony_ci} 1025