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