Annotation of src/usr.bin/ssh/readpassphrase.c, Revision 1.1.2.1
1.1.2.1 ! miod 1: /*
! 2: * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com>
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: * 3. The name of the author may not be used to endorse or promote products
! 14: * derived from this software without specific prior written permission.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! 17: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
! 18: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
! 19: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 20: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 21: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 22: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 23: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 24: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 25: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 26: */
! 27:
! 28: #if defined(LIBC_SCCS) && !defined(lint)
! 29: static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.7 2001/08/07 19:34:11 millert Exp $";
! 30: #endif /* LIBC_SCCS and not lint */
! 31:
! 32: #include <ctype.h>
! 33: #include <errno.h>
! 34: #include <fcntl.h>
! 35: #include <paths.h>
! 36: #include <pwd.h>
! 37: #include <signal.h>
! 38: #include <string.h>
! 39: #include <termios.h>
! 40: #include <unistd.h>
! 41: #include <readpassphrase.h>
! 42:
! 43: char *
! 44: readpassphrase(prompt, buf, bufsiz, flags)
! 45: const char *prompt;
! 46: char *buf;
! 47: size_t bufsiz;
! 48: int flags;
! 49: {
! 50: struct termios term, oterm;
! 51: char ch, *p, *end;
! 52: int input, output;
! 53: sigset_t oset, nset;
! 54:
! 55: /* I suppose we could alloc on demand in this case (XXX). */
! 56: if (bufsiz == 0) {
! 57: errno = EINVAL;
! 58: return(NULL);
! 59: }
! 60:
! 61: /*
! 62: * Read and write to /dev/tty if available. If not, read from
! 63: * stdin and write to stderr unless a tty is required.
! 64: */
! 65: if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) {
! 66: if (flags & RPP_REQUIRE_TTY) {
! 67: errno = ENOTTY;
! 68: return(NULL);
! 69: }
! 70: input = STDIN_FILENO;
! 71: output = STDERR_FILENO;
! 72: }
! 73:
! 74: /*
! 75: * We block SIGINT and SIGTSTP so the terminal is not left
! 76: * in an inconsistent state (ie: no echo). It would probably
! 77: * be better to simply catch these though.
! 78: */
! 79: sigemptyset(&nset);
! 80: sigaddset(&nset, SIGINT);
! 81: sigaddset(&nset, SIGTSTP);
! 82: (void)sigprocmask(SIG_BLOCK, &nset, &oset);
! 83:
! 84: /* Turn off echo if possible. */
! 85: if (tcgetattr(input, &oterm) == 0) {
! 86: memcpy(&term, &oterm, sizeof(term));
! 87: if (!(flags & RPP_ECHO_ON) && (term.c_lflag & ECHO))
! 88: term.c_lflag &= ~ECHO;
! 89: if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
! 90: term.c_cc[VSTATUS] = _POSIX_VDISABLE;
! 91: (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
! 92: } else {
! 93: memset(&term, 0, sizeof(term));
! 94: memset(&oterm, 0, sizeof(oterm));
! 95: }
! 96:
! 97: (void)write(output, prompt, strlen(prompt));
! 98: end = buf + bufsiz - 1;
! 99: for (p = buf; read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) {
! 100: if (p < end) {
! 101: if ((flags & RPP_SEVENBIT))
! 102: ch &= 0x7f;
! 103: if (isalpha(ch)) {
! 104: if ((flags & RPP_FORCELOWER))
! 105: ch = tolower(ch);
! 106: if ((flags & RPP_FORCEUPPER))
! 107: ch = toupper(ch);
! 108: }
! 109: *p++ = ch;
! 110: }
! 111: }
! 112: *p = '\0';
! 113: if (!(term.c_lflag & ECHO))
! 114: (void)write(output, "\n", 1);
! 115:
! 116: /* Restore old terminal settings and signal mask. */
! 117: if (memcmp(&term, &oterm, sizeof(term)) != 0)
! 118: (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm);
! 119: (void)sigprocmask(SIG_SETMASK, &oset, NULL);
! 120: if (input != STDIN_FILENO)
! 121: (void)close(input);
! 122: return(buf);
! 123: }
! 124:
! 125: char *
! 126: getpass(prompt)
! 127: const char *prompt;
! 128: {
! 129: static char buf[_PASSWORD_LEN + 1];
! 130:
! 131: return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
! 132: }