Main Page | Class List | Directories | File List | Class Members | File Members

apps.c

Go to the documentation of this file.
00001 /* apps/apps.c */
00002 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
00003  * All rights reserved.
00004  *
00005  * This package is an SSL implementation written
00006  * by Eric Young (eay@cryptsoft.com).
00007  * The implementation was written so as to conform with Netscapes SSL.
00008  * 
00009  * This library is free for commercial and non-commercial use as long as
00010  * the following conditions are aheared to.  The following conditions
00011  * apply to all code found in this distribution, be it the RC4, RSA,
00012  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
00013  * included with this distribution is covered by the same copyright terms
00014  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
00015  * 
00016  * Copyright remains Eric Young's, and as such any Copyright notices in
00017  * the code are not to be removed.
00018  * If this package is used in a product, Eric Young should be given attribution
00019  * as the author of the parts of the library used.
00020  * This can be in the form of a textual message at program startup or
00021  * in documentation (online or textual) provided with the package.
00022  * 
00023  * Redistribution and use in source and binary forms, with or without
00024  * modification, are permitted provided that the following conditions
00025  * are met:
00026  * 1. Redistributions of source code must retain the copyright
00027  *    notice, this list of conditions and the following disclaimer.
00028  * 2. Redistributions in binary form must reproduce the above copyright
00029  *    notice, this list of conditions and the following disclaimer in the
00030  *    documentation and/or other materials provided with the distribution.
00031  * 3. All advertising materials mentioning features or use of this software
00032  *    must display the following acknowledgement:
00033  *    "This product includes cryptographic software written by
00034  *     Eric Young (eay@cryptsoft.com)"
00035  *    The word 'cryptographic' can be left out if the rouines from the library
00036  *    being used are not cryptographic related :-).
00037  * 4. If you include any Windows specific code (or a derivative thereof) from 
00038  *    the apps directory (application code) you must include an acknowledgement:
00039  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
00040  * 
00041  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
00042  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00043  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00044  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00045  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00046  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00047  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00048  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00049  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00050  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00051  * SUCH DAMAGE.
00052  * 
00053  * The licence and distribution terms for any publically available version or
00054  * derivative of this code cannot be changed.  i.e. this code cannot simply be
00055  * copied and put under another distribution licence
00056  * [including the GNU Public Licence.]
00057  */
00058 /* ====================================================================
00059  * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
00060  *
00061  * Redistribution and use in source and binary forms, with or without
00062  * modification, are permitted provided that the following conditions
00063  * are met:
00064  *
00065  * 1. Redistributions of source code must retain the above copyright
00066  *    notice, this list of conditions and the following disclaimer. 
00067  *
00068  * 2. Redistributions in binary form must reproduce the above copyright
00069  *    notice, this list of conditions and the following disclaimer in
00070  *    the documentation and/or other materials provided with the
00071  *    distribution.
00072  *
00073  * 3. All advertising materials mentioning features or use of this
00074  *    software must display the following acknowledgment:
00075  *    "This product includes software developed by the OpenSSL Project
00076  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
00077  *
00078  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
00079  *    endorse or promote products derived from this software without
00080  *    prior written permission. For written permission, please contact
00081  *    openssl-core@openssl.org.
00082  *
00083  * 5. Products derived from this software may not be called "OpenSSL"
00084  *    nor may "OpenSSL" appear in their names without prior written
00085  *    permission of the OpenSSL Project.
00086  *
00087  * 6. Redistributions of any form whatsoever must retain the following
00088  *    acknowledgment:
00089  *    "This product includes software developed by the OpenSSL Project
00090  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
00091  *
00092  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
00093  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00094  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00095  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
00096  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00097  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00098  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00099  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00103  * OF THE POSSIBILITY OF SUCH DAMAGE.
00104  * ====================================================================
00105  *
00106  * This product includes cryptographic software written by Eric Young
00107  * (eay@cryptsoft.com).  This product includes software written by Tim
00108  * Hudson (tjh@cryptsoft.com).
00109  *
00110  */
00111 
00112 #include <stdio.h>
00113 #include <stdlib.h>
00114 #include <string.h>
00115 #include <sys/types.h>
00116 #include <sys/stat.h>
00117 #include <ctype.h>
00118 #include <openssl/err.h>
00119 #include <openssl/x509.h>
00120 #include <openssl/x509v3.h>
00121 #include <openssl/pem.h>
00122 #include <openssl/pkcs12.h>
00123 #include <openssl/ui.h>
00124 #include <openssl/safestack.h>
00125 #ifndef OPENSSL_NO_ENGINE
00126 #include <openssl/engine.h>
00127 #endif
00128 #ifndef OPENSSL_NO_RSA
00129 #include <openssl/rsa.h>
00130 #endif
00131 #include <openssl/bn.h>
00132 
00133 #define NON_MAIN
00134 #include "apps.h"
00135 #undef NON_MAIN
00136 
00137 typedef struct {
00138         const char *name;
00139         unsigned long flag;
00140         unsigned long mask;
00141 } NAME_EX_TBL;
00142 
00143 static UI_METHOD *ui_method = NULL;
00144 
00145 static int set_table_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
00146 static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl);
00147 
00148 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
00149 /* Looks like this stuff is worth moving into separate function */
00150 static EVP_PKEY *
00151 load_netscape_key(BIO *err, BIO *key, const char *file,
00152                 const char *key_descrip, int format);
00153 #endif
00154 
00155 int app_init(long mesgwin);
00156 #ifdef undef /* never finished - probably never will be :-) */
00157 int args_from_file(char *file, int *argc, char **argv[])
00158         {
00159         FILE *fp;
00160         int num,i;
00161         unsigned int len;
00162         static char *buf=NULL;
00163         static char **arg=NULL;
00164         char *p;
00165         struct stat stbuf;
00166 
00167         if (stat(file,&stbuf) < 0) return(0);
00168 
00169         fp=fopen(file,"r");
00170         if (fp == NULL)
00171                 return(0);
00172 
00173         *argc=0;
00174         *argv=NULL;
00175 
00176         len=(unsigned int)stbuf.st_size;
00177         if (buf != NULL) OPENSSL_free(buf);
00178         buf=(char *)OPENSSL_malloc(len+1);
00179         if (buf == NULL) return(0);
00180 
00181         len=fread(buf,1,len,fp);
00182         if (len <= 1) return(0);
00183         buf[len]='\0';
00184 
00185         i=0;
00186         for (p=buf; *p; p++)
00187                 if (*p == '\n') i++;
00188         if (arg != NULL) OPENSSL_free(arg);
00189         arg=(char **)OPENSSL_malloc(sizeof(char *)*(i*2));
00190 
00191         *argv=arg;
00192         num=0;
00193         p=buf;
00194         for (;;)
00195                 {
00196                 if (!*p) break;
00197                 if (*p == '#') /* comment line */
00198                         {
00199                         while (*p && (*p != '\n')) p++;
00200                         continue;
00201                         }
00202                 /* else we have a line */
00203                 *(arg++)=p;
00204                 num++;
00205                 while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n')))
00206                         p++;
00207                 if (!*p) break;
00208                 if (*p == '\n')
00209                         {
00210                         *(p++)='\0';
00211                         continue;
00212                         }
00213                 /* else it is a tab or space */
00214                 p++;
00215                 while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
00216                         p++;
00217                 if (!*p) break;
00218                 if (*p == '\n')
00219                         {
00220                         p++;
00221                         continue;
00222                         }
00223                 *(arg++)=p++;
00224                 num++;
00225                 while (*p && (*p != '\n')) p++;
00226                 if (!*p) break;
00227                 /* else *p == '\n' */
00228                 *(p++)='\0';
00229                 }
00230         *argc=num;
00231         return(1);
00232         }
00233 #endif
00234 
00235 int str2fmt(char *s)
00236         {
00237         if      ((*s == 'D') || (*s == 'd'))
00238                 return(FORMAT_ASN1);
00239         else if ((*s == 'T') || (*s == 't'))
00240                 return(FORMAT_TEXT);
00241         else if ((*s == 'P') || (*s == 'p'))
00242                 return(FORMAT_PEM);
00243         else if ((*s == 'N') || (*s == 'n'))
00244                 return(FORMAT_NETSCAPE);
00245         else if ((*s == 'S') || (*s == 's'))
00246                 return(FORMAT_SMIME);
00247         else if ((*s == '1')
00248                 || (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0)
00249                 || (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0))
00250                 return(FORMAT_PKCS12);
00251         else if ((*s == 'E') || (*s == 'e'))
00252                 return(FORMAT_ENGINE);
00253         else
00254                 return(FORMAT_UNDEF);
00255         }
00256 
00257 #if defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_WIN16) || defined(OPENSSL_SYS_NETWARE)
00258 void program_name(char *in, char *out, int size)
00259         {
00260         int i,n;
00261         char *p=NULL;
00262 
00263         n=strlen(in);
00264         /* find the last '/', '\' or ':' */
00265         for (i=n-1; i>0; i--)
00266                 {
00267                 if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':'))
00268                         {
00269                         p= &(in[i+1]);
00270                         break;
00271                         }
00272                 }
00273         if (p == NULL)
00274                 p=in;
00275         n=strlen(p);
00276 
00277 #if defined(OPENSSL_SYS_NETWARE)
00278    /* strip off trailing .nlm if present. */
00279    if ((n > 4) && (p[n-4] == '.') &&
00280       ((p[n-3] == 'n') || (p[n-3] == 'N')) &&
00281       ((p[n-2] == 'l') || (p[n-2] == 'L')) &&
00282       ((p[n-1] == 'm') || (p[n-1] == 'M')))
00283       n-=4;
00284 #else
00285         /* strip off trailing .exe if present. */
00286         if ((n > 4) && (p[n-4] == '.') &&
00287                 ((p[n-3] == 'e') || (p[n-3] == 'E')) &&
00288                 ((p[n-2] == 'x') || (p[n-2] == 'X')) &&
00289                 ((p[n-1] == 'e') || (p[n-1] == 'E')))
00290                 n-=4;
00291 #endif
00292 
00293         if (n > size-1)
00294                 n=size-1;
00295 
00296         for (i=0; i<n; i++)
00297                 {
00298                 if ((p[i] >= 'A') && (p[i] <= 'Z'))
00299                         out[i]=p[i]-'A'+'a';
00300                 else
00301                         out[i]=p[i];
00302                 }
00303         out[n]='\0';
00304         }
00305 #else
00306 #ifdef OPENSSL_SYS_VMS
00307 void program_name(char *in, char *out, int size)
00308         {
00309         char *p=in, *q;
00310         char *chars=":]>";
00311 
00312         while(*chars != '\0')
00313                 {
00314                 q=strrchr(p,*chars);
00315                 if (q > p)
00316                         p = q + 1;
00317                 chars++;
00318                 }
00319 
00320         q=strrchr(p,'.');
00321         if (q == NULL)
00322                 q = p + strlen(p);
00323         strncpy(out,p,size-1);
00324         if (q-p >= size)
00325                 {
00326                 out[size-1]='\0';
00327                 }
00328         else
00329                 {
00330                 out[q-p]='\0';
00331                 }
00332         }
00333 #else
00334 void program_name(char *in, char *out, int size)
00335         {
00336         char *p;
00337 
00338         p=strrchr(in,'/');
00339         if (p != NULL)
00340                 p++;
00341         else
00342                 p=in;
00343         BUF_strlcpy(out,p,size);
00344         }
00345 #endif
00346 #endif
00347 
00348 int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
00349         {
00350         int num,len,i;
00351         char *p;
00352 
00353         *argc=0;
00354         *argv=NULL;
00355 
00356         len=strlen(buf);
00357         i=0;
00358         if (arg->count == 0)
00359                 {
00360                 arg->count=20;
00361                 arg->data=(char **)OPENSSL_malloc(sizeof(char *)*arg->count);
00362                 }
00363         for (i=0; i<arg->count; i++)
00364                 arg->data[i]=NULL;
00365 
00366         num=0;
00367         p=buf;
00368         for (;;)
00369                 {
00370                 /* first scan over white space */
00371                 if (!*p) break;
00372                 while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n')))
00373                         p++;
00374                 if (!*p) break;
00375 
00376                 /* The start of something good :-) */
00377                 if (num >= arg->count)
00378                         {
00379                         char **tmp_p;
00380                         int tlen = arg->count + 20;
00381                         tmp_p = (char **)OPENSSL_realloc(arg->data,
00382                                 sizeof(char *)*tlen);
00383                         if (tmp_p == NULL)
00384                                 return 0;
00385                         arg->data  = tmp_p;
00386                         arg->count = tlen;
00387                         /* initialize newly allocated data */
00388                         for (i = num; i < arg->count; i++)
00389                                 arg->data[i] = NULL;
00390                         }
00391                 arg->data[num++]=p;
00392 
00393                 /* now look for the end of this */
00394                 if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */
00395                         {
00396                         i= *(p++);
00397                         arg->data[num-1]++; /* jump over quote */
00398                         while (*p && (*p != i))
00399                                 p++;
00400                         *p='\0';
00401                         }
00402                 else
00403                         {
00404                         while (*p && ((*p != ' ') &&
00405                                 (*p != '\t') && (*p != '\n')))
00406                                 p++;
00407 
00408                         if (*p == '\0')
00409                                 p--;
00410                         else
00411                                 *p='\0';
00412                         }
00413                 p++;
00414                 }
00415         *argc=num;
00416         *argv=arg->data;
00417         return(1);
00418         }
00419 
00420 #ifndef APP_INIT
00421 int app_init(long mesgwin)
00422         {
00423         return(1);
00424         }
00425 #endif
00426 
00427 
00428 int dump_cert_text (BIO *out, X509 *x)
00429 {
00430         char *p;
00431 
00432         p=X509_NAME_oneline(X509_get_subject_name(x),NULL,0);
00433         BIO_puts(out,"subject=");
00434         BIO_puts(out,p);
00435         OPENSSL_free(p);
00436 
00437         p=X509_NAME_oneline(X509_get_issuer_name(x),NULL,0);
00438         BIO_puts(out,"\nissuer=");
00439         BIO_puts(out,p);
00440         BIO_puts(out,"\n");
00441         OPENSSL_free(p);
00442 
00443         return 0;
00444 }
00445 
00446 static int ui_open(UI *ui)
00447         {
00448         return UI_method_get_opener(UI_OpenSSL())(ui);
00449         }
00450 static int ui_read(UI *ui, UI_STRING *uis)
00451         {
00452         if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
00453                 && UI_get0_user_data(ui))
00454                 {
00455                 switch(UI_get_string_type(uis))
00456                         {
00457                 case UIT_PROMPT:
00458                 case UIT_VERIFY:
00459                         {
00460                         const char *password =
00461                                 ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
00462                         if (password && password[0] != '\0')
00463                                 {
00464                                 UI_set_result(ui, uis, password);
00465                                 return 1;
00466                                 }
00467                         }
00468                 default:
00469                         break;
00470                         }
00471                 }
00472         return UI_method_get_reader(UI_OpenSSL())(ui, uis);
00473         }
00474 static int ui_write(UI *ui, UI_STRING *uis)
00475         {
00476         if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD
00477                 && UI_get0_user_data(ui))
00478                 {
00479                 switch(UI_get_string_type(uis))
00480                         {
00481                 case UIT_PROMPT:
00482                 case UIT_VERIFY:
00483                         {
00484                         const char *password =
00485                                 ((PW_CB_DATA *)UI_get0_user_data(ui))->password;
00486                         if (password && password[0] != '\0')
00487                                 return 1;
00488                         }
00489                 default:
00490                         break;
00491                         }
00492                 }
00493         return UI_method_get_writer(UI_OpenSSL())(ui, uis);
00494         }
00495 static int ui_close(UI *ui)
00496         {
00497         return UI_method_get_closer(UI_OpenSSL())(ui);
00498         }
00499 int setup_ui_method(void)
00500         {
00501         ui_method = UI_create_method("OpenSSL application user interface");
00502         UI_method_set_opener(ui_method, ui_open);
00503         UI_method_set_reader(ui_method, ui_read);
00504         UI_method_set_writer(ui_method, ui_write);
00505         UI_method_set_closer(ui_method, ui_close);
00506         return 0;
00507         }
00508 void destroy_ui_method(void)
00509         {
00510         if(ui_method)
00511                 {
00512                 UI_destroy_method(ui_method);
00513                 ui_method = NULL;
00514                 }
00515         }
00516 int password_callback(char *buf, int bufsiz, int verify,
00517         PW_CB_DATA *cb_tmp)
00518         {
00519         UI *ui = NULL;
00520         int res = 0;
00521         const char *prompt_info = NULL;
00522         const char *password = NULL;
00523         PW_CB_DATA *cb_data = (PW_CB_DATA *)cb_tmp;
00524 
00525         if (cb_data)
00526                 {
00527                 if (cb_data->password)
00528                         password = cb_data->password;
00529                 if (cb_data->prompt_info)
00530                         prompt_info = cb_data->prompt_info;
00531                 }
00532 
00533         if (password)
00534                 {
00535                 res = strlen(password);
00536                 if (res > bufsiz)
00537                         res = bufsiz;
00538                 memcpy(buf, password, res);
00539                 return res;
00540                 }
00541 
00542         ui = UI_new_method(ui_method);
00543         if (ui)
00544                 {
00545                 int ok = 0;
00546                 char *buff = NULL;
00547                 int ui_flags = 0;
00548                 char *prompt = NULL;
00549 
00550                 prompt = UI_construct_prompt(ui, "pass phrase",
00551                         prompt_info);
00552 
00553                 ui_flags |= UI_INPUT_FLAG_DEFAULT_PWD;
00554                 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
00555 
00556                 if (ok >= 0)
00557                         ok = UI_add_input_string(ui,prompt,ui_flags,buf,
00558                                 PW_MIN_LENGTH,BUFSIZ-1);
00559                 if (ok >= 0 && verify)
00560                         {
00561                         buff = (char *)OPENSSL_malloc(bufsiz);
00562                         ok = UI_add_verify_string(ui,prompt,ui_flags,buff,
00563                                 PW_MIN_LENGTH,BUFSIZ-1, buf);
00564                         }
00565                 if (ok >= 0)
00566                         do
00567                                 {
00568                                 ok = UI_process(ui);
00569                                 }
00570                         while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
00571 
00572                 if (buff)
00573                         {
00574                         OPENSSL_cleanse(buff,(unsigned int)bufsiz);
00575                         OPENSSL_free(buff);
00576                         }
00577 
00578                 if (ok >= 0)
00579                         res = strlen(buf);
00580                 if (ok == -1)
00581                         {
00582                         BIO_printf(bio_err, "User interface error\n");
00583                         ERR_print_errors(bio_err);
00584                         OPENSSL_cleanse(buf,(unsigned int)bufsiz);
00585                         res = 0;
00586                         }
00587                 if (ok == -2)
00588                         {
00589                         BIO_printf(bio_err,"aborted!\n");
00590                         OPENSSL_cleanse(buf,(unsigned int)bufsiz);
00591                         res = 0;
00592                         }
00593                 UI_free(ui);
00594                 OPENSSL_free(prompt);
00595                 }
00596         return res;
00597         }
00598 
00599 static char *app_get_pass(BIO *err, char *arg, int keepbio);
00600 
00601 int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
00602 {
00603         int same;
00604         if(!arg2 || !arg1 || strcmp(arg1, arg2)) same = 0;
00605         else same = 1;
00606         if(arg1) {
00607                 *pass1 = app_get_pass(err, arg1, same);
00608                 if(!*pass1) return 0;
00609         } else if(pass1) *pass1 = NULL;
00610         if(arg2) {
00611                 *pass2 = app_get_pass(err, arg2, same ? 2 : 0);
00612                 if(!*pass2) return 0;
00613         } else if(pass2) *pass2 = NULL;
00614         return 1;
00615 }
00616 
00617 static char *app_get_pass(BIO *err, char *arg, int keepbio)
00618 {
00619         char *tmp, tpass[APP_PASS_LEN];
00620         static BIO *pwdbio = NULL;
00621         int i;
00622         if(!strncmp(arg, "pass:", 5)) return BUF_strdup(arg + 5);
00623         if(!strncmp(arg, "env:", 4)) {
00624                 tmp = getenv(arg + 4);
00625                 if(!tmp) {
00626                         BIO_printf(err, "Can't read environment variable %s\n", arg + 4);
00627                         return NULL;
00628                 }
00629                 return BUF_strdup(tmp);
00630         }
00631         if(!keepbio || !pwdbio) {
00632                 if(!strncmp(arg, "file:", 5)) {
00633                         pwdbio = BIO_new_file(arg + 5, "r");
00634                         if(!pwdbio) {
00635                                 BIO_printf(err, "Can't open file %s\n", arg + 5);
00636                                 return NULL;
00637                         }
00638                 } else if(!strncmp(arg, "fd:", 3)) {
00639                         BIO *btmp;
00640                         i = atoi(arg + 3);
00641                         if(i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE);
00642                         if((i < 0) || !pwdbio) {
00643                                 BIO_printf(err, "Can't access file descriptor %s\n", arg + 3);
00644                                 return NULL;
00645                         }
00646                         /* Can't do BIO_gets on an fd BIO so add a buffering BIO */
00647                         btmp = BIO_new(BIO_f_buffer());
00648                         pwdbio = BIO_push(btmp, pwdbio);
00649                 } else if(!strcmp(arg, "stdin")) {
00650                         pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
00651                         if(!pwdbio) {
00652                                 BIO_printf(err, "Can't open BIO for stdin\n");
00653                                 return NULL;
00654                         }
00655                 } else {
00656                         BIO_printf(err, "Invalid password argument \"%s\"\n", arg);
00657                         return NULL;
00658                 }
00659         }
00660         i = BIO_gets(pwdbio, tpass, APP_PASS_LEN);
00661         if(keepbio != 1) {
00662                 BIO_free_all(pwdbio);
00663                 pwdbio = NULL;
00664         }
00665         if(i <= 0) {
00666                 BIO_printf(err, "Error reading password from BIO\n");
00667                 return NULL;
00668         }
00669         tmp = strchr(tpass, '\n');
00670         if(tmp) *tmp = 0;
00671         return BUF_strdup(tpass);
00672 }
00673 
00674 int add_oid_section(BIO *err, CONF *conf)
00675 {       
00676         char *p;
00677         STACK_OF(CONF_VALUE) *sktmp;
00678         CONF_VALUE *cnf;
00679         int i;
00680         if(!(p=NCONF_get_string(conf,NULL,"oid_section")))
00681                 {
00682                 ERR_clear_error();
00683                 return 1;
00684                 }
00685         if(!(sktmp = NCONF_get_section(conf, p))) {
00686                 BIO_printf(err, "problem loading oid section %s\n", p);
00687                 return 0;
00688         }
00689         for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
00690                 cnf = sk_CONF_VALUE_value(sktmp, i);
00691                 if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
00692                         BIO_printf(err, "problem creating object %s=%s\n",
00693                                                          cnf->name, cnf->value);
00694                         return 0;
00695                 }
00696         }
00697         return 1;
00698 }
00699 
00700 static int load_pkcs12(BIO *err, BIO *in, const char *desc,
00701                 pem_password_cb *pem_cb,  void *cb_data,
00702                 EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca)
00703         {
00704         const char *pass;
00705         char tpass[PEM_BUFSIZE];
00706         int len, ret = 0;
00707         PKCS12 *p12;
00708         p12 = d2i_PKCS12_bio(in, NULL);
00709         if (p12 == NULL)
00710                 {
00711                 BIO_printf(err, "Error loading PKCS12 file for %s\n", desc);    
00712                 goto die;
00713                 }
00714         /* See if an empty password will do */
00715         if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0))
00716                 pass = "";
00717         else
00718                 {
00719                 if (!pem_cb)
00720                         pem_cb = (pem_password_cb *)password_callback;
00721                 len = pem_cb(tpass, PEM_BUFSIZE, 0, cb_data);
00722                 if (len < 0) 
00723                         {
00724                         BIO_printf(err, "Passpharse callback error for %s\n",
00725                                         desc);
00726                         goto die;
00727                         }
00728                 if (len < PEM_BUFSIZE)
00729                         tpass[len] = 0;
00730                 if (!PKCS12_verify_mac(p12, tpass, len))
00731                         {
00732                         BIO_printf(err,
00733         "Mac verify error (wrong password?) in PKCS12 file for %s\n", desc);    
00734                         goto die;
00735                         }
00736                 pass = tpass;
00737                 }
00738         ret = PKCS12_parse(p12, pass, pkey, cert, ca);
00739         die:
00740         if (p12)
00741                 PKCS12_free(p12);
00742         return ret;
00743         }
00744 
00745 X509 *load_cert(BIO *err, const char *file, int format,
00746         const char *pass, ENGINE *e, const char *cert_descrip)
00747         {
00748         ASN1_HEADER *ah=NULL;
00749         BUF_MEM *buf=NULL;
00750         X509 *x=NULL;
00751         BIO *cert;
00752 
00753         if ((cert=BIO_new(BIO_s_file())) == NULL)
00754                 {
00755                 ERR_print_errors(err);
00756                 goto end;
00757                 }
00758 
00759         if (file == NULL)
00760                 {
00761                 setvbuf(stdin, NULL, _IONBF, 0);
00762                 BIO_set_fp(cert,stdin,BIO_NOCLOSE);
00763                 }
00764         else
00765                 {
00766                 if (BIO_read_filename(cert,file) <= 0)
00767                         {
00768                         BIO_printf(err, "Error opening %s %s\n",
00769                                 cert_descrip, file);
00770                         ERR_print_errors(err);
00771                         goto end;
00772                         }
00773                 }
00774 
00775         if      (format == FORMAT_ASN1)
00776                 x=d2i_X509_bio(cert,NULL);
00777         else if (format == FORMAT_NETSCAPE)
00778                 {
00779                 const unsigned char *p,*op;
00780                 int size=0,i;
00781 
00782                 /* We sort of have to do it this way because it is sort of nice
00783                  * to read the header first and check it, then
00784                  * try to read the certificate */
00785                 buf=BUF_MEM_new();
00786                 for (;;)
00787                         {
00788                         if ((buf == NULL) || (!BUF_MEM_grow(buf,size+1024*10)))
00789                                 goto end;
00790                         i=BIO_read(cert,&(buf->data[size]),1024*10);
00791                         size+=i;
00792                         if (i == 0) break;
00793                         if (i < 0)
00794                                 {
00795                                 perror("reading certificate");
00796                                 goto end;
00797                                 }
00798                         }
00799                 p=(unsigned char *)buf->data;
00800                 op=p;
00801 
00802                 /* First load the header */
00803                 if ((ah=d2i_ASN1_HEADER(NULL,&p,(long)size)) == NULL)
00804                         goto end;
00805                 if ((ah->header == NULL) || (ah->header->data == NULL) ||
00806                         (strncmp(NETSCAPE_CERT_HDR,(char *)ah->header->data,
00807                         ah->header->length) != 0))
00808                         {
00809                         BIO_printf(err,"Error reading header on certificate\n");
00810                         goto end;
00811                         }
00812                 /* header is ok, so now read the object */
00813                 p=op;
00814                 ah->meth=X509_asn1_meth();
00815                 if ((ah=d2i_ASN1_HEADER(&ah,&p,(long)size)) == NULL)
00816                         goto end;
00817                 x=(X509 *)ah->data;
00818                 ah->data=NULL;
00819                 }
00820         else if (format == FORMAT_PEM)
00821                 x=PEM_read_bio_X509_AUX(cert,NULL,
00822                         (pem_password_cb *)password_callback, NULL);
00823         else if (format == FORMAT_PKCS12)
00824                 {
00825                 if (!load_pkcs12(err, cert,cert_descrip, NULL, NULL,
00826                                         NULL, &x, NULL))
00827                         goto end;
00828                 }
00829         else    {
00830                 BIO_printf(err,"bad input format specified for %s\n",
00831                         cert_descrip);
00832                 goto end;
00833                 }
00834 end:
00835         if (x == NULL)
00836                 {
00837                 BIO_printf(err,"unable to load certificate\n");
00838                 ERR_print_errors(err);
00839                 }
00840         if (ah != NULL) ASN1_HEADER_free(ah);
00841         if (cert != NULL) BIO_free(cert);
00842         if (buf != NULL) BUF_MEM_free(buf);
00843         return(x);
00844         }
00845 
00846 EVP_PKEY *load_key(BIO *err, const char *file, int format, int maybe_stdin,
00847         const char *pass, ENGINE *e, const char *key_descrip)
00848         {
00849         BIO *key=NULL;
00850         EVP_PKEY *pkey=NULL;
00851         PW_CB_DATA cb_data;
00852 
00853         cb_data.password = pass;
00854         cb_data.prompt_info = file;
00855 
00856         if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
00857                 {
00858                 BIO_printf(err,"no keyfile specified\n");
00859                 goto end;
00860                 }
00861 #ifndef OPENSSL_NO_ENGINE
00862         if (format == FORMAT_ENGINE)
00863                 {
00864                 if (!e)
00865                         BIO_printf(bio_err,"no engine specified\n");
00866                 else
00867                         pkey = ENGINE_load_private_key(e, file,
00868                                 ui_method, &cb_data);
00869                 goto end;
00870                 }
00871 #endif
00872         key=BIO_new(BIO_s_file());
00873         if (key == NULL)
00874                 {
00875                 ERR_print_errors(err);
00876                 goto end;
00877                 }
00878         if (file == NULL && maybe_stdin)
00879                 {
00880                 setvbuf(stdin, NULL, _IONBF, 0);
00881                 BIO_set_fp(key,stdin,BIO_NOCLOSE);
00882                 }
00883         else
00884                 if (BIO_read_filename(key,file) <= 0)
00885                         {
00886                         BIO_printf(err, "Error opening %s %s\n",
00887                                 key_descrip, file);
00888                         ERR_print_errors(err);
00889                         goto end;
00890                         }
00891         if (format == FORMAT_ASN1)
00892                 {
00893                 pkey=d2i_PrivateKey_bio(key, NULL);
00894                 }
00895         else if (format == FORMAT_PEM)
00896                 {
00897                 pkey=PEM_read_bio_PrivateKey(key,NULL,
00898                         (pem_password_cb *)password_callback, &cb_data);
00899                 }
00900 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
00901         else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
00902                 pkey = load_netscape_key(err, key, file, key_descrip, format);
00903 #endif
00904         else if (format == FORMAT_PKCS12)
00905                 {
00906                 if (!load_pkcs12(err, key, key_descrip,
00907                                 (pem_password_cb *)password_callback, &cb_data,
00908                                 &pkey, NULL, NULL))
00909                         goto end;
00910                 }
00911         else
00912                 {
00913                 BIO_printf(err,"bad input format specified for key file\n");
00914                 goto end;
00915                 }
00916  end:
00917         if (key != NULL) BIO_free(key);
00918         if (pkey == NULL)
00919                 BIO_printf(err,"unable to load %s\n", key_descrip);
00920         return(pkey);
00921         }
00922 
00923 EVP_PKEY *load_pubkey(BIO *err, const char *file, int format, int maybe_stdin,
00924         const char *pass, ENGINE *e, const char *key_descrip)
00925         {
00926         BIO *key=NULL;
00927         EVP_PKEY *pkey=NULL;
00928         PW_CB_DATA cb_data;
00929 
00930         cb_data.password = pass;
00931         cb_data.prompt_info = file;
00932 
00933         if (file == NULL && (!maybe_stdin || format == FORMAT_ENGINE))
00934                 {
00935                 BIO_printf(err,"no keyfile specified\n");
00936                 goto end;
00937                 }
00938 #ifndef OPENSSL_NO_ENGINE
00939         if (format == FORMAT_ENGINE)
00940                 {
00941                 if (!e)
00942                         BIO_printf(bio_err,"no engine specified\n");
00943                 else
00944                         pkey = ENGINE_load_public_key(e, file,
00945                                 ui_method, &cb_data);
00946                 goto end;
00947                 }
00948 #endif
00949         key=BIO_new(BIO_s_file());
00950         if (key == NULL)
00951                 {
00952                 ERR_print_errors(err);
00953                 goto end;
00954                 }
00955         if (file == NULL && maybe_stdin)
00956                 {
00957                 setvbuf(stdin, NULL, _IONBF, 0);
00958                 BIO_set_fp(key,stdin,BIO_NOCLOSE);
00959                 }
00960         else
00961                 if (BIO_read_filename(key,file) <= 0)
00962                         {
00963                         BIO_printf(err, "Error opening %s %s\n",
00964                                 key_descrip, file);
00965                         ERR_print_errors(err);
00966                         goto end;
00967                 }
00968         if (format == FORMAT_ASN1)
00969                 {
00970                 pkey=d2i_PUBKEY_bio(key, NULL);
00971                 }
00972         else if (format == FORMAT_PEM)
00973                 {
00974                 pkey=PEM_read_bio_PUBKEY(key,NULL,
00975                         (pem_password_cb *)password_callback, &cb_data);
00976                 }
00977 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
00978         else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
00979                 pkey = load_netscape_key(err, key, file, key_descrip, format);
00980 #endif
00981         else
00982                 {
00983                 BIO_printf(err,"bad input format specified for key file\n");
00984                 goto end;
00985                 }
00986  end:
00987         if (key != NULL) BIO_free(key);
00988         if (pkey == NULL)
00989                 BIO_printf(err,"unable to load %s\n", key_descrip);
00990         return(pkey);
00991         }
00992 
00993 #if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_RSA)
00994 static EVP_PKEY *
00995 load_netscape_key(BIO *err, BIO *key, const char *file,
00996                 const char *key_descrip, int format)
00997         {
00998         EVP_PKEY *pkey;
00999         BUF_MEM *buf;
01000         RSA     *rsa;
01001         const unsigned char *p;
01002         int size, i;
01003 
01004         buf=BUF_MEM_new();
01005         pkey = EVP_PKEY_new();
01006         size = 0;
01007         if (buf == NULL || pkey == NULL)
01008                 goto error;
01009         for (;;)
01010                 {
01011                 if (!BUF_MEM_grow_clean(buf,size+1024*10))
01012                         goto error;
01013                 i = BIO_read(key, &(buf->data[size]), 1024*10);
01014                 size += i;
01015                 if (i == 0)
01016                         break;
01017                 if (i < 0)
01018                         {
01019                                 BIO_printf(err, "Error reading %s %s",
01020                                         key_descrip, file);
01021                                 goto error;
01022                         }
01023                 }
01024         p=(unsigned char *)buf->data;
01025         rsa = d2i_RSA_NET(NULL,&p,(long)size,NULL,
01026                 (format == FORMAT_IISSGC ? 1 : 0));
01027         if (rsa == NULL)
01028                 goto error;
01029         BUF_MEM_free(buf);
01030         EVP_PKEY_set1_RSA(pkey, rsa);
01031         return pkey;
01032 error:
01033         BUF_MEM_free(buf);
01034         EVP_PKEY_free(pkey);
01035         return NULL;
01036         }
01037 #endif /* ndef OPENSSL_NO_RC4 */
01038 
01039 STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
01040         const char *pass, ENGINE *e, const char *cert_descrip)
01041         {
01042         BIO *certs;
01043         int i;
01044         STACK_OF(X509) *othercerts = NULL;
01045         STACK_OF(X509_INFO) *allcerts = NULL;
01046         X509_INFO *xi;
01047         PW_CB_DATA cb_data;
01048 
01049         cb_data.password = pass;
01050         cb_data.prompt_info = file;
01051 
01052         if((certs = BIO_new(BIO_s_file())) == NULL)
01053                 {
01054                 ERR_print_errors(err);
01055                 goto end;
01056                 }
01057 
01058         if (file == NULL)
01059                 BIO_set_fp(certs,stdin,BIO_NOCLOSE);
01060         else
01061                 {
01062                 if (BIO_read_filename(certs,file) <= 0)
01063                         {
01064                         BIO_printf(err, "Error opening %s %s\n",
01065                                 cert_descrip, file);
01066                         ERR_print_errors(err);
01067                         goto end;
01068                         }
01069                 }
01070 
01071         if      (format == FORMAT_PEM)
01072                 {
01073                 othercerts = sk_X509_new_null();
01074                 if(!othercerts)
01075                         {
01076                         sk_X509_free(othercerts);
01077                         othercerts = NULL;
01078                         goto end;
01079                         }
01080                 allcerts = PEM_X509_INFO_read_bio(certs, NULL,
01081                                 (pem_password_cb *)password_callback, &cb_data);
01082                 for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
01083                         {
01084                         xi = sk_X509_INFO_value (allcerts, i);
01085                         if (xi->x509)
01086                                 {
01087                                 sk_X509_push(othercerts, xi->x509);
01088                                 xi->x509 = NULL;
01089                                 }
01090                         }
01091                 goto end;
01092                 }
01093         else    {
01094                 BIO_printf(err,"bad input format specified for %s\n",
01095                         cert_descrip);
01096                 goto end;
01097                 }
01098 end:
01099         if (othercerts == NULL)
01100                 {
01101                 BIO_printf(err,"unable to load certificates\n");
01102                 ERR_print_errors(err);
01103                 }
01104         if (allcerts) sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
01105         if (certs != NULL) BIO_free(certs);
01106         return(othercerts);
01107         }
01108 
01109 
01110 #define X509V3_EXT_UNKNOWN_MASK         (0xfL << 16)
01111 /* Return error for unknown extensions */
01112 #define X509V3_EXT_DEFAULT              0
01113 /* Print error for unknown extensions */
01114 #define X509V3_EXT_ERROR_UNKNOWN        (1L << 16)
01115 /* ASN1 parse unknown extensions */
01116 #define X509V3_EXT_PARSE_UNKNOWN        (2L << 16)
01117 /* BIO_dump unknown extensions */
01118 #define X509V3_EXT_DUMP_UNKNOWN         (3L << 16)
01119 
01120 #define X509_FLAG_CA (X509_FLAG_NO_ISSUER | X509_FLAG_NO_PUBKEY | \
01121                          X509_FLAG_NO_HEADER | X509_FLAG_NO_VERSION)
01122 
01123 int set_cert_ex(unsigned long *flags, const char *arg)
01124 {
01125         static const NAME_EX_TBL cert_tbl[] = {
01126                 { "compatible", X509_FLAG_COMPAT, 0xffffffffl},
01127                 { "ca_default", X509_FLAG_CA, 0xffffffffl},
01128                 { "no_header", X509_FLAG_NO_HEADER, 0},
01129                 { "no_version", X509_FLAG_NO_VERSION, 0},
01130                 { "no_serial", X509_FLAG_NO_SERIAL, 0},
01131                 { "no_signame", X509_FLAG_NO_SIGNAME, 0},
01132                 { "no_validity", X509_FLAG_NO_VALIDITY, 0},
01133                 { "no_subject", X509_FLAG_NO_SUBJECT, 0},
01134                 { "no_issuer", X509_FLAG_NO_ISSUER, 0},
01135                 { "no_pubkey", X509_FLAG_NO_PUBKEY, 0},
01136                 { "no_extensions", X509_FLAG_NO_EXTENSIONS, 0},
01137                 { "no_sigdump", X509_FLAG_NO_SIGDUMP, 0},
01138                 { "no_aux", X509_FLAG_NO_AUX, 0},
01139                 { "no_attributes", X509_FLAG_NO_ATTRIBUTES, 0},
01140                 { "ext_default", X509V3_EXT_DEFAULT, X509V3_EXT_UNKNOWN_MASK},
01141                 { "ext_error", X509V3_EXT_ERROR_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
01142                 { "ext_parse", X509V3_EXT_PARSE_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
01143                 { "ext_dump", X509V3_EXT_DUMP_UNKNOWN, X509V3_EXT_UNKNOWN_MASK},
01144                 { NULL, 0, 0}
01145         };
01146         return set_multi_opts(flags, arg, cert_tbl);
01147 }
01148 
01149 int set_name_ex(unsigned long *flags, const char *arg)
01150 {
01151         static const NAME_EX_TBL ex_tbl[] = {
01152                 { "esc_2253", ASN1_STRFLGS_ESC_2253, 0},
01153                 { "esc_ctrl", ASN1_STRFLGS_ESC_CTRL, 0},
01154                 { "esc_msb", ASN1_STRFLGS_ESC_MSB, 0},
01155                 { "use_quote", ASN1_STRFLGS_ESC_QUOTE, 0},
01156                 { "utf8", ASN1_STRFLGS_UTF8_CONVERT, 0},
01157                 { "ignore_type", ASN1_STRFLGS_IGNORE_TYPE, 0},
01158                 { "show_type", ASN1_STRFLGS_SHOW_TYPE, 0},