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