188b2373aa0a05a1e78c86991ef7c4cc948e3506
[openssl.git] / apps / apps.c
1 /* apps/apps.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  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
60  *
61  * Redistribution and use in source and binary forms, with or without
62  * modification, are permitted provided that the following conditions
63  * are met:
64  *
65  * 1. Redistributions of source code must retain the above copyright
66  *    notice, this list of conditions and the following disclaimer. 
67  *
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in
70  *    the documentation and/or other materials provided with the
71  *    distribution.
72  *
73  * 3. All advertising materials mentioning features or use of this
74  *    software must display the following acknowledgment:
75  *    "This product includes software developed by the OpenSSL Project
76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77  *
78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79  *    endorse or promote products derived from this software without
80  *    prior written permission. For written permission, please contact
81  *    openssl-core@openssl.org.
82  *
83  * 5. Products derived from this software may not be called "OpenSSL"
84  *    nor may "OpenSSL" appear in their names without prior written
85  *    permission of the OpenSSL Project.
86  *
87  * 6. Redistributions of any form whatsoever must retain the following
88  *    acknowledgment:
89  *    "This product includes software developed by the OpenSSL Project
90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103  * OF THE POSSIBILITY OF SUCH DAMAGE.
104  * ====================================================================
105  *
106  * This product includes cryptographic software written by Eric Young
107  * (eay@cryptsoft.com).  This product includes software written by Tim
108  * Hudson (tjh@cryptsoft.com).
109  *
110  */
111
112 #if !defined(_POSIX_C_SOURCE) && defined(OPENSSL_SYS_VMS)
113 #define _POSIX_C_SOURCE 2       /* On VMS, you need to define this to get
114                                    the declaration of fileno().  The value
115                                    2 is to make sure no function defined
116                                    in POSIX-2 is left undefined. */
117 #endif
118 #include <stdio.h>
119 #include <stdlib.h>
120 #include <string.h>
121 #if !defined(OPENSSL_SYSNAME_WIN32) && !defined(OPENSSL_SYSNAME_WINCE) && !defined(NETWARE_CLIB)
122 #include <strings.h>
123 #endif
124 #include <sys/types.h>
125 #include <ctype.h>
126 #include <errno.h>
127 #include <assert.h>
128 #include <openssl/err.h>
129 #include <openssl/x509.h>
130 #include <openssl/x509v3.h>
131 #include <openssl/pem.h>
132 #include <openssl/pkcs12.h>
133 #include <openssl/ui.h>
134 #include <openssl/safestack.h>
135 #ifndef OPENSSL_NO_ENGINE
136 #include <openssl/engine.h>
137 #endif
138 #ifndef OPENSSL_NO_RSA
139 #include <openssl/rsa.h>
140 #endif
141 #include <openssl/bn.h>
142 #ifndef OPENSSL_NO_JPAKE
143 #include <openssl/jpake.h>
144 #endif
145
146 #define NON_MAIN
147 #include "apps.h"
148 #undef NON_MAIN
149
150 #ifdef _WIN32
151 static int WIN32_rename(const char *from, const char *to);
152 #define rename(from,to) WIN32_rename((from),(to))
153 #endif
154
155 typedef struct {
156         const char *name;
157         unsigned long flag;
158         unsigned long mask;
159 } NAME_EX_TBL;
160
161 static UI_METHOD *ui_method = NULL;
162
163 static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
164 static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
165
166 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
167 /* Looks like this stuff is worth moving into separate function */
168 static EVP_PKEY *
169 load_netscape_key(BIO *err, BIO *key, const char *file,
170                 const char *key_descrip, int format);
171 #endif
172
173 int app_init(long mesgwin);
174 #ifdef undef /* never finished - probably never will be :-) */
175 int args_from_file(char *file, int *argc, char **argv[])
176         {
177         FILE *fp;
178         int num,i;
179         unsigned int len;
180         static char *buf=NULL;
181         static char **arg=NULL;
182         char *p;
183
184         fp=fopen(file,"r");
185         if (fp == NULL)
186                 return(0);
187
188         if (fseek(fp,0,SEEK_END)==0)
189                 len=ftell(fp), rewind(fp);
190         else    len=-1;
191         if (len<=0)
192                 {
193                 fclose(fp);
194                 return(0);
195                 }
196
197         *argc=0;
198         *argv=NULL;
199
200         if (buf != NULL) OPENSSL_free(buf);
201         buf=(char *)OPENSSL_malloc(len+1);
202         if (buf == NULL) return(0);
203
204         len=fread(buf,1,len,fp);
205         if (len <= 1) return(0);
206         buf[len]='\0';
207
208         i=0;
209         for (p=buf; *p; p++)
210                 if (*p == '\n') i++;
211         if (arg != NULL) OPENSSL_free(arg);
212         arg=(char **)OPENSSL_malloc(sizeof(char *)*(i*2));
213
214         *argv=arg;
215         num=0;
216         p=buf;
217         for (;;)
218                 {
219                 if (!*p) break;
220                 if (*p == '#') /* comment line */
221                         {
222                         while (*p && (*p != '\n')) p++;
223                         continue;
224                         }
225                 /* else we have a line */
226                 *(arg++)=p;
227                 num++;
228                 while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
229                         p++;
230                 if (!*p) break;
231                 if (*p == '\n')
232                         {
233                         *(p++)='\0';
234                         continue;
235                         }
236                 /* else it is a tab or space */
237                 p++;
238                 while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
239                         p++;
240                 if (!*p) break;
241                 if (*p == '\n')
242                         {
243                         p++;
244                         continue;
245                         }
246                 *(arg++)=p++;
247                 num++;
248                 while (*p && (*p != '\n')) p++;
249                 if (!*p) break;
250                 /* else *p == '\n' */
251                 *(p++)='\0';
252                 }
253         *argc=num;
254         return(1);
255         }
256 #endif
257
258 int str2fmt(char *s)
259         {
260         if (s == NULL)
261                 return FORMAT_UNDEF;
262         if      ((*s == 'D') || (*s == 'd'))
263                 return(FORMAT_ASN1);
264         else if ((*s == 'T') || (*s == 't'))
265                 return(FORMAT_TEXT);
266         else if ((strcmp(s,"NSS") == 0) || (strcmp(s,"nss") == 0))
267                 return(FORMAT_NSS);
268         else if ((*s == 'N') || (*s == 'n'))
269                 return(FORMAT_NETSCAPE);
270         else if ((*s == 'S') || (*s == 's'))
271                 return(FORMAT_SMIME);
272         else if ((*s == 'M') || (*s == 'm'))
273                 return(FORMAT_MSBLOB);
274         else if ((*s == '1')
275                 || (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0)
276                 || (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0))
277                 return(FORMAT_PKCS12);
278         else if ((*s == 'E') || (*s == 'e'))
279                 return(FORMAT_ENGINE);
280         else if ((*s == 'H') || (*s == 'h'))
281                 return FORMAT_HTTP;
282         else if ((*s == 'P') || (*s == 'p'))
283                 {
284                 if (s[1] == 'V' || s[1] == 'v')
285                         return FORMAT_PVK;
286                 else
287                         return(FORMAT_PEM);
288                 }
289         else
290                 return(FORMAT_UNDEF);
291         }
292
293 #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE)
294 void program_name(char *in, char *out, int size)
295         {
296         int i,n;
297         char *p=NULL;
298
299         n=strlen(in);
300         /* find the last '/', '\' or ':' */
301         for (i=n-1; i>0; i--)
302                 {
303                 if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':'))
304                         {
305                         p= &(in[i+1]);
306                         break;
307                         }
308                 }
309         if (p == NULL)
310                 p=in;
311         n=strlen(p);
312
313 #if defined(OPENSSL_SYS_NETWARE)
314    /* strip off trailing .nlm if present. */
315    if ((n > 4) && (p[n-4] == '.') &&
316       ((p[n-3] == 'n') || (p[n-3] == 'N')) &&
317       ((p[n-2] == 'l') || (p[n-2] == 'L')) &&
318       ((p[n-1] == 'm') || (p[n-1] == 'M')))
319       n-=4;
320 #else
321         /* strip off trailing .exe if present. */
322         if ((n > 4) && (p[n-4] == '.') &&
323                 ((p[n-3] == 'e') || (p[n-3] == 'E')) &&
324                 ((p[n-2] == 'x') || (p[n-2] == 'X')) &&
325                 ((p[n-1] == 'e') || (p[n-1] == 'E')))
326                 n-=4;
327 #endif
328
329         if (n > size-1)
330                 n=size-1;
331
332         for (i=0; i<n; i++)
333                 {
334                 if ((p[i] >= 'A') && (p[i] <= 'Z'))
335                         out[i]=p[i]-'A'+'a';
336                 else
337                         out[i]=p[i];
338                 }
339         out[n]='\0';
340         }
341 #else
342 #ifdef OPENSSL_SYS_VMS
343 void program_name(char *in, char *out, int size)
344         {
345         char *p=in, *q;
346         char *chars=":]>";
347
348         while(*chars != '\0')
349                 {
350                 q=strrchr(p,*chars);
351                 if (q > p)
352                         p = q + 1;
353                 chars++;
354                 }
355
356         q=strrchr(p,'.');
357         if (q == NULL)
358                 q = p + strlen(p);
359         strncpy(out,p,size-1);
360         if (q-p >= size)
361                 {
362                 out[size-1]='\0';
363                 }
364         else
365                 {
366                 out[q-p]='\0';
367                 }
368         }
369 #else
370 void program_name(char *in, char *out, int size)
371         {
372         char *p;
373
374         p=strrchr(in,'/');
375         if (p != NULL)
376                 p++;
377         else
378                 p=in;
379         BUF_strlcpy(out,p,size);
380         }
381 #endif
382 #endif
383
384 int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
385         {
386         int num,i;
387         char *p;
388
389         *argc=0;
390         *argv=NULL;
391
392         i=0;
393         if (arg->count == 0)
394                 {
395                 arg->count=20;
396                 arg->data=(char **)OPENSSL_malloc(sizeof(char *)*arg->count);
397                 if (arg->data == NULL)
398                         return 0;
399                 }
400         for (i=0; i<arg->count; i++)
401                 arg->data[i]=NULL;
402
403         num=0;
404         p=buf;
405         for (;;)
406                 {
407                 /* first scan over white space */
408                 if (!*p) break;
409                 while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
410                         p++;
411                 if (!*p) break;
412
413                 /* The start of something good :-) */
414                 if (num >= arg->count)
415                         {
416                         char **tmp_p;
417                         int tlen = arg->count + 20;
418                         tmp_p = (char **)OPENSSL_realloc(arg->data,
419                                 sizeof(char *)*tlen);
420                         if (tmp_p == NULL)
421                                 return 0;
422                         arg->data  = tmp_p;
423                         arg->count = tlen;
424                         /* initialize newly allocated data */
425                         for (i = num; i < arg->count; i++)
426                                 arg->data[i] = NULL;
427                         }
428                 arg->data[num++]=p;
429
430                 /* now look for the end of this */
431                 if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */
432                         {
433                         i= *(p++);
434                         arg->data[num-1]++; /* jump over quote */
435                         while (*p && (*p != i))
436                                 p++;
437                         *p='\0';
438                         }
439                 else
440                         {
441                         while (*p && ((*p != ' ') &&
442                                 (*p != '\t') && (*p != '\n')))
443                                 p++;
444
445                         if (*p == '\0')
446                                 p--;
447                         else
448                                 *p='\0';
449                         }
450                 p++;
451                 }
452         *argc=num;
453         *argv=arg->data;
454         return(1);
455         }
456
457 #ifndef APP_INIT
458 int app_init(long mesgwin)
459         {
460         return(1);
461         }
462 #endif
463
464
465 int dump_cert_text (BIO *out, X509 *x)
466 {
467         char *p;
468
469         p=X509_NAME_oneline(X509_get_subject_name(x),NULL,0);
470         BIO_puts(out,"subject=");
471         BIO_puts(out,p);
472         OPENSSL_free(p);
473
474         p=X509_NAME_oneline(X509_get_issuer_name(x),NULL,0);
475         BIO_puts(out,"\nissuer=");
476         BIO_puts(out,p);
477         BIO_puts(out,"\n");
478         OPENSSL_free(p);
479
480         return 0;
481 }
482
483 static int ui_open(UI *ui)
484         {
485         return UI_method_get_opener(UI_OpenSSL())(ui);
486         }
487 static int ui_read(UI *ui, UI_STRING *uis)
488         {
489         if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
490                 && UI_get0_user_data(ui))
491                 {
492                 switch(UI_get_string_type(uis))
493                         {
494                 case UIT_PROMPT:
495                 case UIT_VERIFY:
496                         {
497                         const char *password =
498                                 ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
499                         if (password && password[0] != '\0')
500                                 {
501                                 UI_set_result(ui, uis, password);
502                                 return 1;
503                                 }
504                         }
505                 default:
506                         break;
507                         }
508                 }
509         return UI_method_get_reader(UI_OpenSSL())(ui, uis);
510         }
511 static int ui_write(UI *ui, UI_STRING *uis)
512         {
513         if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
514                 && UI_get0_user_data(ui))
515                 {
516                 switch(UI_get_string_type(uis))
517                         {
518                 case UIT_PROMPT:
519                 case UIT_VERIFY:
520                         {
521                         const char *password =
522                                 ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
523                         if (password && password[0] != '\0')
524                                 return 1;
525                         }
526                 default:
527                         break;
528                         }
529                 }
530         return UI_method_get_writer(UI_OpenSSL())(ui, uis);
531         }
532 static int ui_close(UI *ui)
533         {
534         return UI_method_get_closer(UI_OpenSSL())(ui);
535         }
536 int setup_ui_method(void)
537         {
538         ui_method = UI_create_method("OpenSSL application user interface");
539         UI_method_set_opener(ui_method, ui_open);
540         UI_method_set_reader(ui_method, ui_read);
541         UI_method_set_writer(ui_method, ui_write);
542         UI_method_set_closer(ui_method, ui_close);
543         return 0;
544         }
545 void destroy_ui_method(void)
546         {
547         if(ui_method)
548                 {
549                 UI_destroy_method(ui_method);
550                 ui_method = NULL;
551                 }
552         }
553 int password_callback(char *buf, int bufsiz, int verify,
554         PW_CB_DATA *cb_tmp)
555         {
556         UI *ui = NULL;
557         int res = 0;
558         const char *prompt_info = NULL;
559         const char *password = NULL;
560         PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
561
562         if (cb_data)
563                 {
564                 if (cb_data->password)
565                         password = cb_data->password;
566                 if (cb_data->prompt_info)
567                         prompt_info = cb_data->prompt_info;
568                 }
569
570         if (password)
571                 {
572                 res = strlen(password);
573                 if (res > bufsiz)
574                         res = bufsiz;
575                 memcpy(buf, password, res);
576                 return res;
577                 }
578
579         ui = UI_new_method(ui_method);
580         if (ui)
581                 {
582                 int ok = 0;
583                 char *buff = NULL;
584                 int ui_flags = 0;
585                 char *prompt = NULL;
586
587                 prompt = UI_construct_prompt(ui, "pass phrase",
588                         prompt_info);
589
590                 ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
591                 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
592
593                 if (ok >= 0)
594                         ok = UI_add_input_string(ui,prompt,ui_flags,buf,
595                                 PW_MIN_LENGTH,bufsiz-1);
596                 if (ok >= 0 && verify)
597                         {
598                         buff = (char *)OPENSSL_malloc(bufsiz);
599                         ok = UI_add_verify_string(ui,prompt,ui_flags,buff,
600                                 PW_MIN_LENGTH,bufsiz-1, buf);
601                         }
602                 if (ok >= 0)
603                         do
604                                 {
605                                 ok = UI_process(ui);
606                                 }
607                         while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
608
609                 if (buff)
610                         {
611                         OPENSSL_cleanse(buff,(unsigned int)bufsiz);
612                         OPENSSL_free(buff);
613                         }
614
615                 if (ok >= 0)
616                         res = strlen(buf);
617                 if (ok == -1)
618                         {
619                         BIO_printf(bio_err, "User interface error\n");
620                         ERR_print_errors(bio_err);
621                         OPENSSL_cleanse(buf,(unsigned int)bufsiz);
622                         res = 0;
623                         }
624                 if (ok == -2)
625                         {
626                         BIO_printf(bio_err,"aborted!\n");
627                         OPENSSL_cleanse(buf,(unsigned int)bufsiz);
628                         res = 0;
629                         }
630                 UI_free(ui);
631                 OPENSSL_free(prompt);
632                 }
633         return res;
634         }
635
636 static char *app_get_pass(BIO *err, char *arg, int keepbio);
637
638 int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
639 {
640         int same;
641         if(!arg2 || !arg1 || strcmp(arg1, arg2)) same = 0;
642         else same = 1;
643         if(arg1) {
644                 *pass1 = app_get_pass(err, arg1, same);
645                 if(!*pass1) return 0;
646         } else if(pass1) *pass1 = NULL;
647         if(arg2) {
648                 *pass2 = app_get_pass(err, arg2, same ? 2 : 0);
649                 if(!*pass2) return 0;
650         } else if(pass2) *pass2 = NULL;
651         return 1;
652 }
653
654 static char *app_get_pass(BIO *err, char *arg, int keepbio)
655 {
656         char *tmp, tpass[APP_PASS_LEN];
657         static BIO *pwdbio = NULL;
658         int i;
659         if(!strncmp(arg, "pass:", 5)) return BUF_strdup(arg + 5);
660         if(!strncmp(arg, "env:", 4)) {
661                 tmp = getenv(arg + 4);
662                 if(!tmp) {
663                         BIO_printf(err, "Can't read environment variable %s\n", arg + 4);
664                         return NULL;
665                 }
666                 return BUF_strdup(tmp);
667         }
668         if(!keepbio || !pwdbio) {
669                 if(!strncmp(arg, "file:", 5)) {
670                         pwdbio = BIO_new_file(arg + 5, "r");
671                         if(!pwdbio) {
672                                 BIO_printf(err, "Can't open file %s\n", arg + 5);
673                                 return NULL;
674                         }
675 #if !defined(_WIN32)
676                 /*
677                  * Under _WIN32, which covers even Win64 and CE, file
678                  * descriptors referenced by BIO_s_fd are not inherited
679                  * by child process and therefore below is not an option.
680                  * It could have been an option if bss_fd.c was operating
681                  * on real Windows descriptors, such as those obtained
682                  * with CreateFile.
683                  */
684                 } else if(!strncmp(arg, "fd:", 3)) {
685                         BIO *btmp;
686                         i = atoi(arg + 3);
687                         if(i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
688                         if((i < 0) || !pwdbio) {
689                                 BIO_printf(err, "Can't access file descriptor %s\n", arg + 3);
690                                 return NULL;
691                         }
692                         /* Can't do BIO_gets on an fd BIO so add a buffering BIO */
693                         btmp = BIO_new(BIO_f_buffer());
694                         pwdbio = BIO_push(btmp, pwdbio);
695 #endif
696                 } else if(!strcmp(arg, "stdin")) {
697                         pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
698                         if(!pwdbio) {
699                                 BIO_printf(err, "Can't open BIO for stdin\n");
700                                 return NULL;
701                         }
702                 } else {
703                         BIO_printf(err, "Invalid password argument \"%s\"\n", arg);
704                         return NULL;
705                 }
706         }
707         i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
708         if(keepbio != 1) {
709                 BIO_free_all(pwdbio);
710                 pwdbio = NULL;
711         }
712         if(i <= 0) {
713                 BIO_printf(err, "Error reading password from BIO\n");
714                 return NULL;
715         }
716         tmp = strchr(tpass, '\n');
717         if(tmp) *tmp = 0;
718         return BUF_strdup(tpass);
719 }
720
721 int add_oid_section(BIO *err, CONF *conf)
722 {       
723         char *p;
724         STACK_OF(CONF_VALUE) *sktmp;
725         CONF_VALUE *cnf;
726         int i;
727         if(!(p=NCONF_get_string(conf,NULL,"oid_section")))
728                 {
729                 ERR_clear_error();
730                 return 1;
731                 }
732         if(!(sktmp = NCONF_get_section(conf, p))) {
733                 BIO_printf(err, "problem loading oid section %s\n", p);
734                 return 0;
735         }
736         for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
737                 cnf = sk_CONF_VALUE_value(sktmp, i);
738                 if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
739                         BIO_printf(err, "problem creating object %s=%s\n",
740                                                          cnf->name, cnf->value);
741                         return 0;
742                 }
743         }
744         return 1;
745 }
746
747 static int load_pkcs12(BIO *err, BIO *in, const char *desc,
748                 pem_password_cb *pem_cb,  void *cb_data,
749                 EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
750         {
751         const char *pass;
752         char tpass[PEM_BUFSIZE];
753         int len, ret = 0;
754         PKCS12 *p12;
755         p12 = d2i_PKCS12_bio(in, NULL);
756         if (p12 == NULL)
757                 {
758                 BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);    
759                 goto die;
760                 }
761         /* See if an empty password will do */
762         if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
763                 pass = "";
764         else
765                 {
766                 if (!pem_cb)
767                         pem_cb = (pem_password_cb *)password_callback;
768                 len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
769                 if (len < 0) 
770                         {
771                         BIO_printf(err, "Passpharse callback error for %s\n",
772                                         desc);
773                         goto die;
774                         }
775                 if (len < PEM_BUFSIZE)
776                         tpass[len] = 0;
777                 if (!PKCS12_verify_mac(p12, tpass, len))
778                         {
779                         BIO_printf(err,
780         "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc);    
781                         goto die;
782                         }
783                 pass = tpass;
784                 }
785         ret = PKCS12_parse(p12, pass, pkey, cert, ca);
786         die:
787         if (p12)
788                 PKCS12_free(p12);
789         return ret;
790         }
791
792 int load_cert_crl_http(const char *url, BIO *err,
793                                         X509 **pcert, X509_CRL **pcrl)
794         {
795         char *host = NULL, *port = NULL, *path = NULL;
796         BIO *bio = NULL;
797         OCSP_REQ_CTX *rctx = NULL;
798         int use_ssl, rv = 0;
799         if (!OCSP_parse_url(url, &host, &port, &path, &use_ssl))
800                 goto err;
801         if (use_ssl)
802                 {
803                 if (err)
804                         BIO_puts(err, "https not supported\n");
805                 goto err;
806                 }
807         bio = BIO_new_connect(host);
808         if (!bio || !BIO_set_conn_port(bio, port))
809                 goto err;
810         rctx = OCSP_REQ_CTX_new(bio, 1024);
811         if (!rctx)
812                 goto err;
813         if (!OCSP_REQ_CTX_http(rctx, "GET", path))
814                 goto err;
815         if (!OCSP_REQ_CTX_add1_header(rctx, "Host", host))
816                 goto err;
817         if (pcert)
818                 {
819                 do
820                         {
821                         rv = X509_http_nbio(rctx, pcert);
822                         }
823                 while (rv == -1);
824                 }
825         else
826                 {
827                 do
828                         {
829                         rv = X509_CRL_http_nbio(rctx, pcrl);
830                         } while (rv == -1);
831                 }
832
833         err:
834         if (host)
835                 OPENSSL_free(host);
836         if (path)
837                 OPENSSL_free(path);
838         if (port)
839                 OPENSSL_free(port);
840         if (bio)
841                 BIO_free_all(bio);
842         if (rctx)
843                 OCSP_REQ_CTX_free(rctx);
844         if (rv != 1)
845                 {
846                 if (bio && err)
847                         BIO_printf(bio_err, "Error loading %s from %s\n",
848                                         pcert ? "certificate" : "CRL", url);
849                 ERR_print_errors(bio_err);
850                 }
851         return rv;
852         }
853
854 X509 *load_cert(BIO *err, const char *file, int format,
855         const char *pass, ENGINE *e, const char *cert_descrip)
856         {
857         X509 *x=NULL;
858         BIO *cert;
859
860         if (format == FORMAT_HTTP)
861                 {
862                 load_cert_crl_http(file, err, &x, NULL);
863                 return x;
864                 }
865
866         if ((cert=BIO_new(BIO_s_file())) == NULL)
867                 {
868                 ERR_print_errors(err);
869                 goto end;
870                 }
871
872         if (file == NULL)
873                 {
874 #ifdef _IONBF
875 # ifndef OPENSSL_NO_SETVBUF_IONBF
876                 setvbuf(stdin, NULL, _IONBF, 0);
877 # endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
878 #endif
879                 BIO_set_fp(cert,stdin,BIO_NOCLOSE);
880                 }
881         else
882                 {
883                 if (BIO_read_filename(cert,file) <= 0)
884                         {
885                         BIO_printf(err, "Error opening %s %s\n",
886                                 cert_descrip, file);
887                         ERR_print_errors(err);
888                         goto end;
889                         }
890                 }
891
892         if      (format == FORMAT_ASN1)
893                 x=d2i_X509_bio(cert,NULL);
894         else if (format == FORMAT_NETSCAPE)
895                 {
896                 NETSCAPE_X509 *nx;
897                 nx=ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509),cert,NULL);
898                 if (nx == NULL)
899                                 goto end;
900
901                 if ((strncmp(NETSCAPE_CERT_HDR,(char *)nx->header->data,
902                         nx->header->length) != 0))
903                         {
904                         NETSCAPE_X509_free(nx);
905                         BIO_printf(err,"Error reading header on certificate\n");
906                         goto end;
907                         }
908                 x=nx->cert;
909                 nx->cert = NULL;
910                 NETSCAPE_X509_free(nx);
911                 }
912         else if (format == FORMAT_PEM)
913                 x=PEM_read_bio_X509_AUX(cert,NULL,
914                         (pem_password_cb *)password_callback, NULL);
915         else if (format == FORMAT_PKCS12)
916                 {
917                 if (!load_pkcs12(err, cert,cert_descrip, NULL, NULL,
918                                         NULL, &x, NULL))
919                         goto end;
920                 }
921         else    {
922                 BIO_printf(err,"bad input format specified for %s\n",
923                         cert_descrip);
924                 goto end;
925                 }
926 end:
927         if (x == NULL)
928                 {
929                 BIO_printf(err,"unable to load certificate\n");
930                 ERR_print_errors(err);
931                 }
932         if (cert != NULL) BIO_free(cert);
933         return(x);
934         }
935
936 X509_CRL *load_crl(const char *infile, int format)
937         {
938         X509_CRL *x=NULL;
939         BIO *in=NULL;
940
941         if (format == FORMAT_HTTP)
942                 {
943                 load_cert_crl_http(infile, bio_err, NULL, &x);
944                 return x;
945                 }
946
947         in=BIO_new(BIO_s_file());
948         if (in == NULL)
949                 {
950                 ERR_print_errors(bio_err);
951                 goto end;
952                 }
953
954         if (infile == NULL)
955                 BIO_set_fp(in,stdin,BIO_NOCLOSE);
956         else
957                 {
958                 if (BIO_read_filename(in,infile) <= 0)
959                         {
960                         perror(infile);
961                         goto end;
962                         }
963                 }
964         if      (format == FORMAT_ASN1)
965                 x=d2i_X509_CRL_bio(in,NULL);
966         else if (format == FORMAT_PEM)
967                 x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
968         else    {
969                 BIO_printf(bio_err,"bad input format specified for input crl\n");
970                 goto end;
971                 }
972         if (x == NULL)
973                 {
974                 BIO_printf(bio_err,"unable to load CRL\n");
975                 ERR_print_errors(bio_err);
976                 goto end;
977                 }
978         
979 end:
980         BIO_free(in);
981         return(x);
982         }
983
984
985 EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
986         const char *pass, ENGINE *e, const char *key_descrip)
987         {
988         BIO *key=NULL;
989         EVP_PKEY *pkey=NULL;
990         PW_CB_DATA cb_data;
991
992         cb_data.password = pass;
993         cb_data.prompt_info = file;
994
995         if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
996                 {
997                 BIO_printf(err,"no keyfile specified\n");
998                 goto end;
999                 }
1000 #ifndef OPENSSL_NO_ENGINE
1001         if (format == FORMAT_ENGINE)
1002                 {
1003                 if (!e)
1004                         BIO_printf(err,"no engine specified\n");
1005                 else
1006                         {
1007                         pkey = ENGINE_load_private_key(e, file,
1008                                 ui_method, &cb_data);
1009                         if (!pkey) 
1010                                 {
1011                                 BIO_printf(err,"cannot load %s from engine\n",key_descrip);
1012                                 ERR_print_errors(err);
1013                                 }       
1014                         }
1015                 goto end;
1016                 }
1017 #endif
1018         key=BIO_new(BIO_s_file());
1019         if (key == NULL)
1020                 {
1021                 ERR_print_errors(err);
1022                 goto end;
1023                 }
1024         if (file == NULL && maybe_stdin)
1025                 {
1026 #ifdef _IONBF
1027 # ifndef OPENSSL_NO_SETVBUF_IONBF
1028                 setvbuf(stdin, NULL, _IONBF, 0);
1029 # endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
1030 #endif
1031                 BIO_set_fp(key,stdin,BIO_NOCLOSE);
1032                 }
1033         else
1034                 if (BIO_read_filename(key,file) <= 0)
1035                         {
1036                         BIO_printf(err, "Error opening %s %s\n",
1037                                 key_descrip, file);
1038                         ERR_print_errors(err);
1039                         goto end;
1040                         }
1041         if (format == FORMAT_ASN1)
1042                 {
1043                 pkey=d2i_PrivateKey_bio(key, NULL);
1044                 }
1045         else if (format == FORMAT_PEM)
1046                 {
1047                 pkey=PEM_read_bio_PrivateKey(key,NULL,
1048                         (pem_password_cb *)password_callback, &cb_data);
1049                 }
1050 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
1051         else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
1052                 pkey = load_netscape_key(err, key, file, key_descrip, format);
1053 #endif
1054         else if (format == FORMAT_PKCS12)
1055                 {
1056                 if (!load_pkcs12(err, key, key_descrip,
1057                                 (pem_password_cb *)password_callback, &cb_data,
1058                                 &pkey, NULL, NULL))
1059                         goto end;
1060                 }
1061 #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
1062         else if (format == FORMAT_MSBLOB)
1063                 pkey = b2i_PrivateKey_bio(key);
1064         else if (format == FORMAT_PVK)
1065                 pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
1066                                                                 &cb_data);
1067 #endif
1068         else
1069                 {
1070                 BIO_printf(err,"bad input format specified for key file\n");
1071                 goto end;
1072                 }
1073  end:
1074         if (key != NULL) BIO_free(key);
1075         if (pkey == NULL) 
1076                 {
1077                 BIO_printf(err,"unable to load %s\n", key_descrip);
1078                 ERR_print_errors(err);
1079                 }       
1080         return(pkey);
1081         }
1082
1083 EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
1084         const char *pass, ENGINE *e, const char *key_descrip)
1085         {
1086         BIO *key=NULL;
1087         EVP_PKEY *pkey=NULL;
1088         PW_CB_DATA cb_data;
1089
1090         cb_data.password = pass;
1091         cb_data.prompt_info = file;
1092
1093         if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
1094                 {
1095                 BIO_printf(err,"no keyfile specified\n");
1096                 goto end;
1097                 }
1098 #ifndef OPENSSL_NO_ENGINE
1099         if (format == FORMAT_ENGINE)
1100                 {
1101                 if (!e)
1102                         BIO_printf(bio_err,"no engine specified\n");
1103                 else
1104                         pkey = ENGINE_load_public_key(e, file,
1105                                 ui_method, &cb_data);
1106                 goto end;
1107                 }
1108 #endif
1109         key=BIO_new(BIO_s_file());
1110         if (key == NULL)
1111                 {
1112                 ERR_print_errors(err);
1113                 goto end;
1114                 }
1115         if (file == NULL && maybe_stdin)
1116                 {
1117 #ifdef _IONBF
1118 # ifndef OPENSSL_NO_SETVBUF_IONBF
1119                 setvbuf(stdin, NULL, _IONBF, 0);
1120 # endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
1121 #endif
1122                 BIO_set_fp(key,stdin,BIO_NOCLOSE);
1123                 }
1124         else
1125                 if (BIO_read_filename(key,file) <= 0)
1126                         {
1127                         BIO_printf(err, "Error opening %s %s\n",
1128                                 key_descrip, file);
1129                         ERR_print_errors(err);
1130                         goto end;
1131                 }
1132         if (format == FORMAT_ASN1)
1133                 {
1134                 pkey=d2i_PUBKEY_bio(key, NULL);
1135                 }
1136 #ifndef OPENSSL_NO_RSA
1137         else if (format == FORMAT_ASN1RSA)
1138                 {
1139                 RSA *rsa;
1140                 rsa = d2i_RSAPublicKey_bio(key, NULL);
1141                 if (rsa)
1142                         {
1143                         pkey = EVP_PKEY_new();
1144                         if (pkey)
1145                                 EVP_PKEY_set1_RSA(pkey, rsa);
1146                         RSA_free(rsa);
1147                         }
1148                 else
1149                         pkey = NULL;
1150                 }
1151         else if (format == FORMAT_PEMRSA)
1152                 {
1153                 RSA *rsa;
1154                 rsa = PEM_read_bio_RSAPublicKey(key, NULL, 
1155                         (pem_password_cb *)password_callback, &cb_data);
1156                 if (rsa)
1157                         {
1158                         pkey = EVP_PKEY_new();
1159                         if (pkey)
1160                                 EVP_PKEY_set1_RSA(pkey, rsa);
1161                         RSA_free(rsa);
1162                         }
1163                 else
1164                         pkey = NULL;
1165                 }
1166 #endif
1167         else if (format == FORMAT_PEM)
1168                 {
1169                 pkey=PEM_read_bio_PUBKEY(key,NULL,
1170                         (pem_password_cb *)password_callback, &cb_data);
1171                 }
1172 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
1173         else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
1174                 pkey = load_netscape_key(err, key, file, key_descrip, format);
1175 #endif
1176 #if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
1177         else if (format == FORMAT_MSBLOB)
1178                 pkey = b2i_PublicKey_bio(key);
1179 #endif
1180         else
1181                 {
1182                 BIO_printf(err,"bad input format specified for key file\n");
1183                 goto end;
1184                 }
1185  end:
1186         if (key != NULL) BIO_free(key);
1187         if (pkey == NULL)
1188                 BIO_printf(err,"unable to load %s\n", key_descrip);
1189         return(pkey);
1190         }
1191
1192 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
1193 static EVP_PKEY *
1194 load_netscape_key(BIO *err, BIO *key, const char *file,
1195                 const char *key_descrip, int format)
1196         {
1197         EVP_PKEY *pkey;
1198         BUF_MEM *buf;
1199         RSA     *rsa;
1200         const unsigned char *p;
1201         int size, i;
1202
1203         buf=BUF_MEM_new();
1204         pkey = EVP_PKEY_new();
1205         size = 0;
1206         if (buf == NULL || pkey == NULL)
1207                 goto error;
1208         for (;;)
1209                 {
1210                 if (!BUF_MEM_grow_clean(buf,size+1024*10))
1211                         goto error;
1212                 i = BIO_read(key, &(buf->data[size]), 1024*10);
1213                 size += i;
1214                 if (i == 0)
1215                         break;
1216                 if (i < 0)
1217                         {
1218                                 BIO_printf(err, "Error reading %s %s",
1219                                         key_descrip, file);
1220                                 goto error;
1221                         }
1222                 }
1223         p=(unsigned char *)buf->data;
1224         rsa = d2i_RSA_NET(NULL,&p,(long)size,NULL,
1225                 (format == FORMAT_IISSGC ? 1 : 0));
1226         if (rsa == NULL)
1227                 goto error;
1228         BUF_MEM_free(buf);
1229         EVP_PKEY_set1_RSA(pkey, rsa);
1230         return pkey;
1231 error:
1232         BUF_MEM_free(buf);
1233         EVP_PKEY_free(pkey);
1234         return NULL;
1235         }
1236 #endif /* ndef OPENSSL_NO_RC4 */
1237
1238 static int load_certs_crls(BIO *err, const char *file, int format,
1239         const char *pass, ENGINE *e, const char *desc,
1240         STACK_OF(X509) **pcerts, STACK_OF(X509_CRL) **pcrls)
1241         {
1242         int i;
1243         BIO *bio;
1244         STACK_OF(X509_INFO) *xis = NULL;
1245         X509_INFO *xi;
1246         PW_CB_DATA cb_data;
1247         int rv = 0;
1248
1249         cb_data.password = pass;
1250         cb_data.prompt_info = file;
1251
1252         if (format != FORMAT_PEM)
1253                 {
1254                 BIO_printf(err,"bad input format specified for %s\n", desc);
1255                 return 0;
1256                 }
1257
1258         if (file == NULL)
1259                 bio = BIO_new_fp(stdin,BIO_NOCLOSE);
1260         else
1261                 bio = BIO_new_file(file, "r");
1262
1263         if (bio == NULL)
1264                 {
1265                 BIO_printf(err, "Error opening %s %s\n",
1266                                 desc, file ? file : "stdin");
1267                 ERR_print_errors(err);
1268                 return 0;
1269                 }
1270
1271         xis = PEM_X509_INFO_read_bio(bio, NULL,
1272                                 (pem_password_cb *)password_callback, &cb_data);
1273
1274         BIO_free(bio);
1275
1276         if (pcerts)
1277                 {
1278                 *pcerts = sk_X509_new_null();
1279                 if (!*pcerts)
1280                         goto end;
1281                 }
1282
1283         if (pcrls)
1284                 {
1285                 *pcrls = sk_X509_CRL_new_null();
1286                 if (!*pcrls)
1287                         goto end;
1288                 }
1289
1290         for(i = 0; i < sk_X509_INFO_num(xis); i++)
1291                 {
1292                 xi = sk_X509_INFO_value (xis, i);
1293                 if (xi->x509 && pcerts)
1294                         {
1295                         if (!sk_X509_push(*pcerts, xi->x509))
1296                                 goto end;
1297                         xi->x509 = NULL;
1298                         }
1299                 if (xi->crl && pcrls)
1300                         {
1301                         if (!sk_X509_CRL_push(*pcrls, xi->crl))
1302                                 goto end;
1303                         xi->crl = NULL;
1304                         }
1305                 }
1306
1307         if (pcerts && sk_X509_num(*pcerts) > 0)
1308                 rv = 1;
1309
1310         if (pcrls && sk_X509_CRL_num(*pcrls) > 0)
1311                 rv = 1;
1312
1313         end:
1314
1315         if (xis)
1316                 sk_X509_INFO_pop_free(xis, X509_INFO_free);
1317
1318         if (rv == 0)
1319                 {
1320                 if (pcerts)
1321                         {
1322                         sk_X509_pop_free(*pcerts, X509_free);
1323                         *pcerts = NULL;
1324                         }
1325                 if (pcrls)
1326                         {
1327                         sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
1328                         *pcrls = NULL;
1329                         }
1330                 BIO_printf(err,"unable to load %s\n",
1331                                 pcerts ? "certificates" : "CRLs");
1332                 ERR_print_errors(err);
1333                 }
1334         return rv;
1335         }
1336
1337 STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
1338         const char *pass, ENGINE *e, const char *desc)
1339         {
1340         STACK_OF(X509) *certs;
1341         if (!load_certs_crls(err, file, format, pass, e, desc, &certs, NULL))
1342                 return NULL;
1343         return certs;
1344         }       
1345
1346 STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
1347         const char *pass, ENGINE *e, const char *desc)
1348         {
1349         STACK_OF(X509_CRL) *crls;
1350         if (!load_certs_crls(err, file, format, pass, e, desc, NULL, &crls))
1351                 return NULL;
1352         return crls;
1353         }       
1354
1355 #define X509V3_EXT_UNKNOWN_MASK         (0xfL << 16)
1356 /* Return error for unknown extensions */
1357 #define X509V3_EXT_DEFAULT              0
1358 /* Print error for unknown extensions */
1359 #define X509V3_EXT_ERROR_UNKNOWN        (1L << 16)
1360 /* ASN1 parse unknown extensions */
1361 #define X509V3_EXT_PARSE_UNKNOWN        (2L << 16)
1362 /* BIO_dump unknown extensions */
1363 #define X509V3_EXT_DUMP_UNKNOWN         (3L << 16)
1364
1365 #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
1366                          X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
1367
1368 int set_cert_ex(unsigned long *flags, const char *arg)
1369 {
1370         static const NAME_EX_TBL cert_tbl[] = {
1371                 { "compatible", X509_FLAG_COMPAT, 0xffffffffl},
1372                 { "ca_default", X509_FLAG_CA, 0xffffffffl},
1373                 { "no_header", X509_FLAG_NO_HEADER, 0},
1374                 { "no_version", X509_FLAG_NO_VERSION, 0},
1375                 { "no_serial", X509_FLAG_NO_SERIAL, 0},
1376                 { "no_signame", X509_FLAG_NO_SIGNAME, 0},
1377                 { "no_validity", X509_FLAG_NO_VALIDITY, 0},
1378                 { "no_subject", X509_FLAG_NO_SUBJECT, 0},
1379                 { "no_issuer", X509_FLAG_NO_ISSUER, 0},
1380                 { "no_pubkey", X509_FLAG_NO_PUBKEY, 0},
1381                 { "no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
1382                 { "no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
1383                 { "no_aux", X509_FLAG_NO_AUX, 0},
1384                 { "no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
1385                 { "ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
1386                 { "ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1387                 { "ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1388                 { "ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
1389                 { NULL, 0, 0}
1390         };
1391         return set_multi_opts(flags, arg, cert_tbl);
1392 }
1393
1394 int set_name_ex(unsigned long *flags, const char *arg)
1395 {
1396         static const NAME_EX_TBL ex_tbl[] = {
1397                 { "esc_2253", ASN1_STRFLGS_ESC_2253, 0},
1398                 { "esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
1399                 { "esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
1400                 { "use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
1401                 { "utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
1402                 { "ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
1403                 { "show_type", ASN1_STRFLGS_SHOW_TYPE, 0},
1404                 { "dump_all", ASN1_STRFLGS_DUMP_ALL, 0},
1405                 { "dump_nostr", ASN1_STRFLGS_DUMP_UNKNOWN, 0},
1406                 { "dump_der", ASN1_STRFLGS_DUMP_DER, 0},
1407                 { "compat", XN_FLAG_COMPAT, 0xffffffffL},
1408                 { "sep_comma_plus", XN_FLAG_SEP_COMMA_PLUS, XN_FLAG_SEP_MASK},
1409                 { "sep_comma_plus_space", XN_FLAG_SEP_CPLUS_SPC, XN_FLAG_SEP_MASK},
1410                 { "sep_semi_plus_space", XN_FLAG_SEP_SPLUS_SPC, XN_FLAG_SEP_MASK},
1411                 { "sep_multiline", XN_FLAG_SEP_MULTILINE, XN_FLAG_SEP_MASK},
1412                 { "dn_rev", XN_FLAG_DN_REV, 0},
1413                 { "nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
1414                 { "sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
1415                 { "lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
1416                 { "align", XN_FLAG_FN_ALIGN, 0},
1417                 { "oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
1418                 { "space_eq", XN_FLAG_SPC_EQ, 0},
1419                 { "dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
1420                 { "RFC2253", XN_FLAG_RFC2253, 0xffffffffL},
1421                 { "oneline", XN_FLAG_ONELINE, 0xffffffffL},
1422                 { "multiline", XN_FLAG_MULTILINE, 0xffffffffL},
1423                 { "ca_default", XN_FLAG_MULTILINE, 0xffffffffL},
1424                 { NULL, 0, 0}
1425         };
1426         return set_multi_opts(flags, arg, ex_tbl);
1427 }
1428
1429 int set_ext_copy(int *copy_type, const char *arg)
1430 {
1431         if (!strcasecmp(arg, "none"))
1432                 *copy_type = EXT_COPY_NONE;
1433         else if (!strcasecmp(arg, "copy"))
1434                 *copy_type = EXT_COPY_ADD;
1435         else if (!strcasecmp(arg, "copyall"))
1436                 *copy_type = EXT_COPY_ALL;
1437         else
1438                 return 0;
1439         return 1;
1440 }
1441
1442 int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
1443 {
1444         STACK_OF(X509_EXTENSION) *exts = NULL;
1445         X509_EXTENSION *ext, *tmpext;
1446         ASN1_OBJECT *obj;
1447         int i, idx, ret = 0;
1448         if (!x || !req || (copy_type == EXT_COPY_NONE))
1449                 return 1;
1450         exts = X509_REQ_get_extensions(req);
1451
1452         for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
1453                 ext = sk_X509_EXTENSION_value(exts, i);
1454                 obj = X509_EXTENSION_get_object(ext);
1455                 idx = X509_get_ext_by_OBJ(x, obj, -1);
1456                 /* Does extension exist? */
1457                 if (idx != -1) {
1458                         /* If normal copy don't override existing extension */
1459                         if (copy_type == EXT_COPY_ADD)
1460                                 continue;
1461                         /* Delete all extensions of same type */
1462                         do {
1463                                 tmpext = X509_get_ext(x, idx);
1464                                 X509_delete_ext(x, idx);
1465                                 X509_EXTENSION_free(tmpext);
1466                                 idx = X509_get_ext_by_OBJ(x, obj, -1);
1467                         } while (idx != -1);
1468                 }
1469                 if (!X509_add_ext(x, ext, -1))
1470                         goto end;
1471         }
1472
1473         ret = 1;
1474
1475         end:
1476
1477         sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
1478
1479         return ret;
1480 }
1481                 
1482                 
1483                         
1484
1485 static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
1486 {
1487         STACK_OF(CONF_VALUE) *vals;
1488         CONF_VALUE *val;
1489         int i, ret = 1;
1490         if(!arg) return 0;
1491         vals = X509V3_parse_list(arg);
1492         for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
1493                 val = sk_CONF_VALUE_value(vals, i);
1494                 if (!set_table_opts(flags, val->name, in_tbl))
1495                         ret = 0;
1496         }
1497         sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
1498         return ret;
1499 }
1500
1501 static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
1502 {
1503         char c;
1504         const NAME_EX_TBL *ptbl;
1505         c = arg[0];
1506
1507         if(c == '-') {
1508                 c = 0;
1509                 arg++;
1510         } else if (c == '+') {
1511                 c = 1;
1512                 arg++;
1513         } else c = 1;
1514
1515         for(ptbl = in_tbl; ptbl->name; ptbl++) {
1516                 if(!strcasecmp(arg, ptbl->name)) {
1517                         *flags &= ~ptbl->mask;
1518                         if(c) *flags |= ptbl->flag;
1519                         else *flags &= ~ptbl->flag;
1520                         return 1;
1521                 }
1522         }
1523         return 0;
1524 }
1525
1526 void print_name(BIO *out, const char *title, X509_NAME *nm, unsigned long lflags)
1527 {
1528         char *buf;
1529         char mline = 0;
1530         int indent = 0;
1531
1532         if(title) BIO_puts(out, title);
1533         if((lflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
1534                 mline = 1;
1535                 indent = 4;
1536         }
1537         if(lflags == XN_FLAG_COMPAT) {
1538                 buf = X509_NAME_oneline(nm, 0, 0);
1539                 BIO_puts(out, buf);
1540                 BIO_puts(out, "\n");
1541                 OPENSSL_free(buf);
1542         } else {
1543                 if(mline) BIO_puts(out, "\n");
1544                 X509_NAME_print_ex(out, nm, indent, lflags);
1545                 BIO_puts(out, "\n");
1546         }
1547 }
1548
1549 X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
1550 {
1551         X509_STORE *store;
1552         X509_LOOKUP *lookup;
1553         if(!(store = X509_STORE_new())) goto end;
1554         lookup=X509_STORE_add_lookup(store,X509_LOOKUP_file());
1555         if (lookup == NULL) goto end;
1556         if (CAfile) {
1557                 if(!X509_LOOKUP_load_file(lookup,CAfile,X509_FILETYPE_PEM)) {
1558                         BIO_printf(bp, "Error loading file %s\n", CAfile);
1559                         goto end;
1560                 }
1561         } else X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
1562                 
1563         lookup=X509_STORE_add_lookup(store,X509_LOOKUP_hash_dir());
1564         if (lookup == NULL) goto end;
1565         if (CApath) {
1566                 if(!X509_LOOKUP_add_dir(lookup,CApath,X509_FILETYPE_PEM)) {
1567                         BIO_printf(bp, "Error loading directory %s\n", CApath);
1568                         goto end;
1569                 }
1570         } else X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
1571
1572         ERR_clear_error();
1573         return store;
1574         end:
1575         X509_STORE_free(store);
1576         return NULL;
1577 }
1578
1579 #ifndef OPENSSL_NO_ENGINE
1580 /* Try to load an engine in a shareable library */
1581 static ENGINE *try_load_engine(BIO *err, const char *engine, int debug)
1582         {
1583         ENGINE *e = ENGINE_by_id("dynamic");
1584         if (e)
1585                 {
1586                 if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", engine, 0)
1587                         || !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
1588                         {
1589                         ENGINE_free(e);
1590                         e = NULL;
1591                         }
1592                 }
1593         return e;
1594         }
1595
1596 ENGINE *setup_engine(BIO *err, const char *engine, int debug)
1597         {
1598         ENGINE *e = NULL;
1599
1600         if (engine)
1601                 {
1602                 if(strcmp(engine, "auto") == 0)
1603                         {
1604                         BIO_printf(err,"enabling auto ENGINE support\n");
1605                         ENGINE_register_all_complete();
1606                         return NULL;
1607                         }
1608                 if((e = ENGINE_by_id(engine)) == NULL
1609                         && (e = try_load_engine(err, engine, debug)) == NULL)
1610                         {
1611                         BIO_printf(err,"invalid engine \"%s\"\n", engine);
1612                         ERR_print_errors(err);
1613                         return NULL;
1614                         }
1615                 if (debug)
1616                         {
1617                         ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM,
1618                                 0, err, 0);
1619                         }
1620                 ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, ui_method, 0, 1);
1621                 if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
1622                         {
1623                         BIO_printf(err,"can't use that engine\n");
1624                         ERR_print_errors(err);
1625                         ENGINE_free(e);
1626                         return NULL;
1627                         }
1628
1629                 BIO_printf(err,"engine \"%s\" set.\n", ENGINE_get_id(e));
1630
1631                 /* Free our "structural" reference. */
1632                 ENGINE_free(e);
1633                 }
1634         return e;
1635         }
1636 #endif
1637
1638 int load_config(BIO *err, CONF *cnf)
1639         {
1640         static int load_config_called = 0;
1641         if (load_config_called)
1642                 return 1;
1643         load_config_called = 1;
1644         if (!cnf)
1645                 cnf = config;
1646         if (!cnf)
1647                 return 1;
1648
1649         OPENSSL_load_builtin_modules();
1650
1651         if (CONF_modules_load(cnf, NULL, 0) <= 0)
1652                 {
1653                 BIO_printf(err, "Error configuring OpenSSL\n");
1654                 ERR_print_errors(err);
1655                 return 0;
1656                 }
1657         return 1;
1658         }
1659
1660 char *make_config_name()
1661         {
1662         const char *t=X509_get_default_cert_area();
1663         size_t len;
1664         char *p;
1665
1666         len=strlen(t)+strlen(OPENSSL_CONF)+2;
1667         p=OPENSSL_malloc(len);
1668         if (p == NULL)
1669                 return NULL;
1670         BUF_strlcpy(p,t,len);
1671 #ifndef OPENSSL_SYS_VMS
1672         BUF_strlcat(p,"/",len);
1673 #endif
1674         BUF_strlcat(p,OPENSSL_CONF,len);
1675
1676         return p;
1677         }
1678
1679 static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
1680         {
1681         const char *n;
1682
1683         n=a[DB_serial];
1684         while (*n == '0') n++;
1685         return(lh_strhash(n));
1686         }
1687
1688 static int index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1689         {
1690         const char *aa,*bb;
1691
1692         for (aa=a[DB_serial]; *aa == '0'; aa++);
1693         for (bb=b[DB_serial]; *bb == '0'; bb++);
1694         return(strcmp(aa,bb));
1695         }
1696
1697 static int index_name_qual(char **a)
1698         { return(a[0][0] == 'V'); }
1699
1700 static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
1701         { return(lh_strhash(a[DB_name])); }
1702
1703 int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
1704         { return(strcmp(a[DB_name], b[DB_name])); }
1705
1706 static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
1707 static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
1708 static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
1709 static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
1710
1711 #undef BSIZE
1712 #define BSIZE 256
1713
1714 BIGNUM *load_serial(char *serialfile, int create, ASN1_INTEGER **retai)
1715         {
1716         BIO *in=NULL;
1717         BIGNUM *ret=NULL;
1718         MS_STATIC char buf[1024];
1719         ASN1_INTEGER *ai=NULL;
1720
1721         ai=ASN1_INTEGER_new();
1722         if (ai == NULL) goto err;
1723
1724         if ((in=BIO_new(BIO_s_file())) == NULL)
1725                 {
1726                 ERR_print_errors(bio_err);
1727                 goto err;
1728                 }
1729
1730         if (BIO_read_filename(in,serialfile) <= 0)
1731                 {
1732                 if (!create)
1733                         {
1734                         perror(serialfile);
1735                         goto err;
1736                         }
1737                 else
1738                         {
1739                         ret=BN_new();
1740                         if (ret == NULL || !rand_serial(ret, ai))
1741                                 BIO_printf(bio_err, "Out of memory\n");
1742                         }
1743                 }
1744         else
1745                 {
1746                 if (!a2i_ASN1_INTEGER(in,ai,buf,1024))
1747                         {
1748                         BIO_printf(bio_err,"unable to load number from %s\n",
1749                                 serialfile);
1750                         goto err;
1751                         }
1752                 ret=ASN1_INTEGER_to_BN(ai,NULL);
1753                 if (ret == NULL)
1754                         {
1755                         BIO_printf(bio_err,"error converting number from bin to BIGNUM\n");
1756                         goto err;
1757                         }
1758                 }
1759
1760         if (ret && retai)
1761                 {
1762                 *retai = ai;
1763                 ai = NULL;
1764                 }
1765  err:
1766         if (in != NULL) BIO_free(in);
1767         if (ai != NULL) ASN1_INTEGER_free(ai);
1768         return(ret);
1769         }
1770
1771 int save_serial(char *serialfile, char *suffix, BIGNUM *serial, ASN1_INTEGER **retai)
1772         {
1773         char buf[1][BSIZE];
1774         BIO *out = NULL;
1775         int ret=0;
1776         ASN1_INTEGER *ai=NULL;
1777         int j;
1778
1779         if (suffix == NULL)
1780                 j = strlen(serialfile);
1781         else
1782                 j = strlen(serialfile) + strlen(suffix) + 1;
1783         if (j >= BSIZE)
1784                 {
1785                 BIO_printf(bio_err,"file name too long\n");
1786                 goto err;
1787                 }
1788
1789         if (suffix == NULL)
1790                 BUF_strlcpy(buf[0], serialfile, BSIZE);
1791         else
1792                 {
1793 #ifndef OPENSSL_SYS_VMS
1794                 j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", serialfile, suffix);
1795 #else
1796                 j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", serialfile, suffix);
1797 #endif
1798                 }
1799 #ifdef RL_DEBUG
1800         BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
1801 #endif
1802         out=BIO_new(BIO_s_file());
1803         if (out == NULL)
1804                 {
1805                 ERR_print_errors(bio_err);
1806                 goto err;
1807                 }
1808         if (BIO_write_filename(out,buf[0]) <= 0)
1809                 {
1810                 perror(serialfile);
1811                 goto err;
1812                 }
1813
1814         if ((ai=BN_to_ASN1_INTEGER(serial,NULL)) == NULL)
1815                 {
1816                 BIO_printf(bio_err,"error converting serial to ASN.1 format\n");
1817                 goto err;
1818                 }
1819         i2a_ASN1_INTEGER(out,ai);
1820         BIO_puts(out,"\n");
1821         ret=1;
1822         if (retai)
1823                 {
1824                 *retai = ai;
1825                 ai = NULL;
1826                 }
1827 err:
1828         if (out != NULL) BIO_free_all(out);
1829         if (ai != NULL) ASN1_INTEGER_free(ai);
1830         return(ret);
1831         }
1832
1833 int rotate_serial(char *serialfile, char *new_suffix, char *old_suffix)
1834         {
1835         char buf[5][BSIZE];
1836         int i,j;
1837
1838         i = strlen(serialfile) + strlen(old_suffix);
1839         j = strlen(serialfile) + strlen(new_suffix);
1840         if (i > j) j = i;
1841         if (j + 1 >= BSIZE)
1842                 {
1843                 BIO_printf(bio_err,"file name too long\n");
1844                 goto err;
1845                 }
1846
1847 #ifndef OPENSSL_SYS_VMS
1848         j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s",
1849                 serialfile, new_suffix);
1850 #else
1851         j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s",
1852                 serialfile, new_suffix);
1853 #endif
1854 #ifndef OPENSSL_SYS_VMS
1855         j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s",
1856                 serialfile, old_suffix);
1857 #else
1858         j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
1859                 serialfile, old_suffix);
1860 #endif
1861 #ifdef RL_DEBUG
1862         BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1863                 serialfile, buf[1]);
1864 #endif
1865         if (rename(serialfile,buf[1]) < 0 && errno != ENOENT
1866 #ifdef ENOTDIR
1867                         && errno != ENOTDIR
1868 #endif
1869            )            {
1870                         BIO_printf(bio_err,
1871                                 "unable to rename %s to %s\n",
1872                                 serialfile, buf[1]);
1873                         perror("reason");
1874                         goto err;
1875                         }
1876 #ifdef RL_DEBUG
1877         BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
1878                 buf[0],serialfile);
1879 #endif
1880         if (rename(buf[0],serialfile) < 0)
1881                 {
1882                 BIO_printf(bio_err,
1883                         "unable to rename %s to %s\n",
1884                         buf[0],serialfile);
1885                 perror("reason");
1886                 rename(buf[1],serialfile);
1887                 goto err;
1888                 }
1889         return 1;
1890  err:
1891         return 0;
1892         }
1893
1894 int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
1895         {
1896         BIGNUM *btmp;
1897         int ret = 0;
1898         if (b)
1899                 btmp = b;
1900         else
1901                 btmp = BN_new();
1902
1903         if (!btmp)
1904                 return 0;
1905
1906         if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
1907                 goto error;
1908         if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
1909                 goto error;
1910
1911         ret = 1;
1912         
1913         error:
1914
1915         if (!b)
1916                 BN_free(btmp);
1917         
1918         return ret;
1919         }
1920
1921 CA_DB *load_index(char *dbfile, DB_ATTR *db_attr)
1922         {
1923         CA_DB *retdb = NULL;
1924         TXT_DB *tmpdb = NULL;
1925         BIO *in = BIO_new(BIO_s_file());
1926         CONF *dbattr_conf = NULL;
1927         char buf[1][BSIZE];
1928         long errorline= -1;
1929
1930         if (in == NULL)
1931                 {
1932                 ERR_print_errors(bio_err);
1933                 goto err;
1934                 }
1935         if (BIO_read_filename(in,dbfile) <= 0)
1936                 {
1937                 perror(dbfile);
1938                 BIO_printf(bio_err,"unable to open '%s'\n",dbfile);
1939                 goto err;
1940                 }
1941         if ((tmpdb = TXT_DB_read(in,DB_NUMBER)) == NULL)
1942                 goto err;
1943
1944 #ifndef OPENSSL_SYS_VMS
1945         BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile);
1946 #else
1947         BIO_snprintf(buf[0], sizeof buf[0], "%s-attr", dbfile);
1948 #endif
1949         dbattr_conf = NCONF_new(NULL);
1950         if (NCONF_load(dbattr_conf,buf[0],&errorline) <= 0)
1951                 {
1952                 if (errorline > 0)
1953                         {
1954                         BIO_printf(bio_err,
1955                                 "error on line %ld of db attribute file '%s'\n"
1956                                 ,errorline,buf[0]);
1957                         goto err;
1958                         }
1959                 else
1960                         {
1961                         NCONF_free(dbattr_conf);
1962                         dbattr_conf = NULL;
1963                         }
1964                 }
1965
1966         if ((retdb = OPENSSL_malloc(sizeof(CA_DB))) == NULL)
1967                 {
1968                 fprintf(stderr, "Out of memory\n");
1969                 goto err;
1970                 }
1971
1972         retdb->db = tmpdb;
1973         tmpdb = NULL;
1974         if (db_attr)
1975                 retdb->attributes = *db_attr;
1976         else
1977                 {
1978                 retdb->attributes.unique_subject = 1;
1979                 }
1980
1981         if (dbattr_conf)
1982                 {
1983                 char *p = NCONF_get_string(dbattr_conf,NULL,"unique_subject");
1984                 if (p)
1985                         {
1986 #ifdef RL_DEBUG
1987                         BIO_printf(bio_err, "DEBUG[load_index]: unique_subject = \"%s\"\n", p);
1988 #endif
1989                         retdb->attributes.unique_subject = parse_yesno(p,1);
1990                         }
1991                 }
1992
1993  err:
1994         if (dbattr_conf) NCONF_free(dbattr_conf);
1995         if (tmpdb) TXT_DB_free(tmpdb);
1996         if (in) BIO_free_all(in);
1997         return retdb;
1998         }
1999
2000 int index_index(CA_DB *db)
2001         {
2002         if (!TXT_DB_create_index(db->db, DB_serial, NULL,
2003                                 LHASH_HASH_FN(index_serial),
2004                                 LHASH_COMP_FN(index_serial)))
2005                 {
2006                 BIO_printf(bio_err,
2007                   "error creating serial number index:(%ld,%ld,%ld)\n",
2008                                         db->db->error,db->db->arg1,db->db->arg2);
2009                         return 0;
2010                 }
2011
2012         if (db->attributes.unique_subject
2013                 && !TXT_DB_create_index(db->db, DB_name, index_name_qual,
2014                         LHASH_HASH_FN(index_name),
2015                         LHASH_COMP_FN(index_name)))
2016                 {
2017                 BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
2018                         db->db->error,db->db->arg1,db->db->arg2);
2019                 return 0;
2020                 }
2021         return 1;
2022         }
2023
2024 int save_index(const char *dbfile, const char *suffix, CA_DB *db)
2025         {
2026         char buf[3][BSIZE];
2027         BIO *out = BIO_new(BIO_s_file());
2028         int j;
2029
2030         if (out == NULL)
2031                 {
2032                 ERR_print_errors(bio_err);
2033                 goto err;
2034                 }
2035
2036         j = strlen(dbfile) + strlen(suffix);
2037         if (j + 6 >= BSIZE)
2038                 {
2039                 BIO_printf(bio_err,"file name too long\n");
2040                 goto err;
2041                 }
2042
2043 #ifndef OPENSSL_SYS_VMS
2044         j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr", dbfile);
2045 #else
2046         j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr", dbfile);
2047 #endif
2048 #ifndef OPENSSL_SYS_VMS
2049         j = BIO_snprintf(buf[1], sizeof buf[1], "%s.attr.%s", dbfile, suffix);
2050 #else
2051         j = BIO_snprintf(buf[1], sizeof buf[1], "%s-attr-%s", dbfile, suffix);
2052 #endif
2053 #ifndef OPENSSL_SYS_VMS
2054         j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s", dbfile, suffix);
2055 #else
2056         j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s", dbfile, suffix);
2057 #endif
2058 #ifdef RL_DEBUG
2059         BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[0]);
2060 #endif
2061         if (BIO_write_filename(out,buf[0]) <= 0)
2062                 {
2063                 perror(dbfile);
2064                 BIO_printf(bio_err,"unable to open '%s'\n", dbfile);
2065                 goto err;
2066                 }
2067         j=TXT_DB_write(out,db->db);
2068         if (j <= 0) goto err;
2069                         
2070         BIO_free(out);
2071
2072         out = BIO_new(BIO_s_file());
2073 #ifdef RL_DEBUG
2074         BIO_printf(bio_err, "DEBUG: writing \"%s\"\n", buf[1]);
2075 #endif
2076         if (BIO_write_filename(out,buf[1]) <= 0)
2077                 {
2078                 perror(buf[2]);
2079                 BIO_printf(bio_err,"unable to open '%s'\n", buf[2]);
2080                 goto err;
2081                 }
2082         BIO_printf(out,"unique_subject = %s\n",
2083                 db->attributes.unique_subject ? "yes" : "no");
2084         BIO_free(out);
2085
2086         return 1;
2087  err:
2088         return 0;
2089         }
2090
2091 int rotate_index(const char *dbfile, const char *new_suffix, const char *old_suffix)
2092         {
2093         char buf[5][BSIZE];
2094         int i,j;
2095
2096         i = strlen(dbfile) + strlen(old_suffix);
2097         j = strlen(dbfile) + strlen(new_suffix);
2098         if (i > j) j = i;
2099         if (j + 6 >= BSIZE)
2100                 {
2101                 BIO_printf(bio_err,"file name too long\n");
2102                 goto err;
2103                 }
2104
2105 #ifndef OPENSSL_SYS_VMS
2106         j = BIO_snprintf(buf[4], sizeof buf[4], "%s.attr", dbfile);
2107 #else
2108         j = BIO_snprintf(buf[4], sizeof buf[4], "%s-attr", dbfile);
2109 #endif
2110 #ifndef OPENSSL_SYS_VMS
2111         j = BIO_snprintf(buf[2], sizeof buf[2], "%s.attr.%s",
2112                 dbfile, new_suffix);
2113 #else
2114         j = BIO_snprintf(buf[2], sizeof buf[2], "%s-attr-%s",
2115                 dbfile, new_suffix);
2116 #endif
2117 #ifndef OPENSSL_SYS_VMS
2118         j = BIO_snprintf(buf[0], sizeof buf[0], "%s.%s",
2119                 dbfile, new_suffix);
2120 #else
2121         j = BIO_snprintf(buf[0], sizeof buf[0], "%s-%s",
2122                 dbfile, new_suffix);
2123 #endif
2124 #ifndef OPENSSL_SYS_VMS
2125         j = BIO_snprintf(buf[1], sizeof buf[1], "%s.%s",
2126                 dbfile, old_suffix);
2127 #else
2128         j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
2129                 dbfile, old_suffix);
2130 #endif
2131 #ifndef OPENSSL_SYS_VMS
2132         j = BIO_snprintf(buf[3], sizeof buf[3], "%s.attr.%s",
2133                 dbfile, old_suffix);
2134 #else
2135         j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s",
2136                 dbfile, old_suffix);
2137 #endif
2138 #ifdef RL_DEBUG
2139         BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
2140                 dbfile, buf[1]);
2141 #endif
2142         if (rename(dbfile,buf[1]) < 0 && errno != ENOENT
2143 #ifdef ENOTDIR
2144                 && errno != ENOTDIR
2145 #endif
2146            )            {
2147                         BIO_printf(bio_err,
2148                                 "unable to rename %s to %s\n",
2149                                 dbfile, buf[1]);
2150                         perror("reason");
2151                         goto err;
2152                         }
2153 #ifdef RL_DEBUG
2154         BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
2155                 buf[0],dbfile);
2156 #endif
2157         if (rename(buf[0],dbfile) < 0)
2158                 {
2159                 BIO_printf(bio_err,
2160                         "unable to rename %s to %s\n",
2161                         buf[0],dbfile);
2162                 perror("reason");
2163                 rename(buf[1],dbfile);
2164                 goto err;
2165                 }
2166 #ifdef RL_DEBUG
2167         BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
2168                 buf[4],buf[3]);
2169 #endif
2170         if (rename(buf[4],buf[3]) < 0 && errno != ENOENT
2171 #ifdef ENOTDIR
2172                 && errno != ENOTDIR
2173 #endif
2174            )            {
2175                         BIO_printf(bio_err,
2176                                 "unable to rename %s to %s\n",
2177                                 buf[4], buf[3]);
2178                         perror("reason");
2179                         rename(dbfile,buf[0]);
2180                         rename(buf[1],dbfile);
2181                         goto err;
2182                         }
2183 #ifdef RL_DEBUG
2184         BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
2185                 buf[2],buf[4]);
2186 #endif
2187         if (rename(buf[2],buf[4]) < 0)
2188                 {
2189                 BIO_printf(bio_err,
2190                         "unable to rename %s to %s\n",
2191                         buf[2],buf[4]);
2192                 perror("reason");
2193                 rename(buf[3],buf[4]);
2194                 rename(dbfile,buf[0]);
2195                 rename(buf[1],dbfile);
2196                 goto err;
2197                 }
2198         return 1;
2199  err:
2200         return 0;
2201         }
2202
2203 void free_index(CA_DB *db)
2204         {
2205         if (db)
2206                 {
2207                 if (db->db) TXT_DB_free(db->db);
2208                 OPENSSL_free(db);
2209                 }
2210         }
2211
2212 int parse_yesno(const char *str, int def)
2213         {
2214         int ret = def;
2215         if (str)
2216                 {
2217                 switch (*str)
2218                         {
2219                 case 'f': /* false */
2220                 case 'F': /* FALSE */
2221                 case 'n': /* no */
2222                 case 'N': /* NO */
2223                 case '0': /* 0 */
2224                         ret = 0;
2225                         break;
2226                 case 't': /* true */
2227                 case 'T': /* TRUE */
2228                 case 'y': /* yes */
2229                 case 'Y': /* YES */
2230                 case '1': /* 1 */
2231                         ret = 1;
2232                         break;
2233                 default:
2234                         ret = def;
2235                         break;
2236                         }
2237                 }
2238         return ret;
2239         }
2240
2241 /*
2242  * subject is expected to be in the format /type0=value0/type1=value1/type2=...
2243  * where characters may be escaped by \
2244  */
2245 X509_NAME *parse_name(char *subject, long chtype, int multirdn)
2246         {
2247         size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
2248         char *buf = OPENSSL_malloc(buflen);
2249         size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
2250         char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
2251         char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
2252         int *mval = OPENSSL_malloc (max_ne * sizeof (int));
2253
2254         char *sp = subject, *bp = buf;
2255         int i, ne_num = 0;
2256
2257         X509_NAME *n = NULL;
2258         int nid;
2259
2260         if (!buf || !ne_types || !ne_values || !mval)
2261                 {
2262                 BIO_printf(bio_err, "malloc error\n");
2263                 goto error;
2264                 }       
2265
2266         if (*subject != '/')
2267                 {
2268                 BIO_printf(bio_err, "Subject does not start with '/'.\n");
2269                 goto error;
2270                 }
2271         sp++; /* skip leading / */
2272
2273         /* no multivalued RDN by default */
2274         mval[ne_num] = 0;
2275
2276         while (*sp)
2277                 {
2278                 /* collect type */
2279                 ne_types[ne_num] = bp;
2280                 while (*sp)
2281                         {
2282                         if (*sp == '\\') /* is there anything to escape in the type...? */
2283                                 {
2284                                 if (*++sp)
2285                                         *bp++ = *sp++;
2286                                 else    
2287                                         {
2288                                         BIO_printf(bio_err, "escape character at end of string\n");
2289                                         goto error;
2290                                         }
2291                                 }       
2292                         else if (*sp == '=')
2293                                 {
2294                                 sp++;
2295                                 *bp++ = '\0';
2296                                 break;
2297                                 }
2298                         else
2299                                 *bp++ = *sp++;
2300                         }
2301                 if (!*sp)
2302                         {
2303                         BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
2304                         goto error;
2305                         }
2306                 ne_values[ne_num] = bp;
2307                 while (*sp)
2308                         {
2309                         if (*sp == '\\')
2310                                 {
2311                                 if (*++sp)
2312                                         *bp++ = *sp++;
2313                                 else
2314                                         {
2315                                         BIO_printf(bio_err, "escape character at end of string\n");
2316                                         goto error;
2317                                         }
2318                                 }
2319                         else if (*sp == '/')
2320                                 {
2321                                 sp++;
2322                                 /* no multivalued RDN by default */
2323                                 mval[ne_num+1] = 0;
2324                                 break;
2325                                 }
2326                         else if (*sp == '+' && multirdn)
2327                                 {
2328                                 /* a not escaped + signals a mutlivalued RDN */
2329                                 sp++;
2330                                 mval[ne_num+1] = -1;
2331                                 break;
2332                                 }
2333                         else
2334                                 *bp++ = *sp++;
2335                         }
2336                 *bp++ = '\0';
2337                 ne_num++;
2338                 }       
2339
2340         if (!(n = X509_NAME_new()))
2341                 goto error;
2342
2343         for (i = 0; i < ne_num; i++)
2344                 {
2345                 if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
2346                         {
2347                         BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
2348                         continue;
2349                         }
2350
2351                 if (!*ne_values[i])
2352                         {
2353                         BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
2354                         continue;
2355                         }
2356
2357                 if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,mval[i]))
2358                         goto error;
2359                 }
2360
2361         OPENSSL_free(ne_values);
2362         OPENSSL_free(ne_types);
2363         OPENSSL_free(buf);
2364         OPENSSL_free(mval);
2365         return n;
2366
2367 error:
2368         X509_NAME_free(n);
2369         if (ne_values)
2370                 OPENSSL_free(ne_values);
2371         if (ne_types)
2372                 OPENSSL_free(ne_types);
2373         if (mval)
2374                 OPENSSL_free(mval);
2375         if (buf)
2376                 OPENSSL_free(buf);
2377         return NULL;
2378 }
2379
2380 int args_verify(char ***pargs, int *pargc,
2381                         int *badarg, BIO *err, X509_VERIFY_PARAM **pm)
2382         {
2383         ASN1_OBJECT *otmp = NULL;
2384         unsigned long flags = 0;
2385         int i;
2386         int purpose = 0, depth = -1;
2387         char **oldargs = *pargs;
2388         char *arg = **pargs, *argn = (*pargs)[1];
2389         const X509_VERIFY_PARAM *vpm = NULL;
2390         time_t at_time = 0;
2391         const unsigned char *hostname = NULL, *email = NULL;
2392         char *ipasc = NULL;
2393         if (!strcmp(arg, "-policy"))
2394                 {
2395                 if (!argn)
2396                         *badarg = 1;
2397                 else
2398                         {
2399                         otmp = OBJ_txt2obj(argn, 0);
2400                         if (!otmp)
2401                                 {
2402                                 BIO_printf(err, "Invalid Policy \"%s\"\n",
2403                                                                         argn);
2404                                 *badarg = 1;
2405                                 }
2406                         }
2407                 (*pargs)++;
2408                 }
2409         else if (strcmp(arg,"-purpose") == 0)
2410                 {
2411                 X509_PURPOSE *xptmp;
2412                 if (!argn)
2413                         *badarg = 1;
2414                 else
2415                         {
2416                         i = X509_PURPOSE_get_by_sname(argn);
2417                         if(i < 0)
2418                                 {
2419                                 BIO_printf(err, "unrecognized purpose\n");
2420                                 *badarg = 1;
2421                                 }
2422                         else
2423                                 {
2424                                 xptmp = X509_PURPOSE_get0(i);
2425                                 purpose = X509_PURPOSE_get_id(xptmp);
2426                                 }
2427                         }
2428                 (*pargs)++;
2429                 }
2430         else if (strcmp(arg,"-verify_name") == 0)
2431                 {
2432                 if (!argn)
2433                         *badarg = 1;
2434                 else
2435                         {
2436                         vpm = X509_VERIFY_PARAM_lookup(argn);
2437                         if(!vpm)
2438                                 {
2439                                 BIO_printf(err, "unrecognized verify name\n");
2440                                 *badarg = 1;
2441                                 }
2442                         }
2443                 (*pargs)++;
2444                 }
2445         else if (strcmp(arg,"-verify_depth") == 0)
2446                 {
2447                 if (!argn)
2448                         *badarg = 1;
2449                 else
2450                         {
2451                         depth = atoi(argn);
2452                         if(depth < 0)
2453                                 {
2454                                 BIO_printf(err, "invalid depth\n");
2455                                 *badarg = 1;
2456                                 }
2457                         }
2458                 (*pargs)++;
2459                 }
2460         else if (strcmp(arg,"-attime") == 0)
2461                 {
2462                 if (!argn)
2463                         *badarg = 1;
2464                 else
2465                         {
2466                         long timestamp;
2467                         /* interpret the -attime argument as seconds since
2468                          * Epoch */
2469                         if (sscanf(argn, "%li", &timestamp) != 1)
2470                                 {
2471                                 BIO_printf(bio_err,
2472                                                 "Error parsing timestamp %s\n",
2473                                                 argn);
2474                                 *badarg = 1;
2475                                 }
2476                         /* on some platforms time_t may be a float */
2477                         at_time = (time_t) timestamp;
2478                         }
2479                 (*pargs)++;
2480                 }
2481         else if (strcmp(arg,"-verify_hostname") == 0)
2482                 {
2483                 if (!argn)
2484                         *badarg = 1;
2485                 hostname = (unsigned char *)argn;
2486                 (*pargs)++;
2487                 }
2488         else if (strcmp(arg,"-verify_email") == 0)
2489                 {
2490                 if (!argn)
2491                         *badarg = 1;
2492                 email = (unsigned char *)argn;
2493                 (*pargs)++;
2494                 }
2495         else if (strcmp(arg,"-verify_ip") == 0)
2496                 {
2497                 if (!argn)
2498                         *badarg = 1;
2499                 ipasc = argn;
2500                 (*pargs)++;
2501                 }
2502         else if (!strcmp(arg, "-ignore_critical"))
2503                 flags |= X509_V_FLAG_IGNORE_CRITICAL;
2504         else if (!strcmp(arg, "-issuer_checks"))
2505                 flags |= X509_V_FLAG_CB_ISSUER_CHECK;
2506         else if (!strcmp(arg, "-crl_check"))
2507                 flags |=  X509_V_FLAG_CRL_CHECK;
2508         else if (!strcmp(arg, "-crl_check_all"))
2509                 flags |= X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
2510         else if (!strcmp(arg, "-policy_check"))
2511                 flags |= X509_V_FLAG_POLICY_CHECK;
2512         else if (!strcmp(arg, "-explicit_policy"))
2513                 flags |= X509_V_FLAG_EXPLICIT_POLICY;
2514         else if (!strcmp(arg, "-inhibit_any"))
2515                 flags |= X509_V_FLAG_INHIBIT_ANY;
2516         else if (!strcmp(arg, "-inhibit_map"))
2517                 flags |= X509_V_FLAG_INHIBIT_MAP;
2518         else if (!strcmp(arg, "-x509_strict"))
2519                 flags |= X509_V_FLAG_X509_STRICT;
2520         else if (!strcmp(arg, "-extended_crl"))
2521                 flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT;
2522         else if (!strcmp(arg, "-use_deltas"))
2523                 flags |= X509_V_FLAG_USE_DELTAS;
2524         else if (!strcmp(arg, "-policy_print"))
2525                 flags |= X509_V_FLAG_NOTIFY_POLICY;
2526         else if (!strcmp(arg, "-check_ss_sig"))
2527                 flags |= X509_V_FLAG_CHECK_SS_SIGNATURE;
2528         else if (!strcmp(arg, "-trusted_first"))
2529                 flags |= X509_V_FLAG_TRUSTED_FIRST;
2530         else if (!strcmp(arg, "-suiteB_128_only"))
2531                 flags |= X509_V_FLAG_SUITEB_128_LOS_ONLY;
2532         else if (!strcmp(arg, "-suiteB_128"))
2533                 flags |= X509_V_FLAG_SUITEB_128_LOS;
2534         else if (!strcmp(arg, "-suiteB_192"))
2535                 flags |= X509_V_FLAG_SUITEB_192_LOS;
2536         else if (!strcmp(arg, "-partial_chain"))
2537                 flags |= X509_V_FLAG_PARTIAL_CHAIN;
2538         else
2539                 return 0;
2540
2541         if (*badarg)
2542                 {
2543                 if (*pm)
2544                         X509_VERIFY_PARAM_free(*pm);
2545                 *pm = NULL;
2546                 goto end;
2547                 }
2548
2549         if (!*pm && !(*pm = X509_VERIFY_PARAM_new()))
2550                 {
2551                 *badarg = 1;
2552                 goto end;
2553                 }
2554
2555         if (vpm)
2556                 X509_VERIFY_PARAM_set1(*pm, vpm);
2557
2558         if (otmp)
2559                 X509_VERIFY_PARAM_add0_policy(*pm, otmp);
2560         if (flags)
2561                 X509_VERIFY_PARAM_set_flags(*pm, flags);
2562
2563         if (purpose)
2564                 X509_VERIFY_PARAM_set_purpose(*pm, purpose);
2565
2566         if (depth >= 0)
2567                 X509_VERIFY_PARAM_set_depth(*pm, depth);
2568
2569         if (at_time) 
2570                 X509_VERIFY_PARAM_set_time(*pm, at_time);
2571
2572         if (hostname && !X509_VERIFY_PARAM_set1_host(*pm, hostname, 0))
2573                 *badarg = 1;
2574
2575         if (email && !X509_VERIFY_PARAM_set1_email(*pm, email, 0))
2576                 *badarg = 1;
2577
2578         if (ipasc && !X509_VERIFY_PARAM_set1_ip_asc(*pm, ipasc))
2579                 *badarg = 1;
2580
2581         end:
2582
2583         (*pargs)++;
2584
2585         if (pargc)
2586                 *pargc -= *pargs - oldargs;
2587
2588         return 1;
2589
2590         }
2591
2592 /* Read whole contents of a BIO into an allocated memory buffer and
2593  * return it.
2594  */
2595
2596 int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
2597         {
2598         BIO *mem;
2599         int len, ret;
2600         unsigned char tbuf[1024];
2601         mem = BIO_new(BIO_s_mem());
2602         if (!mem)
2603                 return -1;
2604         for(;;)
2605                 {
2606                 if ((maxlen != -1) && maxlen < 1024)
2607                         len = maxlen;
2608                 else
2609                         len = 1024;
2610                 len = BIO_read(in, tbuf, len);
2611                 if (len <= 0)
2612                         break;
2613                 if (BIO_write(mem, tbuf, len) != len)
2614                         {
2615                         BIO_free(mem);
2616                         return -1;
2617                         }
2618                 maxlen -= len;
2619
2620                 if (maxlen == 0)
2621                         break;
2622                 }
2623         ret = BIO_get_mem_data(mem, (char **)out);
2624         BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
2625         BIO_free(mem);
2626         return ret;
2627         }
2628
2629 int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value)
2630         {
2631         int rv;
2632         char *stmp, *vtmp = NULL;
2633         stmp = BUF_strdup(value);
2634         if (!stmp)
2635                 return -1;
2636         vtmp = strchr(stmp, ':');
2637         if (vtmp)
2638                 {
2639                 *vtmp = 0;
2640                 vtmp++;
2641                 }
2642         rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
2643         OPENSSL_free(stmp);
2644         return rv;
2645         }
2646
2647 static void nodes_print(BIO *out, const char *name,
2648         STACK_OF(X509_POLICY_NODE) *nodes)
2649         {
2650         X509_POLICY_NODE *node;
2651         int i;
2652         BIO_printf(out, "%s Policies:", name);
2653         if (nodes)
2654                 {
2655                 BIO_puts(out, "\n");
2656                 for (i = 0; i < sk_X509_POLICY_NODE_num(nodes); i++)
2657                         {
2658                         node = sk_X509_POLICY_NODE_value(nodes, i);
2659                         X509_POLICY_NODE_print(out, node, 2);
2660                         }
2661                 }
2662         else
2663                 BIO_puts(out, " <empty>\n");
2664         }
2665
2666 void policies_print(BIO *out, X509_STORE_CTX *ctx)
2667         {
2668         X509_POLICY_TREE *tree;
2669         int explicit_policy;
2670         int free_out = 0;
2671         if (out == NULL)
2672                 {
2673                 out = BIO_new_fp(stderr, BIO_NOCLOSE);
2674                 free_out = 1;
2675                 }
2676         tree = X509_STORE_CTX_get0_policy_tree(ctx);
2677         explicit_policy = X509_STORE_CTX_get_explicit_policy(ctx);
2678
2679         BIO_printf(out, "Require explicit Policy: %s\n",
2680                                 explicit_policy ? "True" : "False");
2681
2682         nodes_print(out, "Authority", X509_policy_tree_get0_policies(tree));
2683         nodes_print(out, "User", X509_policy_tree_get0_user_policies(tree));
2684         if (free_out)
2685                 BIO_free(out);
2686         }
2687
2688 #if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
2689
2690 static JPAKE_CTX *jpake_init(const char *us, const char *them,
2691                                                          const char *secret)
2692         {
2693         BIGNUM *p = NULL;
2694         BIGNUM *g = NULL;
2695         BIGNUM *q = NULL;
2696         BIGNUM *bnsecret = BN_new();
2697         JPAKE_CTX *ctx;
2698
2699         /* Use a safe prime for p (that we found earlier) */
2700         BN_hex2bn(&p, "F9E5B365665EA7A05A9C534502780FEE6F1AB5BD4F49947FD036DBD7E905269AF46EF28B0FC07487EE4F5D20FB3C0AF8E700F3A2FA3414970CBED44FEDFF80CE78D800F184BB82435D137AADA2C6C16523247930A63B85661D1FC817A51ACD96168E95898A1F83A79FFB529368AA7833ABD1B0C3AEDDB14D2E1A2F71D99F763F");
2701         g = BN_new();
2702         BN_set_word(g, 2);
2703         q = BN_new();
2704         BN_rshift1(q, p);
2705
2706         BN_bin2bn((const unsigned char *)secret, strlen(secret), bnsecret);
2707
2708         ctx = JPAKE_CTX_new(us, them, p, g, q, bnsecret);
2709         BN_free(bnsecret);
2710         BN_free(q);
2711         BN_free(g);
2712         BN_free(p);
2713
2714         return ctx;
2715         }
2716
2717 static void jpake_send_part(BIO *conn, const JPAKE_STEP_PART *p)
2718         {
2719         BN_print(conn, p->gx);
2720         BIO_puts(conn, "\n");
2721         BN_print(conn, p->zkpx.gr);
2722         BIO_puts(conn, "\n");
2723         BN_print(conn, p->zkpx.b);
2724         BIO_puts(conn, "\n");
2725         }
2726
2727 static void jpake_send_step1(BIO *bconn, JPAKE_CTX *ctx)
2728         {
2729         JPAKE_STEP1 s1;
2730
2731         JPAKE_STEP1_init(&s1);
2732         JPAKE_STEP1_generate(&s1, ctx);
2733         jpake_send_part(bconn, &s1.p1);
2734         jpake_send_part(bconn, &s1.p2);
2735         (void)BIO_flush(bconn);
2736         JPAKE_STEP1_release(&s1);
2737         }
2738
2739 static void jpake_send_step2(BIO *bconn, JPAKE_CTX *ctx)
2740         {
2741         JPAKE_STEP2 s2;
2742
2743         JPAKE_STEP2_init(&s2);
2744         JPAKE_STEP2_generate(&s2, ctx);
2745         jpake_send_part(bconn, &s2);
2746         (void)BIO_flush(bconn);
2747         JPAKE_STEP2_release(&s2);
2748         }
2749
2750 static void jpake_send_step3a(BIO *bconn, JPAKE_CTX *ctx)
2751         {
2752         JPAKE_STEP3A s3a;
2753
2754         JPAKE_STEP3A_init(&s3a);
2755         JPAKE_STEP3A_generate(&s3a, ctx);
2756         BIO_write(bconn, s3a.hhk, sizeof s3a.hhk);
2757         (void)BIO_flush(bconn);
2758         JPAKE_STEP3A_release(&s3a);
2759         }
2760
2761 static void jpake_send_step3b(BIO *bconn, JPAKE_CTX *ctx)
2762         {
2763         JPAKE_STEP3B s3b;
2764
2765         JPAKE_STEP3B_init(&s3b);
2766         JPAKE_STEP3B_generate(&s3b, ctx);
2767         BIO_write(bconn, s3b.hk, sizeof s3b.hk);
2768         (void)BIO_flush(bconn);
2769         JPAKE_STEP3B_release(&s3b);
2770         }
2771
2772 static void readbn(BIGNUM **bn, BIO *bconn)
2773         {
2774         char buf[10240];
2775         int l;
2776
2777         l = BIO_gets(bconn, buf, sizeof buf);
2778         assert(l > 0);
2779         assert(buf[l-1] == '\n');
2780         buf[l-1] = '\0';
2781         BN_hex2bn(bn, buf);
2782         }
2783
2784 static void jpake_receive_part(JPAKE_STEP_PART *p, BIO *bconn)
2785         {
2786         readbn(&p->gx, bconn);
2787         readbn(&p->zkpx.gr, bconn);
2788         readbn(&p->zkpx.b, bconn);
2789         }
2790
2791 static void jpake_receive_step1(JPAKE_CTX *ctx, BIO *bconn)
2792         {
2793         JPAKE_STEP1 s1;
2794
2795         JPAKE_STEP1_init(&s1);
2796         jpake_receive_part(&s1.p1, bconn);
2797         jpake_receive_part(&s1.p2, bconn);
2798         if(!JPAKE_STEP1_process(ctx, &s1))
2799                 {
2800                 ERR_print_errors(bio_err);
2801                 exit(1);
2802                 }
2803         JPAKE_STEP1_release(&s1);
2804         }
2805
2806 static void jpake_receive_step2(JPAKE_CTX *ctx, BIO *bconn)
2807         {
2808         JPAKE_STEP2 s2;
2809
2810         JPAKE_STEP2_init(&s2);
2811         jpake_receive_part(&s2, bconn);
2812         if(!JPAKE_STEP2_process(ctx, &s2))
2813                 {
2814                 ERR_print_errors(bio_err);
2815                 exit(1);
2816                 }
2817         JPAKE_STEP2_release(&s2);
2818         }
2819
2820 static void jpake_receive_step3a(JPAKE_CTX *ctx, BIO *bconn)
2821         {
2822         JPAKE_STEP3A s3a;
2823         int l;
2824
2825         JPAKE_STEP3A_init(&s3a);
2826         l = BIO_read(bconn, s3a.hhk, sizeof s3a.hhk);
2827         assert(l == sizeof s3a.hhk);
2828         if(!JPAKE_STEP3A_process(ctx, &s3a))
2829                 {
2830                 ERR_print_errors(bio_err);
2831                 exit(1);
2832                 }
2833         JPAKE_STEP3A_release(&s3a);
2834         }
2835
2836 static void jpake_receive_step3b(JPAKE_CTX *ctx, BIO *bconn)
2837         {
2838         JPAKE_STEP3B s3b;
2839         int l;
2840
2841         JPAKE_STEP3B_init(&s3b);
2842         l = BIO_read(bconn, s3b.hk, sizeof s3b.hk);
2843         assert(l == sizeof s3b.hk);
2844         if(!JPAKE_STEP3B_process(ctx, &s3b))
2845                 {
2846                 ERR_print_errors(bio_err);
2847                 exit(1);
2848                 }
2849         JPAKE_STEP3B_release(&s3b);
2850         }
2851
2852 void jpake_client_auth(BIO *out, BIO *conn, const char *secret)
2853         {
2854         JPAKE_CTX *ctx;
2855         BIO *bconn;
2856
2857         BIO_puts(out, "Authenticating with JPAKE\n");
2858
2859         ctx = jpake_init("client", "server", secret);
2860
2861         bconn = BIO_new(BIO_f_buffer());
2862         BIO_push(bconn, conn);
2863
2864         jpake_send_step1(bconn, ctx);
2865         jpake_receive_step1(ctx, bconn);
2866         jpake_send_step2(bconn, ctx);
2867         jpake_receive_step2(ctx, bconn);
2868         jpake_send_step3a(bconn, ctx);
2869         jpake_receive_step3b(ctx, bconn);
2870
2871         BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
2872
2873         if (psk_key)
2874                 OPENSSL_free(psk_key);
2875
2876         psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
2877
2878         BIO_pop(bconn);
2879         BIO_free(bconn);
2880
2881         JPAKE_CTX_free(ctx);
2882         }
2883
2884 void jpake_server_auth(BIO *out, BIO *conn, const char *secret)
2885         {
2886         JPAKE_CTX *ctx;
2887         BIO *bconn;
2888
2889         BIO_puts(out, "Authenticating with JPAKE\n");
2890
2891         ctx = jpake_init("server", "client", secret);
2892
2893         bconn = BIO_new(BIO_f_buffer());
2894         BIO_push(bconn, conn);
2895
2896         jpake_receive_step1(ctx, bconn);
2897         jpake_send_step1(bconn, ctx);
2898         jpake_receive_step2(ctx, bconn);
2899         jpake_send_step2(bconn, ctx);
2900         jpake_receive_step3a(ctx, bconn);
2901         jpake_send_step3b(bconn, ctx);
2902
2903         BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
2904
2905         if (psk_key)
2906                 OPENSSL_free(psk_key);
2907
2908         psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
2909
2910         BIO_pop(bconn);
2911         BIO_free(bconn);
2912
2913         JPAKE_CTX_free(ctx);
2914         }
2915
2916 #endif
2917
2918 #ifndef OPENSSL_NO_TLSEXT
2919 /* next_protos_parse parses a comma separated list of strings into a string
2920  * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
2921  *   outlen: (output) set to the length of the resulting buffer on success.
2922  *   err: (maybe NULL) on failure, an error message line is written to this BIO.
2923  *   in: a NUL termianted string like "abc,def,ghi"
2924  *
2925  *   returns: a malloced buffer or NULL on failure.
2926  */
2927 unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
2928         {
2929         size_t len;
2930         unsigned char *out;
2931         size_t i, start = 0;
2932
2933         len = strlen(in);
2934         if (len >= 65535)
2935                 return NULL;
2936
2937         out = OPENSSL_malloc(strlen(in) + 1);
2938         if (!out)
2939                 return NULL;
2940
2941         for (i = 0; i <= len; ++i)
2942                 {
2943                 if (i == len || in[i] == ',')
2944                         {
2945                         if (i - start > 255)
2946                                 {
2947                                 OPENSSL_free(out);
2948                                 return NULL;
2949                                 }
2950                         out[start] = i - start;
2951                         start = i + 1;
2952                         }
2953                 else
2954                         out[i+1] = in[i];
2955                 }
2956
2957         *outlen = len + 1;
2958         return out;
2959         }
2960 #endif  /* ndef OPENSSL_NO_TLSEXT */
2961
2962 void print_cert_checks(BIO *bio, X509 *x,
2963                                 const unsigned char *checkhost,
2964                                 const unsigned char *checkemail,
2965                                 const char *checkip)
2966         {
2967         if (x == NULL)
2968                 return;
2969         if (checkhost)
2970                 {
2971                 BIO_printf(bio, "Hostname %s does%s match certificate\n",
2972                                 checkhost,
2973                                 X509_check_host(x, checkhost, 0, 0, NULL)
2974                                                 ? "" : " NOT");
2975                 }
2976
2977         if (checkemail)
2978                 {
2979                 BIO_printf(bio, "Email %s does%s match certificate\n",
2980                                 checkemail, X509_check_email(x, checkemail, 0,
2981                                                 0) ? "" : " NOT");
2982                 }
2983
2984         if (checkip)
2985                 {
2986                 BIO_printf(bio, "IP %s does%s match certificate\n",
2987                                 checkip, X509_check_ip_asc(x, checkip,
2988                                                 0) ? "" : " NOT");
2989                 }
2990         }
2991
2992 /* Get first http URL from a DIST_POINT structure */
2993
2994 static const char *get_dp_url(DIST_POINT *dp)
2995         {
2996         GENERAL_NAMES *gens;
2997         GENERAL_NAME *gen;
2998         int i, gtype;
2999         ASN1_STRING *uri;
3000         if (!dp->distpoint || dp->distpoint->type != 0)
3001                 return NULL;
3002         gens = dp->distpoint->name.fullname;
3003         for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
3004                 {
3005                 gen = sk_GENERAL_NAME_value(gens, i);
3006                 uri = GENERAL_NAME_get0_value(gen, &gtype);
3007                 if (gtype == GEN_URI && ASN1_STRING_length(uri) > 6)
3008                         {
3009                         char *uptr = (char *)ASN1_STRING_data(uri);
3010                         if (!strncmp(uptr, "http://", 7))
3011                                 return uptr;
3012                         }
3013                 }               
3014         return NULL;
3015         }
3016                 
3017
3018 /* Look through a CRLDP structure and attempt to find an http URL to downloads
3019  * a CRL from.
3020  */
3021
3022 static X509_CRL *load_crl_crldp(STACK_OF(DIST_POINT) *crldp)
3023         {
3024         int i;
3025         const char *urlptr = NULL;
3026         for (i = 0; i < sk_DIST_POINT_num(crldp); i++)
3027                 {
3028                 DIST_POINT *dp = sk_DIST_POINT_value(crldp, i);
3029                 urlptr = get_dp_url(dp);
3030                 if (urlptr)
3031                         return load_crl(urlptr, FORMAT_HTTP);
3032                 }
3033         return NULL;
3034         }
3035
3036 /* Example of downloading CRLs from CRLDP: not usable for real world
3037  * as it always downloads, doesn't support non-blocking I/O and doesn't
3038  * cache anything.
3039  */
3040
3041 static STACK_OF(X509_CRL) *crls_http_cb(X509_STORE_CTX *ctx, X509_NAME *nm)
3042         {
3043         X509 *x;
3044         STACK_OF(X509_CRL) *crls = NULL;
3045         X509_CRL *crl;
3046         STACK_OF(DIST_POINT) *crldp;
3047         x = X509_STORE_CTX_get_current_cert(ctx);
3048         crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
3049         crl = load_crl_crldp(crldp);
3050         sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
3051         if (!crl)
3052                 return NULL;
3053         crls = sk_X509_CRL_new_null();
3054         sk_X509_CRL_push(crls, crl);
3055         /* Try to download delta CRL */
3056         crldp = X509_get_ext_d2i(x, NID_freshest_crl, NULL, NULL);
3057         crl = load_crl_crldp(crldp);
3058         sk_DIST_POINT_pop_free(crldp, DIST_POINT_free);
3059         if (crl)
3060                 sk_X509_CRL_push(crls, crl);
3061         return crls;
3062         }
3063
3064 void store_setup_crl_download(X509_STORE *st)
3065         {
3066         X509_STORE_set_lookup_crls_cb(st, crls_http_cb);
3067         }
3068
3069 /*
3070  * Platform-specific sections
3071  */
3072 #if defined(_WIN32)
3073 # ifdef fileno
3074 #  undef fileno
3075 #  define fileno(a) (int)_fileno(a)
3076 # endif
3077
3078 # include <windows.h>
3079 # include <tchar.h>
3080
3081 static int WIN32_rename(const char *from, const char *to)
3082         {
3083         TCHAR  *tfrom=NULL,*tto;
3084         DWORD   err;
3085         int     ret=0;
3086
3087         if (sizeof(TCHAR) == 1)
3088                 {
3089                 tfrom = (TCHAR *)from;
3090                 tto   = (TCHAR *)to;
3091                 }
3092         else    /* UNICODE path */
3093                 {
3094                 size_t i,flen=strlen(from)+1,tlen=strlen(to)+1;
3095                 tfrom = (TCHAR *)malloc(sizeof(TCHAR)*(flen+tlen));
3096                 if (tfrom==NULL) goto err;
3097                 tto=tfrom+flen;
3098 #if !defined(_WIN32_WCE) || _WIN32_WCE>=101
3099                 if (!MultiByteToWideChar(CP_ACP,0,from,flen,(WCHAR *)tfrom,flen))
3100 #endif
3101                         for (i=0;i<flen;i++)    tfrom[i]=(TCHAR)from[i];
3102 #if !defined(_WIN32_WCE) || _WIN32_WCE>=101
3103                 if (!MultiByteToWideChar(CP_ACP,0,to,  tlen,(WCHAR *)tto,  tlen))
3104 #endif
3105                         for (i=0;i<tlen;i++)    tto[i]  =(TCHAR)to[i];
3106                 }
3107
3108         if (MoveFile(tfrom,tto))        goto ok;
3109         err=GetLastError();
3110         if (err==ERROR_ALREADY_EXISTS || err==ERROR_FILE_EXISTS)
3111                 {
3112                 if (DeleteFile(tto) && MoveFile(tfrom,tto))
3113                         goto ok;
3114                 err=GetLastError();
3115                 }
3116         if (err==ERROR_FILE_NOT_FOUND || err==ERROR_PATH_NOT_FOUND)
3117                 errno = ENOENT;
3118         else if (err==ERROR_ACCESS_DENIED)
3119                 errno = EACCES;
3120         else
3121                 errno = EINVAL; /* we could map more codes... */
3122 err:
3123         ret=-1;
3124 ok:
3125         if (tfrom!=NULL && tfrom!=(TCHAR *)from)        free(tfrom);
3126         return ret;
3127         }
3128 #endif
3129
3130 /* app_tminterval section */
3131 #if defined(_WIN32)
3132 double app_tminterval(int stop,int usertime)
3133         {
3134         FILETIME                now;
3135         double                  ret=0;
3136         static ULARGE_INTEGER   tmstart;
3137         static int              warning=1;
3138 #ifdef _WIN32_WINNT
3139         static HANDLE           proc=NULL;
3140
3141         if (proc==NULL)
3142                 {
3143                 if (check_winnt())
3144                         proc = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,
3145                                                 GetCurrentProcessId());
3146                 if (proc==NULL) proc = (HANDLE)-1;
3147                 }
3148
3149         if (usertime && proc!=(HANDLE)-1)
3150                 {
3151                 FILETIME junk;
3152                 GetProcessTimes(proc,&junk,&junk,&junk,&now);
3153                 }
3154         else
3155 #endif
3156                 {
3157                 SYSTEMTIME systime;
3158
3159                 if (usertime && warning)
3160                         {
3161                         BIO_printf(bio_err,"To get meaningful results, run "
3162                                            "this program on idle system.\n");
3163                         warning=0;
3164                         }
3165                 GetSystemTime(&systime);
3166                 SystemTimeToFileTime(&systime,&now);
3167                 }
3168
3169         if (stop==TM_START)
3170                 {
3171                 tmstart.u.LowPart  = now.dwLowDateTime;
3172                 tmstart.u.HighPart = now.dwHighDateTime;
3173                 }
3174         else    {
3175                 ULARGE_INTEGER tmstop;
3176
3177                 tmstop.u.LowPart   = now.dwLowDateTime;
3178                 tmstop.u.HighPart  = now.dwHighDateTime;
3179
3180                 ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart)*1e-7;
3181                 }
3182
3183         return (ret);
3184         }
3185
3186 #elif defined(OPENSSL_SYS_NETWARE)
3187 #include <time.h>
3188
3189 double app_tminterval(int stop,int usertime)
3190         {
3191         double          ret=0;
3192         static clock_t  tmstart;
3193         static int      warning=1;
3194
3195         if (usertime && warning)
3196                 {
3197                 BIO_printf(bio_err,"To get meaningful results, run "
3198                                    "this program on idle system.\n");
3199                 warning=0;
3200                 }
3201
3202         if (stop==TM_START)     tmstart = clock();
3203         else                    ret     = (clock()-tmstart)/(double)CLOCKS_PER_SEC;
3204
3205         return (ret);
3206         }
3207
3208 #elif defined(OPENSSL_SYSTEM_VXWORKS)
3209 #include <time.h>
3210
3211 double app_tminterval(int stop,int usertime)
3212         {
3213         double ret=0;
3214 #ifdef CLOCK_REALTIME
3215         static struct timespec  tmstart;
3216         struct timespec         now;
3217 #else
3218         static unsigned long    tmstart;
3219         unsigned long           now;
3220 #endif
3221         static int warning=1;
3222
3223         if (usertime && warning)
3224                 {
3225                 BIO_printf(bio_err,"To get meaningful results, run "
3226                                    "this program on idle system.\n");
3227                 warning=0;
3228                 }
3229
3230 #ifdef CLOCK_REALTIME
3231         clock_gettime(CLOCK_REALTIME,&now);
3232         if (stop==TM_START)     tmstart = now;
3233         else    ret = ( (now.tv_sec+now.tv_nsec*1e-9)
3234                         - (tmstart.tv_sec+tmstart.tv_nsec*1e-9) );
3235 #else
3236         now = tickGet();
3237         if (stop==TM_START)     tmstart = now;
3238         else                    ret = (now - tmstart)/(double)sysClkRateGet();
3239 #endif
3240         return (ret);
3241         }
3242
3243 #elif defined(OPENSSL_SYSTEM_VMS)
3244 #include <time.h>
3245 #include <times.h>
3246
3247 double app_tminterval(int stop,int usertime)
3248         {
3249         static clock_t  tmstart;
3250         double          ret = 0;
3251         clock_t         now;
3252 #ifdef __TMS
3253         struct tms      rus;
3254
3255         now = times(&rus);
3256         if (usertime)   now = rus.tms_utime;
3257 #else
3258         if (usertime)
3259                 now = clock(); /* sum of user and kernel times */
3260         else    {
3261                 struct timeval tv;
3262                 gettimeofday(&tv,NULL);
3263                 now = (clock_t)(
3264                         (unsigned long long)tv.tv_sec*CLK_TCK +
3265                         (unsigned long long)tv.tv_usec*(1000000/CLK_TCK)
3266                         );
3267                 }
3268 #endif
3269         if (stop==TM_START)     tmstart = now;
3270         else                    ret = (now - tmstart)/(double)(CLK_TCK);
3271
3272         return (ret);
3273         }
3274
3275 #elif defined(_SC_CLK_TCK)      /* by means of unistd.h */
3276 #include <sys/times.h>
3277
3278 double app_tminterval(int stop,int usertime)
3279         {
3280         double          ret = 0;
3281         struct tms      rus;
3282         clock_t         now = times(&rus);
3283         static clock_t  tmstart;
3284
3285         if (usertime)           now = rus.tms_utime;
3286
3287         if (stop==TM_START)     tmstart = now;
3288         else
3289                 {
3290                 long int tck = sysconf(_SC_CLK_TCK);
3291                 ret = (now - tmstart)/(double)tck;
3292                 }
3293
3294         return (ret);
3295         }
3296
3297 #else
3298 #include <sys/time.h>
3299 #include <sys/resource.h>
3300
3301 double app_tminterval(int stop,int usertime)
3302         {
3303         double          ret = 0;
3304         struct rusage   rus;
3305         struct timeval  now;
3306         static struct timeval tmstart;
3307
3308         if (usertime)           getrusage(RUSAGE_SELF,&rus), now = rus.ru_utime;
3309         else                    gettimeofday(&now,NULL);
3310
3311         if (stop==TM_START)     tmstart = now;
3312         else                    ret = ( (now.tv_sec+now.tv_usec*1e-6)
3313                                         - (tmstart.tv_sec+tmstart.tv_usec*1e-6) );
3314
3315         return ret;
3316         }
3317 #endif
3318
3319 /* app_isdir section */
3320 #ifdef _WIN32
3321 int app_isdir(const char *name)
3322         {
3323         HANDLE          hList;
3324         WIN32_FIND_DATA FileData;
3325 #if defined(UNICODE) || defined(_UNICODE)
3326         size_t i, len_0 = strlen(name)+1;
3327
3328         if (len_0 > sizeof(FileData.cFileName)/sizeof(FileData.cFileName[0]))
3329                 return -1;
3330
3331 #if !defined(_WIN32_WCE) || _WIN32_WCE>=101
3332         if (!MultiByteToWideChar(CP_ACP,0,name,len_0,FileData.cFileName,len_0))
3333 #endif
3334                 for (i=0;i<len_0;i++)
3335                         FileData.cFileName[i] = (WCHAR)name[i];
3336
3337         hList = FindFirstFile(FileData.cFileName,&FileData);
3338 #else
3339         hList = FindFirstFile(name,&FileData);
3340 #endif
3341         if (hList == INVALID_HANDLE_VALUE)      return -1;
3342         FindClose(hList);
3343         return ((FileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0);
3344         }
3345 #else
3346 #include <sys/stat.h>
3347 #ifndef S_ISDIR
3348 # if defined(_S_IFMT) && defined(_S_IFDIR)
3349 #  define S_ISDIR(a)   (((a) & _S_IFMT) == _S_IFDIR)
3350 # else 
3351 #  define S_ISDIR(a)   (((a) & S_IFMT) == S_IFDIR)
3352 # endif 
3353 #endif 
3354
3355 int app_isdir(const char *name)
3356         {
3357 #if defined(S_ISDIR)
3358         struct stat st;
3359
3360         if (stat(name,&st)==0)  return S_ISDIR(st.st_mode);
3361         else                    return -1;
3362 #else
3363         return -1;
3364 #endif
3365         }
3366 #endif
3367
3368 /* raw_read|write section */
3369 #if defined(_WIN32) && defined(STD_INPUT_HANDLE)
3370 int raw_read_stdin(void *buf,int siz)
3371         {
3372         DWORD n;
3373         if (ReadFile(GetStdHandle(STD_INPUT_HANDLE),buf,siz,&n,NULL))
3374                 return (n);
3375         else    return (-1);
3376         }
3377 #else
3378 int raw_read_stdin(void *buf,int siz)
3379         {       return read(fileno(stdin),buf,siz);     }
3380 #endif
3381
3382 #if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
3383 int raw_write_stdout(const void *buf,int siz)
3384         {
3385         DWORD n;
3386         if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,siz,&n,NULL))
3387                 return (n);
3388         else    return (-1);
3389         }
3390 #else
3391 int raw_write_stdout(const void *buf,int siz)
3392         {       return write(fileno(stdout),buf,siz);   }
3393 #endif