read_pwd.c revision 100928
1185029Spjd/* crypto/des/read_pwd.c */
2185029Spjd/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3185029Spjd * All rights reserved.
4185029Spjd *
5185029Spjd * This package is an SSL implementation written
6185029Spjd * by Eric Young (eay@cryptsoft.com).
7185029Spjd * The implementation was written so as to conform with Netscapes SSL.
8185029Spjd *
9185029Spjd * This library is free for commercial and non-commercial use as long as
10185029Spjd * the following conditions are aheared to.  The following conditions
11185029Spjd * apply to all code found in this distribution, be it the RC4, RSA,
12185029Spjd * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13185029Spjd * included with this distribution is covered by the same copyright terms
14185029Spjd * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15185029Spjd *
16185029Spjd * Copyright remains Eric Young's, and as such any Copyright notices in
17185029Spjd * the code are not to be removed.
18185029Spjd * If this package is used in a product, Eric Young should be given attribution
19185029Spjd * as the author of the parts of the library used.
20185029Spjd * This can be in the form of a textual message at program startup or
21185029Spjd * in documentation (online or textual) provided with the package.
22219089Spjd *
23248369Smm * Redistribution and use in source and binary forms, with or without
24185029Spjd * modification, are permitted provided that the following conditions
25185029Spjd * are met:
26185029Spjd * 1. Redistributions of source code must retain the copyright
27185029Spjd *    notice, this list of conditions and the following disclaimer.
28185029Spjd * 2. Redistributions in binary form must reproduce the above copyright
29185029Spjd *    notice, this list of conditions and the following disclaimer in the
30185029Spjd *    documentation and/or other materials provided with the distribution.
31185029Spjd * 3. All advertising materials mentioning features or use of this software
32185029Spjd *    must display the following acknowledgement:
33185029Spjd *    "This product includes cryptographic software written by
34185029Spjd *     Eric Young (eay@cryptsoft.com)"
35185029Spjd *    The word 'cryptographic' can be left out if the rouines from the library
36185029Spjd *    being used are not cryptographic related :-).
37185029Spjd * 4. If you include any Windows specific code (or a derivative thereof) from
38185029Spjd *    the apps directory (application code) you must include an acknowledgement:
39185029Spjd *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40185029Spjd *
41185029Spjd * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42185029Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43185029Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44185029Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45219089Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46219089Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47185029Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48185029Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49185029Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50219089Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51185029Spjd * SUCH DAMAGE.
52185029Spjd *
53185029Spjd * The licence and distribution terms for any publically available version or
54185029Spjd * derivative of this code cannot be changed.  i.e. this code cannot simply be
55185029Spjd * copied and put under another distribution licence
56185029Spjd * [including the GNU Public Licence.]
57185029Spjd */
58185029Spjd
59185029Spjd#if !defined(MSDOS) && !defined(VMS) && !defined(WIN32) && !defined(VXWORKS)
60185029Spjd#include <openssl/opensslconf.h>
61185029Spjd#ifdef OPENSSL_UNISTD
62185029Spjd# include OPENSSL_UNISTD
63185029Spjd#else
64185029Spjd# include <unistd.h>
65185029Spjd#endif
66185029Spjd/* If unistd.h defines _POSIX_VERSION, we conclude that we
67185029Spjd * are on a POSIX system and have sigaction and termios. */
68185029Spjd#if defined(_POSIX_VERSION)
69185029Spjd
70185029Spjd# define SIGACTION
71185029Spjd# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
72185029Spjd# define TERMIOS
73219089Spjd# endif
74185029Spjd
75185029Spjd#endif
76185029Spjd#endif
77185029Spjd
78185029Spjd/* #define SIGACTION */ /* Define this if you have sigaction() */
79185029Spjd
80185029Spjd#ifdef WIN16TTY
81185029Spjd#undef WIN16
82185029Spjd#undef _WINDOWS
83185029Spjd#include <graph.h>
84185029Spjd#endif
85185029Spjd
86185029Spjd/* 06-Apr-92 Luke Brennan    Support for VMS */
87185029Spjd#include "des_locl.h"
88185029Spjd#include "cryptlib.h"
89185029Spjd#include <signal.h>
90185029Spjd#include <stdio.h>
91185029Spjd#include <string.h>
92185029Spjd#include <setjmp.h>
93185029Spjd#include <errno.h>
94185029Spjd
95185029Spjd#ifdef VMS			/* prototypes for sys$whatever */
96185029Spjd#include <starlet.h>
97185029Spjd#ifdef __DECC
98185029Spjd#pragma message disable DOLLARID
99185029Spjd#endif
100185029Spjd#endif
101185029Spjd
102185029Spjd#ifdef WIN_CONSOLE_BUG
103185029Spjd#include <windows.h>
104185029Spjd#include <wincon.h>
105185029Spjd#endif
106185029Spjd
107185029Spjd
108185029Spjd/* There are 5 types of terminal interface supported,
109185029Spjd * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
110185029Spjd */
111185029Spjd
112185029Spjd#if defined(__sgi) && !defined(TERMIOS)
113185029Spjd#define TERMIOS
114185029Spjd#undef  TERMIO
115185029Spjd#undef  SGTTY
116185029Spjd#endif
117185029Spjd
118185029Spjd#if defined(linux) && !defined(TERMIO)
119185029Spjd#undef  TERMIOS
120185029Spjd#define TERMIO
121185029Spjd#undef  SGTTY
122185029Spjd#endif
123185029Spjd
124185029Spjd#ifdef _LIBC
125185029Spjd#undef  TERMIOS
126185029Spjd#define TERMIO
127185029Spjd#undef  SGTTY
128185029Spjd#endif
129185029Spjd
130185029Spjd#if !defined(TERMIO) && !defined(TERMIOS) && !defined(VMS) && !defined(MSDOS) && !defined(MAC_OS_pre_X) && !defined(MAC_OS_GUSI_SOURCE)
131185029Spjd#undef  TERMIOS
132185029Spjd#undef  TERMIO
133185029Spjd#define SGTTY
134185029Spjd#endif
135185029Spjd
136185029Spjd#if defined(VXWORKS)
137185029Spjd#undef TERMIOS
138185029Spjd#undef TERMIO
139185029Spjd#undef SGTTY
140185029Spjd#endif
141185029Spjd
142185029Spjd#ifdef TERMIOS
143185029Spjd#include <termios.h>
144185029Spjd#define TTY_STRUCT		struct termios
145185029Spjd#define TTY_FLAGS		c_lflag
146185029Spjd#define	TTY_get(tty,data)	tcgetattr(tty,data)
147186568Srwatson#define TTY_set(tty,data)	tcsetattr(tty,TCSANOW,data)
148185029Spjd#endif
149185029Spjd
150185029Spjd#ifdef TERMIO
151262102Savg#include <termio.h>
152185029Spjd#define TTY_STRUCT		struct termio
153185029Spjd#define TTY_FLAGS		c_lflag
154185029Spjd#define TTY_get(tty,data)	ioctl(tty,TCGETA,data)
155185029Spjd#define TTY_set(tty,data)	ioctl(tty,TCSETA,data)
156185029Spjd#endif
157185029Spjd
158185029Spjd#ifdef SGTTY
159185029Spjd#include <sgtty.h>
160185029Spjd#define TTY_STRUCT		struct sgttyb
161185029Spjd#define TTY_FLAGS		sg_flags
162185029Spjd#define TTY_get(tty,data)	ioctl(tty,TIOCGETP,data)
163185029Spjd#define TTY_set(tty,data)	ioctl(tty,TIOCSETP,data)
164185029Spjd#endif
165185029Spjd
166185029Spjd#if !defined(_LIBC) && !defined(MSDOS) && !defined(VMS) && !defined(MAC_OS_pre_X)
167185029Spjd#include <sys/ioctl.h>
168185029Spjd#endif
169185029Spjd
170185029Spjd#if defined(MSDOS) && !defined(__CYGWIN32__)
171219089Spjd#include <conio.h>
172185029Spjd#define fgets(a,b,c) noecho_fgets(a,b,c)
173185029Spjd#endif
174185029Spjd
175219089Spjd#ifdef VMS
176219089Spjd#include <ssdef.h>
177219089Spjd#include <iodef.h>
178185029Spjd#include <ttdef.h>
179185029Spjd#include <descrip.h>
180185029Spjdstruct IOSB {
181185029Spjd	short iosb$w_value;
182185029Spjd	short iosb$w_count;
183185029Spjd	long  iosb$l_info;
184185029Spjd	};
185185029Spjd#endif
186185029Spjd
187185029Spjd#if defined(MAC_OS_pre_X) || defined(MAC_OS_GUSI_SOURCE)
188185029Spjd/*
189185029Spjd * This one needs work. As a matter of fact the code is unoperational
190185029Spjd * and this is only a trick to get it compiled.
191185029Spjd *					<appro@fy.chalmers.se>
192185029Spjd */
193185029Spjd#define TTY_STRUCT int
194185029Spjd#endif
195185029Spjd
196185029Spjd#ifndef NX509_SIG
197185029Spjd#define NX509_SIG 32
198185029Spjd#endif
199185029Spjd
200185029Spjdstatic void read_till_nl(FILE *);
201219089Spjdstatic void recsig(int);
202219089Spjdstatic void pushsig(void);
203185029Spjdstatic void popsig(void);
204185029Spjd#if defined(MSDOS) && !defined(WIN16)
205185029Spjdstatic int noecho_fgets(char *buf, int size, FILE *tty);
206185029Spjd#endif
207185029Spjd#ifdef SIGACTION
208185029Spjd static struct sigaction savsig[NX509_SIG];
209185029Spjd#else
210185029Spjd  static void (*savsig[NX509_SIG])(int );
211185029Spjd#endif
212185029Spjdstatic jmp_buf save;
213185029Spjd
214185029Spjdint des_read_pw_string(char *buf, int length, const char *prompt,
215185029Spjd	     int verify)
216185029Spjd	{
217185029Spjd	char buff[BUFSIZ];
218185029Spjd	int ret;
219185029Spjd
220185029Spjd	ret=des_read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify);
221185029Spjd	memset(buff,0,BUFSIZ);
222185029Spjd	return(ret);
223185029Spjd	}
224185029Spjd
225185029Spjd#ifndef WIN16
226185029Spjd
227185029Spjdstatic void read_till_nl(FILE *in)
228185029Spjd	{
229185029Spjd#define SIZE 4
230185029Spjd	char buf[SIZE+1];
231219089Spjd
232219089Spjd	do	{
233219089Spjd		fgets(buf,SIZE,in);
234219089Spjd		} while (strchr(buf,'\n') == NULL);
235219089Spjd	}
236219089Spjd
237219089Spjd
238185029Spjd/* return 0 if ok, 1 (or -1) otherwise */
239219089Spjdint des_read_pw(char *buf, char *buff, int size, const char *prompt,
240219089Spjd	     int verify)
241219089Spjd	{
242185029Spjd#ifdef VMS
243219089Spjd	struct IOSB iosb;
244219089Spjd	$DESCRIPTOR(terminal,"TT");
245219089Spjd	long tty_orig[3], tty_new[3];
246219089Spjd	long status;
247219089Spjd	unsigned short channel = 0;
248219089Spjd#else
249219089Spjd#if !defined(MSDOS) && !defined(VXWORKS)
250219089Spjd	TTY_STRUCT tty_orig,tty_new;
251219089Spjd#endif
252219089Spjd#endif
253185029Spjd	int number;
254185029Spjd	int ok;
255185029Spjd	/* statics are simply to avoid warnings about longjmp clobbering
256185029Spjd	   things */
257185029Spjd	static int ps;
258185029Spjd	int is_a_tty;
259185029Spjd	static FILE *tty;
260185029Spjd	char *p;
261185029Spjd
262185029Spjd	if (setjmp(save))
263185029Spjd		{
264185029Spjd		ok=0;
265185029Spjd		goto error;
266185029Spjd		}
267185029Spjd
268185029Spjd	number=5;
269185029Spjd	ok=0;
270185029Spjd	ps=0;
271185029Spjd	is_a_tty=1;
272185029Spjd	tty=NULL;
273185029Spjd
274185029Spjd#ifdef MSDOS
275185029Spjd	if ((tty=fopen("con","r")) == NULL)
276185029Spjd		tty=stdin;
277185029Spjd#elif defined(MAC_OS_pre_X) || defined(VXWORKS)
278185029Spjd	tty=stdin;
279185029Spjd#else
280185029Spjd#ifndef MPE
281185029Spjd	if ((tty=fopen("/dev/tty","r")) == NULL)
282185029Spjd#endif
283185029Spjd		tty=stdin;
284185029Spjd#endif
285185029Spjd
286185029Spjd#if defined(TTY_get) && !defined(VMS)
287185029Spjd	if (TTY_get(fileno(tty),&tty_orig) == -1)
288185029Spjd		{
289185029Spjd#ifdef ENOTTY
290185029Spjd		if (errno == ENOTTY)
291185029Spjd			is_a_tty=0;
292185029Spjd		else
293219089Spjd#endif
294185029Spjd#ifdef EINVAL
295185029Spjd		/* Ariel Glenn ariel@columbia.edu reports that solaris
296185029Spjd		 * can return EINVAL instead.  This should be ok */
297185029Spjd		if (errno == EINVAL)
298185029Spjd			is_a_tty=0;
299185029Spjd		else
300185029Spjd#endif
301185029Spjd			return(-1);
302243674Smm		}
303185029Spjd	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
304185029Spjd#endif
305185029Spjd#ifdef VMS
306185029Spjd	status = sys$assign(&terminal,&channel,0,0);
307185029Spjd	if (status != SS$_NORMAL)
308185029Spjd		return(-1);
309185029Spjd	status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
310219089Spjd	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
311219089Spjd		return(-1);
312219089Spjd#endif
313219089Spjd
314219089Spjd	pushsig();
315219089Spjd	ps=1;
316185029Spjd
317185029Spjd#ifdef TTY_FLAGS
318185029Spjd	tty_new.TTY_FLAGS &= ~ECHO;
319185029Spjd#endif
320185029Spjd
321185029Spjd#if defined(TTY_set) && !defined(VMS)
322185029Spjd	if (is_a_tty && (TTY_set(fileno(tty),&tty_new) == -1))
323185029Spjd#ifdef MPE
324185029Spjd		; /* MPE lies -- echo really has been disabled */
325219089Spjd#else
326185029Spjd		return(-1);
327185029Spjd#endif
328185029Spjd#endif
329185029Spjd#ifdef VMS
330185029Spjd	tty_new[0] = tty_orig[0];
331185029Spjd	tty_new[1] = tty_orig[1] | TT$M_NOECHO;
332185029Spjd	tty_new[2] = tty_orig[2];
333185029Spjd	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
334185029Spjd	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
335185029Spjd		return(-1);
336185029Spjd#endif
337185029Spjd	ps=2;
338185029Spjd
339185029Spjd	while ((!ok) && (number--))
340185029Spjd		{
341185029Spjd		fputs(prompt,stderr);
342185029Spjd		fflush(stderr);
343185029Spjd
344185029Spjd		buf[0]='\0';
345185029Spjd		fgets(buf,size,tty);
346185029Spjd		if (feof(tty)) goto error;
347185029Spjd		if (ferror(tty)) goto error;
348185029Spjd		if ((p=(char *)strchr(buf,'\n')) != NULL)
349185029Spjd			*p='\0';
350185029Spjd		else	read_till_nl(tty);
351185029Spjd		if (verify)
352185029Spjd			{
353185029Spjd			fprintf(stderr,"\nVerifying password - %s",prompt);
354185029Spjd			fflush(stderr);
355185029Spjd			buff[0]='\0';
356185029Spjd			fgets(buff,size,tty);
357219089Spjd			if (feof(tty)) goto error;
358185029Spjd			if ((p=(char *)strchr(buff,'\n')) != NULL)
359185029Spjd				*p='\0';
360185029Spjd			else	read_till_nl(tty);
361185029Spjd
362185029Spjd			if (strcmp(buf,buff) != 0)
363185029Spjd				{
364185029Spjd				fprintf(stderr,"\nVerify failure");
365185029Spjd				fflush(stderr);
366185029Spjd				break;
367185029Spjd				/* continue; */
368185029Spjd				}
369185029Spjd			}
370185029Spjd		ok=1;
371185029Spjd		}
372185029Spjd
373219089Spjderror:
374219089Spjd	fprintf(stderr,"\n");
375219089Spjd#if 0
376219089Spjd	perror("fgets(tty)");
377219089Spjd#endif
378219089Spjd	/* What can we do if there is an error? */
379219089Spjd#if defined(TTY_set) && !defined(VMS)
380219089Spjd	if (ps >= 2) TTY_set(fileno(tty),&tty_orig);
381219089Spjd#endif
382219089Spjd#ifdef VMS
383219089Spjd	if (ps >= 2)
384219089Spjd		status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0
385219089Spjd			,tty_orig,12,0,0,0,0);
386219089Spjd#endif
387219089Spjd
388219089Spjd	if (ps >= 1) popsig();
389219089Spjd	if (stdin != tty) fclose(tty);
390219089Spjd#ifdef VMS
391219089Spjd	status = sys$dassgn(channel);
392219089Spjd#endif
393219089Spjd	return(!ok);
394185029Spjd	}
395185029Spjd
396185029Spjd#else /* WIN16 */
397185029Spjd
398185029Spjdint des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
399185029Spjd	{
400185029Spjd	memset(buf,0,size);
401219089Spjd	memset(buff,0,size);
402185029Spjd	return(0);
403185029Spjd	}
404219089Spjd
405219089Spjd#endif
406219089Spjd
407219089Spjdstatic void pushsig(void)
408219089Spjd	{
409219089Spjd	int i;
410185029Spjd#ifdef SIGACTION
411219089Spjd	struct sigaction sa;
412219089Spjd
413219089Spjd	memset(&sa,0,sizeof sa);
414219089Spjd	sa.sa_handler=recsig;
415219089Spjd#endif
416185029Spjd
417219089Spjd	for (i=1; i<NX509_SIG; i++)
418219089Spjd		{
419219089Spjd#ifdef SIGUSR1
420185029Spjd		if (i == SIGUSR1)
421185029Spjd			continue;
422185029Spjd#endif
423185029Spjd#ifdef SIGUSR2
424185029Spjd		if (i == SIGUSR2)
425185029Spjd			continue;
426185029Spjd#endif
427243674Smm#ifdef SIGACTION
428185029Spjd		sigaction(i,&sa,&savsig[i]);
429185029Spjd#else
430185029Spjd		savsig[i]=signal(i,recsig);
431185029Spjd#endif
432185029Spjd		}
433185029Spjd
434185029Spjd#ifdef SIGWINCH
435185029Spjd	signal(SIGWINCH,SIG_DFL);
436185029Spjd#endif
437185029Spjd	}
438185029Spjd
439185029Spjdstatic void popsig(void)
440185029Spjd	{
441185029Spjd	int i;
442185029Spjd
443185029Spjd	for (i=1; i<NX509_SIG; i++)
444185029Spjd		{
445185029Spjd#ifdef SIGUSR1
446185029Spjd		if (i == SIGUSR1)
447185029Spjd			continue;
448219089Spjd#endif
449219089Spjd#ifdef SIGUSR2
450185029Spjd		if (i == SIGUSR2)
451185029Spjd			continue;
452185029Spjd#endif
453185029Spjd#ifdef SIGACTION
454185029Spjd		sigaction(i,&savsig[i],NULL);
455185029Spjd#else
456185029Spjd		signal(i,savsig[i]);
457185029Spjd#endif
458185029Spjd		}
459185029Spjd	}
460243674Smm
461185029Spjdstatic void recsig(int i)
462185029Spjd	{
463185029Spjd	longjmp(save,1);
464185029Spjd#ifdef LINT
465185029Spjd	i=i;
466185029Spjd#endif
467185029Spjd	}
468185029Spjd
469185029Spjd#if defined(MSDOS) && !defined(WIN16)
470185029Spjdstatic int noecho_fgets(char *buf, int size, FILE *tty)
471185029Spjd	{
472185029Spjd	int i;
473185029Spjd	char *p;
474185029Spjd
475185029Spjd	p=buf;
476185029Spjd	for (;;)
477185029Spjd		{
478185029Spjd		if (size == 0)
479185029Spjd			{
480185029Spjd			*p='\0';
481185029Spjd			break;
482243674Smm			}
483185029Spjd		size--;
484185029Spjd#ifdef WIN16TTY
485185029Spjd		i=_inchar();
486185029Spjd#else
487185029Spjd		i=getch();
488185029Spjd#endif
489185029Spjd		if (i == '\r') i='\n';
490185029Spjd		*(p++)=i;
491185029Spjd		if (i == '\n')
492185029Spjd			{
493185029Spjd			*p='\0';
494185029Spjd			break;
495185029Spjd			}
496185029Spjd		}
497185029Spjd#ifdef WIN_CONSOLE_BUG
498185029Spjd/* Win95 has several evil console bugs: one of these is that the
499185029Spjd * last character read using getch() is passed to the next read: this is
500185029Spjd * usually a CR so this can be trouble. No STDIO fix seems to work but
501185029Spjd * flushing the console appears to do the trick.
502185029Spjd */
503185029Spjd		{
504185029Spjd			HANDLE inh;
505185029Spjd			inh = GetStdHandle(STD_INPUT_HANDLE);
506219089Spjd			FlushConsoleInputBuffer(inh);
507219089Spjd		}
508219089Spjd#endif
509219089Spjd	return(strlen(buf));
510219089Spjd	}
511219089Spjd#endif
512219089Spjd