in crypto/conf/conf.c [383:579]
int NCONF_load_bio(CONF *conf, BIO *in, long *out_error_line) {
static const size_t CONFBUFSIZE = 512;
int bufnum = 0, i, ii;
BUF_MEM *buff = NULL;
char *s, *p, *end;
int again;
long eline = 0;
char btmp[DECIMAL_SIZE(eline) + 1];
CONF_VALUE *v = NULL, *tv;
CONF_VALUE *sv = NULL;
char *section = NULL, *buf;
char *start, *psection, *pname;
if ((buff = BUF_MEM_new()) == NULL) {
OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
goto err;
}
section = OPENSSL_strdup(kDefaultSectionName);
if (section == NULL) {
goto err;
}
sv = NCONF_new_section(conf, section);
if (sv == NULL) {
OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
bufnum = 0;
again = 0;
for (;;) {
if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
OPENSSL_PUT_ERROR(CONF, ERR_R_BUF_LIB);
goto err;
}
p = &(buff->data[bufnum]);
*p = '\0';
BIO_gets(in, p, CONFBUFSIZE - 1);
p[CONFBUFSIZE - 1] = '\0';
ii = i = strlen(p);
if (i == 0 && !again) {
break;
}
again = 0;
while (i > 0) {
if ((p[i - 1] != '\r') && (p[i - 1] != '\n')) {
break;
} else {
i--;
}
}
// we removed some trailing stuff so there is a new
// line on the end.
if (ii && i == ii) {
again = 1; // long line
} else {
p[i] = '\0';
eline++; // another input line
}
// we now have a line with trailing \r\n removed
// i is the number of bytes
bufnum += i;
v = NULL;
// check for line continuation
if (bufnum >= 1) {
// If we have bytes and the last char '\\' and
// second last char is not '\\'
p = &(buff->data[bufnum - 1]);
if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
bufnum--;
again = 1;
}
}
if (again) {
continue;
}
bufnum = 0;
buf = buff->data;
clear_comments(conf, buf);
s = eat_ws(conf, buf);
if (IS_EOF(conf, *s)) {
continue; // blank line
}
if (*s == '[') {
char *ss;
s++;
start = eat_ws(conf, s);
ss = start;
again:
end = eat_alpha_numeric(conf, ss);
p = eat_ws(conf, end);
if (*p != ']') {
if (*p != '\0' && ss != p) {
ss = p;
goto again;
}
OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
goto err;
}
*end = '\0';
if (!str_copy(conf, NULL, §ion, start)) {
goto err;
}
if ((sv = get_section(conf, section)) == NULL) {
sv = NCONF_new_section(conf, section);
}
if (sv == NULL) {
OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
continue;
} else {
pname = s;
psection = NULL;
end = eat_alpha_numeric(conf, s);
if ((end[0] == ':') && (end[1] == ':')) {
*end = '\0';
end += 2;
psection = pname;
pname = end;
end = eat_alpha_numeric(conf, end);
}
p = eat_ws(conf, end);
if (*p != '=') {
OPENSSL_PUT_ERROR(CONF, CONF_R_MISSING_EQUAL_SIGN);
goto err;
}
*end = '\0';
p++;
start = eat_ws(conf, p);
while (!IS_EOF(conf, *p)) {
p++;
}
p--;
while ((p != start) && (IS_WS(conf, *p))) {
p--;
}
p++;
*p = '\0';
if (!(v = CONF_VALUE_new())) {
goto err;
}
if (psection == NULL) {
psection = section;
}
v->name = OPENSSL_strdup(pname);
if (v->name == NULL) {
goto err;
}
if (!str_copy(conf, psection, &(v->value), start)) {
goto err;
}
if (strcmp(psection, section) != 0) {
if ((tv = get_section(conf, psection)) == NULL) {
tv = NCONF_new_section(conf, psection);
}
if (tv == NULL) {
OPENSSL_PUT_ERROR(CONF, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
goto err;
}
} else {
tv = sv;
}
if (add_string(conf, tv, v) == 0) {
goto err;
}
v = NULL;
}
}
BUF_MEM_free(buff);
OPENSSL_free(section);
return 1;
err:
BUF_MEM_free(buff);
OPENSSL_free(section);
if (out_error_line != NULL) {
*out_error_line = eline;
}
snprintf(btmp, sizeof btmp, "%ld", eline);
ERR_add_error_data(2, "line ", btmp);
if (v != NULL) {
OPENSSL_free(v->name);
OPENSSL_free(v->value);
OPENSSL_free(v);
}
return 0;
}