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