xref: /openbsd-src/lib/libcrypto/conf/conf_def.c (revision 140d1653cdffadc1170744856fd9e80e196b4f0a)
1*140d1653Stb /* $OpenBSD: conf_def.c,v 1.44 2024/08/31 09:46:17 tb Exp $ */
2c109e398Sbeck /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3c109e398Sbeck  * All rights reserved.
4c109e398Sbeck  *
5c109e398Sbeck  * This package is an SSL implementation written
6c109e398Sbeck  * by Eric Young (eay@cryptsoft.com).
7c109e398Sbeck  * The implementation was written so as to conform with Netscapes SSL.
8c109e398Sbeck  *
9c109e398Sbeck  * This library is free for commercial and non-commercial use as long as
10c109e398Sbeck  * the following conditions are aheared to.  The following conditions
11c109e398Sbeck  * apply to all code found in this distribution, be it the RC4, RSA,
12c109e398Sbeck  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13c109e398Sbeck  * included with this distribution is covered by the same copyright terms
14c109e398Sbeck  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15c109e398Sbeck  *
16c109e398Sbeck  * Copyright remains Eric Young's, and as such any Copyright notices in
17c109e398Sbeck  * the code are not to be removed.
18c109e398Sbeck  * If this package is used in a product, Eric Young should be given attribution
19c109e398Sbeck  * as the author of the parts of the library used.
20c109e398Sbeck  * This can be in the form of a textual message at program startup or
21c109e398Sbeck  * in documentation (online or textual) provided with the package.
22c109e398Sbeck  *
23c109e398Sbeck  * Redistribution and use in source and binary forms, with or without
24c109e398Sbeck  * modification, are permitted provided that the following conditions
25c109e398Sbeck  * are met:
26c109e398Sbeck  * 1. Redistributions of source code must retain the copyright
27c109e398Sbeck  *    notice, this list of conditions and the following disclaimer.
28c109e398Sbeck  * 2. Redistributions in binary form must reproduce the above copyright
29c109e398Sbeck  *    notice, this list of conditions and the following disclaimer in the
30c109e398Sbeck  *    documentation and/or other materials provided with the distribution.
31c109e398Sbeck  * 3. All advertising materials mentioning features or use of this software
32c109e398Sbeck  *    must display the following acknowledgement:
33c109e398Sbeck  *    "This product includes cryptographic software written by
34c109e398Sbeck  *     Eric Young (eay@cryptsoft.com)"
35c109e398Sbeck  *    The word 'cryptographic' can be left out if the rouines from the library
36c109e398Sbeck  *    being used are not cryptographic related :-).
37c109e398Sbeck  * 4. If you include any Windows specific code (or a derivative thereof) from
38c109e398Sbeck  *    the apps directory (application code) you must include an acknowledgement:
39c109e398Sbeck  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40c109e398Sbeck  *
41c109e398Sbeck  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42c109e398Sbeck  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43c109e398Sbeck  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44c109e398Sbeck  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45c109e398Sbeck  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46c109e398Sbeck  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47c109e398Sbeck  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48c109e398Sbeck  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49c109e398Sbeck  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50c109e398Sbeck  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51c109e398Sbeck  * SUCH DAMAGE.
52c109e398Sbeck  *
53c109e398Sbeck  * The licence and distribution terms for any publically available version or
54c109e398Sbeck  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55c109e398Sbeck  * copied and put under another distribution licence
56c109e398Sbeck  * [including the GNU Public Licence.]
57c109e398Sbeck  */
58c109e398Sbeck 
59c109e398Sbeck /* Part of the code in here was originally in conf.c, which is now removed */
60c109e398Sbeck 
61c109e398Sbeck #include <stdio.h>
62c109e398Sbeck #include <string.h>
63b6ab114eSjsing 
64b6ab114eSjsing #include <openssl/buffer.h>
65c109e398Sbeck #include <openssl/conf.h>
66c109e398Sbeck #include <openssl/err.h>
67b6ab114eSjsing #include <openssl/lhash.h>
68b6ab114eSjsing #include <openssl/stack.h>
69b6ab114eSjsing 
70b6ab114eSjsing #include "conf_def.h"
71a681313fStb #include "conf_local.h"
72c109e398Sbeck 
7336a7e084Sinoguchi #define MAX_CONF_VALUE_LENGTH 65536
7436a7e084Sinoguchi 
75c109e398Sbeck static char *eat_ws(CONF *conf, char *p);
76c109e398Sbeck static char *eat_alpha_numeric(CONF *conf, char *p);
77c109e398Sbeck static void clear_comments(CONF *conf, char *p);
78c109e398Sbeck static int str_copy(CONF *conf, char *section, char **to, char *from);
79c109e398Sbeck static char *scan_quote(CONF *conf, char *p);
80c109e398Sbeck static char *scan_dquote(CONF *conf, char *p);
81c109e398Sbeck #define scan_esc(conf,p)	(((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
82c109e398Sbeck 
8344486fcbSjsing static CONF *
849cc23e66Stb def_create(const CONF_METHOD *meth)
85c109e398Sbeck {
86c109e398Sbeck 	CONF *ret;
87c109e398Sbeck 
888b786cbaStb 	ret = calloc(1, sizeof(CONF) + sizeof(unsigned short *));
89c109e398Sbeck 	if (ret)
9044486fcbSjsing 		if (meth->init(ret) == 0) {
916f3a6cb1Sbeck 			free(ret);
92c109e398Sbeck 			ret = NULL;
93c109e398Sbeck 		}
94c109e398Sbeck 	return ret;
95c109e398Sbeck }
96c109e398Sbeck 
9744486fcbSjsing static int
9844486fcbSjsing def_init_default(CONF *conf)
99c109e398Sbeck {
100c109e398Sbeck 	if (conf == NULL)
101c109e398Sbeck 		return 0;
102c109e398Sbeck 
103ff9a56beStb 	conf->meth = NCONF_default();
104c109e398Sbeck 	conf->data = NULL;
105c109e398Sbeck 
106c109e398Sbeck 	return 1;
107c109e398Sbeck }
108c109e398Sbeck 
10944486fcbSjsing static int
11044486fcbSjsing def_destroy_data(CONF *conf)
111c109e398Sbeck {
112c109e398Sbeck 	if (conf == NULL)
113c109e398Sbeck 		return 0;
114c109e398Sbeck 	_CONF_free_data(conf);
115c109e398Sbeck 	return 1;
116c109e398Sbeck }
117c109e398Sbeck 
11844486fcbSjsing static int
119ff9a56beStb def_destroy(CONF *conf)
120da347917Sbeck {
121ff9a56beStb 	if (def_destroy_data(conf)) {
122ff9a56beStb 		free(conf);
123ff9a56beStb 		return 1;
124da347917Sbeck 	}
125ff9a56beStb 	return 0;
126da347917Sbeck }
127da347917Sbeck 
12844486fcbSjsing static int
12944486fcbSjsing def_load_bio(CONF *conf, BIO *in, long *line)
130c109e398Sbeck {
131767fe2ffSmarkus /* The macro BUFSIZE conflicts with a system macro in VxWorks */
132767fe2ffSmarkus #define CONFBUFSIZE	512
133c109e398Sbeck 	int bufnum = 0, i, ii;
134c109e398Sbeck 	BUF_MEM *buff = NULL;
135c109e398Sbeck 	char *s, *p, *end;
136c32db552Sdjm 	int again;
137c109e398Sbeck 	long eline = 0;
138c109e398Sbeck 	CONF_VALUE *v = NULL, *tv;
139c109e398Sbeck 	CONF_VALUE *sv = NULL;
140c109e398Sbeck 	char *section = NULL, *buf;
141c109e398Sbeck 	char *start, *psection, *pname;
142c109e398Sbeck 	void *h = (void *)(conf->data);
143c109e398Sbeck 
14444486fcbSjsing 	if ((buff = BUF_MEM_new()) == NULL) {
1455067ae9fSbeck 		CONFerror(ERR_R_BUF_LIB);
146c109e398Sbeck 		goto err;
147c109e398Sbeck 	}
148c109e398Sbeck 
149a5a50915Sderaadt 	section = strdup("default");
15044486fcbSjsing 	if (section == NULL) {
1515067ae9fSbeck 		CONFerror(ERR_R_MALLOC_FAILURE);
152c109e398Sbeck 		goto err;
153c109e398Sbeck 	}
154c109e398Sbeck 
15544486fcbSjsing 	if (_CONF_new_data(conf) == 0) {
1565067ae9fSbeck 		CONFerror(ERR_R_MALLOC_FAILURE);
157c109e398Sbeck 		goto err;
158c109e398Sbeck 	}
159c109e398Sbeck 
160c109e398Sbeck 	sv = _CONF_new_section(conf, section);
16144486fcbSjsing 	if (sv == NULL) {
1625067ae9fSbeck 		CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
163c109e398Sbeck 		goto err;
164c109e398Sbeck 	}
165c109e398Sbeck 
166c109e398Sbeck 	bufnum = 0;
167767fe2ffSmarkus 	again = 0;
16844486fcbSjsing 	for (;;) {
16944486fcbSjsing 		if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
1705067ae9fSbeck 			CONFerror(ERR_R_BUF_LIB);
171c109e398Sbeck 			goto err;
172c109e398Sbeck 		}
173c109e398Sbeck 		p = &(buff->data[bufnum]);
174c109e398Sbeck 		*p = '\0';
175767fe2ffSmarkus 		BIO_gets(in, p, CONFBUFSIZE - 1);
176767fe2ffSmarkus 		p[CONFBUFSIZE - 1] = '\0';
177c109e398Sbeck 		ii = i = strlen(p);
17844486fcbSjsing 		if (i == 0 && !again)
17944486fcbSjsing 			break;
180767fe2ffSmarkus 		again = 0;
18144486fcbSjsing 		while (i > 0) {
182c109e398Sbeck 			if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
183c109e398Sbeck 				break;
184c109e398Sbeck 			else
185c109e398Sbeck 				i--;
186c109e398Sbeck 		}
187c109e398Sbeck 		/* we removed some trailing stuff so there is a new
188c109e398Sbeck 		 * line on the end. */
189767fe2ffSmarkus 		if (ii && i == ii)
190c109e398Sbeck 			again = 1; /* long line */
19144486fcbSjsing 		else {
192c109e398Sbeck 			p[i] = '\0';
193c109e398Sbeck 			eline++; /* another input line */
194c109e398Sbeck 		}
195c109e398Sbeck 
196c109e398Sbeck 		/* we now have a line with trailing \r\n removed */
197c109e398Sbeck 
198c109e398Sbeck 		/* i is the number of bytes */
199c109e398Sbeck 		bufnum += i;
200c109e398Sbeck 
201c109e398Sbeck 		v = NULL;
202c109e398Sbeck 		/* check for line continuation */
20344486fcbSjsing 		if (bufnum >= 1) {
204c109e398Sbeck 			/* If we have bytes and the last char '\\' and
205c109e398Sbeck 			 * second last char is not '\\' */
206c109e398Sbeck 			p = &(buff->data[bufnum - 1]);
207c109e398Sbeck 			if (IS_ESC(conf, p[0]) &&
20844486fcbSjsing 			    ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
209c109e398Sbeck 				bufnum--;
210c109e398Sbeck 				again = 1;
211c109e398Sbeck 			}
212c109e398Sbeck 		}
21344486fcbSjsing 		if (again)
21444486fcbSjsing 			continue;
215c109e398Sbeck 		bufnum = 0;
216c109e398Sbeck 		buf = buff->data;
217c109e398Sbeck 
218c109e398Sbeck 		clear_comments(conf, buf);
219c109e398Sbeck 		s = eat_ws(conf, buf);
22044486fcbSjsing 		if (IS_EOF(conf, *s))
22144486fcbSjsing 			continue; /* blank line */
22244486fcbSjsing 		if (*s == '[') {
223c109e398Sbeck 			char *ss;
224c109e398Sbeck 
225c109e398Sbeck 			s++;
226c109e398Sbeck 			start = eat_ws(conf, s);
227c109e398Sbeck 			ss = start;
228c109e398Sbeck again:
229c109e398Sbeck 			end = eat_alpha_numeric(conf, ss);
230c109e398Sbeck 			p = eat_ws(conf, end);
23144486fcbSjsing 			if (*p != ']') {
232be6c5cc2Smiod 				if (*p != '\0' && ss != p) {
233c109e398Sbeck 					ss = p;
234c109e398Sbeck 					goto again;
235c109e398Sbeck 				}
2365067ae9fSbeck 				CONFerror(CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
237c109e398Sbeck 				goto err;
238c109e398Sbeck 			}
239c109e398Sbeck 			*end = '\0';
24044486fcbSjsing 			if (!str_copy(conf, NULL, &section, start))
24144486fcbSjsing 				goto err;
242c109e398Sbeck 			if ((sv = _CONF_get_section(conf, section)) == NULL)
243c109e398Sbeck 				sv = _CONF_new_section(conf, section);
24444486fcbSjsing 			if (sv == NULL) {
2455067ae9fSbeck 				CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
246c109e398Sbeck 				goto err;
247c109e398Sbeck 			}
248c109e398Sbeck 			continue;
24944486fcbSjsing 		} else {
250c109e398Sbeck 			pname = s;
251c109e398Sbeck 			psection = NULL;
252c109e398Sbeck 			end = eat_alpha_numeric(conf, s);
25344486fcbSjsing 			if ((end[0] == ':') && (end[1] == ':')) {
254c109e398Sbeck 				*end = '\0';
255c109e398Sbeck 				end += 2;
256c109e398Sbeck 				psection = pname;
257c109e398Sbeck 				pname = end;
258c109e398Sbeck 				end = eat_alpha_numeric(conf, end);
259c109e398Sbeck 			}
260c109e398Sbeck 			p = eat_ws(conf, end);
26144486fcbSjsing 			if (*p != '=') {
2625067ae9fSbeck 				CONFerror(CONF_R_MISSING_EQUAL_SIGN);
263c109e398Sbeck 				goto err;
264c109e398Sbeck 			}
265c109e398Sbeck 			*end = '\0';
266c109e398Sbeck 			p++;
267c109e398Sbeck 			start = eat_ws(conf, p);
268c109e398Sbeck 			while (!IS_EOF(conf, *p))
269c109e398Sbeck 				p++;
270c109e398Sbeck 			p--;
271c109e398Sbeck 			while ((p != start) && (IS_WS(conf, *p)))
272c109e398Sbeck 				p--;
273c109e398Sbeck 			p++;
274c109e398Sbeck 			*p = '\0';
275c109e398Sbeck 
2764163340bSderaadt 			if (!(v = malloc(sizeof(CONF_VALUE)))) {
2775067ae9fSbeck 				CONFerror(ERR_R_MALLOC_FAILURE);
278c109e398Sbeck 				goto err;
279c109e398Sbeck 			}
28044486fcbSjsing 			if (psection == NULL)
28144486fcbSjsing 				psection = section;
2824d168c75Sbcook 			v->name = strdup(pname);
283c109e398Sbeck 			v->value = NULL;
28444486fcbSjsing 			if (v->name == NULL) {
2855067ae9fSbeck 				CONFerror(ERR_R_MALLOC_FAILURE);
286c109e398Sbeck 				goto err;
287c109e398Sbeck 			}
28844486fcbSjsing 			if (!str_copy(conf, psection, &(v->value), start))
28944486fcbSjsing 				goto err;
290c109e398Sbeck 
29144486fcbSjsing 			if (strcmp(psection, section) != 0) {
292c109e398Sbeck 				if ((tv = _CONF_get_section(conf, psection))
293c109e398Sbeck 					== NULL)
294c109e398Sbeck 					tv = _CONF_new_section(conf, psection);
29544486fcbSjsing 				if (tv == NULL) {
2965067ae9fSbeck 					CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
297c109e398Sbeck 					goto err;
298c109e398Sbeck 				}
29944486fcbSjsing 			} else
300c109e398Sbeck 				tv = sv;
301700744f6Sdoug 
30244486fcbSjsing 			if (_CONF_add_string(conf, tv, v) == 0) {
3035067ae9fSbeck 				CONFerror(ERR_R_MALLOC_FAILURE);
304c109e398Sbeck 				goto err;
305c109e398Sbeck 			}
306c109e398Sbeck 			v = NULL;
307c109e398Sbeck 		}
308c109e398Sbeck 	}
30944486fcbSjsing 	if (buff != NULL)
31044486fcbSjsing 		BUF_MEM_free(buff);
31144486fcbSjsing 	free(section);
312c109e398Sbeck 	return (1);
31344486fcbSjsing 
314c109e398Sbeck err:
31544486fcbSjsing 	if (buff != NULL)
31644486fcbSjsing 		BUF_MEM_free(buff);
31744486fcbSjsing 	free(section);
31844486fcbSjsing 	if (line != NULL)
31944486fcbSjsing 		*line = eline;
3200f637b92Sbeck 	ERR_asprintf_error_data("line %ld", eline);
32144486fcbSjsing 	if ((h != conf->data) && (conf->data != NULL)) {
322*140d1653Stb 		CONF ctmp;
323*140d1653Stb 
324*140d1653Stb 		CONF_set_nconf(&ctmp, conf->data);
325*140d1653Stb 		ctmp.meth->destroy_data(&ctmp);
326da347917Sbeck 		conf->data = NULL;
327da347917Sbeck 	}
32844486fcbSjsing 	if (v != NULL) {
32944486fcbSjsing 		free(v->name);
33044486fcbSjsing 		free(v->value);
33144486fcbSjsing 		free(v);
332c109e398Sbeck 	}
333c109e398Sbeck 	return (0);
334c109e398Sbeck }
335c109e398Sbeck 
336ff9a56beStb static int
337ff9a56beStb def_load(CONF *conf, const char *name, long *line)
338ff9a56beStb {
339ff9a56beStb 	int ret;
340ff9a56beStb 	BIO *in = NULL;
341ff9a56beStb 
342ff9a56beStb 	in = BIO_new_file(name, "rb");
343ff9a56beStb 	if (in == NULL) {
344ff9a56beStb 		if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
345ff9a56beStb 			CONFerror(CONF_R_NO_SUCH_FILE);
346ff9a56beStb 		else
347ff9a56beStb 			CONFerror(ERR_R_SYS_LIB);
348ff9a56beStb 		return 0;
349ff9a56beStb 	}
350ff9a56beStb 
351ff9a56beStb 	ret = def_load_bio(conf, in, line);
352ff9a56beStb 	BIO_free(in);
353ff9a56beStb 
354ff9a56beStb 	return ret;
355ff9a56beStb }
356ff9a56beStb 
35744486fcbSjsing static void
35844486fcbSjsing clear_comments(CONF *conf, char *p)
359c109e398Sbeck {
36044486fcbSjsing 	for (;;) {
36144486fcbSjsing 		if (IS_FCOMMENT(conf, *p)) {
362c109e398Sbeck 			*p = '\0';
363c109e398Sbeck 			return;
364c109e398Sbeck 		}
36544486fcbSjsing 		if (!IS_WS(conf, *p)) {
366c109e398Sbeck 			break;
367c109e398Sbeck 		}
368c109e398Sbeck 		p++;
369c109e398Sbeck 	}
370c109e398Sbeck 
37144486fcbSjsing 	for (;;) {
37244486fcbSjsing 		if (IS_COMMENT(conf, *p)) {
373c109e398Sbeck 			*p = '\0';
374c109e398Sbeck 			return;
375c109e398Sbeck 		}
37644486fcbSjsing 		if (IS_DQUOTE(conf, *p)) {
377c109e398Sbeck 			p = scan_dquote(conf, p);
378c109e398Sbeck 			continue;
379c109e398Sbeck 		}
38044486fcbSjsing 		if (IS_QUOTE(conf, *p)) {
381c109e398Sbeck 			p = scan_quote(conf, p);
382c109e398Sbeck 			continue;
383c109e398Sbeck 		}
38444486fcbSjsing 		if (IS_ESC(conf, *p)) {
385c109e398Sbeck 			p = scan_esc(conf, p);
386c109e398Sbeck 			continue;
387c109e398Sbeck 		}
388c109e398Sbeck 		if (IS_EOF(conf, *p))
389c109e398Sbeck 			return;
390c109e398Sbeck 		else
391c109e398Sbeck 			p++;
392c109e398Sbeck 	}
393c109e398Sbeck }
394c109e398Sbeck 
39544486fcbSjsing static int
39644486fcbSjsing str_copy(CONF *conf, char *section, char **pto, char *from)
397c109e398Sbeck {
398c109e398Sbeck 	int q, r,rr = 0, to = 0, len = 0;
399c109e398Sbeck 	char *s, *e, *rp, *p, *rrp, *np, *cp, v;
40036a7e084Sinoguchi 	size_t newsize;
401c109e398Sbeck 	BUF_MEM *buf;
402c109e398Sbeck 
40344486fcbSjsing 	if ((buf = BUF_MEM_new()) == NULL)
40444486fcbSjsing 		return (0);
405c109e398Sbeck 
406c109e398Sbeck 	len = strlen(from) + 1;
40744486fcbSjsing 	if (!BUF_MEM_grow(buf, len))
40844486fcbSjsing 		goto err;
409c109e398Sbeck 
41044486fcbSjsing 	for (;;) {
41144486fcbSjsing 		if (IS_QUOTE(conf, *from)) {
412c109e398Sbeck 			q = *from;
413c109e398Sbeck 			from++;
41444486fcbSjsing 			while (!IS_EOF(conf, *from) && (*from != q)) {
41544486fcbSjsing 				if (IS_ESC(conf, *from)) {
416c109e398Sbeck 					from++;
41744486fcbSjsing 					if (IS_EOF(conf, *from))
41844486fcbSjsing 						break;
419c109e398Sbeck 				}
420c109e398Sbeck 				buf->data[to++] = *(from++);
421c109e398Sbeck 			}
42244486fcbSjsing 			if (*from == q)
42344486fcbSjsing 				from++;
42444486fcbSjsing 		} else if (IS_DQUOTE(conf, *from)) {
425c109e398Sbeck 			q = *from;
426c109e398Sbeck 			from++;
42744486fcbSjsing 			while (!IS_EOF(conf, *from)) {
42844486fcbSjsing 				if (*from == q) {
42944486fcbSjsing 					if (*(from + 1) == q) {
430c109e398Sbeck 						from++;
43144486fcbSjsing 					} else {
432c109e398Sbeck 						break;
433c109e398Sbeck 					}
434c109e398Sbeck 				}
435c109e398Sbeck 				buf->data[to++] = *(from++);
436c109e398Sbeck 			}
43744486fcbSjsing 			if (*from == q)
43844486fcbSjsing 				from++;
43944486fcbSjsing 		} else if (IS_ESC(conf, *from)) {
440c109e398Sbeck 			from++;
441c109e398Sbeck 			v = *(from++);
44244486fcbSjsing 			if (IS_EOF(conf, v))
443c109e398Sbeck 				break;
44444486fcbSjsing 			else if (v == 'r')
44544486fcbSjsing 				v = '\r';
44644486fcbSjsing 			else if (v == 'n')
44744486fcbSjsing 				v = '\n';
44844486fcbSjsing 			else if (v == 'b')
44944486fcbSjsing 				v = '\b';
45044486fcbSjsing 			else if (v == 't')
45144486fcbSjsing 				v = '\t';
45244486fcbSjsing 			buf->data[to++] = v;
45344486fcbSjsing 		} else if (IS_EOF(conf, *from))
45444486fcbSjsing 			break;
45544486fcbSjsing 		else if (*from == '$') {
456c109e398Sbeck 			/* try to expand it */
457c109e398Sbeck 			rrp = NULL;
458c109e398Sbeck 			s = &(from[1]);
459c109e398Sbeck 			if (*s == '{')
460c109e398Sbeck 				q = '}';
461c109e398Sbeck 			else if (*s == '(')
462c109e398Sbeck 				q = ')';
46344486fcbSjsing 			else
46444486fcbSjsing 				q = 0;
465c109e398Sbeck 
46644486fcbSjsing 			if (q)
46744486fcbSjsing 				s++;
468c109e398Sbeck 			cp = section;
469c109e398Sbeck 			e = np = s;
470c109e398Sbeck 			while (IS_ALPHA_NUMERIC(conf, *e))
471c109e398Sbeck 				e++;
47244486fcbSjsing 			if ((e[0] == ':') && (e[1] == ':')) {
473c109e398Sbeck 				cp = np;
474c109e398Sbeck 				rrp = e;
475c109e398Sbeck 				rr = *e;
476c109e398Sbeck 				*rrp = '\0';
477c109e398Sbeck 				e += 2;
478c109e398Sbeck 				np = e;
479c109e398Sbeck 				while (IS_ALPHA_NUMERIC(conf, *e))
480c109e398Sbeck 					e++;
481c109e398Sbeck 			}
482c109e398Sbeck 			r = *e;
483c109e398Sbeck 			*e = '\0';
484c109e398Sbeck 			rp = e;
48544486fcbSjsing 			if (q) {
48644486fcbSjsing 				if (r != q) {
4875067ae9fSbeck 					CONFerror(CONF_R_NO_CLOSE_BRACE);
488c109e398Sbeck 					goto err;
489c109e398Sbeck 				}
490c109e398Sbeck 				e++;
491c109e398Sbeck 			}
492c109e398Sbeck 			/* So at this point we have
4936d388760Sdjm 			 * np which is the start of the name string which is
494c109e398Sbeck 			 *   '\0' terminated.
4956d388760Sdjm 			 * cp which is the start of the section string which is
496c109e398Sbeck 			 *   '\0' terminated.
497c109e398Sbeck 			 * e is the 'next point after'.
4986d388760Sdjm 			 * r and rr are the chars replaced by the '\0'
4996d388760Sdjm 			 * rp and rrp is where 'r' and 'rr' came from.
500c109e398Sbeck 			 */
501c109e398Sbeck 			p = _CONF_get_string(conf, cp, np);
50244486fcbSjsing 			if (rrp != NULL)
50344486fcbSjsing 				*rrp = rr;
504c109e398Sbeck 			*rp = r;
50544486fcbSjsing 			if (p == NULL) {
5065067ae9fSbeck 				CONFerror(CONF_R_VARIABLE_HAS_NO_VALUE);
507c109e398Sbeck 				goto err;
508c109e398Sbeck 			}
50936a7e084Sinoguchi 			newsize = strlen(p) + buf->length - (e - from);
51036a7e084Sinoguchi 			if (newsize > MAX_CONF_VALUE_LENGTH) {
51136a7e084Sinoguchi 				CONFerror(CONF_R_VARIABLE_EXPANSION_TOO_LONG);
51236a7e084Sinoguchi 				goto err;
51336a7e084Sinoguchi 			}
51436a7e084Sinoguchi 			if (!BUF_MEM_grow_clean(buf, newsize)) {
5155067ae9fSbeck 				CONFerror(CONF_R_MODULE_INITIALIZATION_ERROR);
516f5619d72Sbeck 				goto err;
517f5619d72Sbeck 			}
518c109e398Sbeck 			while (*p)
519c109e398Sbeck 				buf->data[to++] = *(p++);
52040d8aef3Sdjm 
52140d8aef3Sdjm 			/* Since we change the pointer 'from', we also have
52240d8aef3Sdjm 			   to change the perceived length of the string it
52340d8aef3Sdjm 			   points at.  /RL */
52440d8aef3Sdjm 			len -= e - from;
525c109e398Sbeck 			from = e;
5266d388760Sdjm 
5276d388760Sdjm 			/* In case there were no braces or parenthesis around
5286d388760Sdjm 			   the variable reference, we have to put back the
5296d388760Sdjm 			   character that was replaced with a '\0'.  /RL */
5306d388760Sdjm 			*rp = r;
53144486fcbSjsing 		} else
532c109e398Sbeck 			buf->data[to++] = *(from++);
533c109e398Sbeck 	}
534c109e398Sbeck 	buf->data[to]='\0';
53544486fcbSjsing 	free(*pto);
536c109e398Sbeck 	*pto = buf->data;
5376f3a6cb1Sbeck 	free(buf);
538c109e398Sbeck 	return (1);
53944486fcbSjsing 
540c109e398Sbeck err:
54144486fcbSjsing 	if (buf != NULL)
54244486fcbSjsing 		BUF_MEM_free(buf);
543c109e398Sbeck 	return (0);
544c109e398Sbeck }
545c109e398Sbeck 
54644486fcbSjsing static char *
54744486fcbSjsing eat_ws(CONF *conf, char *p)
548c109e398Sbeck {
549c109e398Sbeck 	while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
550c109e398Sbeck 		p++;
551c109e398Sbeck 	return (p);
552c109e398Sbeck }
553c109e398Sbeck 
55444486fcbSjsing static char *
55544486fcbSjsing eat_alpha_numeric(CONF *conf, char *p)
556c109e398Sbeck {
55744486fcbSjsing 	for (;;) {
55844486fcbSjsing 		if (IS_ESC(conf, *p)) {
559c109e398Sbeck 			p = scan_esc(conf, p);
560c109e398Sbeck 			continue;
561c109e398Sbeck 		}
562c109e398Sbeck 		if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p))
563c109e398Sbeck 			return (p);
564c109e398Sbeck 		p++;
565c109e398Sbeck 	}
566c109e398Sbeck }
567c109e398Sbeck 
56844486fcbSjsing static char *
56944486fcbSjsing scan_quote(CONF *conf, char *p)
570c109e398Sbeck {
571c109e398Sbeck 	int q = *p;
572c109e398Sbeck 
573c109e398Sbeck 	p++;
57444486fcbSjsing 	while (!(IS_EOF(conf, *p)) && (*p != q)) {
57544486fcbSjsing 		if (IS_ESC(conf, *p)) {
576c109e398Sbeck 			p++;
57744486fcbSjsing 			if (IS_EOF(conf, *p))
57844486fcbSjsing 				return (p);
579c109e398Sbeck 		}
580c109e398Sbeck 		p++;
581c109e398Sbeck 	}
58244486fcbSjsing 	if (*p == q)
58344486fcbSjsing 		p++;
584c109e398Sbeck 	return (p);
585c109e398Sbeck }
586c109e398Sbeck 
587c109e398Sbeck 
58844486fcbSjsing static char *
58944486fcbSjsing scan_dquote(CONF *conf, char *p)
590c109e398Sbeck {
591c109e398Sbeck 	int q = *p;
592c109e398Sbeck 
593c109e398Sbeck 	p++;
59444486fcbSjsing 	while (!(IS_EOF(conf, *p))) {
59544486fcbSjsing 		if (*p == q) {
59644486fcbSjsing 			if (*(p + 1) == q) {
597c109e398Sbeck 				p++;
59844486fcbSjsing 			} else {
599c109e398Sbeck 				break;
600c109e398Sbeck 			}
601c109e398Sbeck 		}
602c109e398Sbeck 		p++;
603c109e398Sbeck 	}
60444486fcbSjsing 	if (*p == q)
60544486fcbSjsing 		p++;
606c109e398Sbeck 	return (p);
607c109e398Sbeck }
608c109e398Sbeck 
60944486fcbSjsing static void
61044486fcbSjsing dump_value_doall_arg(CONF_VALUE *a, BIO *out)
611c109e398Sbeck {
612c109e398Sbeck 	if (a->name)
613c109e398Sbeck 		BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
614c109e398Sbeck 	else
615c109e398Sbeck 		BIO_printf(out, "[[%s]]\n", a->section);
616c109e398Sbeck }
617c109e398Sbeck 
6180a5d6edeSdjm static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE, BIO)
619da347917Sbeck 
62044486fcbSjsing static int
62144486fcbSjsing def_dump(const CONF *conf, BIO *out)
622c109e398Sbeck {
6230a5d6edeSdjm 	lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value),
6240a5d6edeSdjm 	    BIO, out);
625c109e398Sbeck 	return 1;
626c109e398Sbeck }
627c109e398Sbeck 
62844486fcbSjsing static int
62944486fcbSjsing def_is_number(const CONF *conf, char c)
630c109e398Sbeck {
631c109e398Sbeck 	return IS_NUMBER(conf, c);
632c109e398Sbeck }
633c109e398Sbeck 
63444486fcbSjsing static int
63544486fcbSjsing def_to_int(const CONF *conf, char c)
636c109e398Sbeck {
637c109e398Sbeck 	return c - '0';
638c109e398Sbeck }
639ff9a56beStb 
6409cc23e66Stb static const CONF_METHOD default_method = {
641ff9a56beStb 	.name = "OpenSSL default",
642ff9a56beStb 	.create = def_create,
643ff9a56beStb 	.init = def_init_default,
644ff9a56beStb 	.destroy = def_destroy,
645ff9a56beStb 	.destroy_data = def_destroy_data,
646ff9a56beStb 	.load_bio = def_load_bio,
647ff9a56beStb 	.dump = def_dump,
648ff9a56beStb 	.is_number = def_is_number,
649ff9a56beStb 	.to_int = def_to_int,
650b6c247c1Stb 	.load = def_load,
651ff9a56beStb };
652ff9a56beStb 
6539cc23e66Stb const CONF_METHOD *
654ff9a56beStb NCONF_default(void)
655ff9a56beStb {
656ff9a56beStb 	return &default_method;
657ff9a56beStb }
658