Change #include filenames from <foo.h> to <openssl.h>.
[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 #ifndef NOPROTO
71 static void value_free_hash(CONF_VALUE *a, LHASH *conf);
72 static void value_free_stack(CONF_VALUE *a,LHASH *conf);
73 static unsigned long hash(CONF_VALUE *v);
74 static int cmp(CONF_VALUE *a,CONF_VALUE *b);
75 static char *eat_ws(char *p);
76 static char *eat_alpha_numeric(char *p);
77 static void clear_comments(char *p);
78 static int str_copy(LHASH *conf,char *section,char **to, char *from);
79 static char *scan_quote(char *p);
80 static CONF_VALUE *new_section(LHASH *conf,char *section);
81 static CONF_VALUE *get_section(LHASH *conf,char *section);
82 #else
83 static void value_free_hash();
84 static void value_free_stack();
85 static unsigned long hash();
86 static int cmp();
87 static char *eat_ws();
88 static char *eat_alpha_numeric();
89 static void clear_comments();
90 static int str_copy();
91 static char *scan_quote();
92 static CONF_VALUE *new_section();
93 static CONF_VALUE *get_section();
94 #endif
95
96 #define scan_esc(p)     ((((p)[1] == '\0')?(p++):(p+=2)),p)
97
98 const char *CONF_version="CONF" OPENSSL_VERSION_PTEXT;
99
100 LHASH *CONF_load(LHASH *h, char *file, long *line)
101         {
102         LHASH *ret=NULL;
103         FILE *in=NULL;
104 #define BUFSIZE 512
105         char btmp[16];
106         int bufnum=0,i,ii;
107         BUF_MEM *buff=NULL;
108         char *s,*p,*end;
109         int again,n;
110         long eline=0;
111         CONF_VALUE *v=NULL,*vv,*tv;
112         CONF_VALUE *sv=NULL;
113         char *section=NULL,*buf;
114         STACK *section_sk=NULL,*ts;
115         char *start,*psection,*pname;
116
117         if ((buff=BUF_MEM_new()) == NULL)
118                 {
119                 CONFerr(CONF_F_CONF_LOAD,ERR_R_BUF_LIB);
120                 goto err;
121                 }
122
123         in=fopen(file,"rb");
124         if (in == NULL)
125                 {
126                 SYSerr(SYS_F_FOPEN,get_last_sys_error());
127                 ERR_set_error_data(BUF_strdup(file),
128                         ERR_TXT_MALLOCED|ERR_TXT_STRING);
129                 CONFerr(CONF_F_CONF_LOAD,ERR_R_SYS_LIB);
130                 goto err;
131                 }
132
133         section=(char *)Malloc(10);
134         if (section == NULL)
135                 {
136                 CONFerr(CONF_F_CONF_LOAD,ERR_R_MALLOC_FAILURE);
137                 goto err;
138                 }
139         strcpy(section,"default");
140
141         if (h == NULL)
142                 {
143                 if ((ret=lh_new(hash,cmp)) == NULL)
144                         {
145                         CONFerr(CONF_F_CONF_LOAD,ERR_R_MALLOC_FAILURE);
146                         goto err;
147                         }
148                 }
149         else
150                 ret=h;
151
152         sv=new_section(ret,section);
153         if (sv == NULL)
154                 {
155                 CONFerr(CONF_F_CONF_LOAD,CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
156                 goto err;
157                 }
158         section_sk=(STACK *)sv->value;
159
160         bufnum=0;
161         for (;;)
162                 {
163                 again=0;
164                 if (!BUF_MEM_grow(buff,bufnum+BUFSIZE))
165                         {
166                         CONFerr(CONF_F_CONF_LOAD,ERR_R_BUF_LIB);
167                         goto err;
168                         }
169                 p= &(buff->data[bufnum]);
170                 *p='\0';
171                 fgets(p,BUFSIZE-1,in);
172                 p[BUFSIZE-1]='\0';
173                 ii=i=strlen(p);
174                 if (i == 0) break;
175                 while (i > 0)
176                         {
177                         if ((p[i-1] != '\r') && (p[i-1] != '\n'))
178                                 break;
179                         else
180                                 i--;
181                         }
182                 /* we removed some trailing stuff so there is a new
183                  * line on the end. */
184                 if (i == ii)
185                         again=1; /* long line */
186                 else
187                         {
188                         p[i]='\0';
189                         eline++; /* another input line */
190                         }
191
192                 /* we now have a line with trailing \r\n removed */
193
194                 /* i is the number of bytes */
195                 bufnum+=i;
196
197                 v=NULL;
198                 /* check for line continuation */
199                 if (bufnum >= 1)
200                         {
201                         /* If we have bytes and the last char '\\' and
202                          * second last char is not '\\' */
203                         p= &(buff->data[bufnum-1]);
204                         if (    IS_ESC(p[0]) &&
205                                 ((bufnum <= 1) || !IS_ESC(p[-1])))
206                                 {
207                                 bufnum--;
208                                 again=1;
209                                 }
210                         }
211                 if (again) continue;
212                 bufnum=0;
213                 buf=buff->data;
214
215                 clear_comments(buf);
216                 n=strlen(buf);
217                 s=eat_ws(buf);
218                 if (IS_EOF(*s)) continue; /* blank line */
219                 if (*s == '[')
220                         {
221                         char *ss;
222
223                         s++;
224                         start=eat_ws(s);
225                         ss=start;
226 again:
227                         end=eat_alpha_numeric(ss);
228                         p=eat_ws(end);
229                         if (*p != ']')
230                                 {
231                                 if (*p != '\0')
232                                         {
233                                         ss=p;
234                                         goto again;
235                                         }
236                                 CONFerr(CONF_F_CONF_LOAD,CONF_R_MISSING_CLOSE_SQUARE_BRACKET);
237                                 goto err;
238                                 }
239                         *end='\0';
240                         if (!str_copy(ret,NULL,&section,start)) goto err;
241                         if ((sv=get_section(ret,section)) == NULL)
242                                 sv=new_section(ret,section);
243                         if (sv == NULL)
244                                 {
245                                 CONFerr(CONF_F_CONF_LOAD,CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
246                                 goto err;
247                                 }
248                         section_sk=(STACK *)sv->value;
249                         continue;
250                         }
251                 else
252                         {
253                         pname=s;
254                         psection=NULL;
255                         end=eat_alpha_numeric(s);
256                         if ((end[0] == ':') && (end[1] == ':'))
257                                 {
258                                 *end='\0';
259                                 end+=2;
260                                 psection=pname;
261                                 pname=end;
262                                 end=eat_alpha_numeric(end);
263                                 }
264                         p=eat_ws(end);
265                         if (*p != '=')
266                                 {
267                                 CONFerr(CONF_F_CONF_LOAD,CONF_R_MISSING_EQUAL_SIGN);
268                                 goto err;
269                                 }
270                         *end='\0';
271                         p++;
272                         start=eat_ws(p);
273                         while (!IS_EOF(*p))
274                                 p++;
275                         p--;
276                         while ((p != start) && (IS_WS(*p)))
277                                 p--;
278                         p++;
279                         *p='\0';
280
281                         if ((v=(CONF_VALUE *)Malloc(sizeof(CONF_VALUE))) == NULL)
282                                 {
283                                 CONFerr(CONF_F_CONF_LOAD,ERR_R_MALLOC_FAILURE);
284                                 goto err;
285                                 }
286                         if (psection == NULL) psection=section;
287                         v->name=(char *)Malloc(strlen(pname)+1);
288                         v->value=NULL;
289                         if (v->name == NULL)
290                                 {
291                                 CONFerr(CONF_F_CONF_LOAD,ERR_R_MALLOC_FAILURE);
292                                 goto err;
293                                 }
294                         strcpy(v->name,pname);
295                         if (!str_copy(ret,psection,&(v->value),start)) goto err;
296
297                         if (strcmp(psection,section) != 0)
298                                 {
299                                 if ((tv=get_section(ret,psection))
300                                         == NULL)
301                                         tv=new_section(ret,psection);
302                                 if (tv == NULL)
303                                         {
304                                         CONFerr(CONF_F_CONF_LOAD,CONF_R_UNABLE_TO_CREATE_NEW_SECTION);
305                                         goto err;
306                                         }
307                                 ts=(STACK *)tv->value;
308                                 }
309                         else
310                                 {
311                                 tv=sv;
312                                 ts=section_sk;
313                                 }
314                         v->section=tv->section; 
315                         if (!sk_push(ts,(char *)v))
316                                 {
317                                 CONFerr(CONF_F_CONF_LOAD,ERR_R_MALLOC_FAILURE);
318                                 goto err;
319                                 }
320                         vv=(CONF_VALUE *)lh_insert(ret,(char *)v);
321                         if (vv != NULL)
322                                 {
323                                 sk_delete_ptr(ts,(char *)vv);
324                                 Free(vv->name);
325                                 Free(vv->value);
326                                 Free(vv);
327                                 }
328                         v=NULL;
329                         }
330                 }
331         if (buff != NULL) BUF_MEM_free(buff);
332         if (section != NULL) Free(section);
333         if (in != NULL) fclose(in);
334         return(ret);
335 err:
336         if (buff != NULL) BUF_MEM_free(buff);
337         if (section != NULL) Free(section);
338         if (line != NULL) *line=eline;
339         sprintf(btmp,"%ld",eline);
340         ERR_add_error_data(2,"line ",btmp);
341         if (in != NULL) fclose(in);
342         if ((h != ret) && (ret != NULL)) CONF_free(ret);
343         if (v != NULL)
344                 {
345                 if (v->name != NULL) Free(v->name);
346                 if (v->value != NULL) Free(v->value);
347                 if (v != NULL) Free(v);
348                 }
349         return(NULL);
350         }
351                 
352 char *CONF_get_string(LHASH *conf, char *section, char *name)
353         {
354         CONF_VALUE *v,vv;
355         char *p;
356
357         if (name == NULL) return(NULL);
358         if (conf != NULL)
359                 {
360                 if (section != NULL)
361                         {
362                         vv.name=name;
363                         vv.section=section;
364                         v=(CONF_VALUE *)lh_retrieve(conf,(char *)&vv);
365                         if (v != NULL) return(v->value);
366                         if (strcmp(section,"ENV") == 0)
367                                 {
368                                 p=Getenv(name);
369                                 if (p != NULL) return(p);
370                                 }
371                         }
372                 vv.section=BUF_strdup("default");
373                 vv.name=name;
374                 v=(CONF_VALUE *)lh_retrieve(conf,(char *)&vv);
375                 if (v != NULL)
376                         return(v->value);
377                 else
378                         return(NULL);
379                 }
380         else
381                 return(Getenv(name));
382         }
383
384 static CONF_VALUE *get_section(LHASH *conf, char *section)
385         {
386         CONF_VALUE *v,vv;
387
388         if ((conf == NULL) || (section == NULL)) return(NULL);
389         vv.name=NULL;
390         vv.section=section;
391         v=(CONF_VALUE *)lh_retrieve(conf,(char *)&vv);
392         return(v);
393         }
394
395 STACK *CONF_get_section(LHASH *conf, char *section)
396         {
397         CONF_VALUE *v;
398
399         v=get_section(conf,section);
400         if (v != NULL)
401                 return((STACK *)v->value);
402         else
403                 return(NULL);
404         }
405
406 long CONF_get_number(LHASH *conf, char *section, char *name)
407         {
408         char *str;
409         long ret=0;
410
411         str=CONF_get_string(conf,section,name);
412         if (str == NULL) return(0);
413         for (;;)
414                 {
415                 if (IS_NUMER(*str))
416                         ret=ret*10+(*str -'0');
417                 else
418                         return(ret);
419                 str++;
420                 }
421         }
422
423 void CONF_free(LHASH *conf)
424         {
425         if (conf == NULL) return;
426
427         conf->down_load=0;      /* evil thing to make sure the 'Free()'
428                                  * works as expected */
429         lh_doall_arg(conf,(void (*)())value_free_hash,(char *)conf);
430
431         /* We now have only 'section' entries in the hash table.
432          * Due to problems with */
433
434         lh_doall_arg(conf,(void (*)())value_free_stack,(char *)conf);
435         lh_free(conf);
436         }
437
438 static void value_free_hash(CONF_VALUE *a, LHASH *conf)
439         {
440         if (a->name != NULL)
441                 {
442                 a=(CONF_VALUE *)lh_delete(conf,(char *)a);
443                 }
444         }
445
446 static void value_free_stack(CONF_VALUE *a, LHASH *conf)
447         {
448         CONF_VALUE *vv;
449         STACK *sk;
450         int i;
451
452         if (a->name != NULL) return;
453
454         sk=(STACK *)a->value;
455         for (i=sk_num(sk)-1; i>=0; i--)
456                 {
457                 vv=(CONF_VALUE *)sk_value(sk,i);
458                 Free(vv->value);
459                 Free(vv->name);
460                 Free(vv);
461                 }
462         if (sk != NULL) sk_free(sk);
463         Free(a->section);
464         Free(a);
465         }
466
467 static void clear_comments(char *p)
468         {
469         char *to;
470
471         to=p;
472         for (;;)
473                 {
474                 if (IS_COMMENT(*p))
475                         {
476                         *p='\0';
477                         return;
478                         }
479                 if (IS_QUOTE(*p))
480                         {
481                         p=scan_quote(p);
482                         continue;
483                         }
484                 if (IS_ESC(*p))
485                         {
486                         p=scan_esc(p);
487                         continue;
488                         }
489                 if (IS_EOF(*p))
490                         return;
491                 else
492                         p++;
493                 }
494         }
495
496 static int str_copy(LHASH *conf, char *section, char **pto, char *from)
497         {
498         int q,r,rr=0,to=0,len=0;
499         char *s,*e,*rp,*p,*rrp,*np,*cp,v;
500         BUF_MEM *buf;
501
502         if ((buf=BUF_MEM_new()) == NULL) return(0);
503
504         len=strlen(from)+1;
505         if (!BUF_MEM_grow(buf,len)) goto err;
506
507         for (;;)
508                 {
509                 if (IS_QUOTE(*from))
510                         {
511                         q= *from;
512                         from++;
513                         while ((*from != '\0') && (*from != q))
514                                 {
515                                 if (*from == '\\')
516                                         {
517                                         from++;
518                                         if (*from == '\0') break;
519                                         }
520                                 buf->data[to++]= *(from++);
521                                 }
522                         }
523                 else if (*from == '\\')
524                         {
525                         from++;
526                         v= *(from++);
527                         if (v == '\0') break;
528                         else if (v == 'r') v='\r';
529                         else if (v == 'n') v='\n';
530                         else if (v == 'b') v='\b';
531                         else if (v == 't') v='\t';
532                         buf->data[to++]= v;
533                         }
534                 else if (*from == '\0')
535                         break;
536                 else if (*from == '$')
537                         {
538                         /* try to expand it */
539                         rrp=NULL;
540                         s= &(from[1]);
541                         if (*s == '{')
542                                 q='}';
543                         else if (*s == '(')
544                                 q=')';
545                         else q=0;
546
547                         if (q) s++;
548                         cp=section;
549                         e=np=s;
550                         while (IS_ALPHA_NUMERIC(*e))
551                                 e++;
552                         if ((e[0] == ':') && (e[1] == ':'))
553                                 {
554                                 cp=np;
555                                 rrp=e;
556                                 rr= *e;
557                                 *rrp='\0';
558                                 e+=2;
559                                 np=e;
560                                 while (IS_ALPHA_NUMERIC(*e))
561                                         e++;
562                                 }
563                         r= *e;
564                         *e='\0';
565                         rp=e;
566                         if (q)
567                                 {
568                                 if (r != q)
569                                         {
570                                         CONFerr(CONF_F_STR_COPY,CONF_R_NO_CLOSE_BRACE);
571                                         goto err;
572                                         }
573                                 e++;
574                                 }
575                         /* So at this point we have
576                          * ns which is the start of the name string which is
577                          *   '\0' terminated. 
578                          * cs which is the start of the section string which is
579                          *   '\0' terminated.
580                          * e is the 'next point after'.
581                          * r and s are the chars replaced by the '\0'
582                          * rp and sp is where 'r' and 's' came from.
583                          */
584                         p=CONF_get_string(conf,cp,np);
585                         if (rrp != NULL) *rrp=rr;
586                         *rp=r;
587                         if (p == NULL)
588                                 {
589                                 CONFerr(CONF_F_STR_COPY,CONF_R_VARIABLE_HAS_NO_VALUE);
590                                 goto err;
591                                 }
592                         BUF_MEM_grow(buf,(strlen(p)+len-(e-from)));
593                         while (*p)
594                                 buf->data[to++]= *(p++);
595                         from=e;
596                         }
597                 else
598                         buf->data[to++]= *(from++);
599                 }
600         buf->data[to]='\0';
601         if (*pto != NULL) Free(*pto);
602         *pto=buf->data;
603         Free(buf);
604         return(1);
605 err:
606         if (buf != NULL) BUF_MEM_free(buf);
607         return(0);
608         }
609
610 static char *eat_ws(char *p)
611         {
612         while (IS_WS(*p) && (!IS_EOF(*p)))
613                 p++;
614         return(p);
615         }
616
617 static char *eat_alpha_numeric(char *p)
618         {
619         for (;;)
620                 {
621                 if (IS_ESC(*p))
622                         {
623                         p=scan_esc(p);
624                         continue;
625                         }
626                 if (!IS_ALPHA_NUMERIC_PUNCT(*p))
627                         return(p);
628                 p++;
629                 }
630         }
631
632 static unsigned long hash(CONF_VALUE *v)
633         {
634         return((lh_strhash(v->section)<<2)^lh_strhash(v->name));
635         }
636
637 static int cmp(CONF_VALUE *a, CONF_VALUE *b)
638         {
639         int i;
640
641         if (a->section != b->section)
642                 {
643                 i=strcmp(a->section,b->section);
644                 if (i) return(i);
645                 }
646
647         if ((a->name != NULL) && (b->name != NULL))
648                 {
649                 i=strcmp(a->name,b->name);
650                 return(i);
651                 }
652         else if (a->name == b->name)
653                 return(0);
654         else
655                 return((a->name == NULL)?-1:1);
656         }
657
658 static char *scan_quote(char *p)
659         {
660         int q= *p;
661
662         p++;
663         while (!(IS_EOF(*p)) && (*p != q))
664                 {
665                 if (IS_ESC(*p))
666                         {
667                         p++;
668                         if (IS_EOF(*p)) return(p);
669                         }
670                 p++;
671                 }
672         if (*p == q) p++;
673         return(p);
674         }
675
676 static CONF_VALUE *new_section(LHASH *conf, char *section)
677         {
678         STACK *sk=NULL;
679         int ok=0,i;
680         CONF_VALUE *v=NULL,*vv;
681
682         if ((sk=sk_new_null()) == NULL)
683                 goto err;
684         if ((v=(CONF_VALUE *)Malloc(sizeof(CONF_VALUE))) == NULL)
685                 goto err;
686         i=strlen(section)+1;
687         if ((v->section=(char *)Malloc(i)) == NULL)
688                 goto err;
689
690         memcpy(v->section,section,i);
691         v->name=NULL;
692         v->value=(char *)sk;
693         
694         vv=(CONF_VALUE *)lh_insert(conf,(char *)v);
695         if (vv != NULL)
696                 {
697 #if !defined(NO_STDIO) && !defined(WIN16)
698                 fprintf(stderr,"internal fault\n");
699 #endif
700                 abort();
701                 }
702         ok=1;
703 err:
704         if (!ok)
705                 {
706                 if (sk != NULL) sk_free(sk);
707                 if (v != NULL) Free(v);
708                 v=NULL;
709                 }
710         return(v);
711         }