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.
8280297Sjkim *
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).
15280297Sjkim *
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.
22280297Sjkim *
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 :-).
37280297Sjkim * 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)"
40280297Sjkim *
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.
52280297Sjkim *
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
72325335Sjkim/*
73325335Sjkim * The maximum length we can grow a value to after variable expansion. 64k
74325335Sjkim * should be more than enough for all reasonable uses.
75325335Sjkim */
76325335Sjkim#define MAX_CONF_VALUE_LENGTH       65536
77325335Sjkim
7868651Skrisstatic char *eat_ws(CONF *conf, char *p);
7968651Skrisstatic char *eat_alpha_numeric(CONF *conf, char *p);
8068651Skrisstatic void clear_comments(CONF *conf, char *p);
81280297Sjkimstatic int str_copy(CONF *conf, char *section, char **to, char *from);
8268651Skrisstatic char *scan_quote(CONF *conf, char *p);
8368651Skrisstatic char *scan_dquote(CONF *conf, char *p);
84280297Sjkim#define scan_esc(conf,p)        (((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
8568651Skris
8668651Skrisstatic CONF *def_create(CONF_METHOD *meth);
8768651Skrisstatic int def_init_default(CONF *conf);
8868651Skrisstatic int def_init_WIN32(CONF *conf);
8968651Skrisstatic int def_destroy(CONF *conf);
9068651Skrisstatic int def_destroy_data(CONF *conf);
91109998Smarkmstatic int def_load(CONF *conf, const char *name, long *eline);
92109998Smarkmstatic int def_load_bio(CONF *conf, BIO *bp, long *eline);
93109998Smarkmstatic int def_dump(const CONF *conf, BIO *bp);
94109998Smarkmstatic int def_is_number(const CONF *conf, char c);
95109998Smarkmstatic int def_to_int(const CONF *conf, char c);
9668651Skris
97280297Sjkimconst char CONF_def_version[] = "CONF_def" OPENSSL_VERSION_PTEXT;
9868651Skris
9968651Skrisstatic CONF_METHOD default_method = {
100280297Sjkim    "OpenSSL default",
101280297Sjkim    def_create,
102280297Sjkim    def_init_default,
103280297Sjkim    def_destroy,
104280297Sjkim    def_destroy_data,
105280297Sjkim    def_load_bio,
106280297Sjkim    def_dump,
107280297Sjkim    def_is_number,
108280297Sjkim    def_to_int,
109280297Sjkim    def_load
110280297Sjkim};
11168651Skris
11268651Skrisstatic CONF_METHOD WIN32_method = {
113280297Sjkim    "WIN32",
114280297Sjkim    def_create,
115280297Sjkim    def_init_WIN32,
116280297Sjkim    def_destroy,
117280297Sjkim    def_destroy_data,
118280297Sjkim    def_load_bio,
119280297Sjkim    def_dump,
120280297Sjkim    def_is_number,
121280297Sjkim    def_to_int,
122280297Sjkim    def_load
123280297Sjkim};
12468651Skris
12568651SkrisCONF_METHOD *NCONF_default()
126280297Sjkim{
127280297Sjkim    return &default_method;
128280297Sjkim}
129280297Sjkim
13068651SkrisCONF_METHOD *NCONF_WIN32()
131280297Sjkim{
132280297Sjkim    return &WIN32_method;
133280297Sjkim}
13468651Skris
13568651Skrisstatic CONF *def_create(CONF_METHOD *meth)
136280297Sjkim{
137280297Sjkim    CONF *ret;
13868651Skris
139280297Sjkim    ret = OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *));
140280297Sjkim    if (ret)
141280297Sjkim        if (meth->init(ret) == 0) {
142280297Sjkim            OPENSSL_free(ret);
143280297Sjkim            ret = NULL;
144280297Sjkim        }
145280297Sjkim    return ret;
146280297Sjkim}
147280297Sjkim
14868651Skrisstatic int def_init_default(CONF *conf)
149280297Sjkim{
150280297Sjkim    if (conf == NULL)
151280297Sjkim        return 0;
15268651Skris
153280297Sjkim    conf->meth = &default_method;
154280297Sjkim    conf->meth_data = CONF_type_default;
155280297Sjkim    conf->data = NULL;
15668651Skris
157280297Sjkim    return 1;
158280297Sjkim}
15968651Skris
16068651Skrisstatic int def_init_WIN32(CONF *conf)
161280297Sjkim{
162280297Sjkim    if (conf == NULL)
163280297Sjkim        return 0;
16468651Skris
165280297Sjkim    conf->meth = &WIN32_method;
166280297Sjkim    conf->meth_data = (void *)CONF_type_win32;
167280297Sjkim    conf->data = NULL;
16868651Skris
169280297Sjkim    return 1;
170280297Sjkim}
17168651Skris
17268651Skrisstatic int def_destroy(CONF *conf)
173280297Sjkim{
174280297Sjkim    if (def_destroy_data(conf)) {
175280297Sjkim        OPENSSL_free(conf);
176280297Sjkim        return 1;
177280297Sjkim    }
178280297Sjkim    return 0;
179280297Sjkim}
18068651Skris
18168651Skrisstatic int def_destroy_data(CONF *conf)
182280297Sjkim{
183280297Sjkim    if (conf == NULL)
184280297Sjkim        return 0;
185280297Sjkim    _CONF_free_data(conf);
186280297Sjkim    return 1;
187280297Sjkim}
18868651Skris
189109998Smarkmstatic int def_load(CONF *conf, const char *name, long *line)
190280297Sjkim{
191280297Sjkim    int ret;
192280297Sjkim    BIO *in = NULL;
193109998Smarkm
194109998Smarkm#ifdef OPENSSL_SYS_VMS
195280297Sjkim    in = BIO_new_file(name, "r");
196109998Smarkm#else
197280297Sjkim    in = BIO_new_file(name, "rb");
198109998Smarkm#endif
199280297Sjkim    if (in == NULL) {
200280297Sjkim        if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
201280297Sjkim            CONFerr(CONF_F_DEF_LOAD, CONF_R_NO_SUCH_FILE);
202280297Sjkim        else
203280297Sjkim            CONFerr(CONF_F_DEF_LOAD, ERR_R_SYS_LIB);
204280297Sjkim        return 0;
205280297Sjkim    }
206109998Smarkm
207280297Sjkim    ret = def_load_bio(conf, in, line);
208280297Sjkim    BIO_free(in);
209109998Smarkm
210280297Sjkim    return ret;
211280297Sjkim}
212109998Smarkm
213109998Smarkmstatic int def_load_bio(CONF *conf, BIO *in, long *line)
214280297Sjkim{
215109998Smarkm/* The macro BUFSIZE conflicts with a system macro in VxWorks */
216280297Sjkim#define CONFBUFSIZE     512
217280297Sjkim    int bufnum = 0, i, ii;
218280297Sjkim    BUF_MEM *buff = NULL;
219280297Sjkim    char *s, *p, *end;
220280297Sjkim    int again;
221280297Sjkim    long eline = 0;
222280297Sjkim    char btmp[DECIMAL_SIZE(eline) + 1];
223280297Sjkim    CONF_VALUE *v = NULL, *tv;
224280297Sjkim    CONF_VALUE *sv = NULL;
225280297Sjkim    char *section = NULL, *buf;
226280297Sjkim    char *start, *psection, *pname;
227280297Sjkim    void *h = (void *)(conf->data);
22868651Skris
229280297Sjkim    if ((buff = BUF_MEM_new()) == NULL) {
230280297Sjkim        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
231280297Sjkim        goto err;
232280297Sjkim    }
23368651Skris
234291719Sjkim    section = BUF_strdup("default");
235280297Sjkim    if (section == NULL) {
236280297Sjkim        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
237280297Sjkim        goto err;
238280297Sjkim    }
23968651Skris
240280297Sjkim    if (_CONF_new_data(conf) == 0) {
241280297Sjkim        CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
242280297Sjkim        goto err;
243280297Sjkim    }
24468651Skris
245280297Sjkim    sv = _CONF_new_section(conf, section);
246280297Sjkim    if (sv == NULL) {
247280297Sjkim        CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
248280297Sjkim        goto err;
249280297Sjkim    }
25068651Skris
251280297Sjkim    bufnum = 0;
252280297Sjkim    again = 0;
253280297Sjkim    for (;;) {
254280297Sjkim        if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
255280297Sjkim            CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_BUF_LIB);
256280297Sjkim            goto err;
257280297Sjkim        }
258280297Sjkim        p = &(buff->data[bufnum]);
259280297Sjkim        *p = '\0';
260280297Sjkim        BIO_gets(in, p, CONFBUFSIZE - 1);
261280297Sjkim        p[CONFBUFSIZE - 1] = '\0';
262280297Sjkim        ii = i = strlen(p);
263280297Sjkim        if (i == 0 && !again)
264280297Sjkim            break;
265280297Sjkim        again = 0;
266280297Sjkim        while (i > 0) {
267280297Sjkim            if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
268280297Sjkim                break;
269280297Sjkim            else
270280297Sjkim                i--;
271280297Sjkim        }
272280297Sjkim        /*
273280297Sjkim         * we removed some trailing stuff so there is a new line on the end.
274280297Sjkim         */
275280297Sjkim        if (ii && i == ii)
276280297Sjkim            again = 1;          /* long line */
277280297Sjkim        else {
278280297Sjkim            p[i] = '\0';
279280297Sjkim            eline++;            /* another input line */
280280297Sjkim        }
28168651Skris
282280297Sjkim        /* we now have a line with trailing \r\n removed */
28368651Skris
284280297Sjkim        /* i is the number of bytes */
285280297Sjkim        bufnum += i;
28668651Skris
287280297Sjkim        v = NULL;
288280297Sjkim        /* check for line continuation */
289280297Sjkim        if (bufnum >= 1) {
290280297Sjkim            /*
291280297Sjkim             * If we have bytes and the last char '\\' and second last char
292280297Sjkim             * is not '\\'
293280297Sjkim             */
294280297Sjkim            p = &(buff->data[bufnum - 1]);
295280297Sjkim            if (IS_ESC(conf, p[0]) && ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
296280297Sjkim                bufnum--;
297280297Sjkim                again = 1;
298280297Sjkim            }
299280297Sjkim        }
300280297Sjkim        if (again)
301280297Sjkim            continue;
302280297Sjkim        bufnum = 0;
303280297Sjkim        buf = buff->data;
30468651Skris
305280297Sjkim        clear_comments(conf, buf);
306280297Sjkim        s = eat_ws(conf, buf);
307280297Sjkim        if (IS_EOF(conf, *s))
308280297Sjkim            continue;           /* blank line */
309280297Sjkim        if (*s == '[') {
310280297Sjkim            char *ss;
31168651Skris
312280297Sjkim            s++;
313280297Sjkim            start = eat_ws(conf, s);
314280297Sjkim            ss = start;
315280297Sjkim again:
316280297Sjkim            end = eat_alpha_numeric(conf, ss);
317280297Sjkim            p = eat_ws(conf, end);
318280297Sjkim            if (*p != ']') {
319280297Sjkim                if (*p != '\0' && ss != p) {
320280297Sjkim                    ss = p;
321280297Sjkim                    goto again;
322280297Sjkim                }
323280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO,
324280297Sjkim                        CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
325280297Sjkim                goto err;
326280297Sjkim            }
327280297Sjkim            *end = '\0';
328280297Sjkim            if (!str_copy(conf, NULL, &section, start))
329280297Sjkim                goto err;
330280297Sjkim            if ((sv = _CONF_get_section(conf, section)) == NULL)
331280297Sjkim                sv = _CONF_new_section(conf, section);
332280297Sjkim            if (sv == NULL) {
333280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO,
334280297Sjkim                        CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
335280297Sjkim                goto err;
336280297Sjkim            }
337280297Sjkim            continue;
338280297Sjkim        } else {
339280297Sjkim            pname = s;
340280297Sjkim            psection = NULL;
341280297Sjkim            end = eat_alpha_numeric(conf, s);
342280297Sjkim            if ((end[0] == ':') && (end[1] == ':')) {
343280297Sjkim                *end = '\0';
344280297Sjkim                end += 2;
345280297Sjkim                psection = pname;
346280297Sjkim                pname = end;
347280297Sjkim                end = eat_alpha_numeric(conf, end);
348280297Sjkim            }
349280297Sjkim            p = eat_ws(conf, end);
350280297Sjkim            if (*p != '=') {
351280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO, CONF_R_MISSING_EQUAL_SIGN);
352280297Sjkim                goto err;
353280297Sjkim            }
354280297Sjkim            *end = '\0';
355280297Sjkim            p++;
356280297Sjkim            start = eat_ws(conf, p);
357280297Sjkim            while (!IS_EOF(conf, *p))
358280297Sjkim                p++;
359280297Sjkim            p--;
360280297Sjkim            while ((p != start) && (IS_WS(conf, *p)))
361280297Sjkim                p--;
362280297Sjkim            p++;
363280297Sjkim            *p = '\0';
36468651Skris
365280297Sjkim            if (!(v = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) {
366280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
367280297Sjkim                goto err;
368280297Sjkim            }
369280297Sjkim            if (psection == NULL)
370280297Sjkim                psection = section;
371280297Sjkim            v->name = (char *)OPENSSL_malloc(strlen(pname) + 1);
372280297Sjkim            v->value = NULL;
373280297Sjkim            if (v->name == NULL) {
374280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
375280297Sjkim                goto err;
376280297Sjkim            }
377280297Sjkim            BUF_strlcpy(v->name, pname, strlen(pname) + 1);
378280297Sjkim            if (!str_copy(conf, psection, &(v->value), start))
379280297Sjkim                goto err;
38068651Skris
381280297Sjkim            if (strcmp(psection, section) != 0) {
382280297Sjkim                if ((tv = _CONF_get_section(conf, psection))
383280297Sjkim                    == NULL)
384280297Sjkim                    tv = _CONF_new_section(conf, psection);
385280297Sjkim                if (tv == NULL) {
386280297Sjkim                    CONFerr(CONF_F_DEF_LOAD_BIO,
387280297Sjkim                            CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
388280297Sjkim                    goto err;
389280297Sjkim                }
390280297Sjkim            } else
391280297Sjkim                tv = sv;
39268651Skris#if 1
393280297Sjkim            if (_CONF_add_string(conf, tv, v) == 0) {
394280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
395280297Sjkim                goto err;
396280297Sjkim            }
39768651Skris#else
398280297Sjkim            v->section = tv->section;
399280297Sjkim            if (!sk_CONF_VALUE_push(ts, v)) {
400280297Sjkim                CONFerr(CONF_F_DEF_LOAD_BIO, ERR_R_MALLOC_FAILURE);
401280297Sjkim                goto err;
402280297Sjkim            }
403280297Sjkim            vv = (CONF_VALUE *)lh_insert(conf->data, v);
404280297Sjkim            if (vv != NULL) {
405280297Sjkim                sk_CONF_VALUE_delete_ptr(ts, vv);
406280297Sjkim                OPENSSL_free(vv->name);
407280297Sjkim                OPENSSL_free(vv->value);
408280297Sjkim                OPENSSL_free(vv);
409280297Sjkim            }
41068651Skris#endif
411280297Sjkim            v = NULL;
412280297Sjkim        }
413280297Sjkim    }
414280297Sjkim    if (buff != NULL)
415280297Sjkim        BUF_MEM_free(buff);
416280297Sjkim    if (section != NULL)
417280297Sjkim        OPENSSL_free(section);
418280297Sjkim    return (1);
419280297Sjkim err:
420280297Sjkim    if (buff != NULL)
421280297Sjkim        BUF_MEM_free(buff);
422280297Sjkim    if (section != NULL)
423280297Sjkim        OPENSSL_free(section);
424280297Sjkim    if (line != NULL)
425280297Sjkim        *line = eline;
426331638Sjkim    BIO_snprintf(btmp, sizeof(btmp), "%ld", eline);
427280297Sjkim    ERR_add_error_data(2, "line ", btmp);
428280297Sjkim    if ((h != conf->data) && (conf->data != NULL)) {
429280297Sjkim        CONF_free(conf->data);
430280297Sjkim        conf->data = NULL;
431280297Sjkim    }
432280297Sjkim    if (v != NULL) {
433280297Sjkim        if (v->name != NULL)
434280297Sjkim            OPENSSL_free(v->name);
435280297Sjkim        if (v->value != NULL)
436280297Sjkim            OPENSSL_free(v->value);
437280297Sjkim        if (v != NULL)
438280297Sjkim            OPENSSL_free(v);
439280297Sjkim    }
440280297Sjkim    return (0);
441280297Sjkim}
44268651Skris
44368651Skrisstatic void clear_comments(CONF *conf, char *p)
444280297Sjkim{
445280297Sjkim    for (;;) {
446280297Sjkim        if (IS_FCOMMENT(conf, *p)) {
447280297Sjkim            *p = '\0';
448280297Sjkim            return;
449280297Sjkim        }
450280297Sjkim        if (!IS_WS(conf, *p)) {
451280297Sjkim            break;
452280297Sjkim        }
453280297Sjkim        p++;
454280297Sjkim    }
45568651Skris
456280297Sjkim    for (;;) {
457280297Sjkim        if (IS_COMMENT(conf, *p)) {
458280297Sjkim            *p = '\0';
459280297Sjkim            return;
460280297Sjkim        }
461280297Sjkim        if (IS_DQUOTE(conf, *p)) {
462280297Sjkim            p = scan_dquote(conf, p);
463280297Sjkim            continue;
464280297Sjkim        }
465280297Sjkim        if (IS_QUOTE(conf, *p)) {
466280297Sjkim            p = scan_quote(conf, p);
467280297Sjkim            continue;
468280297Sjkim        }
469280297Sjkim        if (IS_ESC(conf, *p)) {
470280297Sjkim            p = scan_esc(conf, p);
471280297Sjkim            continue;
472280297Sjkim        }
473280297Sjkim        if (IS_EOF(conf, *p))
474280297Sjkim            return;
475280297Sjkim        else
476280297Sjkim            p++;
477280297Sjkim    }
478280297Sjkim}
47968651Skris
48068651Skrisstatic int str_copy(CONF *conf, char *section, char **pto, char *from)
481280297Sjkim{
482280297Sjkim    int q, r, rr = 0, to = 0, len = 0;
483280297Sjkim    char *s, *e, *rp, *p, *rrp, *np, *cp, v;
484280297Sjkim    BUF_MEM *buf;
48568651Skris
486280297Sjkim    if ((buf = BUF_MEM_new()) == NULL)
487280297Sjkim        return (0);
48868651Skris
489280297Sjkim    len = strlen(from) + 1;
490280297Sjkim    if (!BUF_MEM_grow(buf, len))
491280297Sjkim        goto err;
49268651Skris
493280297Sjkim    for (;;) {
494280297Sjkim        if (IS_QUOTE(conf, *from)) {
495280297Sjkim            q = *from;
496280297Sjkim            from++;
497280297Sjkim            while (!IS_EOF(conf, *from) && (*from != q)) {
498280297Sjkim                if (IS_ESC(conf, *from)) {
499280297Sjkim                    from++;
500280297Sjkim                    if (IS_EOF(conf, *from))
501280297Sjkim                        break;
502280297Sjkim                }
503280297Sjkim                buf->data[to++] = *(from++);
504280297Sjkim            }
505280297Sjkim            if (*from == q)
506280297Sjkim                from++;
507280297Sjkim        } else if (IS_DQUOTE(conf, *from)) {
508280297Sjkim            q = *from;
509280297Sjkim            from++;
510280297Sjkim            while (!IS_EOF(conf, *from)) {
511280297Sjkim                if (*from == q) {
512280297Sjkim                    if (*(from + 1) == q) {
513280297Sjkim                        from++;
514280297Sjkim                    } else {
515280297Sjkim                        break;
516280297Sjkim                    }
517280297Sjkim                }
518280297Sjkim                buf->data[to++] = *(from++);
519280297Sjkim            }
520280297Sjkim            if (*from == q)
521280297Sjkim                from++;
522280297Sjkim        } else if (IS_ESC(conf, *from)) {
523280297Sjkim            from++;
524280297Sjkim            v = *(from++);
525280297Sjkim            if (IS_EOF(conf, v))
526280297Sjkim                break;
527280297Sjkim            else if (v == 'r')
528280297Sjkim                v = '\r';
529280297Sjkim            else if (v == 'n')
530280297Sjkim                v = '\n';
531280297Sjkim            else if (v == 'b')
532280297Sjkim                v = '\b';
533280297Sjkim            else if (v == 't')
534280297Sjkim                v = '\t';
535280297Sjkim            buf->data[to++] = v;
536280297Sjkim        } else if (IS_EOF(conf, *from))
537280297Sjkim            break;
538280297Sjkim        else if (*from == '$') {
539325335Sjkim            size_t newsize;
540325335Sjkim
541280297Sjkim            /* try to expand it */
542280297Sjkim            rrp = NULL;
543280297Sjkim            s = &(from[1]);
544280297Sjkim            if (*s == '{')
545280297Sjkim                q = '}';
546280297Sjkim            else if (*s == '(')
547280297Sjkim                q = ')';
548280297Sjkim            else
549280297Sjkim                q = 0;
55068651Skris
551280297Sjkim            if (q)
552280297Sjkim                s++;
553280297Sjkim            cp = section;
554280297Sjkim            e = np = s;
555280297Sjkim            while (IS_ALPHA_NUMERIC(conf, *e))
556280297Sjkim                e++;
557280297Sjkim            if ((e[0] == ':') && (e[1] == ':')) {
558280297Sjkim                cp = np;
559280297Sjkim                rrp = e;
560280297Sjkim                rr = *e;
561280297Sjkim                *rrp = '\0';
562280297Sjkim                e += 2;
563280297Sjkim                np = e;
564280297Sjkim                while (IS_ALPHA_NUMERIC(conf, *e))
565280297Sjkim                    e++;
566280297Sjkim            }
567280297Sjkim            r = *e;
568280297Sjkim            *e = '\0';
569280297Sjkim            rp = e;
570280297Sjkim            if (q) {
571280297Sjkim                if (r != q) {
572280297Sjkim                    CONFerr(CONF_F_STR_COPY, CONF_R_NO_CLOSE_BRACE);
573280297Sjkim                    goto err;
574280297Sjkim                }
575280297Sjkim                e++;
576280297Sjkim            }
577280297Sjkim            /*-
578280297Sjkim             * So at this point we have
579280297Sjkim             * np which is the start of the name string which is
580280297Sjkim             *   '\0' terminated.
581280297Sjkim             * cp which is the start of the section string which is
582280297Sjkim             *   '\0' terminated.
583280297Sjkim             * e is the 'next point after'.
584280297Sjkim             * r and rr are the chars replaced by the '\0'
585280297Sjkim             * rp and rrp is where 'r' and 'rr' came from.
586280297Sjkim             */
587280297Sjkim            p = _CONF_get_string(conf, cp, np);
588280297Sjkim            if (rrp != NULL)
589280297Sjkim                *rrp = rr;
590280297Sjkim            *rp = r;
591280297Sjkim            if (p == NULL) {
592280297Sjkim                CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_HAS_NO_VALUE);
593280297Sjkim                goto err;
594280297Sjkim            }
595325335Sjkim            newsize = strlen(p) + buf->length - (e - from);
596325335Sjkim            if (newsize > MAX_CONF_VALUE_LENGTH) {
597325335Sjkim                CONFerr(CONF_F_STR_COPY, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
598325335Sjkim                goto err;
599325335Sjkim            }
600325335Sjkim            if (!BUF_MEM_grow_clean(buf, newsize)) {
601280297Sjkim                CONFerr(CONF_F_STR_COPY, ERR_R_MALLOC_FAILURE);
602280297Sjkim                goto err;
603280297Sjkim            }
604280297Sjkim            while (*p)
605280297Sjkim                buf->data[to++] = *(p++);
606142425Snectar
607280297Sjkim            /*
608280297Sjkim             * Since we change the pointer 'from', we also have to change the
609280297Sjkim             * perceived length of the string it points at.  /RL
610280297Sjkim             */
611280297Sjkim            len -= e - from;
612280297Sjkim            from = e;
613160814Ssimon
614280297Sjkim            /*
615280297Sjkim             * In case there were no braces or parenthesis around the
616280297Sjkim             * variable reference, we have to put back the character that was
617280297Sjkim             * replaced with a '\0'.  /RL
618280297Sjkim             */
619280297Sjkim            *rp = r;
620280297Sjkim        } else
621280297Sjkim            buf->data[to++] = *(from++);
622280297Sjkim    }
623280297Sjkim    buf->data[to] = '\0';
624280297Sjkim    if (*pto != NULL)
625280297Sjkim        OPENSSL_free(*pto);
626280297Sjkim    *pto = buf->data;
627280297Sjkim    OPENSSL_free(buf);
628280297Sjkim    return (1);
629280297Sjkim err:
630280297Sjkim    if (buf != NULL)
631280297Sjkim        BUF_MEM_free(buf);
632280297Sjkim    return (0);
633280297Sjkim}
63468651Skris
63568651Skrisstatic char *eat_ws(CONF *conf, char *p)
636280297Sjkim{
637280297Sjkim    while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
638280297Sjkim        p++;
639280297Sjkim    return (p);
640280297Sjkim}
64168651Skris
64268651Skrisstatic char *eat_alpha_numeric(CONF *conf, char *p)
643280297Sjkim{
644280297Sjkim    for (;;) {
645280297Sjkim        if (IS_ESC(conf, *p)) {
646280297Sjkim            p = scan_esc(conf, p);
647280297Sjkim            continue;
648280297Sjkim        }
649280297Sjkim        if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p))
650280297Sjkim            return (p);
651280297Sjkim        p++;
652280297Sjkim    }
653280297Sjkim}
65468651Skris
65568651Skrisstatic char *scan_quote(CONF *conf, char *p)
656280297Sjkim{
657280297Sjkim    int q = *p;
65868651Skris
659280297Sjkim    p++;
660280297Sjkim    while (!(IS_EOF(conf, *p)) && (*p != q)) {
661280297Sjkim        if (IS_ESC(conf, *p)) {
662280297Sjkim            p++;
663280297Sjkim            if (IS_EOF(conf, *p))
664280297Sjkim                return (p);
665280297Sjkim        }
666280297Sjkim        p++;
667280297Sjkim    }
668280297Sjkim    if (*p == q)
669280297Sjkim        p++;
670280297Sjkim    return (p);
671280297Sjkim}
67268651Skris
67368651Skrisstatic char *scan_dquote(CONF *conf, char *p)
674280297Sjkim{
675280297Sjkim    int q = *p;
67668651Skris
677280297Sjkim    p++;
678280297Sjkim    while (!(IS_EOF(conf, *p))) {
679280297Sjkim        if (*p == q) {
680280297Sjkim            if (*(p + 1) == q) {
681280297Sjkim                p++;
682280297Sjkim            } else {
683280297Sjkim                break;
684280297Sjkim            }
685280297Sjkim        }
686280297Sjkim        p++;
687280297Sjkim    }
688280297Sjkim    if (*p == q)
689280297Sjkim        p++;
690280297Sjkim    return (p);
691280297Sjkim}
69268651Skris
693238405Sjkimstatic void dump_value_doall_arg(CONF_VALUE *a, BIO *out)
694280297Sjkim{
695280297Sjkim    if (a->name)
696280297Sjkim        BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
697280297Sjkim    else
698280297Sjkim        BIO_printf(out, "[[%s]]\n", a->section);
699280297Sjkim}
70068651Skris
701238405Sjkimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE, BIO)
702109998Smarkm
703109998Smarkmstatic int def_dump(const CONF *conf, BIO *out)
704280297Sjkim{
705280297Sjkim    lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value),
706280297Sjkim                            BIO, out);
707280297Sjkim    return 1;
708280297Sjkim}
70968651Skris
710109998Smarkmstatic int def_is_number(const CONF *conf, char c)
711280297Sjkim{
712280297Sjkim    return IS_NUMBER(conf, c);
713280297Sjkim}
71468651Skris
715109998Smarkmstatic int def_to_int(const CONF *conf, char c)
716280297Sjkim{
717280297Sjkim    return c - '0';
718280297Sjkim}
719