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