1bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* $OpenBSD: readpassphrase.c,v 1.22 2010/01/13 10:20:54 dtucker Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2000-2002, 2007 Todd C. Miller <Todd.Miller@courtesan.com> 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Permission to use, copy, modify, and distribute this software for any 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * purpose with or without fee is hereby granted, provided that the above 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * copyright notice and this permission notice appear in all copies. 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Sponsored in part by the Defense Advanced Research Projects 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Agency (DARPA) and Air Force Research Laboratory, Air Force 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Materiel Command, USAF, under agreement number F39502-99-1-0512. 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */ 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifndef HAVE_READPASSPHRASE 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <termios.h> 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <signal.h> 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <ctype.h> 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h> 33d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <readpassphrase.h> 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h> 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef TCSASOFT 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# define _T_FLUSH (TCSAFLUSH|TCSASOFT) 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# define _T_FLUSH (TCSAFLUSH) 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */ 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if !defined(_POSIX_VDISABLE) && defined(VDISABLE) 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# define _POSIX_VDISABLE VDISABLE 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 49d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifndef _NSIG 50d059297112922cabb0c674840589be8db821fd9aAdam Langley# ifdef NSIG 51d059297112922cabb0c674840589be8db821fd9aAdam Langley# define _NSIG NSIG 52d059297112922cabb0c674840589be8db821fd9aAdam Langley# else 53d059297112922cabb0c674840589be8db821fd9aAdam Langley# define _NSIG 128 54d059297112922cabb0c674840589be8db821fd9aAdam Langley# endif 55d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 56d059297112922cabb0c674840589be8db821fd9aAdam Langley 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic volatile sig_atomic_t signo[_NSIG]; 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void handler(int); 60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanreadpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ssize_t nr; 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int input, output, save_errno, i, need_restart; 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char ch, *p, *end; 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct termios term, oterm; 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm; 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct sigaction savetstp, savettin, savettou, savepipe; 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* I suppose we could alloc on demand in this case (XXX). */ 72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (bufsiz == 0) { 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = EINVAL; 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return(NULL); 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanrestart: 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < _NSIG; i++) 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signo[i] = 0; 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nr = -1; 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman save_errno = 0; 82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman need_restart = 0; 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Read and write to /dev/tty if available. If not, read from 85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * stdin and write to stderr unless a tty is required. 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((flags & RPP_STDIN) || 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (input = output = open(_PATH_TTY, O_RDWR)) == -1) { 89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (flags & RPP_REQUIRE_TTY) { 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = ENOTTY; 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return(NULL); 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman input = STDIN_FILENO; 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman output = STDERR_FILENO; 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Catch signals that would otherwise cause the user to end 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * up with echo turned off in the shell. Don't worry about 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * things like SIGXCPU and SIGVTALRM for now. 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sigemptyset(&sa.sa_mask); 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sa.sa_flags = 0; /* don't restart system calls */ 104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sa.sa_handler = handler; 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGALRM, &sa, &savealrm); 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGHUP, &sa, &savehup); 107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGINT, &sa, &saveint); 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGPIPE, &sa, &savepipe); 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGQUIT, &sa, &savequit); 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTERM, &sa, &saveterm); 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTSTP, &sa, &savetstp); 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTTIN, &sa, &savettin); 113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTTOU, &sa, &savettou); 114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Turn off echo if possible. */ 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) { 117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memcpy(&term, &oterm, sizeof(term)); 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(flags & RPP_ECHO_ON)) 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman term.c_lflag &= ~(ECHO | ECHONL); 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef VSTATUS 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman term.c_cc[VSTATUS] = _POSIX_VDISABLE; 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)tcsetattr(input, _T_FLUSH, &term); 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(&term, 0, sizeof(term)); 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman term.c_lflag |= ECHO; 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(&oterm, 0, sizeof(oterm)); 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman oterm.c_lflag |= ECHO; 130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* No I/O if we are already backgrounded. */ 133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (signo[SIGTTOU] != 1 && signo[SIGTTIN] != 1) { 134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(flags & RPP_STDIN)) 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)write(output, prompt, strlen(prompt)); 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman end = buf + bufsiz - 1; 137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman p = buf; 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') { 139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (p < end) { 140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((flags & RPP_SEVENBIT)) 141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ch &= 0x7f; 142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (isalpha(ch)) { 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((flags & RPP_FORCELOWER)) 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ch = (char)tolower(ch); 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((flags & RPP_FORCEUPPER)) 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ch = (char)toupper(ch); 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *p++ = ch; 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *p = '\0'; 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman save_errno = errno; 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!(term.c_lflag & ECHO)) 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)write(output, "\n", 1); 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Restore old terminal settings and signals. */ 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (memcmp(&term, &oterm, sizeof(term)) != 0) { 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (tcsetattr(input, _T_FLUSH, &oterm) == -1 && 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno == EINTR) 161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGALRM, &savealrm, NULL); 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGHUP, &savehup, NULL); 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGINT, &saveint, NULL); 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGQUIT, &savequit, NULL); 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGPIPE, &savepipe, NULL); 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTERM, &saveterm, NULL); 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTSTP, &savetstp, NULL); 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTTIN, &savettin, NULL); 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)sigaction(SIGTTOU, &savettou, NULL); 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (input != STDIN_FILENO) 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)close(input); 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * If we were interrupted by a signal, resend it to ourselves 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * now that we have restored the signal handlers. 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < _NSIG; i++) { 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (signo[i]) { 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman kill(getpid(), i); 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (i) { 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SIGTSTP: 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SIGTTIN: 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SIGTTOU: 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman need_restart = 1; 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (need_restart) 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto restart; 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (save_errno) 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno = save_errno; 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return(nr == -1 ? NULL : buf); 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if 0 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar * 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmangetpass(const char *prompt) 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static char buf[_PASSWORD_LEN + 1]; 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void handler(int s) 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signo[s] = 1; 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* HAVE_READPASSPHRASE */ 214