b893a1b03a3ed8af121de384f81c31e0a68d41de
[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 #include <openssl/e_os2.h>
60 #if !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WIN32)
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 OPENSSL_SYS_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 OPENSSL_SYS_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(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_MSDOS) && !defined(MAC_OS_pre_X) && !defined(MAC_OS_GUSI_SOURCE)
131 #undef  TERMIOS
132 #undef  TERMIO
133 #define SGTTY
134 #endif
135
136 #if defined(OPENSSL_SYS_VXWORKS)
137 #undef TERMIOS
138 #undef TERMIO
139 #undef SGTTY
140 #endif
141
142 #ifdef TERMIOS
143 #include <termios.h>
144 #define TTY_STRUCT              struct termios
145 #define TTY_FLAGS               c_lflag
146 #define TTY_get(tty,data)       tcgetattr(tty,data)
147 #define TTY_set(tty,data)       tcsetattr(tty,TCSANOW,data)
148 #endif
149
150 #ifdef TERMIO
151 #include <termio.h>
152 #define TTY_STRUCT              struct termio
153 #define TTY_FLAGS               c_lflag
154 #define TTY_get(tty,data)       ioctl(tty,TCGETA,data)
155 #define TTY_set(tty,data)       ioctl(tty,TCSETA,data)
156 #endif
157
158 #ifdef SGTTY
159 #include <sgtty.h>
160 #define TTY_STRUCT              struct sgttyb
161 #define TTY_FLAGS               sg_flags
162 #define TTY_get(tty,data)       ioctl(tty,TIOCGETP,data)
163 #define TTY_set(tty,data)       ioctl(tty,TIOCSETP,data)
164 #endif
165
166 #if !defined(_LIBC) && !defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_VMS) && !defined(MAC_OS_pre_X)
167 #include <sys/ioctl.h>
168 #endif
169
170 #if defined(OPENSSL_SYS_MSDOS) && !defined(__CYGWIN32__)
171 #include <conio.h>
172 #define fgets(a,b,c) noecho_fgets(a,b,c)
173 #endif
174
175 #ifdef OPENSSL_SYS_VMS
176 #include <ssdef.h>
177 #include <iodef.h>
178 #include <ttdef.h>
179 #include <descrip.h>
180 struct IOSB {
181         short iosb$w_value;
182         short iosb$w_count;
183         long  iosb$l_info;
184         };
185 #endif
186
187 #if defined(MAC_OS_pre_X) || defined(MAC_OS_GUSI_SOURCE)
188 /*
189  * This one needs work. As a matter of fact the code is unoperational
190  * and this is only a trick to get it compiled.
191  *                                      <appro@fy.chalmers.se>
192  */
193 #define TTY_STRUCT int
194 #endif
195
196 #ifndef NX509_SIG
197 #define NX509_SIG 32
198 #endif
199
200 static void read_till_nl(FILE *);
201 static void recsig(int);
202 static void pushsig(void);
203 static void popsig(void);
204 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
205 static int noecho_fgets(char *buf, int size, FILE *tty);
206 #endif
207 #ifdef SIGACTION
208  static struct sigaction savsig[NX509_SIG];
209 #else
210   static void (*savsig[NX509_SIG])(int );
211 #endif
212 static jmp_buf save;
213
214 int des_read_pw_string(char *buf, int length, const char *prompt,
215              int verify)
216         {
217         char buff[BUFSIZ];
218         int ret;
219
220         ret=des_read_pw(buf,buff,(length>BUFSIZ)?BUFSIZ:length,prompt,verify);
221         memset(buff,0,BUFSIZ);
222         return(ret);
223         }
224
225 #ifndef OPENSSL_SYS_WIN16
226
227 static void read_till_nl(FILE *in)
228         {
229 #define SIZE 4
230         char buf[SIZE+1];
231
232         do      {
233                 fgets(buf,SIZE,in);
234                 } while (strchr(buf,'\n') == NULL);
235         }
236
237
238 /* return 0 if ok, 1 (or -1) otherwise */
239 int des_read_pw(char *buf, char *buff, int size, const char *prompt,
240              int verify)
241         {
242 #ifdef OPENSSL_SYS_VMS
243         struct IOSB iosb;
244         $DESCRIPTOR(terminal,"TT");
245         long tty_orig[3], tty_new[3];
246         long status;
247         unsigned short channel = 0;
248 #else
249 #if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
250         TTY_STRUCT tty_orig,tty_new;
251 #endif
252 #endif
253         int number;
254         int ok;
255         /* statics are simply to avoid warnings about longjmp clobbering
256            things */
257         static int ps;
258         int is_a_tty;
259         static FILE *tty;
260         char *p;
261
262         if (setjmp(save))
263                 {
264                 ok=0;
265                 goto error;
266                 }
267
268         number=5;
269         ok=0;
270         ps=0;
271         is_a_tty=1;
272         tty=NULL;
273
274 #ifdef OPENSSL_SYS_MSDOS
275         if ((tty=fopen("con","r")) == NULL)
276                 tty=stdin;
277 #elif defined(MAC_OS_pre_X) || defined(OPENSSL_SYS_VXWORKS)
278         tty=stdin;
279 #else
280 #ifndef OPENSSL_SYS_MPE
281         if ((tty=fopen("/dev/tty","r")) == NULL)
282 #endif
283                 tty=stdin;
284 #endif
285
286 #if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
287         if (TTY_get(fileno(tty),&tty_orig) == -1)
288                 {
289 #ifdef ENOTTY
290                 if (errno == ENOTTY)
291                         is_a_tty=0;
292                 else
293 #endif
294 #ifdef EINVAL
295                 /* Ariel Glenn ariel@columbia.edu reports that solaris
296                  * can return EINVAL instead.  This should be ok */
297                 if (errno == EINVAL)
298                         is_a_tty=0;
299                 else
300 #endif
301                         return(-1);
302                 }
303         memcpy(&(tty_new),&(tty_orig),sizeof(tty_orig));
304 #endif
305 #ifdef OPENSSL_SYS_VMS
306         status = sys$assign(&terminal,&channel,0,0);
307         if (status != SS$_NORMAL)
308                 return(-1);
309         status=sys$qiow(0,channel,IO$_SENSEMODE,&iosb,0,0,tty_orig,12,0,0,0,0);
310         if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
311                 return(-1);
312 #endif
313
314         pushsig();
315         ps=1;
316
317 #ifdef TTY_FLAGS
318         tty_new.TTY_FLAGS &= ~ECHO;
319 #endif
320
321 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
322         if (is_a_tty && (TTY_set(fileno(tty),&tty_new) == -1))
323 #ifdef OPENSSL_SYS_MPE 
324                 ; /* MPE lies -- echo really has been disabled */
325 #else
326                 return(-1);
327 #endif
328 #endif
329 #ifdef OPENSSL_SYS_VMS
330         tty_new[0] = tty_orig[0];
331         tty_new[1] = tty_orig[1] | TT$M_NOECHO;
332         tty_new[2] = tty_orig[2];
333         status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0,tty_new,12,0,0,0,0);
334         if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
335                 return(-1);
336 #endif
337         ps=2;
338
339         while ((!ok) && (number--))
340                 {
341                 fputs(prompt,stderr);
342                 fflush(stderr);
343
344                 buf[0]='\0';
345                 fgets(buf,size,tty);
346                 if (feof(tty)) goto error;
347                 if (ferror(tty)) goto error;
348                 if ((p=(char *)strchr(buf,'\n')) != NULL)
349                         *p='\0';
350                 else    read_till_nl(tty);
351                 if (verify)
352                         {
353                         fprintf(stderr,"\nVerifying password - %s",prompt);
354                         fflush(stderr);
355                         buff[0]='\0';
356                         fgets(buff,size,tty);
357                         if (feof(tty)) goto error;
358                         if ((p=(char *)strchr(buff,'\n')) != NULL)
359                                 *p='\0';
360                         else    read_till_nl(tty);
361                                 
362                         if (strcmp(buf,buff) != 0)
363                                 {
364                                 fprintf(stderr,"\nVerify failure");
365                                 fflush(stderr);
366                                 break;
367                                 /* continue; */
368                                 }
369                         }
370                 ok=1;
371                 }
372
373 error:
374         fprintf(stderr,"\n");
375 #if 0
376         perror("fgets(tty)");
377 #endif
378         /* What can we do if there is an error? */
379 #if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
380         if (ps >= 2) TTY_set(fileno(tty),&tty_orig);
381 #endif
382 #ifdef OPENSSL_SYS_VMS
383         if (ps >= 2)
384                 status = sys$qiow(0,channel,IO$_SETMODE,&iosb,0,0
385                         ,tty_orig,12,0,0,0,0);
386 #endif
387         
388         if (ps >= 1) popsig();
389         if (stdin != tty) fclose(tty);
390 #ifdef OPENSSL_SYS_VMS
391         status = sys$dassgn(channel);
392 #endif
393         return(!ok);
394         }
395
396 #else /* OPENSSL_SYS_WIN16 */
397
398 int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
399         { 
400         memset(buf,0,size);
401         memset(buff,0,size);
402         return(0);
403         }
404
405 #endif
406
407 static void pushsig(void)
408         {
409         int i;
410 #ifdef SIGACTION
411         struct sigaction sa;
412
413         memset(&sa,0,sizeof sa);
414         sa.sa_handler=recsig;
415 #endif
416
417         for (i=1; i<NX509_SIG; i++)
418                 {
419 #ifdef SIGUSR1
420                 if (i == SIGUSR1)
421                         continue;
422 #endif
423 #ifdef SIGUSR2
424                 if (i == SIGUSR2)
425                         continue;
426 #endif
427 #ifdef SIGACTION
428                 sigaction(i,&sa,&savsig[i]);
429 #else
430                 savsig[i]=signal(i,recsig);
431 #endif
432                 }
433
434 #ifdef SIGWINCH
435         signal(SIGWINCH,SIG_DFL);
436 #endif
437         }
438
439 static void popsig(void)
440         {
441         int i;
442
443         for (i=1; i<NX509_SIG; i++)
444                 {
445 #ifdef SIGUSR1
446                 if (i == SIGUSR1)
447                         continue;
448 #endif
449 #ifdef SIGUSR2
450                 if (i == SIGUSR2)
451                         continue;
452 #endif
453 #ifdef SIGACTION
454                 sigaction(i,&savsig[i],NULL);
455 #else
456                 signal(i,savsig[i]);
457 #endif
458                 }
459         }
460
461 static void recsig(int i)
462         {
463         longjmp(save,1);
464 #ifdef LINT
465         i=i;
466 #endif
467         }
468
469 #if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
470 static int noecho_fgets(char *buf, int size, FILE *tty)
471         {
472         int i;
473         char *p;
474
475         p=buf;
476         for (;;)
477                 {
478                 if (size == 0)
479                         {
480                         *p='\0';
481                         break;
482                         }
483                 size--;
484 #ifdef WIN16TTY
485                 i=_inchar();
486 #else
487                 i=getch();
488 #endif
489                 if (i == '\r') i='\n';
490                 *(p++)=i;
491                 if (i == '\n')
492                         {
493                         *p='\0';
494                         break;
495                         }
496                 }
497 #ifdef WIN_CONSOLE_BUG
498 /* Win95 has several evil console bugs: one of these is that the
499  * last character read using getch() is passed to the next read: this is
500  * usually a CR so this can be trouble. No STDIO fix seems to work but
501  * flushing the console appears to do the trick.
502  */
503                 {
504                         HANDLE inh;
505                         inh = GetStdHandle(STD_INPUT_HANDLE);
506                         FlushConsoleInputBuffer(inh);
507                 }
508 #endif
509         return(strlen(buf));
510         }
511 #endif