1193323Sed/* crypto/conf/conf.c */
2193323Sed/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3193323Sed * All rights reserved.
4193323Sed *
5193323Sed * This package is an SSL implementation written
6193323Sed * by Eric Young (eay@cryptsoft.com).
7193323Sed * The implementation was written so as to conform with Netscapes SSL.
8193323Sed *
9193323Sed * This library is free for commercial and non-commercial use as long as
10193323Sed * the following conditions are aheared to.  The following conditions
11193323Sed * apply to all code found in this distribution, be it the RC4, RSA,
12193323Sed * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13193323Sed * included with this distribution is covered by the same copyright terms
14193323Sed * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15193323Sed *
16193323Sed * Copyright remains Eric Young's, and as such any Copyright notices in
17193323Sed * the code are not to be removed.
18193323Sed * If this package is used in a product, Eric Young should be given attribution
19249423Sdim * as the author of the parts of the library used.
20193323Sed * This can be in the form of a textual message at program startup or
21193323Sed * in documentation (online or textual) provided with the package.
22249423Sdim *
23249423Sdim * Redistribution and use in source and binary forms, with or without
24193323Sed * modification, are permitted provided that the following conditions
25193323Sed * are met:
26193323Sed * 1. Redistributions of source code must retain the copyright
27193323Sed *    notice, this list of conditions and the following disclaimer.
28193323Sed * 2. Redistributions in binary form must reproduce the above copyright
29193323Sed *    notice, this list of conditions and the following disclaimer in the
30193323Sed *    documentation and/or other materials provided with the distribution.
31193323Sed * 3. All advertising materials mentioning features or use of this software
32208599Srdivacky *    must display the following acknowledgement:
33249423Sdim *    "This product includes cryptographic software written by
34218893Sdim *     Eric Young (eay@cryptsoft.com)"
35193323Sed *    The word 'cryptographic' can be left out if the rouines from the library
36193323Sed *    being used are not cryptographic related :-).
37193323Sed * 4. If you include any Windows specific code (or a derivative thereof) from
38249423Sdim *    the apps directory (application code) you must include an acknowledgement:
39249423Sdim *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40234353Sdim *
41193323Sed * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42234353Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43234353Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44226633Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46239462Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47239462Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49249423Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50226633Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51193323Sed * SUCH DAMAGE.
52193323Sed *
53226633Sdim * The licence and distribution terms for any publically available version or
54193323Sed * derivative of this code cannot be changed.  i.e. this code cannot simply be
55193323Sed * copied and put under another distribution licence
56193323Sed * [including the GNU Public Licence.]
57226633Sdim */
58193323Sed
59193323Sed/* Part of the code in here was originally in conf.c, which is now removed */
60193323Sed
61226633Sdim#include <stdio.h>
62226633Sdim#include <string.h>
63193323Sed#include "cryptlib.h"
64193323Sed#include <openssl/stack.h>
65193323Sed#include <openssl/lhash.h>
66226633Sdim#include <openssl/conf.h>
67193323Sed#include <openssl/conf_api.h>
68193323Sed#include "conf_def.h"
69193323Sed#include <openssl/buffer.h>
70193323Sed#include <openssl/err.h>
71226633Sdim
72193323Sedstatic char *eat_ws(CONF *conf, char *p);
73193323Sedstatic char *eat_alpha_numeric(CONF *conf, char *p);
74193323Sedstatic void clear_comments(CONF *conf, char *p);
75207618Srdivackystatic int str_copy(CONF *conf,char *section,char **to, char *from);
76193323Sedstatic char *scan_quote(CONF *conf, char *p);
77226633Sdimstatic char *scan_dquote(CONF *conf, char *p);
78193323Sed#define scan_esc(conf,p)	(((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2)))
79193323Sed
80210299Sedstatic CONF *def_create(CONF_METHOD *meth);
81210299Sedstatic int def_init_default(CONF *conf);
82226633Sdimstatic int def_init_WIN32(CONF *conf);
83210299Sedstatic int def_destroy(CONF *conf);
84210299Sedstatic int def_destroy_data(CONF *conf);
85226633Sdimstatic int def_load(CONF *conf, const char *name, long *eline);
86226633Sdimstatic int def_load_bio(CONF *conf, BIO *bp, long *eline);
87226633Sdimstatic int def_dump(const CONF *conf, BIO *bp);
88226633Sdimstatic int def_is_number(const CONF *conf, char c);
89226633Sdimstatic int def_to_int(const CONF *conf, char c);
90226633Sdim
91226633Sdimconst char CONF_def_version[]="CONF_def" OPENSSL_VERSION_PTEXT;
92226633Sdim
93226633Sdimstatic CONF_METHOD default_method = {
94226633Sdim	"OpenSSL default",
95226633Sdim	def_create,
96226633Sdim	def_init_default,
97226633Sdim	def_destroy,
98226633Sdim	def_destroy_data,
99226633Sdim	def_load_bio,
100226633Sdim	def_dump,
101226633Sdim	def_is_number,
102193323Sed	def_to_int,
103193323Sed	def_load
104198090Srdivacky	};
105218893Sdim
106234353Sdimstatic CONF_METHOD WIN32_method = {
107193323Sed	"WIN32",
108193323Sed	def_create,
109193323Sed	def_init_WIN32,
110198090Srdivacky	def_destroy,
111193323Sed	def_destroy_data,
112193323Sed	def_load_bio,
113193323Sed	def_dump,
114193323Sed	def_is_number,
115193323Sed	def_to_int,
116193323Sed	def_load
117193323Sed	};
118193323Sed
119218893SdimCONF_METHOD *NCONF_default()
120193323Sed	{
121193323Sed	return &default_method;
122193323Sed	}
123203954SrdivackyCONF_METHOD *NCONF_WIN32()
124226633Sdim	{
125226633Sdim	return &WIN32_method;
126226633Sdim	}
127193323Sed
128193323Sedstatic CONF *def_create(CONF_METHOD *meth)
129226633Sdim	{
130223017Sdim	CONF *ret;
131223017Sdim
132226633Sdim	ret = OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *));
133226633Sdim	if (ret)
134223017Sdim		if (meth->init(ret) == 0)
135223017Sdim			{
136193323Sed			OPENSSL_free(ret);
137226633Sdim			ret = NULL;
138226633Sdim			}
139226633Sdim	return ret;
140193323Sed	}
141193323Sed
142226633Sdimstatic int def_init_default(CONF *conf)
143223017Sdim	{
144223017Sdim	if (conf == NULL)
145226633Sdim		return 0;
146223017Sdim
147223017Sdim	conf->meth = &default_method;
148226633Sdim	conf->meth_data = CONF_type_default;
149226633Sdim	conf->data = NULL;
150226633Sdim
151234353Sdim	return 1;
152226633Sdim	}
153193323Sed
154198090Srdivackystatic int def_init_WIN32(CONF *conf)
155239462Sdim	{
156239462Sdim	if (conf == NULL)
157239462Sdim		return 0;
158239462Sdim
159239462Sdim	conf->meth = &WIN32_method;
160239462Sdim	conf->meth_data = (void *)CONF_type_win32;
161239462Sdim	conf->data = NULL;
162239462Sdim
163239462Sdim	return 1;
164239462Sdim	}
165239462Sdim
166239462Sdimstatic int def_destroy(CONF *conf)
167226633Sdim	{
168226633Sdim	if (def_destroy_data(conf))
169226633Sdim		{
170226633Sdim		OPENSSL_free(conf);
171226633Sdim		return 1;
172193323Sed		}
173193323Sed	return 0;
174193323Sed	}
175193323Sed
176193323Sedstatic int def_destroy_data(CONF *conf)
177193323Sed	{
178193323Sed	if (conf == NULL)
179198090Srdivacky		return 0;
180224145Sdim	_CONF_free_data(conf);
181224145Sdim	return 1;
182224145Sdim	}
183224145Sdim
184224145Sdimstatic int def_load(CONF *conf, const char *name, long *line)
185224145Sdim	{
186224145Sdim	int ret;
187193323Sed	BIO *in=NULL;
188224145Sdim
189224145Sdim#ifdef OPENSSL_SYS_VMS
190224145Sdim	in=BIO_new_file(name, "r");
191193323Sed#else
192224145Sdim	in=BIO_new_file(name, "rb");
193218893Sdim#endif
194249423Sdim	if (in == NULL)
195234353Sdim		{
196193323Sed		if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE)
197193323Sed			CONFerr(CONF_F_DEF_LOAD,CONF_R_NO_SUCH_FILE);
198193323Sed		else
199224145Sdim			CONFerr(CONF_F_DEF_LOAD,ERR_R_SYS_LIB);
200224145Sdim		return 0;
201224145Sdim		}
202224145Sdim
203224145Sdim	ret = def_load_bio(conf, in, line);
204224145Sdim	BIO_free(in);
205193323Sed
206234353Sdim	return ret;
207234353Sdim	}
208234353Sdim
209234982Sdimstatic int def_load_bio(CONF *conf, BIO *in, long *line)
210234353Sdim	{
211234353Sdim/* The macro BUFSIZE conflicts with a system macro in VxWorks */
212234353Sdim#define CONFBUFSIZE	512
213193323Sed	int bufnum=0,i,ii;
214193323Sed	BUF_MEM *buff=NULL;
215193323Sed	char *s,*p,*end;
216193323Sed	int again;
217193323Sed	long eline=0;
218193323Sed	char btmp[DECIMAL_SIZE(eline)+1];
219224145Sdim	CONF_VALUE *v=NULL,*tv;
220193323Sed	CONF_VALUE *sv=NULL;
221193323Sed	char *section=NULL,*buf;
222193323Sed	char *start,*psection,*pname;
223224145Sdim	void *h = (void *)(conf->data);
224208599Srdivacky
225243830Sdim	if ((buff=BUF_MEM_new()) == NULL)
226243830Sdim		{
227243830Sdim		CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_BUF_LIB);
228193323Sed		goto err;
229193323Sed		}
230193323Sed
231224145Sdim	section=(char *)OPENSSL_malloc(10);
232193323Sed	if (section == NULL)
233193323Sed		{
234243830Sdim		CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_MALLOC_FAILURE);
235243830Sdim		goto err;
236193323Sed		}
237193323Sed	BUF_strlcpy(section,"default",10);
238193323Sed
239218893Sdim	if (_CONF_new_data(conf) == 0)
240218893Sdim		{
241218893Sdim		CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_MALLOC_FAILURE);
242218893Sdim		goto err;
243218893Sdim		}
244218893Sdim
245218893Sdim	sv=_CONF_new_section(conf,section);
246218893Sdim	if (sv == NULL)
247218893Sdim		{
248218893Sdim		CONFerr(CONF_F_DEF_LOAD_BIO,
249193323Sed					CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
250218893Sdim		goto err;
251218893Sdim		}
252218893Sdim
253218893Sdim	bufnum=0;
254218893Sdim	again=0;
255218893Sdim	for (;;)
256218893Sdim		{
257218893Sdim		if (!BUF_MEM_grow(buff,bufnum+CONFBUFSIZE))
258218893Sdim			{
259218893Sdim			CONFerr(CONF_F_DEF_LOAD_BIO,ERR_R_BUF_LIB);
260218893Sdim			goto err;
261193323Sed			}
262218893Sdim		p= &(buff->data[bufnum]);
263218893Sdim		*p='\0';
264218893Sdim		BIO_gets(in, p, CONFBUFSIZE-1);
265218893Sdim		p[CONFBUFSIZE-1]='\0';
266218893Sdim		ii=i=strlen(p);
267218893Sdim		if (i == 0 && !again) break;
268218893Sdim		again=0;
269218893Sdim		while (i > 0)
270218893Sdim			{
271218893Sdim			if ((p[i-1] != '\r') && (p[i-1] != '\n'))
272218893Sdim				break;
273218893Sdim			else
274218893Sdim				i--;
275218893Sdim			}
276193323Sed		/* we removed some trailing stuff so there is a new
277193323Sed		 * line on the end. */
278193323Sed		if (ii && i == ii)
279218893Sdim			again=1; /* long line */
280218893Sdim		else
281193323Sed			{
282193323Sed			p[i]='\0';
283193323Sed			eline++; /* another input line */
284193323Sed			}
285193323Sed
286218893Sdim		/* we now have a line with trailing \r\n removed */
287218893Sdim
288193323Sed		/* i is the number of bytes */
289193323Sed		bufnum+=i;
290218893Sdim
291218893Sdim		v=NULL;
292218893Sdim		/* check for line continuation */
293218893Sdim		if (bufnum >= 1)
294223017Sdim			{
295218893Sdim			/* If we have bytes and the last char '\\' and
296218893Sdim			 * second last char is not '\\' */
297218893Sdim			p= &(buff->data[bufnum-1]);
298218893Sdim			if (IS_ESC(conf,p[0]) &&
299218893Sdim				((bufnum <= 1) || !IS_ESC(conf,p[-1])))
300223017Sdim				{
301218893Sdim				bufnum--;
302218893Sdim				again=1;
303210299Sed				}
304210299Sed			}
305210299Sed		if (again) continue;
306210299Sed		bufnum=0;
307210299Sed		buf=buff->data;
308193323Sed
309239462Sdim		clear_comments(conf, buf);
310239462Sdim		s=eat_ws(conf, buf);
311239462Sdim		if (IS_EOF(conf,*s)) continue; /* blank line */
312239462Sdim		if (*s == '[')
313239462Sdim			{
314193323Sed			char *ss;
315193323Sed
316193323Sed			s++;
317198090Srdivacky			start=eat_ws(conf, s);
318193323Sed			ss=start;
319193323Sedagain:
320221345Sdim			end=eat_alpha_numeric(conf, ss);
321221345Sdim			p=eat_ws(conf, end);
322221345Sdim			if (*p != ']')
323224145Sdim				{
324221345Sdim				if (*p != '\0' && ss != p)
325221345Sdim					{
326224145Sdim					ss=p;
327224145Sdim					goto again;
328224145Sdim					}
329224145Sdim				CONFerr(CONF_F_DEF_LOAD_BIO,
330193323Sed					CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
331193323Sed				goto err;
332208599Srdivacky				}
333208599Srdivacky			*end='\0';
334208599Srdivacky			if (!str_copy(conf,NULL,&section,start)) goto err;
335243830Sdim			if ((sv=_CONF_get_section(conf,section)) == NULL)
336243830Sdim				sv=_CONF_new_section(conf,section);
337208599Srdivacky			if (sv == NULL)
338208599Srdivacky				{
339208599Srdivacky				CONFerr(CONF_F_DEF_LOAD_BIO,
340243830Sdim					CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
341243830Sdim				goto err;
342243830Sdim				}
343243830Sdim			continue;
344243830Sdim			}
345243830Sdim		else
346243830Sdim			{
347243830Sdim			pname=s;
348243830Sdim			psection=NULL;
349243830Sdim			end=eat_alpha_numeric(conf, s);
350243830Sdim			if ((end[0] == ':') && (end[1] == ':'))
351243830Sdim				{
352243830Sdim				*end='\0';
353243830Sdim				end+=2;
354243830Sdim				psection=pname;
355243830Sdim				pname=end;
356243830Sdim				end=eat_alpha_numeric(conf, end);
357243830Sdim				}
358243830Sdim			p=eat_ws(conf, end);
359243830Sdim			if (*p != '=')
360243830Sdim				{
361243830Sdim				CONFerr(CONF_F_DEF_LOAD_BIO,
362243830Sdim						CONF_R_MISSING_EQUAL_SIGN);
363243830Sdim				goto err;
364243830Sdim				}
365198090Srdivacky			*end='\0';
366198090Srdivacky			p++;
367198090Srdivacky			start=eat_ws(conf, p);
368224145Sdim			while (!IS_EOF(conf,*p))
369198090Srdivacky				p++;
370198090Srdivacky			p--;
371239462Sdim			while ((p != start) && (IS_WS(conf,*p)))
372239462Sdim				p--;
373239462Sdim			p++;
374239462Sdim			*p='\0';
375239462Sdim
376239462Sdim			if (!(v=(CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE))))
377239462Sdim				{
378239462Sdim				CONFerr(CONF_F_DEF_LOAD_BIO,
379239462Sdim							ERR_R_MALLOC_FAILURE);
380193323Sed				goto err;
381193323Sed				}
382193323Sed			if (psection == NULL) psection=section;
383239462Sdim			v->name=(char *)OPENSSL_malloc(strlen(pname)+1);
384239462Sdim			v->value=NULL;
385239462Sdim			if (v->name == NULL)
386239462Sdim				{
387239462Sdim				CONFerr(CONF_F_DEF_LOAD_BIO,
388239462Sdim							ERR_R_MALLOC_FAILURE);
389239462Sdim				goto err;
390239462Sdim				}
391193323Sed			BUF_strlcpy(v->name,pname,strlen(pname)+1);
392193323Sed			if (!str_copy(conf,psection,&(v->value),start)) goto err;
393193323Sed
394234353Sdim			if (strcmp(psection,section) != 0)
395234353Sdim				{
396249423Sdim				if ((tv=_CONF_get_section(conf,psection))
397193323Sed					== NULL)
398193323Sed					tv=_CONF_new_section(conf,psection);
399234353Sdim				if (tv == NULL)
400234353Sdim					{
401234353Sdim					CONFerr(CONF_F_DEF_LOAD_BIO,
402234353Sdim					   CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
403234353Sdim					goto err;
404234353Sdim					}
405234353Sdim				}
406234353Sdim			else
407234353Sdim				tv=sv;
408234353Sdim#if 1
409234353Sdim			if (_CONF_add_string(conf, tv, v) == 0)
410234353Sdim				{
411234353Sdim				CONFerr(CONF_F_DEF_LOAD_BIO,
412234353Sdim							ERR_R_MALLOC_FAILURE);
413234353Sdim				goto err;
414234353Sdim				}
415234353Sdim#else
416234353Sdim			v->section=tv->section;
417234353Sdim			if (!sk_CONF_VALUE_push(ts,v))
418234353Sdim				{
419234353Sdim				CONFerr(CONF_F_DEF_LOAD_BIO,
420234353Sdim							ERR_R_MALLOC_FAILURE);
421193323Sed				goto err;
422193323Sed				}
423193323Sed			vv=(CONF_VALUE *)lh_insert(conf->data,v);
424193323Sed			if (vv != NULL)
425193323Sed				{
426193323Sed				sk_CONF_VALUE_delete_ptr(ts,vv);
427193323Sed				OPENSSL_free(vv->name);
428193323Sed				OPENSSL_free(vv->value);
429193323Sed				OPENSSL_free(vv);
430198090Srdivacky				}
431193323Sed#endif
432234353Sdim			v=NULL;
433193323Sed			}
434193323Sed		}
435198090Srdivacky	if (buff != NULL) BUF_MEM_free(buff);
436198090Srdivacky	if (section != NULL) OPENSSL_free(section);
437198090Srdivacky	return(1);
438234353Sdimerr:
439234353Sdim	if (buff != NULL) BUF_MEM_free(buff);
440198090Srdivacky	if (section != NULL) OPENSSL_free(section);
441198090Srdivacky	if (line != NULL) *line=eline;
442239462Sdim	BIO_snprintf(btmp,sizeof btmp,"%ld",eline);
443198090Srdivacky	ERR_add_error_data(2,"line ",btmp);
444226633Sdim	if ((h != conf->data) && (conf->data != NULL))
445226633Sdim		{
446226633Sdim		CONF_free(conf->data);
447226633Sdim		conf->data=NULL;
448226633Sdim		}
449226633Sdim	if (v != NULL)
450226633Sdim		{
451226633Sdim		if (v->name != NULL) OPENSSL_free(v->name);
452226633Sdim		if (v->value != NULL) OPENSSL_free(v->value);
453226633Sdim		if (v != NULL) OPENSSL_free(v);
454226633Sdim		}
455234353Sdim	return(0);
456226633Sdim	}
457239462Sdim
458239462Sdimstatic void clear_comments(CONF *conf, char *p)
459239462Sdim	{
460239462Sdim	for (;;)
461226633Sdim		{
462210299Sed		if (IS_FCOMMENT(conf,*p))
463210299Sed			{
464210299Sed			*p='\0';
465243830Sdim			return;
466243830Sdim			}
467210299Sed		if (!IS_WS(conf,*p))
468210299Sed			{
469210299Sed			break;
470210299Sed			}
471210299Sed		p++;
472210299Sed		}
473210299Sed
474210299Sed	for (;;)
475210299Sed		{
476243830Sdim		if (IS_COMMENT(conf,*p))
477243830Sdim			{
478243830Sdim			*p='\0';
479243830Sdim			return;
480210299Sed			}
481210299Sed		if (IS_DQUOTE(conf,*p))
482243830Sdim			{
483243830Sdim			p=scan_dquote(conf, p);
484243830Sdim			continue;
485243830Sdim			}
486243830Sdim		if (IS_QUOTE(conf,*p))
487243830Sdim			{
488243830Sdim			p=scan_quote(conf, p);
489239462Sdim			continue;
490239462Sdim			}
491239462Sdim		if (IS_ESC(conf,*p))
492239462Sdim			{
493239462Sdim			p=scan_esc(conf,p);
494239462Sdim			continue;
495239462Sdim			}
496239462Sdim		if (IS_EOF(conf,*p))
497239462Sdim			return;
498239462Sdim		else
499239462Sdim			p++;
500239462Sdim		}
501239462Sdim	}
502239462Sdim
503239462Sdimstatic int str_copy(CONF *conf, char *section, char **pto, char *from)
504239462Sdim	{
505239462Sdim	int q,r,rr=0,to=0,len=0;
506239462Sdim	char *s,*e,*rp,*p,*rrp,*np,*cp,v;
507239462Sdim	BUF_MEM *buf;
508239462Sdim
509239462Sdim	if ((buf=BUF_MEM_new()) == NULL) return(0);
510239462Sdim
511239462Sdim	len=strlen(from)+1;
512239462Sdim	if (!BUF_MEM_grow(buf,len)) goto err;
513239462Sdim
514239462Sdim	for (;;)
515239462Sdim		{
516239462Sdim		if (IS_QUOTE(conf,*from))
517193323Sed			{
518193323Sed			q= *from;
519193323Sed			from++;
520193323Sed			while (!IS_EOF(conf,*from) && (*from != q))
521193323Sed				{
522193323Sed				if (IS_ESC(conf,*from))
523193323Sed					{
524193323Sed					from++;
525193323Sed					if (IS_EOF(conf,*from)) break;
526193323Sed					}
527193323Sed				buf->data[to++]= *(from++);
528193323Sed				}
529198090Srdivacky			if (*from == q) from++;
530193323Sed			}
531224145Sdim		else if (IS_DQUOTE(conf,*from))
532193323Sed			{
533210299Sed			q= *from;
534210299Sed			from++;
535193323Sed			while (!IS_EOF(conf,*from))
536193323Sed				{
537226633Sdim				if (*from == q)
538226633Sdim					{
539226633Sdim					if (*(from+1) == q)
540226633Sdim						{
541226633Sdim						from++;
542226633Sdim						}
543193323Sed					else
544198090Srdivacky						{
545198090Srdivacky						break;
546239462Sdim						}
547239462Sdim					}
548234353Sdim				buf->data[to++]= *(from++);
549193323Sed				}
550193323Sed			if (*from == q) from++;
551193323Sed			}
552221345Sdim		else if (IS_ESC(conf,*from))
553221345Sdim			{
554221345Sdim			from++;
555221345Sdim			v= *(from++);
556193323Sed			if (IS_EOF(conf,v)) break;
557193323Sed			else if (v == 'r') v='\r';
558221345Sdim			else if (v == 'n') v='\n';
559193323Sed			else if (v == 'b') v='\b';
560193323Sed			else if (v == 't') v='\t';
561221345Sdim			buf->data[to++]= v;
562221345Sdim			}
563221345Sdim		else if (IS_EOF(conf,*from))
564221345Sdim			break;
565221345Sdim		else if (*from == '$')
566221345Sdim			{
567221345Sdim			/* try to expand it */
568221345Sdim			rrp=NULL;
569221345Sdim			s= &(from[1]);
570221345Sdim			if (*s == '{')
571221345Sdim				q='}';
572221345Sdim			else if (*s == '(')
573221345Sdim				q=')';
574221345Sdim			else q=0;
575234353Sdim
576234353Sdim			if (q) s++;
577234353Sdim			cp=section;
578221345Sdim			e=np=s;
579221345Sdim			while (IS_ALPHA_NUMERIC(conf,*e))
580221345Sdim				e++;
581221345Sdim			if ((e[0] == ':') && (e[1] == ':'))
582221345Sdim				{
583249423Sdim				cp=np;
584234353Sdim				rrp=e;
585234353Sdim				rr= *e;
586234353Sdim				*rrp='\0';
587249423Sdim				e+=2;
588249423Sdim				np=e;
589249423Sdim				while (IS_ALPHA_NUMERIC(conf,*e))
590234353Sdim					e++;
591234353Sdim				}
592234353Sdim			r= *e;
593239462Sdim			*e='\0';
594239462Sdim			rp=e;
595239462Sdim			if (q)
596234353Sdim				{
597234353Sdim				if (r != q)
598234353Sdim					{
599234353Sdim					CONFerr(CONF_F_STR_COPY,CONF_R_NO_CLOSE_BRACE);
600234353Sdim					goto err;
601234353Sdim					}
602234353Sdim				e++;
603234353Sdim				}
604234353Sdim			/* So at this point we have
605249423Sdim			 * np which is the start of the name string which is
606249423Sdim			 *   '\0' terminated.
607249423Sdim			 * cp which is the start of the section string which is
608249423Sdim			 *   '\0' terminated.
609249423Sdim			 * e is the 'next point after'.
610249423Sdim			 * r and rr are the chars replaced by the '\0'
611249423Sdim			 * rp and rrp is where 'r' and 'rr' came from.
612249423Sdim			 */
613224145Sdim			p=_CONF_get_string(conf,cp,np);
614249423Sdim			if (rrp != NULL) *rrp=rr;
615249423Sdim			*rp=r;
616249423Sdim			if (p == NULL)
617249423Sdim				{
618249423Sdim				CONFerr(CONF_F_STR_COPY,CONF_R_VARIABLE_HAS_NO_VALUE);
619249423Sdim				goto err;
620249423Sdim				}
621249423Sdim			len = strlen(p)+len-(e-from);
622249423Sdim			BUF_MEM_grow_clean(buf, len);
623249423Sdim			while (*p)
624249423Sdim				buf->data[to++]= *(p++);
625249423Sdim
626249423Sdim			/* Since we change the pointer 'from', we also have
627249423Sdim			   to change the perceived length of the string it
628194612Sed			   points at.  /RL */
629221345Sdim			len -= e-from;
630221345Sdim			from=e;
631221345Sdim
632221345Sdim			/* In case there were no braces or parenthesis around
633221345Sdim			   the variable reference, we have to put back the
634221345Sdim			   character that was replaced with a '\0'.  /RL */
635221345Sdim			*rp = r;
636221345Sdim			}
637194612Sed		else
638194612Sed			buf->data[to++]= *(from++);
639194612Sed		}
640194612Sed	buf->data[to]='\0';
641194612Sed	if (*pto != NULL) OPENSSL_free(*pto);
642194612Sed	*pto=buf->data;
643194612Sed	OPENSSL_free(buf);
644194612Sed	return(1);
645194612Sederr:
646194612Sed	if (buf != NULL) BUF_MEM_free(buf);
647194612Sed	return(0);
648193323Sed	}
649193323Sed
650193323Sedstatic char *eat_ws(CONF *conf, char *p)
651193323Sed	{
652193323Sed	while (IS_WS(conf,*p) && (!IS_EOF(conf,*p)))
653198090Srdivacky		p++;
654221345Sdim	return(p);
655221345Sdim	}
656221345Sdim
657221345Sdimstatic char *eat_alpha_numeric(CONF *conf, char *p)
658221345Sdim	{
659221345Sdim	for (;;)
660221345Sdim		{
661198090Srdivacky		if (IS_ESC(conf,*p))
662198090Srdivacky			{
663198090Srdivacky			p=scan_esc(conf,p);
664198090Srdivacky			continue;
665198090Srdivacky			}
666198090Srdivacky		if (!IS_ALPHA_NUMERIC_PUNCT(conf,*p))
667212904Sdim			return(p);
668212904Sdim		p++;
669212904Sdim		}
670212904Sdim	}
671212904Sdim
672212904Sdimstatic char *scan_quote(CONF *conf, char *p)
673212904Sdim	{
674198090Srdivacky	int q= *p;
675198090Srdivacky
676198090Srdivacky	p++;
677198090Srdivacky	while (!(IS_EOF(conf,*p)) && (*p != q))
678198090Srdivacky		{
679198090Srdivacky		if (IS_ESC(conf,*p))
680212904Sdim			{
681198090Srdivacky			p++;
682198090Srdivacky			if (IS_EOF(conf,*p)) return(p);
683198090Srdivacky			}
684198090Srdivacky		p++;
685239462Sdim		}
686239462Sdim	if (*p == q) p++;
687239462Sdim	return(p);
688239462Sdim	}
689239462Sdim
690239462Sdim
691198090Srdivackystatic char *scan_dquote(CONF *conf, char *p)
692198090Srdivacky	{
693198090Srdivacky	int q= *p;
694193323Sed
695193323Sed	p++;
696193323Sed	while (!(IS_EOF(conf,*p)))
697193323Sed		{
698212904Sdim		if (*p == q)
699218893Sdim			{
700212904Sdim			if (*(p+1) == q)
701212904Sdim				{
702212904Sdim				p++;
703212904Sdim				}
704212904Sdim			else
705212904Sdim				{
706212904Sdim				break;
707212904Sdim				}
708212904Sdim			}
709212904Sdim		p++;
710212904Sdim		}
711212904Sdim	if (*p == q) p++;
712212904Sdim	return(p);
713212904Sdim	}
714212904Sdim
715218893Sdimstatic void dump_value_doall_arg(CONF_VALUE *a, BIO *out)
716212904Sdim	{
717212904Sdim	if (a->name)
718234353Sdim		BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
719234353Sdim	else
720212904Sdim		BIO_printf(out, "[[%s]]\n", a->section);
721212904Sdim	}
722212904Sdim
723212904Sdimstatic IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE, BIO)
724212904Sdim
725212904Sdimstatic int def_dump(const CONF *conf, BIO *out)
726234353Sdim	{
727212904Sdim	lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value),
728212904Sdim				BIO, out);
729212904Sdim	return 1;
730212904Sdim	}
731212904Sdim
732212904Sdimstatic int def_is_number(const CONF *conf, char c)
733234353Sdim	{
734212904Sdim	return IS_NUMBER(conf,c);
735212904Sdim	}
736193323Sed
737198396Srdivackystatic int def_to_int(const CONF *conf, char c)
738198396Srdivacky	{
739198396Srdivacky	return c - '0';
740198090Srdivacky	}
741198090Srdivacky
742198090Srdivacky