d280aa14a568732b2454d11d68f0fcb3be14956a
[openssl.git] / crypto / des / read_pwd.c
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 <unistd.h>
61 /* If unistd.h defines _POSIX_VERSION, we conclude that we
62  * are on a POSIX system and have sigaction and termios. */
63 #if defined(_POSIX_VERSION)
64
65 # define SIGACTION
66 # if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
67 # define TERMIOS
68 # endif
69
70 #endif
71 #endif
72
73 /* #define SIGACTION */ /* Define this if you have sigaction() */
74
75 #ifdef WIN16TTY
76 #undef WIN16
77 #undef _WINDOWS
78 #include <graph.h>
79 #endif
80
81 /* 06-Apr-92 Luke Brennan    Support for VMS */
82 #include "des_locl.h"
83 #include "cryptlib.h"
84 #include <signal.h>
85 #include <stdio.h>
86 #include <string.h>
87 #include <setjmp.h>
88 #include <errno.h>
89
90 #ifdef VMS                      /* prototypes for sys$whatever */
91 #include <starlet.h>
92 #ifdef __DECC
93 #pragma message disable DOLLARID
94 #endif
95 #endif
96
97 #ifdef WIN_CONSOLE_BUG
98 #include <windows.h>
99 #include <wincon.h>
100 #endif
101
102
103 /* There are 5 types of terminal interface supported,
104  * TERMIO, TERMIOS, VMS, MSDOS and SGTTY
105  */
106
107 #if defined(__sgi) && !defined(TERMIOS)
108 #define TERMIOS
109 #undef  TERMIO
110 #undef  SGTTY
111 #endif
112
113 #if defined(linux) && !defined(TERMIO)
114 #undef  TERMIOS
115 #define TERMIO
116 #undef  SGTTY
117 #endif
118
119 #ifdef _LIBC
120 #undef  TERMIOS
121 #define TERMIO
122 #undef  SGTTY
123 #endif
124
125 #if !defined(TERMIO) && !defined(TERMIOS) && !defined(VMS) && !defined(MSDOS)
126 #undef  TERMIOS
127 #undef  TERMIO
128 #define SGTTY
129 #endif
130
131 #ifdef TERMIOS
132 #include <termios.h>
133 #define TTY_STRUCT              struct termios
134 #define TTY_FLAGS               c_lflag
135 #define TTY_get(tty,data)       tcgetattr(tty,data)
136 #define TTY_set(tty,data)       tcsetattr(tty,TCSANOW,data)
137 #endif
138
139 #ifdef TERMIO
140 #include <termio.h>
141 #define TTY_STRUCT              struct termio
142 #define TTY_FLAGS               c_lflag
143 #define TTY_get(tty,data)       ioctl(tty,TCGETA,data)
144 #define TTY_set(tty,data)       ioctl(tty,TCSETA,data)
145 #endif
146
147 #ifdef SGTTY
148 #include <sgtty.h>
149 #define TTY_STRUCT              struct sgttyb
150 #define TTY_FLAGS               sg_flags
151 #define TTY_get(tty,data)       ioctl(tty,TIOCGETP,data)
152 #define TTY_set(tty,data)       ioctl(tty,TIOCSETP,data)
153 #endif
154
155 #if !defined(_LIBC) && !defined(MSDOS) && !defined(VMS)
156 #include <sys/ioctl.h>
157 #endif
158
159 #ifdef MSDOS
160 #include <conio.h>
161 #define fgets(a,b,c) noecho_fgets(a,b,c)
162 #endif
163
164 #ifdef VMS
165 #include <ssdef.h>
166 #include <iodef.h>
167 #include <ttdef.h>
168 #include <descrip.h>
169 struct IOSB {
170         short iosb$w_value;
171         short iosb$w_count;
172         long  iosb$l_info;
173         };
174 #endif
175
176 #ifndef NX509_SIG
177 #define NX509_SIG 32
178 #endif
179
180 static void read_till_nl(FILE *);
181 static void recsig(int);
182 static void pushsig(void);
183 static void popsig(void);
184 #if defined(MSDOS) && !defined(WIN16)
185 static int noecho_fgets(char *buf, int size, FILE *tty);
186 #endif
187 #ifdef SIGACTION
188  static struct sigaction savsig[NX509_SIG];
189 #else
190 # ifndef NOPROTO
191   static void (*savsig[NX509_SIG])(int );
192 # else
193   static void (*savsig[NX509_SIG])();
194 # endif
195 #endif
196 static jmp_buf save;
197
198 int des_read_pw_string(char *buf, int length, const char *prompt,
199              int verify)
200         {
201         char buff[BUFSIZ];
202         int ret;
203
204         ret=des_read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify);
205         memset(buff,0,BUFSIZ);
206         return(ret);
207         }
208
209 #ifndef WIN16
210
211 static void read_till_nl(FILE *in)
212         {
213 #define SIZE 4
214         char buf[SIZE+1];
215
216         do      {
217                 fgets(buf,SIZE,in);
218                 } while (strchr(buf,'\n') == NULL);
219         }
220
221
222 /* return 0 if ok, 1 (or -1) otherwise */
223 int des_read_pw(char *buf, char *buff, int size, const char *prompt,
224              int verify)
225         {
226 #ifdef VMS
227         struct IOSB iosb;
228         $DESCRIPTOR(terminal,"TT");
229         long tty_orig[3], tty_new[3];
230         long status;
231         unsigned short channel = 0;
232 #else
233 #ifndef MSDOS
234         TTY_STRUCT tty_orig,tty_new;
235 #endif
236 #endif
237         int number;
238         int ok;
239         /* statics are simply to avoid warnings about longjmp clobbering
240            things */
241         static int ps;
242         int is_a_tty;
243         static FILE *tty;
244         char *p;
245
246         if (setjmp(save))
247                 {
248                 ok=0;
249                 goto error;
250                 }
251
252         number=5;
253         ok=0;
254         ps=0;
255         is_a_tty=1;
256         tty=NULL;
257
258 #ifndef MSDOS
259         if ((tty=fopen("/dev/tty","r")) == NULL)
260                 tty=stdin;
261 #else /* MSDOS */
262         if ((tty=fopen("con","r")) == NULL)
263                 tty=stdin;
264 #endif /* MSDOS */
265
266 #if defined(TTY_get) && !defined(VMS)
267         if (TTY_get(fileno(tty),&tty_orig) == -1)
268                 {
269 #ifdef ENOTTY
270                 if (errno == ENOTTY)
271                         is_a_tty=0;
272                 else
273 #endif
274 #ifdef EINVAL
275                 /* Ariel Glenn ariel@columbia.edu reports that solaris
276                  * can return EINVAL instead.  This should be ok */
277                 if (errno == EINVAL)
278                         is_a_tty=0;
279                 else
280 #endif
281                         return(-1);
282                 }
283         memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
284 #endif
285 #ifdef VMS
286         status = sys$assign(&terminal,&channel,0,0);
287         if (status != SS$_NORMAL)
288                 return(-1);
289         status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
290         if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
291                 return(-1);
292 #endif
293
294         pushsig();
295         ps=1;
296
297 #ifdef TTY_FLAGS
298         tty_new.TTY_FLAGS &= ~ECHO;
299 #endif
300
301 #if defined(TTY_set) && !defined(VMS)
302         if (is_a_tty && (TTY_set(fileno(tty),&tty_new) == -1))
303                 return(-1);
304 #endif
305 #ifdef VMS
306         tty_new[0] = tty_orig[0];
307         tty_new[1] = tty_orig[1] | TT$M_NOECHO;
308         tty_new[2] = tty_orig[2];
309         status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
310         if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
311                 return(-1);
312 #endif
313         ps=2;
314
315         while ((!ok) && (number--))
316                 {
317                 fputs(prompt,stderr);
318                 fflush(stderr);
319
320                 buf[0]='\0';
321                 fgets(buf,size,tty);
322                 if (feof(tty)) goto error;
323                 if (ferror(tty)) goto error;
324                 if ((p=(char *)strchr(buf,'\n')) != NULL)
325                         *p='\0';
326                 else    read_till_nl(tty);
327                 if (verify)
328                         {
329                         fprintf(stderr,"\nVerifying password - %s",prompt);
330                         fflush(stderr);
331                         buff[0]='\0';
332                         fgets(buff,size,tty);
333                         if (feof(tty)) goto error;
334                         if ((p=(char *)strchr(buff,'\n')) != NULL)
335                                 *p='\0';
336                         else    read_till_nl(tty);
337                                 
338                         if (strcmp(buf,buff) != 0)
339                                 {
340                                 fprintf(stderr,"\nVerify failure");
341                                 fflush(stderr);
342                                 break;
343                                 /* continue; */
344                                 }
345                         }
346                 ok=1;
347                 }
348
349 error:
350         fprintf(stderr,"\n");
351 #ifdef DEBUG
352         perror("fgets(tty)");
353 #endif
354         /* What can we do if there is an error? */
355 #if defined(TTY_set) && !defined(VMS)
356         if (ps >= 2) TTY_set(fileno(tty),&tty_orig);
357 #endif
358 #ifdef VMS
359         if (ps >= 2)
360                 status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0
361                         ,tty_orig,12,0,0,0,0);
362 #endif
363         
364         if (ps >= 1) popsig();
365         if (stdin != tty) fclose(tty);
366 #ifdef VMS
367         status = sys$dassgn(channel);
368 #endif
369         return(!ok);
370         }
371
372 #else /* WIN16 */
373
374 int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
375         { 
376         memset(buf,0,size);
377         memset(buff,0,size);
378         return(0);
379         }
380
381 #endif
382
383 static void pushsig(void)
384         {
385         int i;
386 #ifdef SIGACTION
387         struct sigaction sa;
388
389         memset(&sa,0,sizeof sa);
390         sa.sa_handler=recsig;
391 #endif
392
393         for (i=1; i<NX509_SIG; i++)
394                 {
395 #ifdef SIGUSR1
396                 if (i == SIGUSR1)
397                         continue;
398 #endif
399 #ifdef SIGUSR2
400                 if (i == SIGUSR2)
401                         continue;
402 #endif
403 #ifdef SIGACTION
404                 sigaction(i,&sa,&savsig[i]);
405 #else
406                 savsig[i]=signal(i,recsig);
407 #endif
408                 }
409
410 #ifdef SIGWINCH
411         signal(SIGWINCH,SIG_DFL);
412 #endif
413         }
414
415 static void popsig(void)
416         {
417         int i;
418
419         for (i=1; i<NX509_SIG; i++)
420                 {
421 #ifdef SIGUSR1
422                 if (i == SIGUSR1)
423                         continue;
424 #endif
425 #ifdef SIGUSR2
426                 if (i == SIGUSR2)
427                         continue;
428 #endif
429 #ifdef SIGACTION
430                 sigaction(i,&savsig[i],NULL);
431 #else
432                 signal(i,savsig[i]);
433 #endif
434                 }
435         }
436
437 static void recsig(int i)
438         {
439         longjmp(save,1);
440 #ifdef LINT
441         i=i;
442 #endif
443         }
444
445 #if defined(MSDOS) && !defined(WIN16)
446 static int noecho_fgets(char *buf, int size, FILE *tty)
447         {
448         int i;
449         char *p;
450
451         p=buf;
452         for (;;)
453                 {
454                 if (size == 0)
455                         {
456                         *p='\0';
457                         break;
458                         }
459                 size--;
460 #ifdef WIN16TTY
461                 i=_inchar();
462 #else
463                 i=getch();
464 #endif
465                 if (i == '\r') i='\n';
466                 *(p++)=i;
467                 if (i == '\n')
468                         {
469                         *p='\0';
470                         break;
471                         }
472                 }
473 #ifdef WIN_CONSOLE_BUG
474 /* Win95 has several evil console bugs: one of these is that the
475  * last character read using getch() is passed to the next read: this is
476  * usually a CR so this can be trouble. No STDIO fix seems to work but
477  * flushing the console appears to do the trick.
478  */
479                 {
480                         HANDLE inh;
481                         inh = GetStdHandle(STD_INPUT_HANDLE);
482                         FlushConsoleInputBuffer(inh);
483                 }
484 #endif
485         return(strlen(buf));
486         }
487 #endif