xref: /dflybsd-src/crypto/libressl/crypto/conf/conf_def.c (revision cca6fc5243d2098262ea81f83ad5b28d3b800f4a)
1*cca6fc52SDaniel Fojt /* $OpenBSD: conf_def.c,v 1.33 2020/02/17 12:51:48 inoguchi Exp $ */
2f5b1c8a1SJohn Marino /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3f5b1c8a1SJohn Marino  * All rights reserved.
4f5b1c8a1SJohn Marino  *
5f5b1c8a1SJohn Marino  * This package is an SSL implementation written
6f5b1c8a1SJohn Marino  * by Eric Young (eay@cryptsoft.com).
7f5b1c8a1SJohn Marino  * The implementation was written so as to conform with Netscapes SSL.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * This library is free for commercial and non-commercial use as long as
10f5b1c8a1SJohn Marino  * the following conditions are aheared to.  The following conditions
11f5b1c8a1SJohn Marino  * apply to all code found in this distribution, be it the RC4, RSA,
12f5b1c8a1SJohn Marino  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13f5b1c8a1SJohn Marino  * included with this distribution is covered by the same copyright terms
14f5b1c8a1SJohn Marino  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * Copyright remains Eric Young's, and as such any Copyright notices in
17f5b1c8a1SJohn Marino  * the code are not to be removed.
18f5b1c8a1SJohn Marino  * If this package is used in a product, Eric Young should be given attribution
19f5b1c8a1SJohn Marino  * as the author of the parts of the library used.
20f5b1c8a1SJohn Marino  * This can be in the form of a textual message at program startup or
21f5b1c8a1SJohn Marino  * in documentation (online or textual) provided with the package.
22f5b1c8a1SJohn Marino  *
23f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
24f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
25f5b1c8a1SJohn Marino  * are met:
26f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the copyright
27f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
28f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
29f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
30f5b1c8a1SJohn Marino  *    documentation and/or other materials provided with the distribution.
31f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this software
32f5b1c8a1SJohn Marino  *    must display the following acknowledgement:
33f5b1c8a1SJohn Marino  *    "This product includes cryptographic software written by
34f5b1c8a1SJohn Marino  *     Eric Young (eay@cryptsoft.com)"
35f5b1c8a1SJohn Marino  *    The word 'cryptographic' can be left out if the rouines from the library
36f5b1c8a1SJohn Marino  *    being used are not cryptographic related :-).
37f5b1c8a1SJohn Marino  * 4. If you include any Windows specific code (or a derivative thereof) from
38f5b1c8a1SJohn Marino  *    the apps directory (application code) you must include an acknowledgement:
39f5b1c8a1SJohn Marino  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40f5b1c8a1SJohn Marino  *
41f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42f5b1c8a1SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44f5b1c8a1SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45f5b1c8a1SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46f5b1c8a1SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47f5b1c8a1SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49f5b1c8a1SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50f5b1c8a1SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51f5b1c8a1SJohn Marino  * SUCH DAMAGE.
52f5b1c8a1SJohn Marino  *
53f5b1c8a1SJohn Marino  * The licence and distribution terms for any publically available version or
54f5b1c8a1SJohn Marino  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55f5b1c8a1SJohn Marino  * copied and put under another distribution licence
56f5b1c8a1SJohn Marino  * [including the GNU Public Licence.]
57f5b1c8a1SJohn Marino  */
58f5b1c8a1SJohn Marino 
59f5b1c8a1SJohn Marino /* Part of the code in here was originally in conf.c, which is now removed */
60f5b1c8a1SJohn Marino 
61f5b1c8a1SJohn Marino #include <stdio.h>
62f5b1c8a1SJohn Marino #include <string.h>
63f5b1c8a1SJohn Marino 
64f5b1c8a1SJohn Marino #include <openssl/buffer.h>
65f5b1c8a1SJohn Marino #include <openssl/conf.h>
66f5b1c8a1SJohn Marino #include <openssl/conf_api.h>
67f5b1c8a1SJohn Marino #include <openssl/err.h>
68f5b1c8a1SJohn Marino #include <openssl/lhash.h>
69f5b1c8a1SJohn Marino #include <openssl/stack.h>
70f5b1c8a1SJohn Marino 
71f5b1c8a1SJohn Marino #include "conf_def.h"
72f5b1c8a1SJohn Marino 
73*cca6fc52SDaniel Fojt #define MAX_CONF_VALUE_LENGTH 65536
74*cca6fc52SDaniel Fojt 
75f5b1c8a1SJohn Marino static char *eat_ws(CONF *conf, char *p);
76f5b1c8a1SJohn Marino static char *eat_alpha_numeric(CONF *conf, char *p);
77f5b1c8a1SJohn Marino static void clear_comments(CONF *conf, char *p);
78f5b1c8a1SJohn Marino static int str_copy(CONF *conf, char *section, char **to, char *from);
79f5b1c8a1SJohn Marino static char *scan_quote(CONF *conf, char *p);
80f5b1c8a1SJohn Marino static char *scan_dquote(CONF *conf, char *p);
81f5b1c8a1SJohn Marino #define scan_esc(conf,p)	(((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
82f5b1c8a1SJohn Marino 
83f5b1c8a1SJohn Marino static CONF *def_create(CONF_METHOD *meth);
84f5b1c8a1SJohn Marino static int def_init_default(CONF *conf);
85f5b1c8a1SJohn Marino static int def_init_WIN32(CONF *conf);
86f5b1c8a1SJohn Marino static int def_destroy(CONF *conf);
87f5b1c8a1SJohn Marino static int def_destroy_data(CONF *conf);
88f5b1c8a1SJohn Marino static int def_load(CONF *conf, const char *name, long *eline);
89f5b1c8a1SJohn Marino static int def_load_bio(CONF *conf, BIO *bp, long *eline);
90f5b1c8a1SJohn Marino static int def_dump(const CONF *conf, BIO *bp);
91f5b1c8a1SJohn Marino static int def_is_number(const CONF *conf, char c);
92f5b1c8a1SJohn Marino static int def_to_int(const CONF *conf, char c);
93f5b1c8a1SJohn Marino 
94f5b1c8a1SJohn Marino static CONF_METHOD default_method = {
95f5b1c8a1SJohn Marino 	.name = "OpenSSL default",
96f5b1c8a1SJohn Marino 	.create = def_create,
97f5b1c8a1SJohn Marino 	.init = def_init_default,
98f5b1c8a1SJohn Marino 	.destroy = def_destroy,
99f5b1c8a1SJohn Marino 	.destroy_data = def_destroy_data,
100f5b1c8a1SJohn Marino 	.load_bio = def_load_bio,
101f5b1c8a1SJohn Marino 	.dump = def_dump,
102f5b1c8a1SJohn Marino 	.is_number = def_is_number,
103f5b1c8a1SJohn Marino 	.to_int = def_to_int,
104f5b1c8a1SJohn Marino 	.load = def_load
105f5b1c8a1SJohn Marino };
106f5b1c8a1SJohn Marino 
107f5b1c8a1SJohn Marino static CONF_METHOD WIN32_method = {
108f5b1c8a1SJohn Marino 	"WIN32",
109f5b1c8a1SJohn Marino 	def_create,
110f5b1c8a1SJohn Marino 	def_init_WIN32,
111f5b1c8a1SJohn Marino 	def_destroy,
112f5b1c8a1SJohn Marino 	def_destroy_data,
113f5b1c8a1SJohn Marino 	def_load_bio,
114f5b1c8a1SJohn Marino 	def_dump,
115f5b1c8a1SJohn Marino 	def_is_number,
116f5b1c8a1SJohn Marino 	def_to_int,
117f5b1c8a1SJohn Marino 	def_load
118f5b1c8a1SJohn Marino };
119f5b1c8a1SJohn Marino 
120f5b1c8a1SJohn Marino CONF_METHOD *
NCONF_default(void)121f5b1c8a1SJohn Marino NCONF_default(void)
122f5b1c8a1SJohn Marino {
123f5b1c8a1SJohn Marino 	return &default_method;
124f5b1c8a1SJohn Marino }
125f5b1c8a1SJohn Marino 
126f5b1c8a1SJohn Marino CONF_METHOD *
NCONF_WIN32(void)127f5b1c8a1SJohn Marino NCONF_WIN32(void)
128f5b1c8a1SJohn Marino {
129f5b1c8a1SJohn Marino 	return &WIN32_method;
130f5b1c8a1SJohn Marino }
131f5b1c8a1SJohn Marino 
132f5b1c8a1SJohn Marino static CONF *
def_create(CONF_METHOD * meth)133f5b1c8a1SJohn Marino def_create(CONF_METHOD *meth)
134f5b1c8a1SJohn Marino {
135f5b1c8a1SJohn Marino 	CONF *ret;
136f5b1c8a1SJohn Marino 
137f5b1c8a1SJohn Marino 	ret = malloc(sizeof(CONF) + sizeof(unsigned short *));
138f5b1c8a1SJohn Marino 	if (ret)
139f5b1c8a1SJohn Marino 		if (meth->init(ret) == 0) {
140f5b1c8a1SJohn Marino 			free(ret);
141f5b1c8a1SJohn Marino 			ret = NULL;
142f5b1c8a1SJohn Marino 		}
143f5b1c8a1SJohn Marino 	return ret;
144f5b1c8a1SJohn Marino }
145f5b1c8a1SJohn Marino 
146f5b1c8a1SJohn Marino static int
def_init_default(CONF * conf)147f5b1c8a1SJohn Marino def_init_default(CONF *conf)
148f5b1c8a1SJohn Marino {
149f5b1c8a1SJohn Marino 	if (conf == NULL)
150f5b1c8a1SJohn Marino 		return 0;
151f5b1c8a1SJohn Marino 
152f5b1c8a1SJohn Marino 	conf->meth = &default_method;
153f5b1c8a1SJohn Marino 	conf->meth_data = CONF_type_default;
154f5b1c8a1SJohn Marino 	conf->data = NULL;
155f5b1c8a1SJohn Marino 
156f5b1c8a1SJohn Marino 	return 1;
157f5b1c8a1SJohn Marino }
158f5b1c8a1SJohn Marino 
159f5b1c8a1SJohn Marino static int
def_init_WIN32(CONF * conf)160f5b1c8a1SJohn Marino def_init_WIN32(CONF *conf)
161f5b1c8a1SJohn Marino {
162f5b1c8a1SJohn Marino 	if (conf == NULL)
163f5b1c8a1SJohn Marino 		return 0;
164f5b1c8a1SJohn Marino 
165f5b1c8a1SJohn Marino 	conf->meth = &WIN32_method;
166f5b1c8a1SJohn Marino 	conf->meth_data = (void *)CONF_type_win32;
167f5b1c8a1SJohn Marino 	conf->data = NULL;
168f5b1c8a1SJohn Marino 
169f5b1c8a1SJohn Marino 	return 1;
170f5b1c8a1SJohn Marino }
171f5b1c8a1SJohn Marino 
172f5b1c8a1SJohn Marino static int
def_destroy(CONF * conf)173f5b1c8a1SJohn Marino def_destroy(CONF *conf)
174f5b1c8a1SJohn Marino {
175f5b1c8a1SJohn Marino 	if (def_destroy_data(conf)) {
176f5b1c8a1SJohn Marino 		free(conf);
177f5b1c8a1SJohn Marino 		return 1;
178f5b1c8a1SJohn Marino 	}
179f5b1c8a1SJohn Marino 	return 0;
180f5b1c8a1SJohn Marino }
181f5b1c8a1SJohn Marino 
182f5b1c8a1SJohn Marino static int
def_destroy_data(CONF * conf)183f5b1c8a1SJohn Marino def_destroy_data(CONF *conf)
184f5b1c8a1SJohn Marino {
185f5b1c8a1SJohn Marino 	if (conf == NULL)
186f5b1c8a1SJohn Marino 		return 0;
187f5b1c8a1SJohn Marino 	_CONF_free_data(conf);
188f5b1c8a1SJohn Marino 	return 1;
189f5b1c8a1SJohn Marino }
190f5b1c8a1SJohn Marino 
191f5b1c8a1SJohn Marino static int
def_load(CONF * conf,const char * name,long * line)192f5b1c8a1SJohn Marino def_load(CONF *conf, const char *name, long *line)
193f5b1c8a1SJohn Marino {
194f5b1c8a1SJohn Marino 	int ret;
195f5b1c8a1SJohn Marino 	BIO *in = NULL;
196f5b1c8a1SJohn Marino 
197f5b1c8a1SJohn Marino 	in = BIO_new_file(name, "rb");
198f5b1c8a1SJohn Marino 	if (in == NULL) {
199f5b1c8a1SJohn Marino 		if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
20072c33676SMaxim Ag 			CONFerror(CONF_R_NO_SUCH_FILE);
201f5b1c8a1SJohn Marino 		else
20272c33676SMaxim Ag 			CONFerror(ERR_R_SYS_LIB);
203f5b1c8a1SJohn Marino 		return 0;
204f5b1c8a1SJohn Marino 	}
205f5b1c8a1SJohn Marino 
206f5b1c8a1SJohn Marino 	ret = def_load_bio(conf, in, line);
207f5b1c8a1SJohn Marino 	BIO_free(in);
208f5b1c8a1SJohn Marino 
209f5b1c8a1SJohn Marino 	return ret;
210f5b1c8a1SJohn Marino }
211f5b1c8a1SJohn Marino 
212f5b1c8a1SJohn Marino static int
def_load_bio(CONF * conf,BIO * in,long * line)213f5b1c8a1SJohn Marino def_load_bio(CONF *conf, BIO *in, long *line)
214f5b1c8a1SJohn Marino {
215f5b1c8a1SJohn Marino /* The macro BUFSIZE conflicts with a system macro in VxWorks */
216f5b1c8a1SJohn Marino #define CONFBUFSIZE	512
217f5b1c8a1SJohn Marino 	int bufnum = 0, i, ii;
218f5b1c8a1SJohn Marino 	BUF_MEM *buff = NULL;
219f5b1c8a1SJohn Marino 	char *s, *p, *end;
220f5b1c8a1SJohn Marino 	int again;
221f5b1c8a1SJohn Marino 	long eline = 0;
222f5b1c8a1SJohn Marino 	CONF_VALUE *v = NULL, *tv;
223f5b1c8a1SJohn Marino 	CONF_VALUE *sv = NULL;
224f5b1c8a1SJohn Marino 	char *section = NULL, *buf;
225f5b1c8a1SJohn Marino 	char *start, *psection, *pname;
226f5b1c8a1SJohn Marino 	void *h = (void *)(conf->data);
227f5b1c8a1SJohn Marino 
228f5b1c8a1SJohn Marino 	if ((buff = BUF_MEM_new()) == NULL) {
22972c33676SMaxim Ag 		CONFerror(ERR_R_BUF_LIB);
230f5b1c8a1SJohn Marino 		goto err;
231f5b1c8a1SJohn Marino 	}
232f5b1c8a1SJohn Marino 
233f5b1c8a1SJohn Marino 	section = strdup("default");
234f5b1c8a1SJohn Marino 	if (section == NULL) {
23572c33676SMaxim Ag 		CONFerror(ERR_R_MALLOC_FAILURE);
236f5b1c8a1SJohn Marino 		goto err;
237f5b1c8a1SJohn Marino 	}
238f5b1c8a1SJohn Marino 
239f5b1c8a1SJohn Marino 	if (_CONF_new_data(conf) == 0) {
24072c33676SMaxim Ag 		CONFerror(ERR_R_MALLOC_FAILURE);
241f5b1c8a1SJohn Marino 		goto err;
242f5b1c8a1SJohn Marino 	}
243f5b1c8a1SJohn Marino 
244f5b1c8a1SJohn Marino 	sv = _CONF_new_section(conf, section);
245f5b1c8a1SJohn Marino 	if (sv == NULL) {
24672c33676SMaxim Ag 		CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
247f5b1c8a1SJohn Marino 		goto err;
248f5b1c8a1SJohn Marino 	}
249f5b1c8a1SJohn Marino 
250f5b1c8a1SJohn Marino 	bufnum = 0;
251f5b1c8a1SJohn Marino 	again = 0;
252f5b1c8a1SJohn Marino 	for (;;) {
253f5b1c8a1SJohn Marino 		if (!BUF_MEM_grow(buff, bufnum + CONFBUFSIZE)) {
25472c33676SMaxim Ag 			CONFerror(ERR_R_BUF_LIB);
255f5b1c8a1SJohn Marino 			goto err;
256f5b1c8a1SJohn Marino 		}
257f5b1c8a1SJohn Marino 		p = &(buff->data[bufnum]);
258f5b1c8a1SJohn Marino 		*p = '\0';
259f5b1c8a1SJohn Marino 		BIO_gets(in, p, CONFBUFSIZE - 1);
260f5b1c8a1SJohn Marino 		p[CONFBUFSIZE - 1] = '\0';
261f5b1c8a1SJohn Marino 		ii = i = strlen(p);
262f5b1c8a1SJohn Marino 		if (i == 0 && !again)
263f5b1c8a1SJohn Marino 			break;
264f5b1c8a1SJohn Marino 		again = 0;
265f5b1c8a1SJohn Marino 		while (i > 0) {
266f5b1c8a1SJohn Marino 			if ((p[i - 1] != '\r') && (p[i - 1] != '\n'))
267f5b1c8a1SJohn Marino 				break;
268f5b1c8a1SJohn Marino 			else
269f5b1c8a1SJohn Marino 				i--;
270f5b1c8a1SJohn Marino 		}
271f5b1c8a1SJohn Marino 		/* we removed some trailing stuff so there is a new
272f5b1c8a1SJohn Marino 		 * line on the end. */
273f5b1c8a1SJohn Marino 		if (ii && i == ii)
274f5b1c8a1SJohn Marino 			again = 1; /* long line */
275f5b1c8a1SJohn Marino 		else {
276f5b1c8a1SJohn Marino 			p[i] = '\0';
277f5b1c8a1SJohn Marino 			eline++; /* another input line */
278f5b1c8a1SJohn Marino 		}
279f5b1c8a1SJohn Marino 
280f5b1c8a1SJohn Marino 		/* we now have a line with trailing \r\n removed */
281f5b1c8a1SJohn Marino 
282f5b1c8a1SJohn Marino 		/* i is the number of bytes */
283f5b1c8a1SJohn Marino 		bufnum += i;
284f5b1c8a1SJohn Marino 
285f5b1c8a1SJohn Marino 		v = NULL;
286f5b1c8a1SJohn Marino 		/* check for line continuation */
287f5b1c8a1SJohn Marino 		if (bufnum >= 1) {
288f5b1c8a1SJohn Marino 			/* If we have bytes and the last char '\\' and
289f5b1c8a1SJohn Marino 			 * second last char is not '\\' */
290f5b1c8a1SJohn Marino 			p = &(buff->data[bufnum - 1]);
291f5b1c8a1SJohn Marino 			if (IS_ESC(conf, p[0]) &&
292f5b1c8a1SJohn Marino 			    ((bufnum <= 1) || !IS_ESC(conf, p[-1]))) {
293f5b1c8a1SJohn Marino 				bufnum--;
294f5b1c8a1SJohn Marino 				again = 1;
295f5b1c8a1SJohn Marino 			}
296f5b1c8a1SJohn Marino 		}
297f5b1c8a1SJohn Marino 		if (again)
298f5b1c8a1SJohn Marino 			continue;
299f5b1c8a1SJohn Marino 		bufnum = 0;
300f5b1c8a1SJohn Marino 		buf = buff->data;
301f5b1c8a1SJohn Marino 
302f5b1c8a1SJohn Marino 		clear_comments(conf, buf);
303f5b1c8a1SJohn Marino 		s = eat_ws(conf, buf);
304f5b1c8a1SJohn Marino 		if (IS_EOF(conf, *s))
305f5b1c8a1SJohn Marino 			continue; /* blank line */
306f5b1c8a1SJohn Marino 		if (*s == '[') {
307f5b1c8a1SJohn Marino 			char *ss;
308f5b1c8a1SJohn Marino 
309f5b1c8a1SJohn Marino 			s++;
310f5b1c8a1SJohn Marino 			start = eat_ws(conf, s);
311f5b1c8a1SJohn Marino 			ss = start;
312f5b1c8a1SJohn Marino again:
313f5b1c8a1SJohn Marino 			end = eat_alpha_numeric(conf, ss);
314f5b1c8a1SJohn Marino 			p = eat_ws(conf, end);
315f5b1c8a1SJohn Marino 			if (*p != ']') {
316f5b1c8a1SJohn Marino 				if (*p != '\0' && ss != p) {
317f5b1c8a1SJohn Marino 					ss = p;
318f5b1c8a1SJohn Marino 					goto again;
319f5b1c8a1SJohn Marino 				}
32072c33676SMaxim Ag 				CONFerror(CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
321f5b1c8a1SJohn Marino 				goto err;
322f5b1c8a1SJohn Marino 			}
323f5b1c8a1SJohn Marino 			*end = '\0';
324f5b1c8a1SJohn Marino 			if (!str_copy(conf, NULL, &section, start))
325f5b1c8a1SJohn Marino 				goto err;
326f5b1c8a1SJohn Marino 			if ((sv = _CONF_get_section(conf, section)) == NULL)
327f5b1c8a1SJohn Marino 				sv = _CONF_new_section(conf, section);
328f5b1c8a1SJohn Marino 			if (sv == NULL) {
32972c33676SMaxim Ag 				CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
330f5b1c8a1SJohn Marino 				goto err;
331f5b1c8a1SJohn Marino 			}
332f5b1c8a1SJohn Marino 			continue;
333f5b1c8a1SJohn Marino 		} else {
334f5b1c8a1SJohn Marino 			pname = s;
335f5b1c8a1SJohn Marino 			psection = NULL;
336f5b1c8a1SJohn Marino 			end = eat_alpha_numeric(conf, s);
337f5b1c8a1SJohn Marino 			if ((end[0] == ':') && (end[1] == ':')) {
338f5b1c8a1SJohn Marino 				*end = '\0';
339f5b1c8a1SJohn Marino 				end += 2;
340f5b1c8a1SJohn Marino 				psection = pname;
341f5b1c8a1SJohn Marino 				pname = end;
342f5b1c8a1SJohn Marino 				end = eat_alpha_numeric(conf, end);
343f5b1c8a1SJohn Marino 			}
344f5b1c8a1SJohn Marino 			p = eat_ws(conf, end);
345f5b1c8a1SJohn Marino 			if (*p != '=') {
34672c33676SMaxim Ag 				CONFerror(CONF_R_MISSING_EQUAL_SIGN);
347f5b1c8a1SJohn Marino 				goto err;
348f5b1c8a1SJohn Marino 			}
349f5b1c8a1SJohn Marino 			*end = '\0';
350f5b1c8a1SJohn Marino 			p++;
351f5b1c8a1SJohn Marino 			start = eat_ws(conf, p);
352f5b1c8a1SJohn Marino 			while (!IS_EOF(conf, *p))
353f5b1c8a1SJohn Marino 				p++;
354f5b1c8a1SJohn Marino 			p--;
355f5b1c8a1SJohn Marino 			while ((p != start) && (IS_WS(conf, *p)))
356f5b1c8a1SJohn Marino 				p--;
357f5b1c8a1SJohn Marino 			p++;
358f5b1c8a1SJohn Marino 			*p = '\0';
359f5b1c8a1SJohn Marino 
360f5b1c8a1SJohn Marino 			if (!(v = malloc(sizeof(CONF_VALUE)))) {
36172c33676SMaxim Ag 				CONFerror(ERR_R_MALLOC_FAILURE);
362f5b1c8a1SJohn Marino 				goto err;
363f5b1c8a1SJohn Marino 			}
364f5b1c8a1SJohn Marino 			if (psection == NULL)
365f5b1c8a1SJohn Marino 				psection = section;
366f5b1c8a1SJohn Marino 			v->name = strdup(pname);
367f5b1c8a1SJohn Marino 			v->value = NULL;
368f5b1c8a1SJohn Marino 			if (v->name == NULL) {
36972c33676SMaxim Ag 				CONFerror(ERR_R_MALLOC_FAILURE);
370f5b1c8a1SJohn Marino 				goto err;
371f5b1c8a1SJohn Marino 			}
372f5b1c8a1SJohn Marino 			if (!str_copy(conf, psection, &(v->value), start))
373f5b1c8a1SJohn Marino 				goto err;
374f5b1c8a1SJohn Marino 
375f5b1c8a1SJohn Marino 			if (strcmp(psection, section) != 0) {
376f5b1c8a1SJohn Marino 				if ((tv = _CONF_get_section(conf, psection))
377f5b1c8a1SJohn Marino 					== NULL)
378f5b1c8a1SJohn Marino 					tv = _CONF_new_section(conf, psection);
379f5b1c8a1SJohn Marino 				if (tv == NULL) {
38072c33676SMaxim Ag 					CONFerror(CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
381f5b1c8a1SJohn Marino 					goto err;
382f5b1c8a1SJohn Marino 				}
383f5b1c8a1SJohn Marino 			} else
384f5b1c8a1SJohn Marino 				tv = sv;
385f5b1c8a1SJohn Marino 
386f5b1c8a1SJohn Marino 			if (_CONF_add_string(conf, tv, v) == 0) {
38772c33676SMaxim Ag 				CONFerror(ERR_R_MALLOC_FAILURE);
388f5b1c8a1SJohn Marino 				goto err;
389f5b1c8a1SJohn Marino 			}
390f5b1c8a1SJohn Marino 			v = NULL;
391f5b1c8a1SJohn Marino 		}
392f5b1c8a1SJohn Marino 	}
393f5b1c8a1SJohn Marino 	if (buff != NULL)
394f5b1c8a1SJohn Marino 		BUF_MEM_free(buff);
395f5b1c8a1SJohn Marino 	free(section);
396f5b1c8a1SJohn Marino 	return (1);
397f5b1c8a1SJohn Marino 
398f5b1c8a1SJohn Marino err:
399f5b1c8a1SJohn Marino 	if (buff != NULL)
400f5b1c8a1SJohn Marino 		BUF_MEM_free(buff);
401f5b1c8a1SJohn Marino 	free(section);
402f5b1c8a1SJohn Marino 	if (line != NULL)
403f5b1c8a1SJohn Marino 		*line = eline;
404f5b1c8a1SJohn Marino 	ERR_asprintf_error_data("line %ld", eline);
405f5b1c8a1SJohn Marino 	if ((h != conf->data) && (conf->data != NULL)) {
406f5b1c8a1SJohn Marino 		CONF_free(conf->data);
407f5b1c8a1SJohn Marino 		conf->data = NULL;
408f5b1c8a1SJohn Marino 	}
409f5b1c8a1SJohn Marino 	if (v != NULL) {
410f5b1c8a1SJohn Marino 		free(v->name);
411f5b1c8a1SJohn Marino 		free(v->value);
412f5b1c8a1SJohn Marino 		free(v);
413f5b1c8a1SJohn Marino 	}
414f5b1c8a1SJohn Marino 	return (0);
415f5b1c8a1SJohn Marino }
416f5b1c8a1SJohn Marino 
417f5b1c8a1SJohn Marino static void
clear_comments(CONF * conf,char * p)418f5b1c8a1SJohn Marino clear_comments(CONF *conf, char *p)
419f5b1c8a1SJohn Marino {
420f5b1c8a1SJohn Marino 	for (;;) {
421f5b1c8a1SJohn Marino 		if (IS_FCOMMENT(conf, *p)) {
422f5b1c8a1SJohn Marino 			*p = '\0';
423f5b1c8a1SJohn Marino 			return;
424f5b1c8a1SJohn Marino 		}
425f5b1c8a1SJohn Marino 		if (!IS_WS(conf, *p)) {
426f5b1c8a1SJohn Marino 			break;
427f5b1c8a1SJohn Marino 		}
428f5b1c8a1SJohn Marino 		p++;
429f5b1c8a1SJohn Marino 	}
430f5b1c8a1SJohn Marino 
431f5b1c8a1SJohn Marino 	for (;;) {
432f5b1c8a1SJohn Marino 		if (IS_COMMENT(conf, *p)) {
433f5b1c8a1SJohn Marino 			*p = '\0';
434f5b1c8a1SJohn Marino 			return;
435f5b1c8a1SJohn Marino 		}
436f5b1c8a1SJohn Marino 		if (IS_DQUOTE(conf, *p)) {
437f5b1c8a1SJohn Marino 			p = scan_dquote(conf, p);
438f5b1c8a1SJohn Marino 			continue;
439f5b1c8a1SJohn Marino 		}
440f5b1c8a1SJohn Marino 		if (IS_QUOTE(conf, *p)) {
441f5b1c8a1SJohn Marino 			p = scan_quote(conf, p);
442f5b1c8a1SJohn Marino 			continue;
443f5b1c8a1SJohn Marino 		}
444f5b1c8a1SJohn Marino 		if (IS_ESC(conf, *p)) {
445f5b1c8a1SJohn Marino 			p = scan_esc(conf, p);
446f5b1c8a1SJohn Marino 			continue;
447f5b1c8a1SJohn Marino 		}
448f5b1c8a1SJohn Marino 		if (IS_EOF(conf, *p))
449f5b1c8a1SJohn Marino 			return;
450f5b1c8a1SJohn Marino 		else
451f5b1c8a1SJohn Marino 			p++;
452f5b1c8a1SJohn Marino 	}
453f5b1c8a1SJohn Marino }
454f5b1c8a1SJohn Marino 
455f5b1c8a1SJohn Marino static int
str_copy(CONF * conf,char * section,char ** pto,char * from)456f5b1c8a1SJohn Marino str_copy(CONF *conf, char *section, char **pto, char *from)
457f5b1c8a1SJohn Marino {
458f5b1c8a1SJohn Marino 	int q, r,rr = 0, to = 0, len = 0;
459f5b1c8a1SJohn Marino 	char *s, *e, *rp, *p, *rrp, *np, *cp, v;
460*cca6fc52SDaniel Fojt 	size_t newsize;
461f5b1c8a1SJohn Marino 	BUF_MEM *buf;
462f5b1c8a1SJohn Marino 
463f5b1c8a1SJohn Marino 	if ((buf = BUF_MEM_new()) == NULL)
464f5b1c8a1SJohn Marino 		return (0);
465f5b1c8a1SJohn Marino 
466f5b1c8a1SJohn Marino 	len = strlen(from) + 1;
467f5b1c8a1SJohn Marino 	if (!BUF_MEM_grow(buf, len))
468f5b1c8a1SJohn Marino 		goto err;
469f5b1c8a1SJohn Marino 
470f5b1c8a1SJohn Marino 	for (;;) {
471f5b1c8a1SJohn Marino 		if (IS_QUOTE(conf, *from)) {
472f5b1c8a1SJohn Marino 			q = *from;
473f5b1c8a1SJohn Marino 			from++;
474f5b1c8a1SJohn Marino 			while (!IS_EOF(conf, *from) && (*from != q)) {
475f5b1c8a1SJohn Marino 				if (IS_ESC(conf, *from)) {
476f5b1c8a1SJohn Marino 					from++;
477f5b1c8a1SJohn Marino 					if (IS_EOF(conf, *from))
478f5b1c8a1SJohn Marino 						break;
479f5b1c8a1SJohn Marino 				}
480f5b1c8a1SJohn Marino 				buf->data[to++] = *(from++);
481f5b1c8a1SJohn Marino 			}
482f5b1c8a1SJohn Marino 			if (*from == q)
483f5b1c8a1SJohn Marino 				from++;
484f5b1c8a1SJohn Marino 		} else if (IS_DQUOTE(conf, *from)) {
485f5b1c8a1SJohn Marino 			q = *from;
486f5b1c8a1SJohn Marino 			from++;
487f5b1c8a1SJohn Marino 			while (!IS_EOF(conf, *from)) {
488f5b1c8a1SJohn Marino 				if (*from == q) {
489f5b1c8a1SJohn Marino 					if (*(from + 1) == q) {
490f5b1c8a1SJohn Marino 						from++;
491f5b1c8a1SJohn Marino 					} else {
492f5b1c8a1SJohn Marino 						break;
493f5b1c8a1SJohn Marino 					}
494f5b1c8a1SJohn Marino 				}
495f5b1c8a1SJohn Marino 				buf->data[to++] = *(from++);
496f5b1c8a1SJohn Marino 			}
497f5b1c8a1SJohn Marino 			if (*from == q)
498f5b1c8a1SJohn Marino 				from++;
499f5b1c8a1SJohn Marino 		} else if (IS_ESC(conf, *from)) {
500f5b1c8a1SJohn Marino 			from++;
501f5b1c8a1SJohn Marino 			v = *(from++);
502f5b1c8a1SJohn Marino 			if (IS_EOF(conf, v))
503f5b1c8a1SJohn Marino 				break;
504f5b1c8a1SJohn Marino 			else if (v == 'r')
505f5b1c8a1SJohn Marino 				v = '\r';
506f5b1c8a1SJohn Marino 			else if (v == 'n')
507f5b1c8a1SJohn Marino 				v = '\n';
508f5b1c8a1SJohn Marino 			else if (v == 'b')
509f5b1c8a1SJohn Marino 				v = '\b';
510f5b1c8a1SJohn Marino 			else if (v == 't')
511f5b1c8a1SJohn Marino 				v = '\t';
512f5b1c8a1SJohn Marino 			buf->data[to++] = v;
513f5b1c8a1SJohn Marino 		} else if (IS_EOF(conf, *from))
514f5b1c8a1SJohn Marino 			break;
515f5b1c8a1SJohn Marino 		else if (*from == '$') {
516f5b1c8a1SJohn Marino 			/* try to expand it */
517f5b1c8a1SJohn Marino 			rrp = NULL;
518f5b1c8a1SJohn Marino 			s = &(from[1]);
519f5b1c8a1SJohn Marino 			if (*s == '{')
520f5b1c8a1SJohn Marino 				q = '}';
521f5b1c8a1SJohn Marino 			else if (*s == '(')
522f5b1c8a1SJohn Marino 				q = ')';
523f5b1c8a1SJohn Marino 			else
524f5b1c8a1SJohn Marino 				q = 0;
525f5b1c8a1SJohn Marino 
526f5b1c8a1SJohn Marino 			if (q)
527f5b1c8a1SJohn Marino 				s++;
528f5b1c8a1SJohn Marino 			cp = section;
529f5b1c8a1SJohn Marino 			e = np = s;
530f5b1c8a1SJohn Marino 			while (IS_ALPHA_NUMERIC(conf, *e))
531f5b1c8a1SJohn Marino 				e++;
532f5b1c8a1SJohn Marino 			if ((e[0] == ':') && (e[1] == ':')) {
533f5b1c8a1SJohn Marino 				cp = np;
534f5b1c8a1SJohn Marino 				rrp = e;
535f5b1c8a1SJohn Marino 				rr = *e;
536f5b1c8a1SJohn Marino 				*rrp = '\0';
537f5b1c8a1SJohn Marino 				e += 2;
538f5b1c8a1SJohn Marino 				np = e;
539f5b1c8a1SJohn Marino 				while (IS_ALPHA_NUMERIC(conf, *e))
540f5b1c8a1SJohn Marino 					e++;
541f5b1c8a1SJohn Marino 			}
542f5b1c8a1SJohn Marino 			r = *e;
543f5b1c8a1SJohn Marino 			*e = '\0';
544f5b1c8a1SJohn Marino 			rp = e;
545f5b1c8a1SJohn Marino 			if (q) {
546f5b1c8a1SJohn Marino 				if (r != q) {
54772c33676SMaxim Ag 					CONFerror(CONF_R_NO_CLOSE_BRACE);
548f5b1c8a1SJohn Marino 					goto err;
549f5b1c8a1SJohn Marino 				}
550f5b1c8a1SJohn Marino 				e++;
551f5b1c8a1SJohn Marino 			}
552f5b1c8a1SJohn Marino 			/* So at this point we have
553f5b1c8a1SJohn Marino 			 * np which is the start of the name string which is
554f5b1c8a1SJohn Marino 			 *   '\0' terminated.
555f5b1c8a1SJohn Marino 			 * cp which is the start of the section string which is
556f5b1c8a1SJohn Marino 			 *   '\0' terminated.
557f5b1c8a1SJohn Marino 			 * e is the 'next point after'.
558f5b1c8a1SJohn Marino 			 * r and rr are the chars replaced by the '\0'
559f5b1c8a1SJohn Marino 			 * rp and rrp is where 'r' and 'rr' came from.
560f5b1c8a1SJohn Marino 			 */
561f5b1c8a1SJohn Marino 			p = _CONF_get_string(conf, cp, np);
562f5b1c8a1SJohn Marino 			if (rrp != NULL)
563f5b1c8a1SJohn Marino 				*rrp = rr;
564f5b1c8a1SJohn Marino 			*rp = r;
565f5b1c8a1SJohn Marino 			if (p == NULL) {
56672c33676SMaxim Ag 				CONFerror(CONF_R_VARIABLE_HAS_NO_VALUE);
567f5b1c8a1SJohn Marino 				goto err;
568f5b1c8a1SJohn Marino 			}
569*cca6fc52SDaniel Fojt 			newsize = strlen(p) + buf->length - (e - from);
570*cca6fc52SDaniel Fojt 			if (newsize > MAX_CONF_VALUE_LENGTH) {
571*cca6fc52SDaniel Fojt 				CONFerror(CONF_R_VARIABLE_EXPANSION_TOO_LONG);
572*cca6fc52SDaniel Fojt 				goto err;
573*cca6fc52SDaniel Fojt 			}
574*cca6fc52SDaniel Fojt 			if (!BUF_MEM_grow_clean(buf, newsize)) {
57572c33676SMaxim Ag 				CONFerror(CONF_R_MODULE_INITIALIZATION_ERROR);
576f5b1c8a1SJohn Marino 				goto err;
577f5b1c8a1SJohn Marino 			}
578f5b1c8a1SJohn Marino 			while (*p)
579f5b1c8a1SJohn Marino 				buf->data[to++] = *(p++);
580f5b1c8a1SJohn Marino 
581f5b1c8a1SJohn Marino 			/* Since we change the pointer 'from', we also have
582f5b1c8a1SJohn Marino 			   to change the perceived length of the string it
583f5b1c8a1SJohn Marino 			   points at.  /RL */
584f5b1c8a1SJohn Marino 			len -= e - from;
585f5b1c8a1SJohn Marino 			from = e;
586f5b1c8a1SJohn Marino 
587f5b1c8a1SJohn Marino 			/* In case there were no braces or parenthesis around
588f5b1c8a1SJohn Marino 			   the variable reference, we have to put back the
589f5b1c8a1SJohn Marino 			   character that was replaced with a '\0'.  /RL */
590f5b1c8a1SJohn Marino 			*rp = r;
591f5b1c8a1SJohn Marino 		} else
592f5b1c8a1SJohn Marino 			buf->data[to++] = *(from++);
593f5b1c8a1SJohn Marino 	}
594f5b1c8a1SJohn Marino 	buf->data[to]='\0';
595f5b1c8a1SJohn Marino 	free(*pto);
596f5b1c8a1SJohn Marino 	*pto = buf->data;
597f5b1c8a1SJohn Marino 	free(buf);
598f5b1c8a1SJohn Marino 	return (1);
599f5b1c8a1SJohn Marino 
600f5b1c8a1SJohn Marino err:
601f5b1c8a1SJohn Marino 	if (buf != NULL)
602f5b1c8a1SJohn Marino 		BUF_MEM_free(buf);
603f5b1c8a1SJohn Marino 	return (0);
604f5b1c8a1SJohn Marino }
605f5b1c8a1SJohn Marino 
606f5b1c8a1SJohn Marino static char *
eat_ws(CONF * conf,char * p)607f5b1c8a1SJohn Marino eat_ws(CONF *conf, char *p)
608f5b1c8a1SJohn Marino {
609f5b1c8a1SJohn Marino 	while (IS_WS(conf, *p) && (!IS_EOF(conf, *p)))
610f5b1c8a1SJohn Marino 		p++;
611f5b1c8a1SJohn Marino 	return (p);
612f5b1c8a1SJohn Marino }
613f5b1c8a1SJohn Marino 
614f5b1c8a1SJohn Marino static char *
eat_alpha_numeric(CONF * conf,char * p)615f5b1c8a1SJohn Marino eat_alpha_numeric(CONF *conf, char *p)
616f5b1c8a1SJohn Marino {
617f5b1c8a1SJohn Marino 	for (;;) {
618f5b1c8a1SJohn Marino 		if (IS_ESC(conf, *p)) {
619f5b1c8a1SJohn Marino 			p = scan_esc(conf, p);
620f5b1c8a1SJohn Marino 			continue;
621f5b1c8a1SJohn Marino 		}
622f5b1c8a1SJohn Marino 		if (!IS_ALPHA_NUMERIC_PUNCT(conf, *p))
623f5b1c8a1SJohn Marino 			return (p);
624f5b1c8a1SJohn Marino 		p++;
625f5b1c8a1SJohn Marino 	}
626f5b1c8a1SJohn Marino }
627f5b1c8a1SJohn Marino 
628f5b1c8a1SJohn Marino static char *
scan_quote(CONF * conf,char * p)629f5b1c8a1SJohn Marino scan_quote(CONF *conf, char *p)
630f5b1c8a1SJohn Marino {
631f5b1c8a1SJohn Marino 	int q = *p;
632f5b1c8a1SJohn Marino 
633f5b1c8a1SJohn Marino 	p++;
634f5b1c8a1SJohn Marino 	while (!(IS_EOF(conf, *p)) && (*p != q)) {
635f5b1c8a1SJohn Marino 		if (IS_ESC(conf, *p)) {
636f5b1c8a1SJohn Marino 			p++;
637f5b1c8a1SJohn Marino 			if (IS_EOF(conf, *p))
638f5b1c8a1SJohn Marino 				return (p);
639f5b1c8a1SJohn Marino 		}
640f5b1c8a1SJohn Marino 		p++;
641f5b1c8a1SJohn Marino 	}
642f5b1c8a1SJohn Marino 	if (*p == q)
643f5b1c8a1SJohn Marino 		p++;
644f5b1c8a1SJohn Marino 	return (p);
645f5b1c8a1SJohn Marino }
646f5b1c8a1SJohn Marino 
647f5b1c8a1SJohn Marino 
648f5b1c8a1SJohn Marino static char *
scan_dquote(CONF * conf,char * p)649f5b1c8a1SJohn Marino scan_dquote(CONF *conf, char *p)
650f5b1c8a1SJohn Marino {
651f5b1c8a1SJohn Marino 	int q = *p;
652f5b1c8a1SJohn Marino 
653f5b1c8a1SJohn Marino 	p++;
654f5b1c8a1SJohn Marino 	while (!(IS_EOF(conf, *p))) {
655f5b1c8a1SJohn Marino 		if (*p == q) {
656f5b1c8a1SJohn Marino 			if (*(p + 1) == q) {
657f5b1c8a1SJohn Marino 				p++;
658f5b1c8a1SJohn Marino 			} else {
659f5b1c8a1SJohn Marino 				break;
660f5b1c8a1SJohn Marino 			}
661f5b1c8a1SJohn Marino 		}
662f5b1c8a1SJohn Marino 		p++;
663f5b1c8a1SJohn Marino 	}
664f5b1c8a1SJohn Marino 	if (*p == q)
665f5b1c8a1SJohn Marino 		p++;
666f5b1c8a1SJohn Marino 	return (p);
667f5b1c8a1SJohn Marino }
668f5b1c8a1SJohn Marino 
669f5b1c8a1SJohn Marino static void
dump_value_doall_arg(CONF_VALUE * a,BIO * out)670f5b1c8a1SJohn Marino dump_value_doall_arg(CONF_VALUE *a, BIO *out)
671f5b1c8a1SJohn Marino {
672f5b1c8a1SJohn Marino 	if (a->name)
673f5b1c8a1SJohn Marino 		BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
674f5b1c8a1SJohn Marino 	else
675f5b1c8a1SJohn Marino 		BIO_printf(out, "[[%s]]\n", a->section);
676f5b1c8a1SJohn Marino }
677f5b1c8a1SJohn Marino 
IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value,CONF_VALUE,BIO)678f5b1c8a1SJohn Marino static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE, BIO)
679f5b1c8a1SJohn Marino 
680f5b1c8a1SJohn Marino static int
681f5b1c8a1SJohn Marino def_dump(const CONF *conf, BIO *out)
682f5b1c8a1SJohn Marino {
683f5b1c8a1SJohn Marino 	lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value),
684f5b1c8a1SJohn Marino 	    BIO, out);
685f5b1c8a1SJohn Marino 	return 1;
686f5b1c8a1SJohn Marino }
687f5b1c8a1SJohn Marino 
688f5b1c8a1SJohn Marino static int
def_is_number(const CONF * conf,char c)689f5b1c8a1SJohn Marino def_is_number(const CONF *conf, char c)
690f5b1c8a1SJohn Marino {
691f5b1c8a1SJohn Marino 	return IS_NUMBER(conf, c);
692f5b1c8a1SJohn Marino }
693f5b1c8a1SJohn Marino 
694f5b1c8a1SJohn Marino static int
def_to_int(const CONF * conf,char c)695f5b1c8a1SJohn Marino def_to_int(const CONF *conf, char c)
696f5b1c8a1SJohn Marino {
697f5b1c8a1SJohn Marino 	return c - '0';
698f5b1c8a1SJohn Marino }
699