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