read_pwd.c revision 296341
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