From b64270d1e45fe7f3241e4c9b6ce60d5ac89bc2e9 Mon Sep 17 00:00:00 2001 From: beck <> Date: Wed, 15 May 2002 02:29:21 +0000 Subject: OpenSSL 0.9.7 stable 2002 05 08 merge --- src/lib/libcrypto/conf/conf.c | 730 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 730 insertions(+) create mode 100644 src/lib/libcrypto/conf/conf.c (limited to 'src/lib/libcrypto/conf/conf.c') diff --git a/src/lib/libcrypto/conf/conf.c b/src/lib/libcrypto/conf/conf.c new file mode 100644 index 0000000000..3031fa3b44 --- /dev/null +++ b/src/lib/libcrypto/conf/conf.c @@ -0,0 +1,730 @@ +/* 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.] + */ + +#include +#include +#include "cryptlib.h" +#include +#include +#include +#include +#include + +#include "conf_lcl.h" + +static void value_free_hash(CONF_VALUE *a, LHASH *conf); +static void value_free_stack(CONF_VALUE *a,LHASH *conf); +static unsigned long hash(CONF_VALUE *v); +static int cmp_conf(CONF_VALUE *a,CONF_VALUE *b); +static char *eat_ws(char *p); +static char *eat_alpha_numeric(char *p); +static void clear_comments(char *p); +static int str_copy(LHASH *conf,char *section,char **to, char *from); +static char *scan_quote(char *p); +static CONF_VALUE *new_section(LHASH *conf,char *section); +static CONF_VALUE *get_section(LHASH *conf,char *section); +#define scan_esc(p) ((((p)[1] == '\0')?(p++):(p+=2)),p) + +const char *CONF_version="CONF" OPENSSL_VERSION_PTEXT; + + +LHASH *CONF_load(LHASH *h, const char *file, long *line) + { + LHASH *ltmp; + BIO *in=NULL; + +#ifdef VMS + in=BIO_new_file(file, "r"); +#else + in=BIO_new_file(file, "rb"); +#endif + if (in == NULL) + { + CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB); + return NULL; + } + + ltmp = CONF_load_bio(h, in, line); + BIO_free(in); + + return ltmp; +} +#ifndef NO_FP_API +LHASH *CONF_load_fp(LHASH *h, FILE *in, long *line) +{ + BIO *btmp; + LHASH *ltmp; + if(!(btmp = BIO_new_fp(in, BIO_NOCLOSE))) { + CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB); + return NULL; + } + ltmp = CONF_load_bio(h, btmp, line); + BIO_free(btmp); + return ltmp; +} +#endif + +LHASH *CONF_load_bio(LHASH *h, BIO *in, long *line) + { + LHASH *ret=NULL; +#define BUFSIZE 512 + char btmp[16]; + int bufnum=0,i,ii; + BUF_MEM *buff=NULL; + char *s,*p,*end; + int again,n; + long eline=0; + CONF_VALUE *v=NULL,*vv,*tv; + CONF_VALUE *sv=NULL; + char *section=NULL,*buf; + STACK_OF(CONF_VALUE) *section_sk=NULL,*ts; + char *start,*psection,*pname; + + if ((buff=BUF_MEM_new()) == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); + goto err; + } + + section=(char *)Malloc(10); + if (section == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); + goto err; + } + strcpy(section,"default"); + + if (h == NULL) + { + if ((ret=lh_new(hash,cmp_conf)) == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE); + goto err; + } + } + else + ret=h; + + sv=new_section(ret,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; + for (;;) + { + again=0; + if (!BUF_MEM_grow(buff,bufnum+BUFSIZE)) + { + CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB); + goto err; + } + p= &(buff->data[bufnum]); + *p='\0'; + BIO_gets(in, p, BUFSIZE-1); + p[BUFSIZE-1]='\0'; + ii=i=strlen(p); + if (i == 0) break; + 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 (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(p[0]) && + ((bufnum <= 1) || !IS_ESC(p[-1]))) + { + bufnum--; + again=1; + } + } + if (again) continue; + bufnum=0; + buf=buff->data; + + clear_comments(buf); + n=strlen(buf); + s=eat_ws(buf); + if (IS_EOF(*s)) continue; /* blank line */ + if (*s == '[') + { + char *ss; + + s++; + start=eat_ws(s); + ss=start; +again: + end=eat_alpha_numeric(ss); + p=eat_ws(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(ret,NULL,§ion,start)) goto err; + if ((sv=get_section(ret,section)) == NULL) + sv=new_section(ret,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(s); + if ((end[0] == ':') && (end[1] == ':')) + { + *end='\0'; + end+=2; + psection=pname; + pname=end; + end=eat_alpha_numeric(end); + } + p=eat_ws(end); + if (*p != '=') + { + CONFerr(CONF_F_CONF_LOAD_BIO, + CONF_R_MISSING_EQUAL_SIGN); + goto err; + } + *end='\0'; + p++; + start=eat_ws(p); + while (!IS_EOF(*p)) + p++; + p--; + while ((p != start) && (IS_WS(*p))) + p--; + p++; + *p='\0'; + + if (!(v=(CONF_VALUE *)Malloc(sizeof(CONF_VALUE)))) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + if (psection == NULL) psection=section; + v->name=(char *)Malloc(strlen(pname)+1); + v->value=NULL; + if (v->name == NULL) + { + CONFerr(CONF_F_CONF_LOAD_BIO, + ERR_R_MALLOC_FAILURE); + goto err; + } + strcpy(v->name,pname); + if (!str_copy(ret,psection,&(v->value),start)) goto err; + + if (strcmp(psection,section) != 0) + { + if ((tv=get_section(ret,psection)) + == NULL) + tv=new_section(ret,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; + } + 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(ret,v); + if (vv != NULL) + { + sk_CONF_VALUE_delete_ptr(ts,vv); + Free(vv->name); + Free(vv->value); + Free(vv); + } + v=NULL; + } + } + if (buff != NULL) BUF_MEM_free(buff); + if (section != NULL) Free(section); + return(ret); +err: + if (buff != NULL) BUF_MEM_free(buff); + if (section != NULL) Free(section); + if (line != NULL) *line=eline; + sprintf(btmp,"%ld",eline); + ERR_add_error_data(2,"line ",btmp); + if ((h != ret) && (ret != NULL)) CONF_free(ret); + if (v != NULL) + { + if (v->name != NULL) Free(v->name); + if (v->value != NULL) Free(v->value); + if (v != NULL) Free(v); + } + return(NULL); + } + +char *CONF_get_string(LHASH *conf, char *section, char *name) + { + CONF_VALUE *v,vv; + char *p; + + if (name == NULL) return(NULL); + if (conf != NULL) + { + if (section != NULL) + { + vv.name=name; + vv.section=section; + v=(CONF_VALUE *)lh_retrieve(conf,&vv); + if (v != NULL) return(v->value); + if (strcmp(section,"ENV") == 0) + { + p=Getenv(name); + if (p != NULL) return(p); + } + } + vv.section="default"; + vv.name=name; + v=(CONF_VALUE *)lh_retrieve(conf,&vv); + if (v != NULL) + return(v->value); + else + return(NULL); + } + else + return(Getenv(name)); + } + +static CONF_VALUE *get_section(LHASH *conf, char *section) + { + CONF_VALUE *v,vv; + + if ((conf == NULL) || (section == NULL)) return(NULL); + vv.name=NULL; + vv.section=section; + v=(CONF_VALUE *)lh_retrieve(conf,&vv); + return(v); + } + +STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf, char *section) + { + CONF_VALUE *v; + + v=get_section(conf,section); + if (v != NULL) + return((STACK_OF(CONF_VALUE) *)v->value); + else + return(NULL); + } + +long CONF_get_number(LHASH *conf, char *section, char *name) + { + char *str; + long ret=0; + + str=CONF_get_string(conf,section,name); + if (str == NULL) return(0); + for (;;) + { + if (IS_NUMER(*str)) + ret=ret*10+(*str -'0'); + else + return(ret); + str++; + } + } + +void CONF_free(LHASH *conf) + { + if (conf == NULL) return; + + conf->down_load=0; /* evil thing to make sure the 'Free()' + * works as expected */ + lh_doall_arg(conf,(void (*)())value_free_hash,conf); + + /* We now have only 'section' entries in the hash table. + * Due to problems with */ + + lh_doall_arg(conf,(void (*)())value_free_stack,conf); + lh_free(conf); + } + +static void value_free_hash(CONF_VALUE *a, LHASH *conf) + { + if (a->name != NULL) + { + a=(CONF_VALUE *)lh_delete(conf,a); + } + } + +static void value_free_stack(CONF_VALUE *a, LHASH *conf) + { + CONF_VALUE *vv; + STACK *sk; + int i; + + if (a->name != NULL) return; + + sk=(STACK *)a->value; + for (i=sk_num(sk)-1; i>=0; i--) + { + vv=(CONF_VALUE *)sk_value(sk,i); + Free(vv->value); + Free(vv->name); + Free(vv); + } + if (sk != NULL) sk_free(sk); + Free(a->section); + Free(a); + } + +static void clear_comments(char *p) + { + char *to; + + to=p; + for (;;) + { + if (IS_COMMENT(*p)) + { + *p='\0'; + return; + } + if (IS_QUOTE(*p)) + { + p=scan_quote(p); + continue; + } + if (IS_ESC(*p)) + { + p=scan_esc(p); + continue; + } + if (IS_EOF(*p)) + return; + else + p++; + } + } + +static int str_copy(LHASH *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(*from)) + { + q= *from; + from++; + while ((*from != '\0') && (*from != q)) + { + if (*from == '\\') + { + from++; + if (*from == '\0') break; + } + buf->data[to++]= *(from++); + } + } + else if (*from == '\\') + { + from++; + v= *(from++); + if (v == '\0') 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 (*from == '\0') + 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(*e)) + e++; + if ((e[0] == ':') && (e[1] == ':')) + { + cp=np; + rrp=e; + rr= *e; + *rrp='\0'; + e+=2; + np=e; + while (IS_ALPHA_NUMERIC(*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(buf,(strlen(p)+len-(e-from))); + while (*p) + buf->data[to++]= *(p++); + from=e; + } + else + buf->data[to++]= *(from++); + } + buf->data[to]='\0'; + if (*pto != NULL) Free(*pto); + *pto=buf->data; + Free(buf); + return(1); +err: + if (buf != NULL) BUF_MEM_free(buf); + return(0); + } + +static char *eat_ws(char *p) + { + while (IS_WS(*p) && (!IS_EOF(*p))) + p++; + return(p); + } + +static char *eat_alpha_numeric(char *p) + { + for (;;) + { + if (IS_ESC(*p)) + { + p=scan_esc(p); + continue; + } + if (!IS_ALPHA_NUMERIC_PUNCT(*p)) + return(p); + p++; + } + } + +static unsigned long hash(CONF_VALUE *v) + { + return((lh_strhash(v->section)<<2)^lh_strhash(v->name)); + } + +static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) + { + int i; + + if (a->section != b->section) + { + i=strcmp(a->section,b->section); + if (i) return(i); + } + + if ((a->name != NULL) && (b->name != NULL)) + { + i=strcmp(a->name,b->name); + return(i); + } + else if (a->name == b->name) + return(0); + else + return((a->name == NULL)?-1:1); + } + +static char *scan_quote(char *p) + { + int q= *p; + + p++; + while (!(IS_EOF(*p)) && (*p != q)) + { + if (IS_ESC(*p)) + { + p++; + if (IS_EOF(*p)) return(p); + } + p++; + } + if (*p == q) p++; + return(p); + } + +static CONF_VALUE *new_section(LHASH *conf, char *section) + { + STACK *sk=NULL; + int ok=0,i; + CONF_VALUE *v=NULL,*vv; + + if ((sk=sk_new_null()) == NULL) + goto err; + if ((v=(CONF_VALUE *)Malloc(sizeof(CONF_VALUE))) == NULL) + goto err; + i=strlen(section)+1; + if ((v->section=(char *)Malloc(i)) == NULL) + goto err; + + memcpy(v->section,section,i); + v->name=NULL; + v->value=(char *)sk; + + vv=(CONF_VALUE *)lh_insert(conf,v); + if (vv != NULL) + { +#if !defined(NO_STDIO) && !defined(WIN16) + fprintf(stderr,"internal fault\n"); +#endif + abort(); + } + ok=1; +err: + if (!ok) + { + if (sk != NULL) sk_free(sk); + if (v != NULL) Free(v); + v=NULL; + } + return(v); + } + +IMPLEMENT_STACK_OF(CONF_VALUE) -- cgit v1.2.3-55-g6feb