read_pwd.c revision 296465
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>
185struct 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
205static void read_till_nl(FILE *);
206static void recsig(int);
207static void pushsig(void);
208static void popsig(void);
209#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN16)
210static int noecho_fgets(char *buf, int size, FILE *tty);
211#endif
212#ifdef SIGACTION
213static struct sigaction savsig[NX509_SIG];
214#else
215static void (*savsig[NX509_SIG]) (int);
216#endif
217static jmp_buf save;
218
219int 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
233int 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
243int 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
252static 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 */
263int 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
431static 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
462static 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
483static void recsig(int i)
484{
485    longjmp(save, 1);
486# ifdef LINT
487    i = i;
488# endif
489}
490
491# ifdef OPENSSL_SYS_MSDOS
492static 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 */
534