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 #include <unistd.h>
61 /*
62  * If unistd.h defines _POSIX_VERSION, we conclude that we are on a POSIX
63  * system and have sigaction and termios.
64  */
65 # if defined(_POSIX_VERSION)
66 
67 #  define SIGACTION
68 #  if !defined(TERMIOS) && !defined(TERMIO) && !defined(SGTTY)
69 #   define TERMIOS
70 #  endif
71 
72 # endif
73 #endif
74 
75 /* Define this if you have sigaction() */
76 /* #define SIGACTION */
77 
78 #ifdef WIN16TTY
79 # undef OPENSSL_SYS_WIN16
80 # undef _WINDOWS
81 # include <graph.h>
82 #endif
83 
84 /* 06-Apr-92 Luke Brennan    Support for VMS */
85 #include "des_locl.h"
86 #include "cryptlib.h"
87 #include <signal.h>
88 #include <stdio.h>
89 #include <string.h>
90 #include <setjmp.h>
91 #include <errno.h>
92 
93 #ifdef OPENSSL_SYS_VMS          /* prototypes for sys$whatever */
94 # include <starlet.h>
95 # ifdef __DECC
96 #  pragma message disable DOLLARID
97 # endif
98 #endif
99 
100 #ifdef WIN_CONSOLE_BUG
101 # include <windows.h>
102 # ifndef OPENSSL_SYS_WINCE
103 #  include <wincon.h>
104 # endif
105 #endif
106 
107 /*
108  * There are 5 types of terminal interface supported, TERMIO, TERMIOS, VMS,
109  * 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__) && !defined(OPENSSL_SYS_WINCE)
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 
des_read_pw_string(char * buf,int length,const char * prompt,int verify)214 int des_read_pw_string(char *buf, int length, const char *prompt, int verify)
215 {
216     char buff[BUFSIZ];
217     int ret;
218 
219     ret =
220         des_read_pw(buf, buff, (length > BUFSIZ) ? BUFSIZ : length, prompt,
221                     verify);
222     OPENSSL_cleanse(buff, BUFSIZ);
223     return (ret);
224 }
225 
226 #ifdef OPENSSL_SYS_WINCE
227 
des_read_pw(char * buf,char * buff,int size,const char * prompt,int verify)228 int des_read_pw(char *buf, char *buff, int size, const char *prompt,
229                 int verify)
230 {
231     memset(buf, 0, size);
232     memset(buff, 0, size);
233     return (0);
234 }
235 
236 #elif defined(OPENSSL_SYS_WIN16)
237 
des_read_pw(char * buf,char * buff,int size,char * prompt,int verify)238 int des_read_pw(char *buf, char *buff, int size, char *prompt, int verify)
239 {
240     memset(buf, 0, size);
241     memset(buff, 0, size);
242     return (0);
243 }
244 
245 #else                           /* !OPENSSL_SYS_WINCE && !OPENSSL_SYS_WIN16 */
246 
read_till_nl(FILE * in)247 static void read_till_nl(FILE *in)
248 {
249 # define SIZE 4
250     char buf[SIZE + 1];
251 
252     do {
253         fgets(buf, SIZE, in);
254     } while (strchr(buf, '\n') == NULL);
255 }
256 
257 /* return 0 if ok, 1 (or -1) otherwise */
des_read_pw(char * buf,char * buff,int size,const char * prompt,int verify)258 int des_read_pw(char *buf, char *buff, int size, const char *prompt,
259                 int verify)
260 {
261 # ifdef OPENSSL_SYS_VMS
262     struct IOSB iosb;
263     $DESCRIPTOR(terminal, "TT");
264     long tty_orig[3], tty_new[3];
265     long status;
266     unsigned short channel = 0;
267 # else
268 #  if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
269     TTY_STRUCT tty_orig, tty_new;
270 #  endif
271 # endif
272     int number;
273     int ok;
274     /*
275      * statics are simply to avoid warnings about longjmp clobbering things
276      */
277     static int ps;
278     int is_a_tty;
279     static FILE *tty;
280     char *p;
281 
282     if (setjmp(save)) {
283         ok = 0;
284         goto error;
285     }
286 
287     number = 5;
288     ok = 0;
289     ps = 0;
290     is_a_tty = 1;
291     tty = NULL;
292 
293 # ifdef OPENSSL_SYS_MSDOS
294     if ((tty = fopen("con", "r")) == NULL)
295         tty = stdin;
296 # elif defined(MAC_OS_pre_X) || defined(OPENSSL_SYS_VXWORKS)
297     tty = stdin;
298 # else
299 #  ifndef OPENSSL_SYS_MPE
300     if ((tty = fopen("/dev/tty", "r")) == NULL)
301 #  endif
302         tty = stdin;
303 # endif
304 
305 # if defined(TTY_get) && !defined(OPENSSL_SYS_VMS)
306     if (TTY_get(fileno(tty), &tty_orig) == -1) {
307 #  ifdef ENOTTY
308         if (errno == ENOTTY)
309             is_a_tty = 0;
310         else
311 #  endif
312 #  ifdef EINVAL
313             /*
314              * Ariel Glenn ariel@columbia.edu reports that solaris can return
315              * EINVAL instead.  This should be ok
316              */
317         if (errno == EINVAL)
318             is_a_tty = 0;
319         else
320 #  endif
321             return (-1);
322     }
323     memcpy(&(tty_new), &(tty_orig), sizeof(tty_orig));
324 # endif
325 # ifdef OPENSSL_SYS_VMS
326     status = sys$assign(&terminal, &channel, 0, 0);
327     if (status != SS$_NORMAL)
328         return (-1);
329     status =
330         sys$qiow(0, channel, IO$_SENSEMODE, &iosb, 0, 0, tty_orig, 12, 0, 0,
331                  0, 0);
332     if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
333         return (-1);
334 # endif
335 
336     pushsig();
337     ps = 1;
338 
339 # ifdef TTY_FLAGS
340     tty_new.TTY_FLAGS &= ~ECHO;
341 # endif
342 
343 # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
344     if (is_a_tty && (TTY_set(fileno(tty), &tty_new) == -1))
345 #  ifdef OPENSSL_SYS_MPE
346         ;                       /* MPE lies -- echo really has been disabled */
347 #  else
348         return (-1);
349 #  endif
350 # endif
351 # ifdef OPENSSL_SYS_VMS
352     tty_new[0] = tty_orig[0];
353     tty_new[1] = tty_orig[1] | TT$M_NOECHO;
354     tty_new[2] = tty_orig[2];
355     status =
356         sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_new, 12, 0, 0, 0,
357                  0);
358     if ((status != SS$_NORMAL) || (iosb.iosb$w_value != SS$_NORMAL))
359         return (-1);
360 # endif
361     ps = 2;
362 
363     while ((!ok) && (number--)) {
364         fputs(prompt, stderr);
365         fflush(stderr);
366 
367         buf[0] = '\0';
368         fgets(buf, size, tty);
369         if (feof(tty))
370             goto error;
371         if (ferror(tty))
372             goto error;
373         if ((p = (char *)strchr(buf, '\n')) != NULL)
374             *p = '\0';
375         else
376             read_till_nl(tty);
377         if (verify) {
378             fprintf(stderr, "\nVerifying password - %s", prompt);
379             fflush(stderr);
380             buff[0] = '\0';
381             fgets(buff, size, tty);
382             if (feof(tty))
383                 goto error;
384             if ((p = (char *)strchr(buff, '\n')) != NULL)
385                 *p = '\0';
386             else
387                 read_till_nl(tty);
388 
389             if (strcmp(buf, buff) != 0) {
390                 fprintf(stderr, "\nVerify failure");
391                 fflush(stderr);
392                 break;
393                 /* continue; */
394             }
395         }
396         ok = 1;
397     }
398 
399  error:
400     fprintf(stderr, "\n");
401 # if 0
402     perror("fgets(tty)");
403 # endif
404     /* What can we do if there is an error? */
405 # if defined(TTY_set) && !defined(OPENSSL_SYS_VMS)
406     if (ps >= 2)
407         TTY_set(fileno(tty), &tty_orig);
408 # endif
409 # ifdef OPENSSL_SYS_VMS
410     if (ps >= 2)
411         status =
412             sys$qiow(0, channel, IO$_SETMODE, &iosb, 0, 0, tty_orig, 12, 0, 0,
413                      0, 0);
414 # endif
415 
416     if (ps >= 1)
417         popsig();
418     if (stdin != tty)
419         fclose(tty);
420 # ifdef OPENSSL_SYS_VMS
421     status = sys$dassgn(channel);
422 # endif
423     return (!ok);
424 }
425 
pushsig(void)426 static void pushsig(void)
427 {
428     int i;
429 # ifdef SIGACTION
430     struct sigaction sa;
431 
432     memset(&sa, 0, sizeof sa);
433     sa.sa_handler = recsig;
434 # endif
435 
436     for (i = 1; i < NX509_SIG; i++) {
437 # ifdef SIGUSR1
438         if (i == SIGUSR1)
439             continue;
440 # endif
441 # ifdef SIGUSR2
442         if (i == SIGUSR2)
443             continue;
444 # endif
445 # ifdef SIGACTION
446         sigaction(i, &sa, &savsig[i]);
447 # else
448         savsig[i] = signal(i, recsig);
449 # endif
450     }
451 
452 # ifdef SIGWINCH
453     signal(SIGWINCH, SIG_DFL);
454 # endif
455 }
456 
popsig(void)457 static void popsig(void)
458 {
459     int i;
460 
461     for (i = 1; i < NX509_SIG; i++) {
462 # ifdef SIGUSR1
463         if (i == SIGUSR1)
464             continue;
465 # endif
466 # ifdef SIGUSR2
467         if (i == SIGUSR2)
468             continue;
469 # endif
470 # ifdef SIGACTION
471         sigaction(i, &savsig[i], NULL);
472 # else
473         signal(i, savsig[i]);
474 # endif
475     }
476 }
477 
recsig(int i)478 static void recsig(int i)
479 {
480     longjmp(save, 1);
481 # ifdef LINT
482     i = i;
483 # endif
484 }
485 
486 # ifdef OPENSSL_SYS_MSDOS
noecho_fgets(char * buf,int size,FILE * tty)487 static int noecho_fgets(char *buf, int size, FILE *tty)
488 {
489     int i;
490     char *p;
491 
492     p = buf;
493     for (;;) {
494         if (size == 0) {
495             *p = '\0';
496             break;
497         }
498         size--;
499 #  ifdef WIN16TTY
500         i = _inchar();
501 #  else
502         i = getch();
503 #  endif
504         if (i == '\r')
505             i = '\n';
506         *(p++) = i;
507         if (i == '\n') {
508             *p = '\0';
509             break;
510         }
511     }
512 #  ifdef WIN_CONSOLE_BUG
513     /*
514      * Win95 has several evil console bugs: one of these is that the last
515      * character read using getch() is passed to the next read: this is
516      * usually a CR so this can be trouble. No STDIO fix seems to work but
517      * flushing the console appears to do the trick.
518      */
519     {
520         HANDLE inh;
521         inh = GetStdHandle(STD_INPUT_HANDLE);
522         FlushConsoleInputBuffer(inh);
523     }
524 #  endif
525     return (strlen(buf));
526 }
527 # endif
528 #endif                          /* !OPENSSL_SYS_WINCE && !WIN16 */
529