/* readpass.c Author: Tatu Ylonen Copyright (c) 1995 Tatu Ylonen , Espoo, Finland All rights reserved Created: Mon Jul 10 22:08:59 1995 ylo Functions for reading passphrases and passwords. */ #include "includes.h" RCSID("$Id: readpass.c,v 1.4 1999/10/11 20:24:54 markus Exp $"); #include "xmalloc.h" #include "ssh.h" /* Saved old terminal mode for read_passphrase. */ static struct termios saved_tio; /* Old interrupt signal handler for read_passphrase. */ static void (*old_handler)(int sig) = NULL; /* Interrupt signal handler for read_passphrase. */ void intr_handler(int sig) { /* Restore terminal modes. */ tcsetattr(fileno(stdin), TCSANOW, &saved_tio); /* Restore the old signal handler. */ signal(sig, old_handler); /* Resend the signal, with the old handler. */ kill(getpid(), sig); } /* Reads a passphrase from /dev/tty with echo turned off. Returns the passphrase (allocated with xmalloc). Exits if EOF is encountered. The passphrase if read from stdin if from_stdin is true (as is the case with ssh-keygen). */ char *read_passphrase(const char *prompt, int from_stdin) { char buf[1024], *cp; struct termios tio; FILE *f; if (from_stdin) f = stdin; else { /* Read the passphrase from /dev/tty to make it possible to ask it even when stdin has been redirected. */ f = fopen("/dev/tty", "r"); if (!f) { /* No controlling terminal and no DISPLAY. Nowhere to read. */ fprintf(stderr, "You have no controlling tty and no DISPLAY. Cannot read passphrase.\n"); exit(1); } } /* Display the prompt (on stderr because stdout might be redirected). */ fflush(stdout); fprintf(stderr, "%s", prompt); fflush(stderr); /* Get terminal modes. */ tcgetattr(fileno(f), &tio); saved_tio = tio; /* Save signal handler and set the new handler. */ old_handler = signal(SIGINT, intr_handler); /* Set new terminal modes disabling all echo. */ tio.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); tcsetattr(fileno(f), TCSANOW, &tio); /* Read the passphrase from the terminal. */ if (fgets(buf, sizeof(buf), f) == NULL) { /* Got EOF. Just exit. */ /* Restore terminal modes. */ tcsetattr(fileno(f), TCSANOW, &saved_tio); /* Restore the signal handler. */ signal(SIGINT, old_handler); /* Print a newline (the prompt probably didn\'t have one). */ fprintf(stderr, "\n"); /* Close the file. */ if (f != stdin) fclose(f); exit(1); } /* Restore terminal modes. */ tcsetattr(fileno(f), TCSANOW, &saved_tio); /* Restore the signal handler. */ (void)signal(SIGINT, old_handler); /* Remove newline from the passphrase. */ if (strchr(buf, '\n')) *strchr(buf, '\n') = 0; /* Allocate a copy of the passphrase. */ cp = xstrdup(buf); /* Clear the buffer so we don\'t leave copies of the passphrase laying around. */ memset(buf, 0, sizeof(buf)); /* Print a newline since the prompt probably didn\'t have one. */ fprintf(stderr, "\n"); /* Close the file. */ if (f != stdin) fclose(f); return cp; }