apps.c revision 59191
1259698Sdim/* apps/apps.c */ 2259698Sdim/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3259698Sdim * All rights reserved. 4259698Sdim * 5259698Sdim * This package is an SSL implementation written 6259698Sdim * by Eric Young (eay@cryptsoft.com). 7259698Sdim * The implementation was written so as to conform with Netscapes SSL. 8259698Sdim * 9259698Sdim * This library is free for commercial and non-commercial use as long as 10259698Sdim * the following conditions are aheared to. The following conditions 11259698Sdim * apply to all code found in this distribution, be it the RC4, RSA, 12259698Sdim * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13259698Sdim * included with this distribution is covered by the same copyright terms 14259698Sdim * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15259698Sdim * 16259698Sdim * Copyright remains Eric Young's, and as such any Copyright notices in 17259698Sdim * the code are not to be removed. 18259698Sdim * If this package is used in a product, Eric Young should be given attribution 19259698Sdim * as the author of the parts of the library used. 20259698Sdim * This can be in the form of a textual message at program startup or 21259698Sdim * in documentation (online or textual) provided with the package. 22259698Sdim * 23259698Sdim * Redistribution and use in source and binary forms, with or without 24259698Sdim * modification, are permitted provided that the following conditions 25259698Sdim * are met: 26259698Sdim * 1. Redistributions of source code must retain the copyright 27259698Sdim * notice, this list of conditions and the following disclaimer. 28259698Sdim * 2. Redistributions in binary form must reproduce the above copyright 29259698Sdim * notice, this list of conditions and the following disclaimer in the 30259698Sdim * documentation and/or other materials provided with the distribution. 31259698Sdim * 3. All advertising materials mentioning features or use of this software 32259698Sdim * must display the following acknowledgement: 33259698Sdim * "This product includes cryptographic software written by 34259698Sdim * Eric Young (eay@cryptsoft.com)" 35259698Sdim * The word 'cryptographic' can be left out if the rouines from the library 36259698Sdim * being used are not cryptographic related :-). 37259698Sdim * 4. If you include any Windows specific code (or a derivative thereof) from 38259698Sdim * the apps directory (application code) you must include an acknowledgement: 39259698Sdim * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40259698Sdim * 41259698Sdim * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42259698Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43259698Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44259698Sdim * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45259698Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46259698Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47259698Sdim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48259698Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49259698Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50259698Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51259698Sdim * SUCH DAMAGE. 52259698Sdim * 53259698Sdim * The licence and distribution terms for any publically available version or 54259698Sdim * derivative of this code cannot be changed. i.e. this code cannot simply be 55259698Sdim * copied and put under another distribution licence 56259698Sdim * [including the GNU Public Licence.] 57259698Sdim */ 58259698Sdim 59259698Sdim#include <stdio.h> 60259698Sdim#include <stdlib.h> 61259698Sdim#include <string.h> 62259698Sdim#include <sys/types.h> 63259698Sdim#include <sys/stat.h> 64259698Sdim#define NON_MAIN 65259698Sdim#include "apps.h" 66259698Sdim#undef NON_MAIN 67259698Sdim 68259698Sdim#ifdef WINDOWS 69259698Sdim# include "bss_file.c" 70259698Sdim#endif 71259698Sdim 72259698Sdimint app_init(long mesgwin); 73259698Sdim#ifdef undef /* never finished - probably never will be :-) */ 74259698Sdimint args_from_file(char *file, int *argc, char **argv[]) 75259698Sdim { 76259698Sdim FILE *fp; 77259698Sdim int num,i; 78259698Sdim unsigned int len; 79259698Sdim static char *buf=NULL; 80259698Sdim static char **arg=NULL; 81259698Sdim char *p; 82259698Sdim struct stat stbuf; 83259698Sdim 84259698Sdim if (stat(file,&stbuf) < 0) return(0); 85259698Sdim 86259698Sdim fp=fopen(file,"r"); 87259698Sdim if (fp == NULL) 88259698Sdim return(0); 89259698Sdim 90259698Sdim *argc=0; 91259698Sdim *argv=NULL; 92259698Sdim 93259698Sdim len=(unsigned int)stbuf.st_size; 94259698Sdim if (buf != NULL) Free(buf); 95259698Sdim buf=(char *)Malloc(len+1); 96259698Sdim if (buf == NULL) return(0); 97259698Sdim 98259698Sdim len=fread(buf,1,len,fp); 99259698Sdim if (len <= 1) return(0); 100259698Sdim buf[len]='\0'; 101259698Sdim 102259698Sdim i=0; 103259698Sdim for (p=buf; *p; p++) 104259698Sdim if (*p == '\n') i++; 105259698Sdim if (arg != NULL) Free(arg); 106259698Sdim arg=(char **)Malloc(sizeof(char *)*(i*2)); 107259698Sdim 108259698Sdim *argv=arg; 109259698Sdim num=0; 110259698Sdim p=buf; 111259698Sdim for (;;) 112259698Sdim { 113259698Sdim if (!*p) break; 114259698Sdim if (*p == '#') /* comment line */ 115259698Sdim { 116259698Sdim while (*p && (*p != '\n')) p++; 117259698Sdim continue; 118259698Sdim } 119259698Sdim /* else we have a line */ 120259698Sdim *(arg++)=p; 121259698Sdim num++; 122259698Sdim while (*p && ((*p != ' ') && (*p != '\t') && (*p != '\n'))) 123259698Sdim p++; 124259698Sdim if (!*p) break; 125259698Sdim if (*p == '\n') 126259698Sdim { 127259698Sdim *(p++)='\0'; 128259698Sdim continue; 129259698Sdim } 130259698Sdim /* else it is a tab or space */ 131259698Sdim p++; 132259698Sdim while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 133259698Sdim p++; 134259698Sdim if (!*p) break; 135259698Sdim if (*p == '\n') 136259698Sdim { 137259698Sdim p++; 138259698Sdim continue; 139259698Sdim } 140259698Sdim *(arg++)=p++; 141259698Sdim num++; 142259698Sdim while (*p && (*p != '\n')) p++; 143259698Sdim if (!*p) break; 144259698Sdim /* else *p == '\n' */ 145259698Sdim *(p++)='\0'; 146259698Sdim } 147259698Sdim *argc=num; 148259698Sdim return(1); 149259698Sdim } 150259698Sdim#endif 151259698Sdim 152259698Sdimint str2fmt(char *s) 153259698Sdim { 154259698Sdim if ((*s == 'D') || (*s == 'd')) 155259698Sdim return(FORMAT_ASN1); 156259698Sdim else if ((*s == 'T') || (*s == 't')) 157259698Sdim return(FORMAT_TEXT); 158259698Sdim else if ((*s == 'P') || (*s == 'p')) 159259698Sdim return(FORMAT_PEM); 160259698Sdim else if ((*s == 'N') || (*s == 'n')) 161259698Sdim return(FORMAT_NETSCAPE); 162259698Sdim else 163259698Sdim return(FORMAT_UNDEF); 164259698Sdim } 165259698Sdim 166259698Sdim#if defined(MSDOS) || defined(WIN32) || defined(WIN16) 167259698Sdimvoid program_name(char *in, char *out, int size) 168259698Sdim { 169259698Sdim int i,n; 170259698Sdim char *p=NULL; 171259698Sdim 172259698Sdim n=strlen(in); 173259698Sdim /* find the last '/', '\' or ':' */ 174259698Sdim for (i=n-1; i>0; i--) 175259698Sdim { 176259698Sdim if ((in[i] == '/') || (in[i] == '\\') || (in[i] == ':')) 177259698Sdim { 178259698Sdim p= &(in[i+1]); 179259698Sdim break; 180259698Sdim } 181259698Sdim } 182259698Sdim if (p == NULL) 183259698Sdim p=in; 184259698Sdim n=strlen(p); 185259698Sdim /* strip off trailing .exe if present. */ 186259698Sdim if ((n > 4) && (p[n-4] == '.') && 187259698Sdim ((p[n-3] == 'e') || (p[n-3] == 'E')) && 188259698Sdim ((p[n-2] == 'x') || (p[n-2] == 'X')) && 189259698Sdim ((p[n-1] == 'e') || (p[n-1] == 'E'))) 190259698Sdim n-=4; 191259698Sdim if (n > size-1) 192259698Sdim n=size-1; 193259698Sdim 194259698Sdim for (i=0; i<n; i++) 195259698Sdim { 196259698Sdim if ((p[i] >= 'A') && (p[i] <= 'Z')) 197259698Sdim out[i]=p[i]-'A'+'a'; 198259698Sdim else 199259698Sdim out[i]=p[i]; 200259698Sdim } 201259698Sdim out[n]='\0'; 202259698Sdim } 203259698Sdim#else 204259698Sdim#ifdef VMS 205259698Sdimvoid program_name(char *in, char *out, int size) 206259698Sdim { 207259698Sdim char *p=in, *q; 208259698Sdim char *chars=":]>"; 209259698Sdim 210259698Sdim while(*chars != '\0') 211259698Sdim { 212259698Sdim q=strrchr(p,*chars); 213259698Sdim if (q > p) 214259698Sdim p = q + 1; 215259698Sdim chars++; 216259698Sdim } 217259698Sdim 218259698Sdim q=strrchr(p,'.'); 219259698Sdim if (q == NULL) 220259698Sdim q = in+size; 221259698Sdim strncpy(out,p,q-p); 222259698Sdim out[q-p]='\0'; 223259698Sdim } 224259698Sdim#else 225259698Sdimvoid program_name(char *in, char *out, int size) 226259698Sdim { 227259698Sdim char *p; 228259698Sdim 229259698Sdim p=strrchr(in,'/'); 230259698Sdim if (p != NULL) 231259698Sdim p++; 232259698Sdim else 233259698Sdim p=in; 234259698Sdim strncpy(out,p,size-1); 235259698Sdim out[size-1]='\0'; 236259698Sdim } 237259698Sdim#endif 238259698Sdim#endif 239259698Sdim 240259698Sdim#ifdef WIN32 241259698Sdimint WIN32_rename(char *from, char *to) 242259698Sdim { 243259698Sdim#ifdef WINNT 244259698Sdim int ret; 245259698Sdim/* Note: MoveFileEx() doesn't work under Win95, Win98 */ 246259698Sdim 247259698Sdim ret=MoveFileEx(from,to,MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED); 248259698Sdim return(ret?0:-1); 249259698Sdim#else 250259698Sdim unlink(to); 251259698Sdim return MoveFile(from, to); 252259698Sdim#endif 253259698Sdim } 254259698Sdim#endif 255259698Sdim 256259698Sdimint chopup_args(ARGS *arg, char *buf, int *argc, char **argv[]) 257259698Sdim { 258259698Sdim int num,len,i; 259259698Sdim char *p; 260259698Sdim 261259698Sdim *argc=0; 262259698Sdim *argv=NULL; 263259698Sdim 264259698Sdim len=strlen(buf); 265259698Sdim i=0; 266259698Sdim if (arg->count == 0) 267259698Sdim { 268259698Sdim arg->count=20; 269259698Sdim arg->data=(char **)Malloc(sizeof(char *)*arg->count); 270259698Sdim } 271259698Sdim for (i=0; i<arg->count; i++) 272259698Sdim arg->data[i]=NULL; 273259698Sdim 274259698Sdim num=0; 275259698Sdim p=buf; 276259698Sdim for (;;) 277259698Sdim { 278259698Sdim /* first scan over white space */ 279259698Sdim if (!*p) break; 280259698Sdim while (*p && ((*p == ' ') || (*p == '\t') || (*p == '\n'))) 281259698Sdim p++; 282259698Sdim if (!*p) break; 283259698Sdim 284259698Sdim /* The start of something good :-) */ 285259698Sdim if (num >= arg->count) 286259698Sdim { 287259698Sdim arg->count+=20; 288259698Sdim arg->data=(char **)Realloc(arg->data, 289259698Sdim sizeof(char *)*arg->count); 290259698Sdim if (argc == 0) return(0); 291259698Sdim } 292259698Sdim arg->data[num++]=p; 293259698Sdim 294 /* now look for the end of this */ 295 if ((*p == '\'') || (*p == '\"')) /* scan for closing quote */ 296 { 297 i= *(p++); 298 arg->data[num-1]++; /* jump over quote */ 299 while (*p && (*p != i)) 300 p++; 301 *p='\0'; 302 } 303 else 304 { 305 while (*p && ((*p != ' ') && 306 (*p != '\t') && (*p != '\n'))) 307 p++; 308 309 if (*p == '\0') 310 p--; 311 else 312 *p='\0'; 313 } 314 p++; 315 } 316 *argc=num; 317 *argv=arg->data; 318 return(1); 319 } 320 321#ifndef APP_INIT 322int app_init(long mesgwin) 323 { 324 return(1); 325 } 326#endif 327 328 329int dump_cert_text (BIO *out, X509 *x) 330{ 331 char buf[256]; 332 X509_NAME_oneline(X509_get_subject_name(x),buf,256); 333 BIO_puts(out,"subject="); 334 BIO_puts(out,buf); 335 336 X509_NAME_oneline(X509_get_issuer_name(x),buf,256); 337 BIO_puts(out,"\nissuer= "); 338 BIO_puts(out,buf); 339 BIO_puts(out,"\n"); 340 return 0; 341} 342 343static char *app_get_pass(BIO *err, char *arg, int keepbio); 344 345int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2) 346{ 347 int same; 348 if(!arg2 || !arg1 || strcmp(arg1, arg2)) same = 0; 349 else same = 1; 350 if(arg1) { 351 *pass1 = app_get_pass(err, arg1, same); 352 if(!*pass1) return 0; 353 } else if(pass1) *pass1 = NULL; 354 if(arg2) { 355 *pass2 = app_get_pass(err, arg2, same ? 2 : 0); 356 if(!*pass2) return 0; 357 } else if(pass2) *pass2 = NULL; 358 return 1; 359} 360 361static char *app_get_pass(BIO *err, char *arg, int keepbio) 362{ 363 char *tmp, tpass[APP_PASS_LEN]; 364 static BIO *pwdbio = NULL; 365 int i; 366 if(!strncmp(arg, "pass:", 5)) return BUF_strdup(arg + 5); 367 if(!strncmp(arg, "env:", 4)) { 368 tmp = getenv(arg + 4); 369 if(!tmp) { 370 BIO_printf(err, "Can't read environment variable %s\n", arg + 4); 371 return NULL; 372 } 373 return BUF_strdup(tmp); 374 } 375 if(!keepbio || !pwdbio) { 376 if(!strncmp(arg, "file:", 5)) { 377 pwdbio = BIO_new_file(arg + 5, "r"); 378 if(!pwdbio) { 379 BIO_printf(err, "Can't open file %s\n", arg + 5); 380 return NULL; 381 } 382 } else if(!strncmp(arg, "fd:", 3)) { 383 BIO *btmp; 384 i = atoi(arg + 3); 385 if(i >= 0) pwdbio = BIO_new_fd(i, BIO_NOCLOSE); 386 if((i < 0) || !pwdbio) { 387 BIO_printf(err, "Can't access file descriptor %s\n", arg + 3); 388 return NULL; 389 } 390 /* Can't do BIO_gets on an fd BIO so add a buffering BIO */ 391 btmp = BIO_new(BIO_f_buffer()); 392 pwdbio = BIO_push(btmp, pwdbio); 393 } else if(!strcmp(arg, "stdin")) { 394 pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE); 395 if(!pwdbio) { 396 BIO_printf(err, "Can't open BIO for stdin\n"); 397 return NULL; 398 } 399 } else { 400 BIO_printf(err, "Invalid password argument \"%s\"\n", arg); 401 return NULL; 402 } 403 } 404 i = BIO_gets(pwdbio, tpass, APP_PASS_LEN); 405 if(keepbio != 1) { 406 BIO_free_all(pwdbio); 407 pwdbio = NULL; 408 } 409 if(i <= 0) { 410 BIO_printf(err, "Error reading password from BIO\n"); 411 return NULL; 412 } 413 tmp = strchr(tpass, '\n'); 414 if(tmp) *tmp = 0; 415 return BUF_strdup(tpass); 416} 417