read_pwd.c revision 68651
1/* crypto/des/read_pwd.c */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved.
4 *
5 * This package is an SSL implementation written
6 * by Eric Young (eay@cryptsoft.com).
7 * The implementation was written so as to conform with Netscapes SSL.
8 *
9 * This library is free for commercial and non-commercial use as long as
10 * the following conditions are aheared to.  The following conditions
11 * apply to all code found in this distribution, be it the RC4, RSA,
12 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13 * included with this distribution is covered by the same copyright terms
14 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15 *
16 * Copyright remains Eric Young's, and as such any Copyright notices in
17 * the code are not to be removed.
18 * If this package is used in a product, Eric Young should be given attribution
19 * as the author of the parts of the library used.
20 * This can be in the form of a textual message at program startup or
21 * in documentation (online or textual) provided with the package.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the copyright
27 *    notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 *    notice, this list of conditions and the following disclaimer in the
30 *    documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 *    must display the following acknowledgement:
33 *    "This product includes cryptographic software written by
34 *     Eric Young (eay@cryptsoft.com)"
35 *    The word 'cryptographic' can be left out if the rouines from the library
36 *    being used are not cryptographic related :-).
37 * 4. If you include any Windows specific code (or a derivative thereof) from
38 *    the apps directory (application code) you must include an acknowledgement:
39 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * The licence and distribution terms for any publically available version or
54 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.]
57 */
58
59#if !defined(MSDOS) && !defined(VMS) && !defined(WIN32)
60#include <openssl/opensslconf.h>
61#ifdef OPENSSL_UNISTD
62# include OPENSSL_UNISTD
63#else
64# include <unistd.h>
65#endif
66/* If unistd.h defines _POSIX_VERSION, we conclude that we
67 * are on a POSIX system and have sigaction and termios. */
68#if defined(_POSIX_VERSION)
69
70# define SIGACTION
71# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
72# define TERMIOS
73# endif
74
75#endif
76#endif
77
78/* #define SIGACTION */ /* Define this if you have sigaction() */
79
80#ifdef WIN16TTY
81#undef WIN16
82#undef _WINDOWS
83#include <graph.h>
84#endif
85
86/* 06-Apr-92 Luke Brennan    Support for VMS */
87#include "des_locl.h"
88#include "cryptlib.h"
89#include <signal.h>
90#include <stdio.h>
91#include <string.h>
92#include <setjmp.h>
93#include <errno.h>
94
95#ifdef VMS			/* prototypes for sys$whatever */
96#include <starlet.h>
97#ifdef __DECC
98#pragma message disable DOLLARID
99#endif
100#endif
101
102#ifdef WIN_CONSOLE_BUG
103#include <windows.h>
104#include <wincon.h>
105#endif
106
107
108/* There are 5 types of terminal interface supported,
109 * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
110 */
111
112#if defined(__sgi) && !defined(TERMIOS)
113#define TERMIOS
114#undef  TERMIO
115#undef  SGTTY
116#endif
117
118#if defined(linux) && !defined(TERMIO)
119#undef  TERMIOS
120#define TERMIO
121#undef  SGTTY
122#endif
123
124#ifdef _LIBC
125#undef  TERMIOS
126#define TERMIO
127#undef  SGTTY
128#endif
129
130#if !defined(TERMIO) && !defined(TERMIOS) && !defined(VMS) && !defined(MSDOS) && !defined(MAC_OS_pre_X) && !defined(MAC_OS_GUSI_SOURCE)
131#undef  TERMIOS
132#undef  TERMIO
133#define SGTTY
134#endif
135
136#ifdef TERMIOS
137#include <termios.h>
138#define TTY_STRUCT		struct termios
139#define TTY_FLAGS		c_lflag
140#define	TTY_get(tty,data)	tcgetattr(tty,data)
141#define TTY_set(tty,data)	tcsetattr(tty,TCSANOW,data)
142#endif
143
144#ifdef TERMIO
145#include <termio.h>
146#define TTY_STRUCT		struct termio
147#define TTY_FLAGS		c_lflag
148#define TTY_get(tty,data)	ioctl(tty,TCGETA,data)
149#define TTY_set(tty,data)	ioctl(tty,TCSETA,data)
150#endif
151
152#ifdef SGTTY
153#include <sgtty.h>
154#define TTY_STRUCT		struct sgttyb
155#define TTY_FLAGS		sg_flags
156#define TTY_get(tty,data)	ioctl(tty,TIOCGETP,data)
157#define TTY_set(tty,data)	ioctl(tty,TIOCSETP,data)
158#endif
159
160#if !defined(_LIBC) && !defined(MSDOS) && !defined(VMS) && !defined(MAC_OS_pre_X)
161#include <sys/ioctl.h>
162#endif
163
164#if defined(MSDOS) && !defined(__CYGWIN32__)
165#include <conio.h>
166#define fgets(a,b,c) noecho_fgets(a,b,c)
167#endif
168
169#ifdef VMS
170#include <ssdef.h>
171#include <iodef.h>
172#include <ttdef.h>
173#include <descrip.h>
174struct IOSB {
175	short iosb$w_value;
176	short iosb$w_count;
177	long  iosb$l_info;
178	};
179#endif
180
181#if defined(MAC_OS_pre_X) || defined(MAC_OS_GUSI_SOURCE)
182/*
183 * This one needs work. As a matter of fact the code is unoperational
184 * and this is only a trick to get it compiled.
185 *					<appro@fy.chalmers.se>
186 */
187#define TTY_STRUCT int
188#endif
189
190#ifndef NX509_SIG
191#define NX509_SIG 32
192#endif
193
194static void read_till_nl(FILE *);
195static void recsig(int);
196static void pushsig(void);
197static void popsig(void);
198#if defined(MSDOS) && !defined(WIN16)
199static int noecho_fgets(char *buf, int size, FILE *tty);
200#endif
201#ifdef SIGACTION
202 static struct sigaction savsig[NX509_SIG];
203#else
204  static void (*savsig[NX509_SIG])(int );
205#endif
206static jmp_buf save;
207
208int des_read_pw_string(char *buf, int length, const char *prompt,
209	     int verify)
210	{
211	char buff[BUFSIZ];
212	int ret;
213
214	ret=des_read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify);
215	memset(buff,0,BUFSIZ);
216	return(ret);
217	}
218
219#ifndef WIN16
220
221static void read_till_nl(FILE *in)
222	{
223#define SIZE 4
224	char buf[SIZE+1];
225
226	do	{
227		fgets(buf,SIZE,in);
228		} while (strchr(buf,'\n') == NULL);
229	}
230
231
232/* return 0 if ok, 1 (or -1) otherwise */
233int des_read_pw(char *buf, char *buff, int size, const char *prompt,
234	     int verify)
235	{
236#ifdef VMS
237	struct IOSB iosb;
238	$DESCRIPTOR(terminal,"TT");
239	long tty_orig[3], tty_new[3];
240	long status;
241	unsigned short channel = 0;
242#else
243#ifndef MSDOS
244	TTY_STRUCT tty_orig,tty_new;
245#endif
246#endif
247	int number;
248	int ok;
249	/* statics are simply to avoid warnings about longjmp clobbering
250	   things */
251	static int ps;
252	int is_a_tty;
253	static FILE *tty;
254	char *p;
255
256	if (setjmp(save))
257		{
258		ok=0;
259		goto error;
260		}
261
262	number=5;
263	ok=0;
264	ps=0;
265	is_a_tty=1;
266	tty=NULL;
267
268#ifdef MSDOS
269	if ((tty=fopen("con","r")) == NULL)
270		tty=stdin;
271#elif defined(MAC_OS_pre_X)
272	tty=stdin;
273#else
274#ifndef MPE
275	if ((tty=fopen("/dev/tty","r")) == NULL)
276#endif
277		tty=stdin;
278#endif
279
280#if defined(TTY_get) && !defined(VMS)
281	if (TTY_get(fileno(tty),&tty_orig) == -1)
282		{
283#ifdef ENOTTY
284		if (errno == ENOTTY)
285			is_a_tty=0;
286		else
287#endif
288#ifdef EINVAL
289		/* Ariel Glenn ariel@columbia.edu reports that solaris
290		 * can return EINVAL instead.  This should be ok */
291		if (errno == EINVAL)
292			is_a_tty=0;
293		else
294#endif
295			return(-1);
296		}
297	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
298#endif
299#ifdef VMS
300	status = sys$assign(&terminal,&channel,0,0);
301	if (status != SS$_NORMAL)
302		return(-1);
303	status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
304	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
305		return(-1);
306#endif
307
308	pushsig();
309	ps=1;
310
311#ifdef TTY_FLAGS
312	tty_new.TTY_FLAGS &= ~ECHO;
313#endif
314
315#if defined(TTY_set) && !defined(VMS)
316	if (is_a_tty && (TTY_set(fileno(tty),&tty_new) == -1))
317#ifdef MPE
318		; /* MPE lies -- echo really has been disabled */
319#else
320		return(-1);
321#endif
322#endif
323#ifdef VMS
324	tty_new[0] = tty_orig[0];
325	tty_new[1] = tty_orig[1] | TT$M_NOECHO;
326	tty_new[2] = tty_orig[2];
327	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
328	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
329		return(-1);
330#endif
331	ps=2;
332
333	while ((!ok) && (number--))
334		{
335		fputs(prompt,stderr);
336		fflush(stderr);
337
338		buf[0]='\0';
339		fgets(buf,size,tty);
340		if (feof(tty)) goto error;
341		if (ferror(tty)) goto error;
342		if ((p=(char *)strchr(buf,'\n')) != NULL)
343			*p='\0';
344		else	read_till_nl(tty);
345		if (verify)
346			{
347			fprintf(stderr,"\nVerifying password - %s",prompt);
348			fflush(stderr);
349			buff[0]='\0';
350			fgets(buff,size,tty);
351			if (feof(tty)) goto error;
352			if ((p=(char *)strchr(buff,'\n')) != NULL)
353				*p='\0';
354			else	read_till_nl(tty);
355
356			if (strcmp(buf,buff) != 0)
357				{
358				fprintf(stderr,"\nVerify failure");
359				fflush(stderr);
360				break;
361				/* continue; */
362				}
363			}
364		ok=1;
365		}
366
367error:
368	fprintf(stderr,"\n");
369#ifdef DEBUG
370	perror("fgets(tty)");
371#endif
372	/* What can we do if there is an error? */
373#if defined(TTY_set) && !defined(VMS)
374	if (ps >= 2) TTY_set(fileno(tty),&tty_orig);
375#endif
376#ifdef VMS
377	if (ps >= 2)
378		status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0
379			,tty_orig,12,0,0,0,0);
380#endif
381
382	if (ps >= 1) popsig();
383	if (stdin != tty) fclose(tty);
384#ifdef VMS
385	status = sys$dassgn(channel);
386#endif
387	return(!ok);
388	}
389
390#else /* WIN16 */
391
392int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
393	{
394	memset(buf,0,size);
395	memset(buff,0,size);
396	return(0);
397	}
398
399#endif
400
401static void pushsig(void)
402	{
403	int i;
404#ifdef SIGACTION
405	struct sigaction sa;
406
407	memset(&sa,0,sizeof sa);
408	sa.sa_handler=recsig;
409#endif
410
411	for (i=1; i<NX509_SIG; i++)
412		{
413#ifdef SIGUSR1
414		if (i == SIGUSR1)
415			continue;
416#endif
417#ifdef SIGUSR2
418		if (i == SIGUSR2)
419			continue;
420#endif
421#ifdef SIGACTION
422		sigaction(i,&sa,&savsig[i]);
423#else
424		savsig[i]=signal(i,recsig);
425#endif
426		}
427
428#ifdef SIGWINCH
429	signal(SIGWINCH,SIG_DFL);
430#endif
431	}
432
433static void popsig(void)
434	{
435	int i;
436
437	for (i=1; i<NX509_SIG; i++)
438		{
439#ifdef SIGUSR1
440		if (i == SIGUSR1)
441			continue;
442#endif
443#ifdef SIGUSR2
444		if (i == SIGUSR2)
445			continue;
446#endif
447#ifdef SIGACTION
448		sigaction(i,&savsig[i],NULL);
449#else
450		signal(i,savsig[i]);
451#endif
452		}
453	}
454
455static void recsig(int i)
456	{
457	longjmp(save,1);
458#ifdef LINT
459	i=i;
460#endif
461	}
462
463#if defined(MSDOS) && !defined(WIN16)
464static int noecho_fgets(char *buf, int size, FILE *tty)
465	{
466	int i;
467	char *p;
468
469	p=buf;
470	for (;;)
471		{
472		if (size == 0)
473			{
474			*p='\0';
475			break;
476			}
477		size--;
478#ifdef WIN16TTY
479		i=_inchar();
480#else
481		i=getch();
482#endif
483		if (i == '\r') i='\n';
484		*(p++)=i;
485		if (i == '\n')
486			{
487			*p='\0';
488			break;
489			}
490		}
491#ifdef WIN_CONSOLE_BUG
492/* Win95 has several evil console bugs: one of these is that the
493 * last character read using getch() is passed to the next read: this is
494 * usually a CR so this can be trouble. No STDIO fix seems to work but
495 * flushing the console appears to do the trick.
496 */
497		{
498			HANDLE inh;
499			inh = GetStdHandle(STD_INPUT_HANDLE);
500			FlushConsoleInputBuffer(inh);
501		}
502#endif
503	return(strlen(buf));
504	}
505#endif
506