155714Skris/* crypto/des/read_pwd.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
59109998Smarkm#include <openssl/e_os2.h>
60109998Smarkm#if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WIN32)
6159191Skris#ifdef OPENSSL_UNISTD
6259191Skris# include OPENSSL_UNISTD
6359191Skris#else
6459191Skris# include <unistd.h>
6559191Skris#endif
6655714Skris/* If unistd.h defines _POSIX_VERSION, we conclude that we
6755714Skris * are on a POSIX system and have sigaction and termios. */
6855714Skris#if defined(_POSIX_VERSION)
6955714Skris
7055714Skris# define SIGACTION
7155714Skris# if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
7255714Skris# define TERMIOS
7355714Skris# endif
7455714Skris
7555714Skris#endif
7655714Skris#endif
7755714Skris
7855714Skris/* #define SIGACTION */ /* Define this if you have sigaction() */
7955714Skris
8055714Skris#ifdef WIN16TTY
81109998Smarkm#undef OPENSSL_SYS_WIN16
8255714Skris#undef _WINDOWS
8355714Skris#include <graph.h>
8455714Skris#endif
8555714Skris
8655714Skris/* 06-Apr-92 Luke Brennan    Support for VMS */
8755714Skris#include "des_locl.h"
8855714Skris#include "cryptlib.h"
8955714Skris#include <signal.h>
9055714Skris#include <stdio.h>
9155714Skris#include <string.h>
9255714Skris#include <setjmp.h>
9355714Skris#include <errno.h>
9455714Skris
95109998Smarkm#ifdef OPENSSL_SYS_VMS			/* prototypes for sys$whatever */
9655714Skris#include <starlet.h>
9755714Skris#ifdef __DECC
9855714Skris#pragma message disable DOLLARID
9955714Skris#endif
10055714Skris#endif
10155714Skris
10255714Skris#ifdef WIN_CONSOLE_BUG
10355714Skris#include <windows.h>
104109998Smarkm#ifndef OPENSSL_SYS_WINCE
10555714Skris#include <wincon.h>
10655714Skris#endif
107109998Smarkm#endif
10855714Skris
10955714Skris
11055714Skris/* There are 5 types of terminal interface supported,
11155714Skris * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
11255714Skris */
11355714Skris
11455714Skris#if defined(__sgi) && !defined(TERMIOS)
11555714Skris#define TERMIOS
11655714Skris#undef  TERMIO
11755714Skris#undef  SGTTY
11855714Skris#endif
11955714Skris
12055714Skris#if defined(linux) && !defined(TERMIO)
12155714Skris#undef  TERMIOS
12255714Skris#define TERMIO
12355714Skris#undef  SGTTY
12455714Skris#endif
12555714Skris
12655714Skris#ifdef _LIBC
12755714Skris#undef  TERMIOS
12855714Skris#define TERMIO
12955714Skris#undef  SGTTY
13055714Skris#endif
13155714Skris
132109998Smarkm#if !defined(TERMIO) && !defined(TERMIOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(MAC_OS_pre_X) && !defined(MAC_OS_GUSI_SOURCE)
13355714Skris#undef  TERMIOS
13455714Skris#undef  TERMIO
13555714Skris#define SGTTY
13655714Skris#endif
13755714Skris
138109998Smarkm#if defined(OPENSSL_SYS_VXWORKS)
139100928Snectar#undef TERMIOS
140100928Snectar#undef TERMIO
141100928Snectar#undef SGTTY
142100928Snectar#endif
143100928Snectar
14455714Skris#ifdef TERMIOS
14555714Skris#include <termios.h>
14655714Skris#define TTY_STRUCT		struct termios
14755714Skris#define TTY_FLAGS		c_lflag
14855714Skris#define	TTY_get(tty,data)	tcgetattr(tty,data)
14955714Skris#define TTY_set(tty,data)	tcsetattr(tty,TCSANOW,data)
15055714Skris#endif
15155714Skris
15255714Skris#ifdef TERMIO
15355714Skris#include <termio.h>
15455714Skris#define TTY_STRUCT		struct termio
15555714Skris#define TTY_FLAGS		c_lflag
15655714Skris#define TTY_get(tty,data)	ioctl(tty,TCGETA,data)
15755714Skris#define TTY_set(tty,data)	ioctl(tty,TCSETA,data)
15855714Skris#endif
15955714Skris
16055714Skris#ifdef SGTTY
16155714Skris#include <sgtty.h>
16255714Skris#define TTY_STRUCT		struct sgttyb
16355714Skris#define TTY_FLAGS		sg_flags
16455714Skris#define TTY_get(tty,data)	ioctl(tty,TIOCGETP,data)
16555714Skris#define TTY_set(tty,data)	ioctl(tty,TIOCSETP,data)
16655714Skris#endif
16755714Skris
168109998Smarkm#if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(MAC_OS_pre_X)
16955714Skris#include <sys/ioctl.h>
17055714Skris#endif
17155714Skris
172109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(__CYGWIN32__) && !defined(OPENSSL_SYS_WINCE)
17355714Skris#include <conio.h>
17455714Skris#define fgets(a,b,c) noecho_fgets(a,b,c)
17555714Skris#endif
17655714Skris
177109998Smarkm#ifdef OPENSSL_SYS_VMS
17855714Skris#include <ssdef.h>
17955714Skris#include <iodef.h>
18055714Skris#include <ttdef.h>
18155714Skris#include <descrip.h>
18255714Skrisstruct IOSB {
18355714Skris	short iosb$w_value;
18455714Skris	short iosb$w_count;
18555714Skris	long  iosb$l_info;
18655714Skris	};
18755714Skris#endif
18855714Skris
18959191Skris#if defined(MAC_OS_pre_X) || defined(MAC_OS_GUSI_SOURCE)
19059191Skris/*
19159191Skris * This one needs work. As a matter of fact the code is unoperational
19259191Skris * and this is only a trick to get it compiled.
19359191Skris *					<appro@fy.chalmers.se>
19459191Skris */
19559191Skris#define TTY_STRUCT int
19659191Skris#endif
19759191Skris
19855714Skris#ifndef NX509_SIG
19955714Skris#define NX509_SIG 32
20055714Skris#endif
20155714Skris
20255714Skrisstatic void read_till_nl(FILE *);
20355714Skrisstatic void recsig(int);
20455714Skrisstatic void pushsig(void);
20555714Skrisstatic void popsig(void);
206109998Smarkm#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
20755714Skrisstatic int noecho_fgets(char *buf, int size, FILE *tty);
20855714Skris#endif
20955714Skris#ifdef SIGACTION
21055714Skris static struct sigaction savsig[NX509_SIG];
21155714Skris#else
21255714Skris  static void (*savsig[NX509_SIG])(int );
21355714Skris#endif
21455714Skrisstatic jmp_buf save;
21555714Skris
21655714Skrisint des_read_pw_string(char *buf, int length, const char *prompt,
21755714Skris	     int verify)
21855714Skris	{
21955714Skris	char buff[BUFSIZ];
22055714Skris	int ret;
22155714Skris
22255714Skris	ret=des_read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify);
223109998Smarkm	OPENSSL_cleanse(buff,BUFSIZ);
22455714Skris	return(ret);
22555714Skris	}
22655714Skris
227109998Smarkm#ifdef OPENSSL_SYS_WINCE
22855714Skris
229109998Smarkmint des_read_pw(char *buf, char *buff, int size, const char *prompt, int verify)
230109998Smarkm	{
231109998Smarkm	memset(buf,0,size);
232109998Smarkm	memset(buff,0,size);
233109998Smarkm	return(0);
234109998Smarkm	}
235109998Smarkm
236109998Smarkm#elif defined(OPENSSL_SYS_WIN16)
237109998Smarkm
238109998Smarkmint des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
239109998Smarkm	{
240109998Smarkm	memset(buf,0,size);
241109998Smarkm	memset(buff,0,size);
242109998Smarkm	return(0);
243109998Smarkm	}
244109998Smarkm
245109998Smarkm#else /* !OPENSSL_SYS_WINCE && !OPENSSL_SYS_WIN16 */
246109998Smarkm
24755714Skrisstatic void read_till_nl(FILE *in)
24855714Skris	{
24955714Skris#define SIZE 4
25055714Skris	char buf[SIZE+1];
25155714Skris
25255714Skris	do	{
25355714Skris		fgets(buf,SIZE,in);
25455714Skris		} while (strchr(buf,'\n') == NULL);
25555714Skris	}
25655714Skris
25755714Skris
25855714Skris/* return 0 if ok, 1 (or -1) otherwise */
25955714Skrisint des_read_pw(char *buf, char *buff, int size, const char *prompt,
26055714Skris	     int verify)
26155714Skris	{
262109998Smarkm#ifdef OPENSSL_SYS_VMS
26355714Skris	struct IOSB iosb;
26455714Skris	$DESCRIPTOR(terminal,"TT");
26555714Skris	long tty_orig[3], tty_new[3];
26655714Skris	long status;
26755714Skris	unsigned short channel = 0;
26855714Skris#else
269109998Smarkm#if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
27055714Skris	TTY_STRUCT tty_orig,tty_new;
27155714Skris#endif
27255714Skris#endif
27355714Skris	int number;
27455714Skris	int ok;
27555714Skris	/* statics are simply to avoid warnings about longjmp clobbering
27655714Skris	   things */
27755714Skris	static int ps;
27855714Skris	int is_a_tty;
27955714Skris	static FILE *tty;
28055714Skris	char *p;
28155714Skris
28255714Skris	if (setjmp(save))
28355714Skris		{
28455714Skris		ok=0;
28555714Skris		goto error;
28655714Skris		}
28755714Skris
28855714Skris	number=5;
28955714Skris	ok=0;
29055714Skris	ps=0;
29155714Skris	is_a_tty=1;
29255714Skris	tty=NULL;
29355714Skris
294109998Smarkm#ifdef OPENSSL_SYS_MSDOS
29568651Skris	if ((tty=fopen("con","r")) == NULL)
29668651Skris		tty=stdin;
297109998Smarkm#elif defined(MAC_OS_pre_X) || defined(OPENSSL_SYS_VXWORKS)
29868651Skris	tty=stdin;
29968651Skris#else
300109998Smarkm#ifndef OPENSSL_SYS_MPE
30155714Skris	if ((tty=fopen("/dev/tty","r")) == NULL)
30268651Skris#endif
30355714Skris		tty=stdin;
30468651Skris#endif
30555714Skris
306109998Smarkm#if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
30755714Skris	if (TTY_get(fileno(tty),&tty_orig) == -1)
30855714Skris		{
30955714Skris#ifdef ENOTTY
31055714Skris		if (errno == ENOTTY)
31155714Skris			is_a_tty=0;
31255714Skris		else
31355714Skris#endif
31455714Skris#ifdef EINVAL
31555714Skris		/* Ariel Glenn ariel@columbia.edu reports that solaris
31655714Skris		 * can return EINVAL instead.  This should be ok */
31755714Skris		if (errno == EINVAL)
31855714Skris			is_a_tty=0;
31955714Skris		else
32055714Skris#endif
32155714Skris			return(-1);
32255714Skris		}
32355714Skris	memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
32455714Skris#endif
325109998Smarkm#ifdef OPENSSL_SYS_VMS
32655714Skris	status = sys$assign(&terminal,&channel,0,0);
32755714Skris	if (status != SS$_NORMAL)
32855714Skris		return(-1);
32955714Skris	status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
33055714Skris	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
33155714Skris		return(-1);
33255714Skris#endif
33355714Skris
33455714Skris	pushsig();
33555714Skris	ps=1;
33655714Skris
33755714Skris#ifdef TTY_FLAGS
33855714Skris	tty_new.TTY_FLAGS &= ~ECHO;
33955714Skris#endif
34055714Skris
341109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
34255714Skris	if (is_a_tty && (TTY_set(fileno(tty),&tty_new) == -1))
343109998Smarkm#ifdef OPENSSL_SYS_MPE
34468651Skris		; /* MPE lies -- echo really has been disabled */
34568651Skris#else
34655714Skris		return(-1);
34755714Skris#endif
34868651Skris#endif
349109998Smarkm#ifdef OPENSSL_SYS_VMS
35055714Skris	tty_new[0] = tty_orig[0];
35155714Skris	tty_new[1] = tty_orig[1] | TT$M_NOECHO;
35255714Skris	tty_new[2] = tty_orig[2];
35355714Skris	status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
35455714Skris	if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
35555714Skris		return(-1);
35655714Skris#endif
35755714Skris	ps=2;
35855714Skris
35955714Skris	while ((!ok) && (number--))
36055714Skris		{
36155714Skris		fputs(prompt,stderr);
36255714Skris		fflush(stderr);
36355714Skris
36455714Skris		buf[0]='\0';
36555714Skris		fgets(buf,size,tty);
36655714Skris		if (feof(tty)) goto error;
36755714Skris		if (ferror(tty)) goto error;
36855714Skris		if ((p=(char *)strchr(buf,'\n')) != NULL)
36955714Skris			*p='\0';
37055714Skris		else	read_till_nl(tty);
37155714Skris		if (verify)
37255714Skris			{
37355714Skris			fprintf(stderr,"\nVerifying password - %s",prompt);
37455714Skris			fflush(stderr);
37555714Skris			buff[0]='\0';
37655714Skris			fgets(buff,size,tty);
37755714Skris			if (feof(tty)) goto error;
37855714Skris			if ((p=(char *)strchr(buff,'\n')) != NULL)
37955714Skris				*p='\0';
38055714Skris			else	read_till_nl(tty);
38155714Skris
38255714Skris			if (strcmp(buf,buff) != 0)
38355714Skris				{
38455714Skris				fprintf(stderr,"\nVerify failure");
38555714Skris				fflush(stderr);
38655714Skris				break;
38755714Skris				/* continue; */
38855714Skris				}
38955714Skris			}
39055714Skris		ok=1;
39155714Skris		}
39255714Skris
39355714Skriserror:
39455714Skris	fprintf(stderr,"\n");
395100928Snectar#if 0
39655714Skris	perror("fgets(tty)");
39755714Skris#endif
39855714Skris	/* What can we do if there is an error? */
399109998Smarkm#if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
40055714Skris	if (ps >= 2) TTY_set(fileno(tty),&tty_orig);
40155714Skris#endif
402109998Smarkm#ifdef OPENSSL_SYS_VMS
40355714Skris	if (ps >= 2)
40455714Skris		status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0
40555714Skris			,tty_orig,12,0,0,0,0);
40655714Skris#endif
40755714Skris
40855714Skris	if (ps >= 1) popsig();
40955714Skris	if (stdin != tty) fclose(tty);
410109998Smarkm#ifdef OPENSSL_SYS_VMS
41155714Skris	status = sys$dassgn(channel);
41255714Skris#endif
41355714Skris	return(!ok);
41455714Skris	}
41555714Skris
41655714Skrisstatic void pushsig(void)
41755714Skris	{
41855714Skris	int i;
41955714Skris#ifdef SIGACTION
42055714Skris	struct sigaction sa;
42155714Skris
42255714Skris	memset(&sa,0,sizeof sa);
42355714Skris	sa.sa_handler=recsig;
42455714Skris#endif
42555714Skris
42655714Skris	for (i=1; i<NX509_SIG; i++)
42755714Skris		{
42855714Skris#ifdef SIGUSR1
42955714Skris		if (i == SIGUSR1)
43055714Skris			continue;
43155714Skris#endif
43255714Skris#ifdef SIGUSR2
43355714Skris		if (i == SIGUSR2)
43455714Skris			continue;
43555714Skris#endif
43655714Skris#ifdef SIGACTION
43755714Skris		sigaction(i,&sa,&savsig[i]);
43855714Skris#else
43955714Skris		savsig[i]=signal(i,recsig);
44055714Skris#endif
44155714Skris		}
44255714Skris
44355714Skris#ifdef SIGWINCH
44455714Skris	signal(SIGWINCH,SIG_DFL);
44555714Skris#endif
44655714Skris	}
44755714Skris
44855714Skrisstatic void popsig(void)
44955714Skris	{
45055714Skris	int i;
45155714Skris
45255714Skris	for (i=1; i<NX509_SIG; i++)
45355714Skris		{
45455714Skris#ifdef SIGUSR1
45555714Skris		if (i == SIGUSR1)
45655714Skris			continue;
45755714Skris#endif
45855714Skris#ifdef SIGUSR2
45955714Skris		if (i == SIGUSR2)
46055714Skris			continue;
46155714Skris#endif
46255714Skris#ifdef SIGACTION
46355714Skris		sigaction(i,&savsig[i],NULL);
46455714Skris#else
46555714Skris		signal(i,savsig[i]);
46655714Skris#endif
46755714Skris		}
46855714Skris	}
46955714Skris
47055714Skrisstatic void recsig(int i)
47155714Skris	{
47255714Skris	longjmp(save,1);
47355714Skris#ifdef LINT
47455714Skris	i=i;
47555714Skris#endif
47655714Skris	}
47755714Skris
478109998Smarkm#ifdef OPENSSL_SYS_MSDOS
47955714Skrisstatic int noecho_fgets(char *buf, int size, FILE *tty)
48055714Skris	{
48155714Skris	int i;
48255714Skris	char *p;
48355714Skris
48455714Skris	p=buf;
48555714Skris	for (;;)
48655714Skris		{
48755714Skris		if (size == 0)
48855714Skris			{
48955714Skris			*p='\0';
49055714Skris			break;
49155714Skris			}
49255714Skris		size--;
49355714Skris#ifdef WIN16TTY
49455714Skris		i=_inchar();
49555714Skris#else
49655714Skris		i=getch();
49755714Skris#endif
49855714Skris		if (i == '\r') i='\n';
49955714Skris		*(p++)=i;
50055714Skris		if (i == '\n')
50155714Skris			{
50255714Skris			*p='\0';
50355714Skris			break;
50455714Skris			}
50555714Skris		}
50655714Skris#ifdef WIN_CONSOLE_BUG
50755714Skris/* Win95 has several evil console bugs: one of these is that the
50855714Skris * last character read using getch() is passed to the next read: this is
50955714Skris * usually a CR so this can be trouble. No STDIO fix seems to work but
51055714Skris * flushing the console appears to do the trick.
51155714Skris */
51255714Skris		{
51355714Skris			HANDLE inh;
51455714Skris			inh = GetStdHandle(STD_INPUT_HANDLE);
51555714Skris			FlushConsoleInputBuffer(inh);
51655714Skris		}
51755714Skris#endif
51855714Skris	return(strlen(buf));
51955714Skris	}
52055714Skris#endif
521109998Smarkm#endif /* !OPENSSL_SYS_WINCE && !WIN16 */
522