| /* crypto/conf/conf.c */ | 
 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 
 |  * All rights reserved. | 
 |  * | 
 |  * This package is an SSL implementation written | 
 |  * by Eric Young (eay@cryptsoft.com). | 
 |  * The implementation was written so as to conform with Netscapes SSL. | 
 |  *  | 
 |  * This library is free for commercial and non-commercial use as long as | 
 |  * the following conditions are aheared to.  The following conditions | 
 |  * apply to all code found in this distribution, be it the RC4, RSA, | 
 |  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation | 
 |  * included with this distribution is covered by the same copyright terms | 
 |  * except that the holder is Tim Hudson (tjh@cryptsoft.com). | 
 |  *  | 
 |  * Copyright remains Eric Young's, and as such any Copyright notices in | 
 |  * the code are not to be removed. | 
 |  * If this package is used in a product, Eric Young should be given attribution | 
 |  * as the author of the parts of the library used. | 
 |  * This can be in the form of a textual message at program startup or | 
 |  * in documentation (online or textual) provided with the package. | 
 |  *  | 
 |  * Redistribution and use in source and binary forms, with or without | 
 |  * modification, are permitted provided that the following conditions | 
 |  * are met: | 
 |  * 1. Redistributions of source code must retain the copyright | 
 |  *    notice, this list of conditions and the following disclaimer. | 
 |  * 2. Redistributions in binary form must reproduce the above copyright | 
 |  *    notice, this list of conditions and the following disclaimer in the | 
 |  *    documentation and/or other materials provided with the distribution. | 
 |  * 3. All advertising materials mentioning features or use of this software | 
 |  *    must display the following acknowledgement: | 
 |  *    "This product includes cryptographic software written by | 
 |  *     Eric Young (eay@cryptsoft.com)" | 
 |  *    The word 'cryptographic' can be left out if the rouines from the library | 
 |  *    being used are not cryptographic related :-). | 
 |  * 4. If you include any Windows specific code (or a derivative thereof) from  | 
 |  *    the apps directory (application code) you must include an acknowledgement: | 
 |  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | 
 |  *  | 
 |  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND | 
 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 
 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 |  * SUCH DAMAGE. | 
 |  *  | 
 |  * The licence and distribution terms for any publically available version or | 
 |  * derivative of this code cannot be changed.  i.e. this code cannot simply be | 
 |  * copied and put under another distribution licence | 
 |  * [including the GNU Public Licence.] | 
 |  */ | 
 |  | 
 | /* Part of the code in here was originally in conf.c, which is now removed */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <openssl/stack.h> | 
 | #include <openssl/lhash.h> | 
 | #include <openssl/conf.h> | 
 | #include <openssl/conf_api.h> | 
 | #include "conf_def.h" | 
 | #include <openssl/buffer.h> | 
 | #include <openssl/err.h> | 
 | #include "cryptlib.h" | 
 |  | 
 | static char *eat_ws(CONF *conf, char *p); | 
 | static char *eat_alpha_numeric(CONF *conf, char *p); | 
 | static void clear_comments(CONF *conf, char *p); | 
 | static int str_copy(CONF *conf,char *section,char **to, char *from); | 
 | static char *scan_quote(CONF *conf, char *p); | 
 | static char *scan_dquote(CONF *conf, char *p); | 
 | #define scan_esc(conf,p)	(((IS_EOF((conf),(p)[1]))?((p)+1):((p)+2))) | 
 |  | 
 | static CONF *def_create(CONF_METHOD *meth); | 
 | static int def_init_default(CONF *conf); | 
 | static int def_init_WIN32(CONF *conf); | 
 | static int def_destroy(CONF *conf); | 
 | static int def_destroy_data(CONF *conf); | 
 | static int def_load(CONF *conf, const char *name, long *eline); | 
 | static int def_load_bio(CONF *conf, BIO *bp, long *eline); | 
 | static int def_dump(const CONF *conf, BIO *bp); | 
 | static int def_is_number(const CONF *conf, char c); | 
 | static int def_to_int(const CONF *conf, char c); | 
 |  | 
 | const char *CONF_def_version="CONF_def" OPENSSL_VERSION_PTEXT; | 
 |  | 
 | static CONF_METHOD default_method = { | 
 | 	"OpenSSL default", | 
 | 	def_create, | 
 | 	def_init_default, | 
 | 	def_destroy, | 
 | 	def_destroy_data, | 
 | 	def_load_bio, | 
 | 	def_dump, | 
 | 	def_is_number, | 
 | 	def_to_int, | 
 | 	def_load | 
 | 	}; | 
 |  | 
 | static CONF_METHOD WIN32_method = { | 
 | 	"WIN32", | 
 | 	def_create, | 
 | 	def_init_WIN32, | 
 | 	def_destroy, | 
 | 	def_destroy_data, | 
 | 	def_load_bio, | 
 | 	def_dump, | 
 | 	def_is_number, | 
 | 	def_to_int, | 
 | 	def_load | 
 | 	}; | 
 |  | 
 | CONF_METHOD *NCONF_default() | 
 | 	{ | 
 | 	return &default_method; | 
 | 	} | 
 | CONF_METHOD *NCONF_WIN32() | 
 | 	{ | 
 | 	return &WIN32_method; | 
 | 	} | 
 |  | 
 | static CONF *def_create(CONF_METHOD *meth) | 
 | 	{ | 
 | 	CONF *ret; | 
 |  | 
 | 	ret = (CONF *)OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *)); | 
 | 	if (ret) | 
 | 		if (meth->init(ret) == 0) | 
 | 			{ | 
 | 			OPENSSL_free(ret); | 
 | 			ret = NULL; | 
 | 			} | 
 | 	return ret; | 
 | 	} | 
 | 	 | 
 | static int def_init_default(CONF *conf) | 
 | 	{ | 
 | 	if (conf == NULL) | 
 | 		return 0; | 
 |  | 
 | 	conf->meth = &default_method; | 
 | 	conf->meth_data = (void *)CONF_type_default; | 
 | 	conf->data = NULL; | 
 |  | 
 | 	return 1; | 
 | 	} | 
 |  | 
 | static int def_init_WIN32(CONF *conf) | 
 | 	{ | 
 | 	if (conf == NULL) | 
 | 		return 0; | 
 |  | 
 | 	conf->meth = &WIN32_method; | 
 | 	conf->meth_data = (void *)CONF_type_win32; | 
 | 	conf->data = NULL; | 
 |  | 
 | 	return 1; | 
 | 	} | 
 |  | 
 | static int def_destroy(CONF *conf) | 
 | 	{ | 
 | 	if (def_destroy_data(conf)) | 
 | 		{ | 
 | 		OPENSSL_free(conf); | 
 | 		return 1; | 
 | 		} | 
 | 	return 0; | 
 | 	} | 
 |  | 
 | static int def_destroy_data(CONF *conf) | 
 | 	{ | 
 | 	if (conf == NULL) | 
 | 		return 0; | 
 | 	_CONF_free_data(conf); | 
 | 	return 1; | 
 | 	} | 
 |  | 
 | static int def_load(CONF *conf, const char *name, long *line) | 
 | 	{ | 
 | 	int ret; | 
 | 	BIO *in=NULL; | 
 |  | 
 | #ifdef OPENSSL_SYS_VMS | 
 | 	in=BIO_new_file(name, "r"); | 
 | #else | 
 | 	in=BIO_new_file(name, "rb"); | 
 | #endif | 
 | 	if (in == NULL) | 
 | 		{ | 
 | 		if (ERR_GET_REASON(ERR_peek_last_error()) == BIO_R_NO_SUCH_FILE) | 
 | 			CONFerr(CONF_F_CONF_LOAD,CONF_R_NO_SUCH_FILE); | 
 | 		else | 
 | 			CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB); | 
 | 		return 0; | 
 | 		} | 
 |  | 
 | 	ret = def_load_bio(conf, in, line); | 
 | 	BIO_free(in); | 
 |  | 
 | 	return ret; | 
 | 	} | 
 |  | 
 | static int def_load_bio(CONF *conf, BIO *in, long *line) | 
 | 	{ | 
 | /* The macro BUFSIZE conflicts with a system macro in VxWorks */ | 
 | #define CONFBUFSIZE	512 | 
 | 	int bufnum=0,i,ii; | 
 | 	BUF_MEM *buff=NULL; | 
 | 	char *s,*p,*end; | 
 | 	int again,n; | 
 | 	long eline=0; | 
 | 	char btmp[DECIMAL_SIZE(eline)+1]; | 
 | 	CONF_VALUE *v=NULL,*tv; | 
 | 	CONF_VALUE *sv=NULL; | 
 | 	char *section=NULL,*buf; | 
 | 	STACK_OF(CONF_VALUE) *section_sk=NULL,*ts; | 
 | 	char *start,*psection,*pname; | 
 | 	void *h = (void *)(conf->data); | 
 |  | 
 | 	if ((buff=BUF_MEM_new()) == NULL) | 
 | 		{ | 
 | 		CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); | 
 | 		goto err; | 
 | 		} | 
 |  | 
 | 	section=(char *)OPENSSL_malloc(10); | 
 | 	if (section == NULL) | 
 | 		{ | 
 | 		CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); | 
 | 		goto err; | 
 | 		} | 
 | 	BUF_strlcpy(section,"default",10); | 
 |  | 
 | 	if (_CONF_new_data(conf) == 0) | 
 | 		{ | 
 | 		CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); | 
 | 		goto err; | 
 | 		} | 
 |  | 
 | 	sv=_CONF_new_section(conf,section); | 
 | 	if (sv == NULL) | 
 | 		{ | 
 | 		CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 					CONF_R_UNABLE_TO_CREATE_NEW_SECTION); | 
 | 		goto err; | 
 | 		} | 
 | 	section_sk=(STACK_OF(CONF_VALUE) *)sv->value; | 
 |  | 
 | 	bufnum=0; | 
 | 	again=0; | 
 | 	for (;;) | 
 | 		{ | 
 | 		if (!BUF_MEM_grow(buff,bufnum+CONFBUFSIZE)) | 
 | 			{ | 
 | 			CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); | 
 | 			goto err; | 
 | 			} | 
 | 		p= &(buff->data[bufnum]); | 
 | 		*p='\0'; | 
 | 		BIO_gets(in, p, CONFBUFSIZE-1); | 
 | 		p[CONFBUFSIZE-1]='\0'; | 
 | 		ii=i=strlen(p); | 
 | 		if (i == 0 && !again) break; | 
 | 		again=0; | 
 | 		while (i > 0) | 
 | 			{ | 
 | 			if ((p[i-1] != '\r') && (p[i-1] != '\n')) | 
 | 				break; | 
 | 			else | 
 | 				i--; | 
 | 			} | 
 | 		/* we removed some trailing stuff so there is a new | 
 | 		 * line on the end. */ | 
 | 		if (ii && i == ii) | 
 | 			again=1; /* long line */ | 
 | 		else | 
 | 			{ | 
 | 			p[i]='\0'; | 
 | 			eline++; /* another input line */ | 
 | 			} | 
 |  | 
 | 		/* we now have a line with trailing \r\n removed */ | 
 |  | 
 | 		/* i is the number of bytes */ | 
 | 		bufnum+=i; | 
 |  | 
 | 		v=NULL; | 
 | 		/* check for line continuation */ | 
 | 		if (bufnum >= 1) | 
 | 			{ | 
 | 			/* If we have bytes and the last char '\\' and | 
 | 			 * second last char is not '\\' */ | 
 | 			p= &(buff->data[bufnum-1]); | 
 | 			if (IS_ESC(conf,p[0]) && | 
 | 				((bufnum <= 1) || !IS_ESC(conf,p[-1]))) | 
 | 				{ | 
 | 				bufnum--; | 
 | 				again=1; | 
 | 				} | 
 | 			} | 
 | 		if (again) continue; | 
 | 		bufnum=0; | 
 | 		buf=buff->data; | 
 |  | 
 | 		clear_comments(conf, buf); | 
 | 		n=strlen(buf); | 
 | 		s=eat_ws(conf, buf); | 
 | 		if (IS_EOF(conf,*s)) continue; /* blank line */ | 
 | 		if (*s == '[') | 
 | 			{ | 
 | 			char *ss; | 
 |  | 
 | 			s++; | 
 | 			start=eat_ws(conf, s); | 
 | 			ss=start; | 
 | again: | 
 | 			end=eat_alpha_numeric(conf, ss); | 
 | 			p=eat_ws(conf, end); | 
 | 			if (*p != ']') | 
 | 				{ | 
 | 				if (*p != '\0') | 
 | 					{ | 
 | 					ss=p; | 
 | 					goto again; | 
 | 					} | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 					CONF_R_MISSING_CLOSE_SQUARE_BRACKET); | 
 | 				goto err; | 
 | 				} | 
 | 			*end='\0'; | 
 | 			if (!str_copy(conf,NULL,§ion,start)) goto err; | 
 | 			if ((sv=_CONF_get_section(conf,section)) == NULL) | 
 | 				sv=_CONF_new_section(conf,section); | 
 | 			if (sv == NULL) | 
 | 				{ | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 					CONF_R_UNABLE_TO_CREATE_NEW_SECTION); | 
 | 				goto err; | 
 | 				} | 
 | 			section_sk=(STACK_OF(CONF_VALUE) *)sv->value; | 
 | 			continue; | 
 | 			} | 
 | 		else | 
 | 			{ | 
 | 			pname=s; | 
 | 			psection=NULL; | 
 | 			end=eat_alpha_numeric(conf, s); | 
 | 			if ((end[0] == ':') && (end[1] == ':')) | 
 | 				{ | 
 | 				*end='\0'; | 
 | 				end+=2; | 
 | 				psection=pname; | 
 | 				pname=end; | 
 | 				end=eat_alpha_numeric(conf, end); | 
 | 				} | 
 | 			p=eat_ws(conf, end); | 
 | 			if (*p != '=') | 
 | 				{ | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 						CONF_R_MISSING_EQUAL_SIGN); | 
 | 				goto err; | 
 | 				} | 
 | 			*end='\0'; | 
 | 			p++; | 
 | 			start=eat_ws(conf, p); | 
 | 			while (!IS_EOF(conf,*p)) | 
 | 				p++; | 
 | 			p--; | 
 | 			while ((p != start) && (IS_WS(conf,*p))) | 
 | 				p--; | 
 | 			p++; | 
 | 			*p='\0'; | 
 |  | 
 | 			if (!(v=(CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) | 
 | 				{ | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 							ERR_R_MALLOC_FAILURE); | 
 | 				goto err; | 
 | 				} | 
 | 			if (psection == NULL) psection=section; | 
 | 			v->name=(char *)OPENSSL_malloc(strlen(pname)+1); | 
 | 			v->value=NULL; | 
 | 			if (v->name == NULL) | 
 | 				{ | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 							ERR_R_MALLOC_FAILURE); | 
 | 				goto err; | 
 | 				} | 
 | 			BUF_strlcpy(v->name,pname,strlen(pname)+1); | 
 | 			if (!str_copy(conf,psection,&(v->value),start)) goto err; | 
 |  | 
 | 			if (strcmp(psection,section) != 0) | 
 | 				{ | 
 | 				if ((tv=_CONF_get_section(conf,psection)) | 
 | 					== NULL) | 
 | 					tv=_CONF_new_section(conf,psection); | 
 | 				if (tv == NULL) | 
 | 					{ | 
 | 					CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 					   CONF_R_UNABLE_TO_CREATE_NEW_SECTION); | 
 | 					goto err; | 
 | 					} | 
 | 				ts=(STACK_OF(CONF_VALUE) *)tv->value; | 
 | 				} | 
 | 			else | 
 | 				{ | 
 | 				tv=sv; | 
 | 				ts=section_sk; | 
 | 				} | 
 | #if 1 | 
 | 			if (_CONF_add_string(conf, tv, v) == 0) | 
 | 				{ | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 							ERR_R_MALLOC_FAILURE); | 
 | 				goto err; | 
 | 				} | 
 | #else | 
 | 			v->section=tv->section;	 | 
 | 			if (!sk_CONF_VALUE_push(ts,v)) | 
 | 				{ | 
 | 				CONFerr(CONF_F_CONF_LOAD_BIO, | 
 | 							ERR_R_MALLOC_FAILURE); | 
 | 				goto err; | 
 | 				} | 
 | 			vv=(CONF_VALUE *)lh_insert(conf->data,v); | 
 | 			if (vv != NULL) | 
 | 				{ | 
 | 				sk_CONF_VALUE_delete_ptr(ts,vv); | 
 | 				OPENSSL_free(vv->name); | 
 | 				OPENSSL_free(vv->value); | 
 | 				OPENSSL_free(vv); | 
 | 				} | 
 | #endif | 
 | 			v=NULL; | 
 | 			} | 
 | 		} | 
 | 	if (buff != NULL) BUF_MEM_free(buff); | 
 | 	if (section != NULL) OPENSSL_free(section); | 
 | 	return(1); | 
 | err: | 
 | 	if (buff != NULL) BUF_MEM_free(buff); | 
 | 	if (section != NULL) OPENSSL_free(section); | 
 | 	if (line != NULL) *line=eline; | 
 | 	BIO_snprintf(btmp,sizeof btmp,"%ld",eline); | 
 | 	ERR_add_error_data(2,"line ",btmp); | 
 | 	if ((h != conf->data) && (conf->data != NULL)) | 
 | 		{ | 
 | 		CONF_free(conf->data); | 
 | 		conf->data=NULL; | 
 | 		} | 
 | 	if (v != NULL) | 
 | 		{ | 
 | 		if (v->name != NULL) OPENSSL_free(v->name); | 
 | 		if (v->value != NULL) OPENSSL_free(v->value); | 
 | 		if (v != NULL) OPENSSL_free(v); | 
 | 		} | 
 | 	return(0); | 
 | 	} | 
 |  | 
 | static void clear_comments(CONF *conf, char *p) | 
 | 	{ | 
 | 	char *to; | 
 |  | 
 | 	to=p; | 
 | 	for (;;) | 
 | 		{ | 
 | 		if (IS_FCOMMENT(conf,*p)) | 
 | 			{ | 
 | 			*p='\0'; | 
 | 			return; | 
 | 			} | 
 | 		if (!IS_WS(conf,*p)) | 
 | 			{ | 
 | 			break; | 
 | 			} | 
 | 		p++; | 
 | 		} | 
 |  | 
 | 	for (;;) | 
 | 		{ | 
 | 		if (IS_COMMENT(conf,*p)) | 
 | 			{ | 
 | 			*p='\0'; | 
 | 			return; | 
 | 			} | 
 | 		if (IS_DQUOTE(conf,*p)) | 
 | 			{ | 
 | 			p=scan_dquote(conf, p); | 
 | 			continue; | 
 | 			} | 
 | 		if (IS_QUOTE(conf,*p)) | 
 | 			{ | 
 | 			p=scan_quote(conf, p); | 
 | 			continue; | 
 | 			} | 
 | 		if (IS_ESC(conf,*p)) | 
 | 			{ | 
 | 			p=scan_esc(conf,p); | 
 | 			continue; | 
 | 			} | 
 | 		if (IS_EOF(conf,*p)) | 
 | 			return; | 
 | 		else | 
 | 			p++; | 
 | 		} | 
 | 	} | 
 |  | 
 | static int str_copy(CONF *conf, char *section, char **pto, char *from) | 
 | 	{ | 
 | 	int q,r,rr=0,to=0,len=0; | 
 | 	char *s,*e,*rp,*p,*rrp,*np,*cp,v; | 
 | 	BUF_MEM *buf; | 
 |  | 
 | 	if ((buf=BUF_MEM_new()) == NULL) return(0); | 
 |  | 
 | 	len=strlen(from)+1; | 
 | 	if (!BUF_MEM_grow(buf,len)) goto err; | 
 |  | 
 | 	for (;;) | 
 | 		{ | 
 | 		if (IS_QUOTE(conf,*from)) | 
 | 			{ | 
 | 			q= *from; | 
 | 			from++; | 
 | 			while (!IS_EOF(conf,*from) && (*from != q)) | 
 | 				{ | 
 | 				if (IS_ESC(conf,*from)) | 
 | 					{ | 
 | 					from++; | 
 | 					if (IS_EOF(conf,*from)) break; | 
 | 					} | 
 | 				buf->data[to++]= *(from++); | 
 | 				} | 
 | 			if (*from == q) from++; | 
 | 			} | 
 | 		else if (IS_DQUOTE(conf,*from)) | 
 | 			{ | 
 | 			q= *from; | 
 | 			from++; | 
 | 			while (!IS_EOF(conf,*from)) | 
 | 				{ | 
 | 				if (*from == q) | 
 | 					{ | 
 | 					if (*(from+1) == q) | 
 | 						{ | 
 | 						from++; | 
 | 						} | 
 | 					else | 
 | 						{ | 
 | 						break; | 
 | 						} | 
 | 					} | 
 | 				buf->data[to++]= *(from++); | 
 | 				} | 
 | 			if (*from == q) from++; | 
 | 			} | 
 | 		else if (IS_ESC(conf,*from)) | 
 | 			{ | 
 | 			from++; | 
 | 			v= *(from++); | 
 | 			if (IS_EOF(conf,v)) break; | 
 | 			else if (v == 'r') v='\r'; | 
 | 			else if (v == 'n') v='\n'; | 
 | 			else if (v == 'b') v='\b'; | 
 | 			else if (v == 't') v='\t'; | 
 | 			buf->data[to++]= v; | 
 | 			} | 
 | 		else if (IS_EOF(conf,*from)) | 
 | 			break; | 
 | 		else if (*from == '$') | 
 | 			{ | 
 | 			/* try to expand it */ | 
 | 			rrp=NULL; | 
 | 			s= &(from[1]); | 
 | 			if (*s == '{') | 
 | 				q='}'; | 
 | 			else if (*s == '(') | 
 | 				q=')'; | 
 | 			else q=0; | 
 |  | 
 | 			if (q) s++; | 
 | 			cp=section; | 
 | 			e=np=s; | 
 | 			while (IS_ALPHA_NUMERIC(conf,*e)) | 
 | 				e++; | 
 | 			if ((e[0] == ':') && (e[1] == ':')) | 
 | 				{ | 
 | 				cp=np; | 
 | 				rrp=e; | 
 | 				rr= *e; | 
 | 				*rrp='\0'; | 
 | 				e+=2; | 
 | 				np=e; | 
 | 				while (IS_ALPHA_NUMERIC(conf,*e)) | 
 | 					e++; | 
 | 				} | 
 | 			r= *e; | 
 | 			*e='\0'; | 
 | 			rp=e; | 
 | 			if (q) | 
 | 				{ | 
 | 				if (r != q) | 
 | 					{ | 
 | 					CONFerr(CONF_F_STR_COPY,CONF_R_NO_CLOSE_BRACE); | 
 | 					goto err; | 
 | 					} | 
 | 				e++; | 
 | 				} | 
 | 			/* So at this point we have | 
 | 			 * ns which is the start of the name string which is | 
 | 			 *   '\0' terminated.  | 
 | 			 * cs which is the start of the section string which is | 
 | 			 *   '\0' terminated. | 
 | 			 * e is the 'next point after'. | 
 | 			 * r and s are the chars replaced by the '\0' | 
 | 			 * rp and sp is where 'r' and 's' came from. | 
 | 			 */ | 
 | 			p=_CONF_get_string(conf,cp,np); | 
 | 			if (rrp != NULL) *rrp=rr; | 
 | 			*rp=r; | 
 | 			if (p == NULL) | 
 | 				{ | 
 | 				CONFerr(CONF_F_STR_COPY,CONF_R_VARIABLE_HAS_NO_VALUE); | 
 | 				goto err; | 
 | 				} | 
 | 			BUF_MEM_grow_clean(buf,(strlen(p)+buf->length-(e-from))); | 
 | 			while (*p) | 
 | 				buf->data[to++]= *(p++); | 
 |  | 
 | 			/* Since we change the pointer 'from', we also have | 
 | 			   to change the perceived length of the string it | 
 | 			   points at.  /RL */ | 
 | 			len -= e-from; | 
 | 			from=e; | 
 | 			} | 
 | 		else | 
 | 			buf->data[to++]= *(from++); | 
 | 		} | 
 | 	buf->data[to]='\0'; | 
 | 	if (*pto != NULL) OPENSSL_free(*pto); | 
 | 	*pto=buf->data; | 
 | 	OPENSSL_free(buf); | 
 | 	return(1); | 
 | err: | 
 | 	if (buf != NULL) BUF_MEM_free(buf); | 
 | 	return(0); | 
 | 	} | 
 |  | 
 | static char *eat_ws(CONF *conf, char *p) | 
 | 	{ | 
 | 	while (IS_WS(conf,*p) && (!IS_EOF(conf,*p))) | 
 | 		p++; | 
 | 	return(p); | 
 | 	} | 
 |  | 
 | static char *eat_alpha_numeric(CONF *conf, char *p) | 
 | 	{ | 
 | 	for (;;) | 
 | 		{ | 
 | 		if (IS_ESC(conf,*p)) | 
 | 			{ | 
 | 			p=scan_esc(conf,p); | 
 | 			continue; | 
 | 			} | 
 | 		if (!IS_ALPHA_NUMERIC_PUNCT(conf,*p)) | 
 | 			return(p); | 
 | 		p++; | 
 | 		} | 
 | 	} | 
 |  | 
 | static char *scan_quote(CONF *conf, char *p) | 
 | 	{ | 
 | 	int q= *p; | 
 |  | 
 | 	p++; | 
 | 	while (!(IS_EOF(conf,*p)) && (*p != q)) | 
 | 		{ | 
 | 		if (IS_ESC(conf,*p)) | 
 | 			{ | 
 | 			p++; | 
 | 			if (IS_EOF(conf,*p)) return(p); | 
 | 			} | 
 | 		p++; | 
 | 		} | 
 | 	if (*p == q) p++; | 
 | 	return(p); | 
 | 	} | 
 |  | 
 |  | 
 | static char *scan_dquote(CONF *conf, char *p) | 
 | 	{ | 
 | 	int q= *p; | 
 |  | 
 | 	p++; | 
 | 	while (!(IS_EOF(conf,*p))) | 
 | 		{ | 
 | 		if (*p == q) | 
 | 			{ | 
 | 			if (*(p+1) == q) | 
 | 				{ | 
 | 				p++; | 
 | 				} | 
 | 			else | 
 | 				{ | 
 | 				break; | 
 | 				} | 
 | 			} | 
 | 		p++; | 
 | 		} | 
 | 	if (*p == q) p++; | 
 | 	return(p); | 
 | 	} | 
 |  | 
 | static void dump_value(CONF_VALUE *a, BIO *out) | 
 | 	{ | 
 | 	if (a->name) | 
 | 		BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value); | 
 | 	else | 
 | 		BIO_printf(out, "[[%s]]\n", a->section); | 
 | 	} | 
 |  | 
 | static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE *, BIO *) | 
 |  | 
 | static int def_dump(const CONF *conf, BIO *out) | 
 | 	{ | 
 | 	lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value), out); | 
 | 	return 1; | 
 | 	} | 
 |  | 
 | static int def_is_number(const CONF *conf, char c) | 
 | 	{ | 
 | 	return IS_NUMBER(conf,c); | 
 | 	} | 
 |  | 
 | static int def_to_int(const CONF *conf, char c) | 
 | 	{ | 
 | 	return c - '0'; | 
 | 	} | 
 |  |