168651Skris/* crypto/conf/conf.c */
268651Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
368651Skris * All rights reserved.
468651Skris *
568651Skris * This package is an SSL implementation written
668651Skris * by Eric Young (eay@cryptsoft.com).
768651Skris * The implementation was written so as to conform with Netscapes SSL.
8296465Sdelphij *
968651Skris * This library is free for commercial and non-commercial use as long as
1068651Skris * the following conditions are aheared to.  The following conditions
1168651Skris * apply to all code found in this distribution, be it the RC4, RSA,
1268651Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1368651Skris * included with this distribution is covered by the same copyright terms
1468651Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296465Sdelphij *
1668651Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1768651Skris * the code are not to be removed.
1868651Skris * If this package is used in a product, Eric Young should be given attribution
1968651Skris * as the author of the parts of the library used.
2068651Skris * This can be in the form of a textual message at program startup or
2168651Skris * in documentation (online or textual) provided with the package.
22296465Sdelphij *
2368651Skris * Redistribution and use in source and binary forms, with or without
2468651Skris * modification, are permitted provided that the following conditions
2568651Skris * are met:
2668651Skris * 1. Redistributions of source code must retain the copyright
2768651Skris *    notice, this list of conditions and the following disclaimer.
2868651Skris * 2. Redistributions in binary form must reproduce the above copyright
2968651Skris *    notice, this list of conditions and the following disclaimer in the
3068651Skris *    documentation and/or other materials provided with the distribution.
3168651Skris * 3. All advertising materials mentioning features or use of this software
3268651Skris *    must display the following acknowledgement:
3368651Skris *    "This product includes cryptographic software written by
3468651Skris *     Eric Young (eay@cryptsoft.com)"
3568651Skris *    The word 'cryptographic' can be left out if the rouines from the library
3668651Skris *    being used are not cryptographic related :-).
37296465Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3868651Skris *    the apps directory (application code) you must include an acknowledgement:
3968651Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296465Sdelphij *
4168651Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4268651Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4368651Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4468651Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4568651Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4668651Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4768651Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4868651Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4968651Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5068651Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5168651Skris * SUCH DAMAGE.
52296465Sdelphij *
5368651Skris * The licence and distribution terms for any publically available version or
5468651Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5568651Skris * copied and put under another distribution licence
5668651Skris * [including the GNU Public Licence.]
5768651Skris */
5868651Skris
5968651Skris/* Part of the code in here was originally in conf.c, which is now removed */
6068651Skris
6168651Skris#include <stdio.h>
6268651Skris#include <string.h>
63160814Ssimon#include "cryptlib.h"
6468651Skris#include <openssl/stack.h>
6568651Skris#include <openssl/lhash.h>
6668651Skris#include <openssl/conf.h>
6768651Skris#include <openssl/conf_api.h>
6868651Skris#include "conf_def.h"
6968651Skris#include <openssl/buffer.h>
7068651Skris#include <openssl/err.h>
7168651Skris
7268651Skrisstatic char *eat_ws(CONF *conf, char *p);
7368651Skrisstatic char *eat_alpha_numeric(CONF *conf, char *p);
7468651Skrisstatic void clear_comments(CONF *conf, char *p);
75296465Sdelphijstatic int str_copy(CONF *conf, char *section, char **to, char *from);
7668651Skrisstatic char *scan_quote(CONF *conf, char *p);
7768651Skrisstatic char *scan_dquote(CONF *conf, char *p);
78296465Sdelphij#define scan_esc(conf,p)        (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
7968651Skris
8068651Skrisstatic CONF *def_create(CONF_METHOD *meth);
8168651Skrisstatic int def_init_default(CONF *conf);
8268651Skrisstatic int def_init_WIN32(CONF *conf);
8368651Skrisstatic int def_destroy(CONF *conf);
8468651Skrisstatic int def_destroy_data(CONF *conf);
85109998Smarkmstatic int def_load(CONF *conf, const char *name, long *eline);
86109998Smarkmstatic int def_load_bio(CONF *conf, BIO *bp, long *eline);
87109998Smarkmstatic int def_dump(const CONF *conf, BIO *bp);
88109998Smarkmstatic int def_is_number(const CONF *conf, char c);
89109998Smarkmstatic int def_to_int(const CONF *conf, char c);
9068651Skris
91296465Sdelphijconst char CONF_def_version[] = "CONF_def" OPENSSL_VERSION_PTEXT;
9268651Skris
9368651Skrisstatic CONF_METHOD default_method = {
94296465Sdelphij    "OpenSSL default",
95296465Sdelphij    def_create,
96296465Sdelphij    def_init_default,
97296465Sdelphij    def_destroy,
98296465Sdelphij    def_destroy_data,
99296465Sdelphij    def_load_bio,
100296465Sdelphij    def_dump,
101296465Sdelphij    def_is_number,
102296465Sdelphij    def_to_int,
103296465Sdelphij    def_load
104296465Sdelphij};
10568651Skris
10668651Skrisstatic CONF_METHOD WIN32_method = {
107296465Sdelphij    "WIN32",
108296465Sdelphij    def_create,
109296465Sdelphij    def_init_WIN32,
110296465Sdelphij    def_destroy,
111296465Sdelphij    def_destroy_data,
112296465Sdelphij    def_load_bio,
113296465Sdelphij    def_dump,
114296465Sdelphij    def_is_number,
115296465Sdelphij    def_to_int,
116296465Sdelphij    def_load
117296465Sdelphij};
11868651Skris
11968651SkrisCONF_METHOD *NCONF_default()
120296465Sdelphij{
121296465Sdelphij    return &default_method;
122296465Sdelphij}
123296465Sdelphij
12468651SkrisCONF_METHOD *NCONF_WIN32()
125296465Sdelphij{
126296465Sdelphij    return &WIN32_method;
127296465Sdelphij}
12868651Skris
12968651Skrisstatic CONF *def_create(CONF_METHOD *meth)
130296465Sdelphij{
131296465Sdelphij    CONF *ret;
13268651Skris
133296465Sdelphij    ret = (CONF *)OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *));
134296465Sdelphij    if (ret)
135296465Sdelphij        if (meth->init(ret) == 0) {
136296465Sdelphij            OPENSSL_free(ret);
137296465Sdelphij            ret = NULL;
138296465Sdelphij        }
139296465Sdelphij    return ret;
140296465Sdelphij}
141296465Sdelphij
14268651Skrisstatic int def_init_default(CONF *conf)
143296465Sdelphij{
144296465Sdelphij    if (conf == NULL)
145296465Sdelphij        return 0;
14668651Skris
147296465Sdelphij    conf->meth = &default_method;
148296465Sdelphij    conf->meth_data = (void *)CONF_type_default;
149296465Sdelphij    conf->data = NULL;
15068651Skris
151296465Sdelphij    return 1;
152296465Sdelphij}
15368651Skris
15468651Skrisstatic int def_init_WIN32(CONF *conf)
155296465Sdelphij{
156296465Sdelphij    if (conf == NULL)
157296465Sdelphij        return 0;
15868651Skris
159296465Sdelphij    conf->meth = &WIN32_method;
160296465Sdelphij    conf->meth_data = (void *)CONF_type_win32;
161296465Sdelphij    conf->data = NULL;
16268651Skris
163296465Sdelphij    return 1;
164296465Sdelphij}
16568651Skris
16668651Skrisstatic int def_destroy(CONF *conf)
167296465Sdelphij{
168296465Sdelphij    if (def_destroy_data(conf)) {
169296465Sdelphij        OPENSSL_free(conf);
170296465Sdelphij        return 1;
171296465Sdelphij    }
172296465Sdelphij    return 0;
173296465Sdelphij}
17468651Skris
17568651Skrisstatic int def_destroy_data(CONF *conf)
176296465Sdelphij{
177296465Sdelphij    if (conf == NULL)
178296465Sdelphij        return 0;
179296465Sdelphij    _CONF_free_data(conf);
180296465Sdelphij    return 1;
181296465Sdelphij}
18268651Skris
183109998Smarkmstatic int def_load(CONF *conf, const char *name, long *line)
184296465Sdelphij{
185296465Sdelphij    int ret;
186296465Sdelphij    BIO *in = NULL;
187109998Smarkm
188109998Smarkm#ifdef OPENSSL_SYS_VMS
189296465Sdelphij    in = BIO_new_file(name, "r");
190109998Smarkm#else
191296465Sdelphij    in = BIO_new_file(name, "rb");
192109998Smarkm#endif
193296465Sdelphij    if (in == NULL) {
194296465Sdelphij        if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
195296465Sdelphij            CONFerr(CONF_F_DEF_LOAD, CONF_R_NO_SUCH_FILE);
196296465Sdelphij        else
197296465Sdelphij            CONFerr(CONF_F_DEF_LOAD, ERR_R_SYS_LIB);
198296465Sdelphij        return 0;
199296465Sdelphij    }
200109998Smarkm
201296465Sdelphij    ret = def_load_bio(conf, in, line);
202296465Sdelphij    BIO_free(in);
203109998Smarkm
204296465Sdelphij    return ret;
205296465Sdelphij}
206109998Smarkm
207109998Smarkmstatic int def_load_bio(CONF *conf, BIO *in, long *line)
208296465Sdelphij{
209109998Smarkm/* The macro BUFSIZE conflicts with a system macro in VxWorks */
210296465Sdelphij#define CONFBUFSIZE     512
211296465Sdelphij    int bufnum = 0, i, ii;
212296465Sdelphij    BUF_MEM *buff = NULL;
213296465Sdelphij    char *s, *p, *end;
214296465Sdelphij    int again;
215296465Sdelphij    long eline = 0;
216296465Sdelphij    char btmp[DECIMAL_SIZE(eline) + 1];
217296465Sdelphij    CONF_VALUE *v = NULL, *tv;
218296465Sdelphij    CONF_VALUE *sv = NULL;
219296465Sdelphij    char *section = NULL, *buf;
220296465Sdelphij/*      STACK_OF(CONF_VALUE) *section_sk=NULL;*/
221296465Sdelphij/*      STACK_OF(CONF_VALUE) *ts=NULL;*/
222296465Sdelphij    char *start, *psection, *pname;
223296465Sdelphij    void *h = (void *)(conf->data);
22468651Skris
225296465Sdelphij    if ((buff = BUF_MEM_new()) == NULL) {
226296465Sdelphij        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
227296465Sdelphij        goto err;
228296465Sdelphij    }
22968651Skris
230296465Sdelphij    section = (char *)OPENSSL_malloc(10);
231296465Sdelphij    if (section == NULL) {
232296465Sdelphij        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
233296465Sdelphij        goto err;
234296465Sdelphij    }
235296465Sdelphij    BUF_strlcpy(section, "default", 10);
23668651Skris
237296465Sdelphij    if (_CONF_new_data(conf) == 0) {
238296465Sdelphij        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
239296465Sdelphij        goto err;
240296465Sdelphij    }
24168651Skris
242296465Sdelphij    sv = _CONF_new_section(conf, section);
243296465Sdelphij    if (sv == NULL) {
244296465Sdelphij        CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
245296465Sdelphij        goto err;
246296465Sdelphij    }
247296465Sdelphij/*      section_sk=(STACK_OF(CONF_VALUE) *)sv->value;*/
24868651Skris
249296465Sdelphij    bufnum = 0;
250296465Sdelphij    again = 0;
251296465Sdelphij    for (;;) {
252296465Sdelphij        if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
253296465Sdelphij            CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
254296465Sdelphij            goto err;
255296465Sdelphij        }
256296465Sdelphij        p = &(buff->data[bufnum]);
257296465Sdelphij        *p = '\0';
258296465Sdelphij        BIO_gets(in, p, CONFBUFSIZE - 1);
259296465Sdelphij        p[CONFBUFSIZE - 1] = '\0';
260296465Sdelphij        ii = i = strlen(p);
261296465Sdelphij        if (i == 0 && !again)
262296465Sdelphij            break;
263296465Sdelphij        again = 0;
264296465Sdelphij        while (i > 0) {
265296465Sdelphij            if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
266296465Sdelphij                break;
267296465Sdelphij            else
268296465Sdelphij                i--;
269296465Sdelphij        }
270296465Sdelphij        /*
271296465Sdelphij         * we removed some trailing stuff so there is a new line on the end.
272296465Sdelphij         */
273296465Sdelphij        if (ii && i == ii)
274296465Sdelphij            again = 1;          /* long line */
275296465Sdelphij        else {
276296465Sdelphij            p[i] = '\0';
277296465Sdelphij            eline++;            /* another input line */
278296465Sdelphij        }
27968651Skris
280296465Sdelphij        /* we now have a line with trailing \r\n removed */
28168651Skris
282296465Sdelphij        /* i is the number of bytes */
283296465Sdelphij        bufnum += i;
28468651Skris
285296465Sdelphij        v = NULL;
286296465Sdelphij        /* check for line continuation */
287296465Sdelphij        if (bufnum >= 1) {
288296465Sdelphij            /*
289296465Sdelphij             * If we have bytes and the last char '\\' and second last char
290296465Sdelphij             * is not '\\'
291296465Sdelphij             */
292296465Sdelphij            p = &(buff->data[bufnum - 1]);
293296465Sdelphij            if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
294296465Sdelphij                bufnum--;
295296465Sdelphij                again = 1;
296296465Sdelphij            }
297296465Sdelphij        }
298296465Sdelphij        if (again)
299296465Sdelphij            continue;
300296465Sdelphij        bufnum = 0;
301296465Sdelphij        buf = buff->data;
30268651Skris
303296465Sdelphij        clear_comments(conf, buf);
304296465Sdelphij        s = eat_ws(conf, buf);
305296465Sdelphij        if (IS_EOF(conf, *s))
306296465Sdelphij            continue;           /* blank line */
307296465Sdelphij        if (*s == '[') {
308296465Sdelphij            char *ss;
30968651Skris
310296465Sdelphij            s++;
311296465Sdelphij            start = eat_ws(conf, s);
312296465Sdelphij            ss = start;
313296465Sdelphij again:
314296465Sdelphij            end = eat_alpha_numeric(conf, ss);
315296465Sdelphij            p = eat_ws(conf, end);
316296465Sdelphij            if (*p != ']') {
317296465Sdelphij                if (*p != '\0' && ss != p) {
318296465Sdelphij                    ss = p;
319296465Sdelphij                    goto again;
320296465Sdelphij                }
321296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO,
322296465Sdelphij                        CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
323296465Sdelphij                goto err;
324296465Sdelphij            }
325296465Sdelphij            *end = '\0';
326296465Sdelphij            if (!str_copy(conf, NULL, &section, start))
327296465Sdelphij                goto err;
328296465Sdelphij            if ((sv = _CONF_get_section(conf, section)) == NULL)
329296465Sdelphij                sv = _CONF_new_section(conf, section);
330296465Sdelphij            if (sv == NULL) {
331296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO,
332296465Sdelphij                        CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
333296465Sdelphij                goto err;
334296465Sdelphij            }
335296465Sdelphij/*                      section_sk=(STACK_OF(CONF_VALUE) *)sv->value;*/
336296465Sdelphij            continue;
337296465Sdelphij        } else {
338296465Sdelphij            pname = s;
339296465Sdelphij            psection = NULL;
340296465Sdelphij            end = eat_alpha_numeric(conf, s);
341296465Sdelphij            if ((end[0] == ':') && (end[1] == ':')) {
342296465Sdelphij                *end = '\0';
343296465Sdelphij                end += 2;
344296465Sdelphij                psection = pname;
345296465Sdelphij                pname = end;
346296465Sdelphij                end = eat_alpha_numeric(conf, end);
347296465Sdelphij            }
348296465Sdelphij            p = eat_ws(conf, end);
349296465Sdelphij            if (*p != '=') {
350296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
351296465Sdelphij                goto err;
352296465Sdelphij            }
353296465Sdelphij            *end = '\0';
354296465Sdelphij            p++;
355296465Sdelphij            start = eat_ws(conf, p);
356296465Sdelphij            while (!IS_EOF(conf, *p))
357296465Sdelphij                p++;
358296465Sdelphij            p--;
359296465Sdelphij            while ((p != start) && (IS_WS(conf, *p)))
360296465Sdelphij                p--;
361296465Sdelphij            p++;
362296465Sdelphij            *p = '\0';
36368651Skris
364296465Sdelphij            if (!(v = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) {
365296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
366296465Sdelphij                goto err;
367296465Sdelphij            }
368296465Sdelphij            if (psection == NULL)
369296465Sdelphij                psection = section;
370296465Sdelphij            v->name = (char *)OPENSSL_malloc(strlen(pname) + 1);
371296465Sdelphij            v->value = NULL;
372296465Sdelphij            if (v->name == NULL) {
373296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
374296465Sdelphij                goto err;
375296465Sdelphij            }
376296465Sdelphij            BUF_strlcpy(v->name, pname, strlen(pname) + 1);
377296465Sdelphij            if (!str_copy(conf, psection, &(v->value), start))
378296465Sdelphij                goto err;
37968651Skris
380296465Sdelphij            if (strcmp(psection, section) != 0) {
381296465Sdelphij                if ((tv = _CONF_get_section(conf, psection))
382296465Sdelphij                    == NULL)
383296465Sdelphij                    tv = _CONF_new_section(conf, psection);
384296465Sdelphij                if (tv == NULL) {
385296465Sdelphij                    CONFerr(CONF_F_DEF_LOAD_BIO,
386296465Sdelphij                            CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
387296465Sdelphij                    goto err;
388296465Sdelphij                }
389296465Sdelphij/*                              ts=(STACK_OF(CONF_VALUE) *)tv->value;*/
390296465Sdelphij            } else {
391296465Sdelphij                tv = sv;
392296465Sdelphij/*                              ts=section_sk;*/
393296465Sdelphij            }
39468651Skris#if 1
395296465Sdelphij            if (_CONF_add_string(conf, tv, v) == 0) {
396296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
397296465Sdelphij                goto err;
398296465Sdelphij            }
39968651Skris#else
400296465Sdelphij            v->section = tv->section;
401296465Sdelphij            if (!sk_CONF_VALUE_push(ts, v)) {
402296465Sdelphij                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
403296465Sdelphij                goto err;
404296465Sdelphij            }
405296465Sdelphij            vv = (CONF_VALUE *)lh_insert(conf->data, v);
406296465Sdelphij            if (vv != NULL) {
407296465Sdelphij                sk_CONF_VALUE_delete_ptr(ts, vv);
408296465Sdelphij                OPENSSL_free(vv->name);
409296465Sdelphij                OPENSSL_free(vv->value);
410296465Sdelphij                OPENSSL_free(vv);
411296465Sdelphij            }
41268651Skris#endif
413296465Sdelphij            v = NULL;
414296465Sdelphij        }
415296465Sdelphij    }
416296465Sdelphij    if (buff != NULL)
417296465Sdelphij        BUF_MEM_free(buff);
418296465Sdelphij    if (section != NULL)
419296465Sdelphij        OPENSSL_free(section);
420296465Sdelphij    return (1);
421296465Sdelphij err:
422296465Sdelphij    if (buff != NULL)
423296465Sdelphij        BUF_MEM_free(buff);
424296465Sdelphij    if (section != NULL)
425296465Sdelphij        OPENSSL_free(section);
426296465Sdelphij    if (line != NULL)
427296465Sdelphij        *line = eline;
428296465Sdelphij    BIO_snprintf(btmp, sizeof btmp, "%ld", eline);
429296465Sdelphij    ERR_add_error_data(2, "line ", btmp);
430296465Sdelphij    if ((h != conf->data) && (conf->data != NULL)) {
431296465Sdelphij        CONF_free(conf->data);
432296465Sdelphij        conf->data = NULL;
433296465Sdelphij    }
434296465Sdelphij    if (v != NULL) {
435296465Sdelphij        if (v->name != NULL)
436296465Sdelphij            OPENSSL_free(v->name);
437296465Sdelphij        if (v->value != NULL)
438296465Sdelphij            OPENSSL_free(v->value);
439296465Sdelphij        if (v != NULL)
440296465Sdelphij            OPENSSL_free(v);
441296465Sdelphij    }
442296465Sdelphij    return (0);
443296465Sdelphij}
44468651Skris
44568651Skrisstatic void clear_comments(CONF *conf, char *p)
446296465Sdelphij{
447296465Sdelphij    for (;;) {
448296465Sdelphij        if (IS_FCOMMENT(conf, *p)) {
449296465Sdelphij            *p = '\0';
450296465Sdelphij            return;
451296465Sdelphij        }
452296465Sdelphij        if (!IS_WS(conf, *p)) {
453296465Sdelphij            break;
454296465Sdelphij        }
455296465Sdelphij        p++;
456296465Sdelphij    }
45768651Skris
458296465Sdelphij    for (;;) {
459296465Sdelphij        if (IS_COMMENT(conf, *p)) {
460296465Sdelphij            *p = '\0';
461296465Sdelphij            return;
462296465Sdelphij        }
463296465Sdelphij        if (IS_DQUOTE(conf, *p)) {
464296465Sdelphij            p = scan_dquote(conf, p);
465296465Sdelphij            continue;
466296465Sdelphij        }
467296465Sdelphij        if (IS_QUOTE(conf, *p)) {
468296465Sdelphij            p = scan_quote(conf, p);
469296465Sdelphij            continue;
470296465Sdelphij        }
471296465Sdelphij        if (IS_ESC(conf, *p)) {
472296465Sdelphij            p = scan_esc(conf, p);
473296465Sdelphij            continue;
474296465Sdelphij        }
475296465Sdelphij        if (IS_EOF(conf, *p))
476296465Sdelphij            return;
477296465Sdelphij        else
478296465Sdelphij            p++;
479296465Sdelphij    }
480296465Sdelphij}
48168651Skris
48268651Skrisstatic int str_copy(CONF *conf, char *section, char **pto, char *from)
483296465Sdelphij{
484296465Sdelphij    int q, r, rr = 0, to = 0, len = 0;
485296465Sdelphij    char *s, *e, *rp, *p, *rrp, *np, *cp, v;
486296465Sdelphij    BUF_MEM *buf;
48768651Skris
488296465Sdelphij    if ((buf = BUF_MEM_new()) == NULL)
489296465Sdelphij        return (0);
49068651Skris
491296465Sdelphij    len = strlen(from) + 1;
492296465Sdelphij    if (!BUF_MEM_grow(buf, len))
493296465Sdelphij        goto err;
49468651Skris
495296465Sdelphij    for (;;) {
496296465Sdelphij        if (IS_QUOTE(conf, *from)) {
497296465Sdelphij            q = *from;
498296465Sdelphij            from++;
499296465Sdelphij            while (!IS_EOF(conf, *from) && (*from != q)) {
500296465Sdelphij                if (IS_ESC(conf, *from)) {
501296465Sdelphij                    from++;
502296465Sdelphij                    if (IS_EOF(conf, *from))
503296465Sdelphij                        break;
504296465Sdelphij                }
505296465Sdelphij                buf->data[to++] = *(from++);
506296465Sdelphij            }
507296465Sdelphij            if (*from == q)
508296465Sdelphij                from++;
509296465Sdelphij        } else if (IS_DQUOTE(conf, *from)) {
510296465Sdelphij            q = *from;
511296465Sdelphij            from++;
512296465Sdelphij            while (!IS_EOF(conf, *from)) {
513296465Sdelphij                if (*from == q) {
514296465Sdelphij                    if (*(from + 1) == q) {
515296465Sdelphij                        from++;
516296465Sdelphij                    } else {
517296465Sdelphij                        break;
518296465Sdelphij                    }
519296465Sdelphij                }
520296465Sdelphij                buf->data[to++] = *(from++);
521296465Sdelphij            }
522296465Sdelphij            if (*from == q)
523296465Sdelphij                from++;
524296465Sdelphij        } else if (IS_ESC(conf, *from)) {
525296465Sdelphij            from++;
526296465Sdelphij            v = *(from++);
527296465Sdelphij            if (IS_EOF(conf, v))
528296465Sdelphij                break;
529296465Sdelphij            else if (v == 'r')
530296465Sdelphij                v = '\r';
531296465Sdelphij            else if (v == 'n')
532296465Sdelphij                v = '\n';
533296465Sdelphij            else if (v == 'b')
534296465Sdelphij                v = '\b';
535296465Sdelphij            else if (v == 't')
536296465Sdelphij                v = '\t';
537296465Sdelphij            buf->data[to++] = v;
538296465Sdelphij        } else if (IS_EOF(conf, *from))
539296465Sdelphij            break;
540296465Sdelphij        else if (*from == '$') {
541296465Sdelphij            /* try to expand it */
542296465Sdelphij            rrp = NULL;
543296465Sdelphij            s = &(from[1]);
544296465Sdelphij            if (*s == '{')
545296465Sdelphij                q = '}';
546296465Sdelphij            else if (*s == '(')
547296465Sdelphij                q = ')';
548296465Sdelphij            else
549296465Sdelphij                q = 0;
55068651Skris
551296465Sdelphij            if (q)
552296465Sdelphij                s++;
553296465Sdelphij            cp = section;
554296465Sdelphij            e = np = s;
555296465Sdelphij            while (IS_ALPHA_NUMERIC(conf, *e))
556296465Sdelphij                e++;
557296465Sdelphij            if ((e[0] == ':') && (e[1] == ':')) {
558296465Sdelphij                cp = np;
559296465Sdelphij                rrp = e;
560296465Sdelphij                rr = *e;
561296465Sdelphij                *rrp = '\0';
562296465Sdelphij                e += 2;
563296465Sdelphij                np = e;
564296465Sdelphij                while (IS_ALPHA_NUMERIC(conf, *e))
565296465Sdelphij                    e++;
566296465Sdelphij            }
567296465Sdelphij            r = *e;
568296465Sdelphij            *e = '\0';
569296465Sdelphij            rp = e;
570296465Sdelphij            if (q) {
571296465Sdelphij                if (r != q) {
572296465Sdelphij                    CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE);
573296465Sdelphij                    goto err;
574296465Sdelphij                }
575296465Sdelphij                e++;
576296465Sdelphij            }
577296465Sdelphij            /*-
578296465Sdelphij             * So at this point we have
579296465Sdelphij             * np which is the start of the name string which is
580296465Sdelphij             *   '\0' terminated.
581296465Sdelphij             * cp which is the start of the section string which is
582296465Sdelphij             *   '\0' terminated.
583296465Sdelphij             * e is the 'next point after'.
584296465Sdelphij             * r and rr are the chars replaced by the '\0'
585296465Sdelphij             * rp and rrp is where 'r' and 'rr' came from.
586296465Sdelphij             */
587296465Sdelphij            p = _CONF_get_string(conf, cp, np);
588296465Sdelphij            if (rrp != NULL)
589296465Sdelphij                *rrp = rr;
590296465Sdelphij            *rp = r;
591296465Sdelphij            if (p == NULL) {
592296465Sdelphij                CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE);
593296465Sdelphij                goto err;
594296465Sdelphij            }
595296465Sdelphij            BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from)));
596296465Sdelphij            while (*p)
597296465Sdelphij                buf->data[to++] = *(p++);
598142425Snectar
599296465Sdelphij            /*
600296465Sdelphij             * Since we change the pointer 'from', we also have to change the
601296465Sdelphij             * perceived length of the string it points at.  /RL
602296465Sdelphij             */
603296465Sdelphij            len -= e - from;
604296465Sdelphij            from = e;
605160814Ssimon
606296465Sdelphij            /*
607296465Sdelphij             * In case there were no braces or parenthesis around the
608296465Sdelphij             * variable reference, we have to put back the character that was
609296465Sdelphij             * replaced with a '\0'.  /RL
610296465Sdelphij             */
611296465Sdelphij            *rp = r;
612296465Sdelphij        } else
613296465Sdelphij            buf->data[to++] = *(from++);
614296465Sdelphij    }
615296465Sdelphij    buf->data[to] = '\0';
616296465Sdelphij    if (*pto != NULL)
617296465Sdelphij        OPENSSL_free(*pto);
618296465Sdelphij    *pto = buf->data;
619296465Sdelphij    OPENSSL_free(buf);
620296465Sdelphij    return (1);
621296465Sdelphij err:
622296465Sdelphij    if (buf != NULL)
623296465Sdelphij        BUF_MEM_free(buf);
624296465Sdelphij    return (0);
625296465Sdelphij}
62668651Skris
62768651Skrisstatic char *eat_ws(CONF *conf, char *p)
628296465Sdelphij{
629296465Sdelphij    while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
630296465Sdelphij        p++;
631296465Sdelphij    return (p);
632296465Sdelphij}
63368651Skris
63468651Skrisstatic char *eat_alpha_numeric(CONF *conf, char *p)
635296465Sdelphij{
636296465Sdelphij    for (;;) {
637296465Sdelphij        if (IS_ESC(conf, *p)) {
638296465Sdelphij            p = scan_esc(conf, p);
639296465Sdelphij            continue;
640296465Sdelphij        }
641296465Sdelphij        if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p))
642296465Sdelphij            return (p);
643296465Sdelphij        p++;
644296465Sdelphij    }
645296465Sdelphij}
64668651Skris
64768651Skrisstatic char *scan_quote(CONF *conf, char *p)
648296465Sdelphij{
649296465Sdelphij    int q = *p;
65068651Skris
651296465Sdelphij    p++;
652296465Sdelphij    while (!(IS_EOF(conf, *p)) && (*p != q)) {
653296465Sdelphij        if (IS_ESC(conf, *p)) {
654296465Sdelphij            p++;
655296465Sdelphij            if (IS_EOF(conf, *p))
656296465Sdelphij                return (p);
657296465Sdelphij        }
658296465Sdelphij        p++;
659296465Sdelphij    }
660296465Sdelphij    if (*p == q)
661296465Sdelphij        p++;
662296465Sdelphij    return (p);
663296465Sdelphij}
66468651Skris
66568651Skrisstatic char *scan_dquote(CONF *conf, char *p)
666296465Sdelphij{
667296465Sdelphij    int q = *p;
66868651Skris
669296465Sdelphij    p++;
670296465Sdelphij    while (!(IS_EOF(conf, *p))) {
671296465Sdelphij        if (*p == q) {
672296465Sdelphij            if (*(p + 1) == q) {
673296465Sdelphij                p++;
674296465Sdelphij            } else {
675296465Sdelphij                break;
676296465Sdelphij            }
677296465Sdelphij        }
678296465Sdelphij        p++;
679296465Sdelphij    }
680296465Sdelphij    if (*p == q)
681296465Sdelphij        p++;
682296465Sdelphij    return (p);
683296465Sdelphij}
68468651Skris
68568651Skrisstatic void dump_value(CONF_VALUE *a, BIO *out)
686296465Sdelphij{
687296465Sdelphij    if (a->name)
688296465Sdelphij        BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
689296465Sdelphij    else
690296465Sdelphij        BIO_printf(out, "[[%s]]\n", a->section);
691296465Sdelphij}
69268651Skris
693109998Smarkmstatic IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE *, BIO *)
694109998Smarkm
695109998Smarkmstatic int def_dump(const CONF *conf, BIO *out)
696296465Sdelphij{
697296465Sdelphij    lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value), out);
698296465Sdelphij    return 1;
699296465Sdelphij}
70068651Skris
701109998Smarkmstatic int def_is_number(const CONF *conf, char c)
702296465Sdelphij{
703296465Sdelphij    return IS_NUMBER(conf, c);
704296465Sdelphij}
70568651Skris
706109998Smarkmstatic int def_to_int(const CONF *conf, char c)
707296465Sdelphij{
708296465Sdelphij    return c - '0';
709296465Sdelphij}
710