f98451e77d548c9f9241dcf68403079978d2ab5a
[openssl.git] / crypto / conf / conf.c
1 /* crypto/conf/conf.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <errno.h>
61 #include "cryptlib.h"
62 #include <openssl/stack.h>
63 #include <openssl/lhash.h>
64 #include <openssl/conf.h>
65 #include <openssl/buffer.h>
66 #include <openssl/err.h>
67
68 #include "conf_lcl.h"
69
70 static void value_free_hash(CONF_VALUE *a, LHASH *conf);
71 static void value_free_stack(CONF_VALUE *a,LHASH *conf);
72 static unsigned long hash(CONF_VALUE *v);
73 static int cmp(CONF_VALUE *a,CONF_VALUE *b);
74 static char *eat_ws(char *p);
75 static char *eat_alpha_numeric(char *p);
76 static void clear_comments(char *p);
77 static int str_copy(LHASH *conf,char *section,char **to, char *from);
78 static char *scan_quote(char *p);
79 static CONF_VALUE *new_section(LHASH *conf,char *section);
80 static CONF_VALUE *get_section(LHASH *conf,char *section);
81 #define scan_esc(p)     ((((p)[1] == '\0')?(p++):(p+=2)),p)
82
83 const char *CONF_version="CONF" OPENSSL_VERSION_PTEXT;
84
85
86 LHASH *CONF_load(LHASH *h, const char *file, long *line)
87         {
88         LHASH *ltmp;
89         FILE *in=NULL;
90
91 #ifdef VMS
92         in=fopen(file,"r");
93 #else
94         in=fopen(file,"rb");
95 #endif
96         if (in == NULL)
97                 {
98                 SYSerr(SYS_F_FOPEN,get_last_sys_error());
99                 ERR_set_error_data(BUF_strdup(file),
100                         ERR_TXT_MALLOCED|ERR_TXT_STRING);
101                 CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB);
102                 return NULL;
103                 }
104
105         ltmp = CONF_load_fp(h, in, line);
106         fclose(in);
107
108         return ltmp;
109 }
110
111 LHASH *CONF_load_fp(LHASH *h, FILE *in, long *line)
112 {
113         BIO *btmp;
114         LHASH *ltmp;
115         if(!(btmp = BIO_new_fp(in, BIO_NOCLOSE))) {
116                 CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB);
117                 return NULL;
118         }
119         ltmp = CONF_load_bio(h, btmp, line);
120         BIO_free(btmp);
121         return ltmp;
122 }
123
124 LHASH *CONF_load_bio(LHASH *h, BIO *in, long *line)
125         {
126         LHASH *ret=NULL;
127 #define BUFSIZE 512
128         char btmp[16];
129         int bufnum=0,i,ii;
130         BUF_MEM *buff=NULL;
131         char *s,*p,*end;
132         int again,n;
133         long eline=0;
134         CONF_VALUE *v=NULL,*vv,*tv;
135         CONF_VALUE *sv=NULL;
136         char *section=NULL,*buf;
137         STACK_OF(CONF_VALUE) *section_sk=NULL,*ts;
138         char *start,*psection,*pname;
139
140         if ((buff=BUF_MEM_new()) == NULL)
141                 {
142                 CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB);
143                 goto err;
144                 }
145
146         section=(char *)Malloc(10);
147         if (section == NULL)
148                 {
149                 CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE);
150                 goto err;
151                 }
152         strcpy(section,"default");
153
154         if (h == NULL)
155                 {
156                 if ((ret=lh_new(hash,cmp)) == NULL)
157                         {
158                         CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_MALLOC_FAILURE);
159                         goto err;
160                         }
161                 }
162         else
163                 ret=h;
164
165         sv=new_section(ret,section);
166         if (sv == NULL)
167                 {
168                 CONFerr(CONF_F_CONF_LOAD_BIO,
169                                         CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
170                 goto err;
171                 }
172         section_sk=(STACK_OF(CONF_VALUE) *)sv->value;
173
174         bufnum=0;
175         for (;;)
176                 {
177                 again=0;
178                 if (!BUF_MEM_grow(buff,bufnum+BUFSIZE))
179                         {
180                         CONFerr(CONF_F_CONF_LOAD_BIO,ERR_R_BUF_LIB);
181                         goto err;
182                         }
183                 p= &(buff->data[bufnum]);
184                 *p='\0';
185                 BIO_gets(in, p, BUFSIZE-1);
186                 p[BUFSIZE-1]='\0';
187                 ii=i=strlen(p);
188                 if (i == 0) break;
189                 while (i > 0)
190                         {
191                         if ((p[i-1] != '\r') && (p[i-1] != '\n'))
192                                 break;
193                         else
194                                 i--;
195                         }
196                 /* we removed some trailing stuff so there is a new
197                  * line on the end. */
198                 if (i == ii)
199                         again=1; /* long line */
200                 else
201                         {
202                         p[i]='\0';
203                         eline++; /* another input line */
204                         }
205
206                 /* we now have a line with trailing \r\n removed */
207
208                 /* i is the number of bytes */
209                 bufnum+=i;
210
211                 v=NULL;
212                 /* check for line continuation */
213                 if (bufnum >= 1)
214                         {
215                         /* If we have bytes and the last char '\\' and
216                          * second last char is not '\\' */
217                         p= &(buff->data[bufnum-1]);
218                         if (    IS_ESC(p[0]) &&
219                                 ((bufnum <= 1) || !IS_ESC(p[-1])))
220                                 {
221                                 bufnum--;
222                                 again=1;
223                                 }
224                         }
225                 if (again) continue;
226                 bufnum=0;
227                 buf=buff->data;
228
229                 clear_comments(buf);
230                 n=strlen(buf);
231                 s=eat_ws(buf);
232                 if (IS_EOF(*s)) continue; /* blank line */
233                 if (*s == '[')
234                         {
235                         char *ss;
236
237                         s++;
238                         start=eat_ws(s);
239                         ss=start;
240 again:
241                         end=eat_alpha_numeric(ss);
242                         p=eat_ws(end);
243                         if (*p != ']')
244                                 {
245                                 if (*p != '\0')
246                                         {
247                                         ss=p;
248                                         goto again;
249                                         }
250                                 CONFerr(CONF_F_CONF_LOAD_BIO,
251                                         CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
252                                 goto err;
253                                 }
254                         *end='\0';
255                         if (!str_copy(ret,NULL,&section,start)) goto err;
256                         if ((sv=get_section(ret,section)) == NULL)
257                                 sv=new_section(ret,section);
258                         if (sv == NULL)
259                                 {
260                                 CONFerr(CONF_F_CONF_LOAD_BIO,
261                                         CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
262                                 goto err;
263                                 }
264                         section_sk=(STACK_OF(CONF_VALUE) *)sv->value;
265                         continue;
266                         }
267                 else
268                         {
269                         pname=s;
270                         psection=NULL;
271                         end=eat_alpha_numeric(s);
272                         if ((end[0] == ':') && (end[1] == ':'))
273                                 {
274                                 *end='\0';
275                                 end+=2;
276                                 psection=pname;
277                                 pname=end;
278                                 end=eat_alpha_numeric(end);
279                                 }
280                         p=eat_ws(end);
281                         if (*p != '=')
282                                 {
283                                 CONFerr(CONF_F_CONF_LOAD_BIO,
284                                                 CONF_R_MISSING_EQUAL_SIGN);
285                                 goto err;
286                                 }
287                         *end='\0';
288                         p++;
289                         start=eat_ws(p);
290                         while (!IS_EOF(*p))
291                                 p++;
292                         p--;
293                         while ((p != start) && (IS_WS(*p)))
294                                 p--;
295                         p++;
296                         *p='\0';
297
298                         if (!(v=(CONF_VALUE *)Malloc(sizeof(CONF_VALUE))))
299                                 {
300                                 CONFerr(CONF_F_CONF_LOAD_BIO,
301                                                         ERR_R_MALLOC_FAILURE);
302                                 goto err;
303                                 }
304                         if (psection == NULL) psection=section;
305                         v->name=(char *)Malloc(strlen(pname)+1);
306                         v->value=NULL;
307                         if (v->name == NULL)
308                                 {
309                                 CONFerr(CONF_F_CONF_LOAD_BIO,
310                                                         ERR_R_MALLOC_FAILURE);
311                                 goto err;
312                                 }
313                         strcpy(v->name,pname);
314                         if (!str_copy(ret,psection,&(v->value),start)) goto err;
315
316                         if (strcmp(psection,section) != 0)
317                                 {
318                                 if ((tv=get_section(ret,psection))
319                                         == NULL)
320                                         tv=new_section(ret,psection);
321                                 if (tv == NULL)
322                                         {
323                                         CONFerr(CONF_F_CONF_LOAD_BIO,
324                                            CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
325                                         goto err;
326                                         }
327                                 ts=(STACK_OF(CONF_VALUE) *)tv->value;
328                                 }
329                         else
330                                 {
331                                 tv=sv;
332                                 ts=section_sk;
333                                 }
334                         v->section=tv->section; 
335                         if (!sk_CONF_VALUE_push(ts,v))
336                                 {
337                                 CONFerr(CONF_F_CONF_LOAD_BIO,
338                                                         ERR_R_MALLOC_FAILURE);
339                                 goto err;
340                                 }
341                         vv=(CONF_VALUE *)lh_insert(ret,(char *)v);
342                         if (vv != NULL)
343                                 {
344                                 sk_CONF_VALUE_delete_ptr(ts,vv);
345                                 Free(vv->name);
346                                 Free(vv->value);
347                                 Free(vv);
348                                 }
349                         v=NULL;
350                         }
351                 }
352         if (buff != NULL) BUF_MEM_free(buff);
353         if (section != NULL) Free(section);
354         return(ret);
355 err:
356         if (buff != NULL) BUF_MEM_free(buff);
357         if (section != NULL) Free(section);
358         if (line != NULL) *line=eline;
359         sprintf(btmp,"%ld",eline);
360         ERR_add_error_data(2,"line ",btmp);
361         if ((h != ret) && (ret != NULL)) CONF_free(ret);
362         if (v != NULL)
363                 {
364                 if (v->name != NULL) Free(v->name);
365                 if (v->value != NULL) Free(v->value);
366                 if (v != NULL) Free(v);
367                 }
368         return(NULL);
369         }
370
371 char *CONF_get_string(LHASH *conf, char *section, char *name)
372         {
373         CONF_VALUE *v,vv;
374         char *p;
375
376         if (name == NULL) return(NULL);
377         if (conf != NULL)
378                 {
379                 if (section != NULL)
380                         {
381                         vv.name=name;
382                         vv.section=section;
383                         v=(CONF_VALUE *)lh_retrieve(conf,(char *)&vv);
384                         if (v != NULL) return(v->value);
385                         if (strcmp(section,"ENV") == 0)
386                                 {
387                                 p=Getenv(name);
388                                 if (p != NULL) return(p);
389                                 }
390                         }
391                 vv.section="default";
392                 vv.name=name;
393                 v=(CONF_VALUE *)lh_retrieve(conf,(char *)&vv);
394                 if (v != NULL)
395                         return(v->value);
396                 else
397                         return(NULL);
398                 }
399         else
400                 return(Getenv(name));
401         }
402
403 static CONF_VALUE *get_section(LHASH *conf, char *section)
404         {
405         CONF_VALUE *v,vv;
406
407         if ((conf == NULL) || (section == NULL)) return(NULL);
408         vv.name=NULL;
409         vv.section=section;
410         v=(CONF_VALUE *)lh_retrieve(conf,(char *)&vv);
411         return(v);
412         }
413
414 STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf, char *section)
415         {
416         CONF_VALUE *v;
417
418         v=get_section(conf,section);
419         if (v != NULL)
420                 return((STACK_OF(CONF_VALUE) *)v->value);
421         else
422                 return(NULL);
423         }
424
425 long CONF_get_number(LHASH *conf, char *section, char *name)
426         {
427         char *str;
428         long ret=0;
429
430         str=CONF_get_string(conf,section,name);
431         if (str == NULL) return(0);
432         for (;;)
433                 {
434                 if (IS_NUMER(*str))
435                         ret=ret*10+(*str -'0');
436                 else
437                         return(ret);
438                 str++;
439                 }
440         }
441
442 void CONF_free(LHASH *conf)
443         {
444         if (conf == NULL) return;
445
446         conf->down_load=0;      /* evil thing to make sure the 'Free()'
447                                  * works as expected */
448         lh_doall_arg(conf,(void (*)())value_free_hash,(char *)conf);
449
450         /* We now have only 'section' entries in the hash table.
451          * Due to problems with */
452
453         lh_doall_arg(conf,(void (*)())value_free_stack,(char *)conf);
454         lh_free(conf);
455         }
456
457 static void value_free_hash(CONF_VALUE *a, LHASH *conf)
458         {
459         if (a->name != NULL)
460                 {
461                 a=(CONF_VALUE *)lh_delete(conf,(char *)a);
462                 }
463         }
464
465 static void value_free_stack(CONF_VALUE *a, LHASH *conf)
466         {
467         CONF_VALUE *vv;
468         STACK *sk;
469         int i;
470
471         if (a->name != NULL) return;
472
473         sk=(STACK *)a->value;
474         for (i=sk_num(sk)-1; i>=0; i--)
475                 {
476                 vv=(CONF_VALUE *)sk_value(sk,i);
477                 Free(vv->value);
478                 Free(vv->name);
479                 Free(vv);
480                 }
481         if (sk != NULL) sk_free(sk);
482         Free(a->section);
483         Free(a);
484         }
485
486 static void clear_comments(char *p)
487         {
488         char *to;
489
490         to=p;
491         for (;;)
492                 {
493                 if (IS_COMMENT(*p))
494                         {
495                         *p='\0';
496                         return;
497                         }
498                 if (IS_QUOTE(*p))
499                         {
500                         p=scan_quote(p);
501                         continue;
502                         }
503                 if (IS_ESC(*p))
504                         {
505                         p=scan_esc(p);
506                         continue;
507                         }
508                 if (IS_EOF(*p))
509                         return;
510                 else
511                         p++;
512                 }
513         }
514
515 static int str_copy(LHASH *conf, char *section, char **pto, char *from)
516         {
517         int q,r,rr=0,to=0,len=0;
518         char *s,*e,*rp,*p,*rrp,*np,*cp,v;
519         BUF_MEM *buf;
520
521         if ((buf=BUF_MEM_new()) == NULL) return(0);
522
523         len=strlen(from)+1;
524         if (!BUF_MEM_grow(buf,len)) goto err;
525
526         for (;;)
527                 {
528                 if (IS_QUOTE(*from))
529                         {
530                         q= *from;
531                         from++;
532                         while ((*from != '\0') && (*from != q))
533                                 {
534                                 if (*from == '\\')
535                                         {
536                                         from++;
537                                         if (*from == '\0') break;
538                                         }
539                                 buf->data[to++]= *(from++);
540                                 }
541                         }
542                 else if (*from == '\\')
543                         {
544                         from++;
545                         v= *(from++);
546                         if (v == '\0') break;
547                         else if (v == 'r') v='\r';
548                         else if (v == 'n') v='\n';
549                         else if (v == 'b') v='\b';
550                         else if (v == 't') v='\t';
551                         buf->data[to++]= v;
552                         }
553                 else if (*from == '\0')
554                         break;
555                 else if (*from == '$')
556                         {
557                         /* try to expand it */
558                         rrp=NULL;
559                         s= &(from[1]);
560                         if (*s == '{')
561                                 q='}';
562                         else if (*s == '(')
563                                 q=')';
564                         else q=0;
565
566                         if (q) s++;
567                         cp=section;
568                         e=np=s;
569                         while (IS_ALPHA_NUMERIC(*e))
570                                 e++;
571                         if ((e[0] == ':') && (e[1] == ':'))
572                                 {
573                                 cp=np;
574                                 rrp=e;
575                                 rr= *e;
576                                 *rrp='\0';
577                                 e+=2;
578                                 np=e;
579                                 while (IS_ALPHA_NUMERIC(*e))
580                                         e++;
581                                 }
582                         r= *e;
583                         *e='\0';
584                         rp=e;
585                         if (q)
586                                 {
587                                 if (r != q)
588                                         {
589                                         CONFerr(CONF_F_STR_COPY,CONF_R_NO_CLOSE_BRACE);
590                                         goto err;
591                                         }
592                                 e++;
593                                 }
594                         /* So at this point we have
595                          * ns which is the start of the name string which is
596                          *   '\0' terminated. 
597                          * cs which is the start of the section string which is
598                          *   '\0' terminated.
599                          * e is the 'next point after'.
600                          * r and s are the chars replaced by the '\0'
601                          * rp and sp is where 'r' and 's' came from.
602                          */
603                         p=CONF_get_string(conf,cp,np);
604                         if (rrp != NULL) *rrp=rr;
605                         *rp=r;
606                         if (p == NULL)
607                                 {
608                                 CONFerr(CONF_F_STR_COPY,CONF_R_VARIABLE_HAS_NO_VALUE);
609                                 goto err;
610                                 }
611                         BUF_MEM_grow(buf,(strlen(p)+len-(e-from)));
612                         while (*p)
613                                 buf->data[to++]= *(p++);
614                         from=e;
615                         }
616                 else
617                         buf->data[to++]= *(from++);
618                 }
619         buf->data[to]='\0';
620         if (*pto != NULL) Free(*pto);
621         *pto=buf->data;
622         Free(buf);
623         return(1);
624 err:
625         if (buf != NULL) BUF_MEM_free(buf);
626         return(0);
627         }
628
629 static char *eat_ws(char *p)
630         {
631         while (IS_WS(*p) && (!IS_EOF(*p)))
632                 p++;
633         return(p);
634         }
635
636 static char *eat_alpha_numeric(char *p)
637         {
638         for (;;)
639                 {
640                 if (IS_ESC(*p))
641                         {
642                         p=scan_esc(p);
643                         continue;
644                         }
645                 if (!IS_ALPHA_NUMERIC_PUNCT(*p))
646                         return(p);
647                 p++;
648                 }
649         }
650
651 static unsigned long hash(CONF_VALUE *v)
652         {
653         return((lh_strhash(v->section)<<2)^lh_strhash(v->name));
654         }
655
656 static int cmp(CONF_VALUE *a, CONF_VALUE *b)
657         {
658         int i;
659
660         if (a->section != b->section)
661                 {
662                 i=strcmp(a->section,b->section);
663                 if (i) return(i);
664                 }
665
666         if ((a->name != NULL) && (b->name != NULL))
667                 {
668                 i=strcmp(a->name,b->name);
669                 return(i);
670                 }
671         else if (a->name == b->name)
672                 return(0);
673         else
674                 return((a->name == NULL)?-1:1);
675         }
676
677 static char *scan_quote(char *p)
678         {
679         int q= *p;
680
681         p++;
682         while (!(IS_EOF(*p)) && (*p != q))
683                 {
684                 if (IS_ESC(*p))
685                         {
686                         p++;
687                         if (IS_EOF(*p)) return(p);
688                         }
689                 p++;
690                 }
691         if (*p == q) p++;
692         return(p);
693         }
694
695 static CONF_VALUE *new_section(LHASH *conf, char *section)
696         {
697         STACK *sk=NULL;
698         int ok=0,i;
699         CONF_VALUE *v=NULL,*vv;
700
701         if ((sk=sk_new_null()) == NULL)
702                 goto err;
703         if ((v=(CONF_VALUE *)Malloc(sizeof(CONF_VALUE))) == NULL)
704                 goto err;
705         i=strlen(section)+1;
706         if ((v->section=(char *)Malloc(i)) == NULL)
707                 goto err;
708
709         memcpy(v->section,section,i);
710         v->name=NULL;
711         v->value=(char *)sk;
712         
713         vv=(CONF_VALUE *)lh_insert(conf,(char *)v);
714         if (vv != NULL)
715                 {
716 #if !defined(NO_STDIO) && !defined(WIN16)
717                 fprintf(stderr,"internal fault\n");
718 #endif
719                 abort();
720                 }
721         ok=1;
722 err:
723         if (!ok)
724                 {
725                 if (sk != NULL) sk_free(sk);
726                 if (v != NULL) Free(v);
727                 v=NULL;
728                 }
729         return(v);
730         }
731
732 IMPLEMENT_STACK_OF(CONF_VALUE)