xref: /freebsd/contrib/libarchive/libarchive_fe/passphrase.c (revision e64fe029e9d3ce476e77a478318e0c3cd201ff08)
1cdf63a70SMartin Matuska /*-
2cdf63a70SMartin Matuska  * Copyright (c) 2014 Michihiro NAKAJIMA
3cdf63a70SMartin Matuska  * All rights reserved.
4cdf63a70SMartin Matuska  *
5cdf63a70SMartin Matuska  * Redistribution and use in source and binary forms, with or without
6cdf63a70SMartin Matuska  * modification, are permitted provided that the following conditions
7cdf63a70SMartin Matuska  * are met:
8cdf63a70SMartin Matuska  * 1. Redistributions of source code must retain the above copyright
9cdf63a70SMartin Matuska  *    notice, this list of conditions and the following disclaimer
10cdf63a70SMartin Matuska  *    in this position and unchanged.
11cdf63a70SMartin Matuska  * 2. Redistributions in binary form must reproduce the above copyright
12cdf63a70SMartin Matuska  *    notice, this list of conditions and the following disclaimer in the
13cdf63a70SMartin Matuska  *    documentation and/or other materials provided with the distribution.
14cdf63a70SMartin Matuska  *
15cdf63a70SMartin Matuska  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16cdf63a70SMartin Matuska  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17cdf63a70SMartin Matuska  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18cdf63a70SMartin Matuska  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19cdf63a70SMartin Matuska  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20cdf63a70SMartin Matuska  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21cdf63a70SMartin Matuska  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22cdf63a70SMartin Matuska  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23cdf63a70SMartin Matuska  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24cdf63a70SMartin Matuska  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25cdf63a70SMartin Matuska  */
26fae5c36eSMartin Matuska /*	$OpenBSD: readpassphrase.c,v 1.27 2019/01/25 00:19:25 millert Exp $	*/
27fae5c36eSMartin Matuska 
28cdf63a70SMartin Matuska /*
29fae5c36eSMartin Matuska  * Copyright (c) 2000-2002, 2007, 2010
30fae5c36eSMartin Matuska  * 	Todd C. Miller <millert@openbsd.org>
31cdf63a70SMartin Matuska  *
32cdf63a70SMartin Matuska  * Permission to use, copy, modify, and distribute this software for any
33cdf63a70SMartin Matuska  * purpose with or without fee is hereby granted, provided that the above
34cdf63a70SMartin Matuska  * copyright notice and this permission notice appear in all copies.
35cdf63a70SMartin Matuska  *
36cdf63a70SMartin Matuska  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
37cdf63a70SMartin Matuska  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
38cdf63a70SMartin Matuska  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
39cdf63a70SMartin Matuska  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
40cdf63a70SMartin Matuska  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
41cdf63a70SMartin Matuska  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
42cdf63a70SMartin Matuska  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
43cdf63a70SMartin Matuska  *
44cdf63a70SMartin Matuska  * Sponsored in part by the Defense Advanced Research Projects
45cdf63a70SMartin Matuska  * Agency (DARPA) and Air Force Research Laboratory, Air Force
46cdf63a70SMartin Matuska  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
47cdf63a70SMartin Matuska  */
48cdf63a70SMartin Matuska 
49cdf63a70SMartin Matuska /* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */
50cdf63a70SMartin Matuska 
51cdf63a70SMartin Matuska 
52cdf63a70SMartin Matuska #include "lafe_platform.h"
53cdf63a70SMartin Matuska __FBSDID("$FreeBSD$");
54cdf63a70SMartin Matuska 
55cdf63a70SMartin Matuska #include <errno.h>
56cdf63a70SMartin Matuska #ifdef HAVE_STDLIB_H
57cdf63a70SMartin Matuska #include <stdlib.h>
58cdf63a70SMartin Matuska #endif
59cdf63a70SMartin Matuska #ifdef HAVE_UNISTD_H
60cdf63a70SMartin Matuska #include <unistd.h>
61cdf63a70SMartin Matuska #endif
62cdf63a70SMartin Matuska #ifdef HAVE_READPASSPHRASE_H
63cdf63a70SMartin Matuska #include <readpassphrase.h>
64cdf63a70SMartin Matuska #endif
65cdf63a70SMartin Matuska 
66cdf63a70SMartin Matuska #include "err.h"
67cdf63a70SMartin Matuska #include "passphrase.h"
68cdf63a70SMartin Matuska 
69cdf63a70SMartin Matuska #ifndef HAVE_READPASSPHRASE
70cdf63a70SMartin Matuska 
71cdf63a70SMartin Matuska #define RPP_ECHO_OFF    0x00		/* Turn off echo (default). */
72cdf63a70SMartin Matuska #define RPP_ECHO_ON     0x01		/* Leave echo on. */
73cdf63a70SMartin Matuska #define RPP_REQUIRE_TTY 0x02		/* Fail if there is no tty. */
74cdf63a70SMartin Matuska #define RPP_FORCELOWER  0x04		/* Force input to lower case. */
75cdf63a70SMartin Matuska #define RPP_FORCEUPPER  0x08		/* Force input to upper case. */
76cdf63a70SMartin Matuska #define RPP_SEVENBIT    0x10		/* Strip the high bit from input. */
77cdf63a70SMartin Matuska #define RPP_STDIN       0x20		/* Read from stdin, not /dev/tty */
78cdf63a70SMartin Matuska 
79cdf63a70SMartin Matuska 
80cdf63a70SMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__)
81cdf63a70SMartin Matuska #include <windows.h>
82cdf63a70SMartin Matuska 
83cdf63a70SMartin Matuska static char *
84cdf63a70SMartin Matuska readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
85cdf63a70SMartin Matuska {
86cdf63a70SMartin Matuska 	HANDLE hStdin, hStdout;
87cdf63a70SMartin Matuska 	DWORD mode, rbytes;
88cdf63a70SMartin Matuska 	BOOL success;
89cdf63a70SMartin Matuska 
90cdf63a70SMartin Matuska 	(void)flags;
91cdf63a70SMartin Matuska 
92cdf63a70SMartin Matuska 	hStdin = GetStdHandle(STD_INPUT_HANDLE);
93cdf63a70SMartin Matuska 	if (hStdin == INVALID_HANDLE_VALUE)
94cdf63a70SMartin Matuska 		return (NULL);
95cdf63a70SMartin Matuska 	hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
96cdf63a70SMartin Matuska 	if (hStdout == INVALID_HANDLE_VALUE)
97cdf63a70SMartin Matuska 		return (NULL);
98cdf63a70SMartin Matuska 
99cdf63a70SMartin Matuska 	success = GetConsoleMode(hStdin, &mode);
100cdf63a70SMartin Matuska 	if (!success)
101cdf63a70SMartin Matuska 		return (NULL);
102cdf63a70SMartin Matuska 	mode &= ~ENABLE_ECHO_INPUT;
103cdf63a70SMartin Matuska 	mode |= ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT;
104cdf63a70SMartin Matuska 	success = SetConsoleMode(hStdin, mode);
105cdf63a70SMartin Matuska 	if (!success)
106cdf63a70SMartin Matuska 		return (NULL);
107cdf63a70SMartin Matuska 
108cdf63a70SMartin Matuska 	success = WriteFile(hStdout, prompt, (DWORD)strlen(prompt),
109cdf63a70SMartin Matuska 		NULL, NULL);
110cdf63a70SMartin Matuska 	if (!success)
111cdf63a70SMartin Matuska 		return (NULL);
112cdf63a70SMartin Matuska 	success = ReadFile(hStdin, buf, (DWORD)bufsiz - 1, &rbytes, NULL);
113cdf63a70SMartin Matuska 	if (!success)
114cdf63a70SMartin Matuska 		return (NULL);
115cdf63a70SMartin Matuska 	WriteFile(hStdout, "\r\n", 2, NULL, NULL);
116cdf63a70SMartin Matuska 	buf[rbytes] = '\0';
117cdf63a70SMartin Matuska 	/* Remove trailing carriage return(s). */
118cdf63a70SMartin Matuska 	if (rbytes > 2 && buf[rbytes - 2] == '\r' && buf[rbytes - 1] == '\n')
119cdf63a70SMartin Matuska 		buf[rbytes - 2] = '\0';
120cdf63a70SMartin Matuska 
121cdf63a70SMartin Matuska 	return (buf);
122cdf63a70SMartin Matuska }
123cdf63a70SMartin Matuska 
124cdf63a70SMartin Matuska #else /* _WIN32 && !__CYGWIN__ */
125cdf63a70SMartin Matuska 
126f061a221SMartin Matuska #include <assert.h>
127cdf63a70SMartin Matuska #include <ctype.h>
128cdf63a70SMartin Matuska #include <fcntl.h>
129cdf63a70SMartin Matuska #ifdef HAVE_PATHS_H
130cdf63a70SMartin Matuska #include <paths.h>
131cdf63a70SMartin Matuska #endif
132f061a221SMartin Matuska #include <signal.h>
133cdf63a70SMartin Matuska #include <string.h>
134f061a221SMartin Matuska #include <termios.h>
135cdf63a70SMartin Matuska #include <unistd.h>
136cdf63a70SMartin Matuska 
137ae5876eaSMartin Matuska #ifndef _PATH_TTY
138ae5876eaSMartin Matuska #define _PATH_TTY "/dev/tty"
139ae5876eaSMartin Matuska #endif
140ae5876eaSMartin Matuska 
141cdf63a70SMartin Matuska #ifdef TCSASOFT
142cdf63a70SMartin Matuska # define _T_FLUSH	(TCSAFLUSH|TCSASOFT)
143cdf63a70SMartin Matuska #else
144cdf63a70SMartin Matuska # define _T_FLUSH	(TCSAFLUSH)
145cdf63a70SMartin Matuska #endif
146cdf63a70SMartin Matuska 
147cdf63a70SMartin Matuska /* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
148cdf63a70SMartin Matuska #if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
149cdf63a70SMartin Matuska #  define _POSIX_VDISABLE       VDISABLE
150cdf63a70SMartin Matuska #endif
151cdf63a70SMartin Matuska 
152f061a221SMartin Matuska #define M(a,b) (a > b ? a : b)
153f061a221SMartin Matuska #define MAX_SIGNO M(M(M(SIGALRM, SIGHUP), \
154f061a221SMartin Matuska                       M(SIGINT, SIGPIPE)), \
155f061a221SMartin Matuska                     M(M(SIGQUIT, SIGTERM), \
156f061a221SMartin Matuska                       M(M(SIGTSTP, SIGTTIN), SIGTTOU)))
157f061a221SMartin Matuska 
158f061a221SMartin Matuska static volatile sig_atomic_t signo[MAX_SIGNO + 1];
159cdf63a70SMartin Matuska 
160cdf63a70SMartin Matuska static void
161cdf63a70SMartin Matuska handler(int s)
162cdf63a70SMartin Matuska {
163f061a221SMartin Matuska 	assert(s <= MAX_SIGNO);
164cdf63a70SMartin Matuska 	signo[s] = 1;
165cdf63a70SMartin Matuska }
166cdf63a70SMartin Matuska 
167cdf63a70SMartin Matuska static char *
168cdf63a70SMartin Matuska readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
169cdf63a70SMartin Matuska {
170cdf63a70SMartin Matuska 	ssize_t nr;
171cdf63a70SMartin Matuska 	int input, output, save_errno, i, need_restart;
172cdf63a70SMartin Matuska 	char ch, *p, *end;
173cdf63a70SMartin Matuska 	struct termios term, oterm;
174*e64fe029SMartin Matuska #ifdef HAVE_SIGACTION
175cdf63a70SMartin Matuska 	struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
176cdf63a70SMartin Matuska 	struct sigaction savetstp, savettin, savettou, savepipe;
177*e64fe029SMartin Matuska #endif
178cdf63a70SMartin Matuska 
179cdf63a70SMartin Matuska 	/* I suppose we could alloc on demand in this case (XXX). */
180cdf63a70SMartin Matuska 	if (bufsiz == 0) {
181cdf63a70SMartin Matuska 		errno = EINVAL;
182cdf63a70SMartin Matuska 		return(NULL);
183cdf63a70SMartin Matuska 	}
184cdf63a70SMartin Matuska 
185cdf63a70SMartin Matuska restart:
186f061a221SMartin Matuska 	for (i = 0; i <= MAX_SIGNO; i++)
187cdf63a70SMartin Matuska 		signo[i] = 0;
188cdf63a70SMartin Matuska 	nr = -1;
189cdf63a70SMartin Matuska 	save_errno = 0;
190cdf63a70SMartin Matuska 	need_restart = 0;
191cdf63a70SMartin Matuska 	/*
192cdf63a70SMartin Matuska 	 * Read and write to /dev/tty if available.  If not, read from
193cdf63a70SMartin Matuska 	 * stdin and write to stderr unless a tty is required.
194cdf63a70SMartin Matuska 	 */
195cdf63a70SMartin Matuska 	if ((flags & RPP_STDIN) ||
196cdf63a70SMartin Matuska 	    (input = output = open(_PATH_TTY, O_RDWR)) == -1) {
197cdf63a70SMartin Matuska 		if (flags & RPP_REQUIRE_TTY) {
198cdf63a70SMartin Matuska 			errno = ENOTTY;
199cdf63a70SMartin Matuska 			return(NULL);
200cdf63a70SMartin Matuska 		}
201cdf63a70SMartin Matuska 		input = STDIN_FILENO;
202cdf63a70SMartin Matuska 		output = STDERR_FILENO;
203cdf63a70SMartin Matuska 	}
204cdf63a70SMartin Matuska 
205cdf63a70SMartin Matuska 	/*
206fae5c36eSMartin Matuska 	 * Turn off echo if possible.
207fae5c36eSMartin Matuska 	 * If we are using a tty but are not the foreground pgrp this will
208fae5c36eSMartin Matuska 	 * generate SIGTTOU, so do it *before* installing the signal handlers.
209fae5c36eSMartin Matuska 	 */
210fae5c36eSMartin Matuska 	if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
211fae5c36eSMartin Matuska 		memcpy(&term, &oterm, sizeof(term));
212fae5c36eSMartin Matuska 		if (!(flags & RPP_ECHO_ON))
213fae5c36eSMartin Matuska 			term.c_lflag &= ~(ECHO | ECHONL);
214fae5c36eSMartin Matuska #ifdef VSTATUS
215fae5c36eSMartin Matuska 		if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
216fae5c36eSMartin Matuska 			term.c_cc[VSTATUS] = _POSIX_VDISABLE;
217fae5c36eSMartin Matuska #endif
218fae5c36eSMartin Matuska 		(void)tcsetattr(input, _T_FLUSH, &term);
219fae5c36eSMartin Matuska 	} else {
220fae5c36eSMartin Matuska 		memset(&term, 0, sizeof(term));
221fae5c36eSMartin Matuska 		term.c_lflag |= ECHO;
222fae5c36eSMartin Matuska 		memset(&oterm, 0, sizeof(oterm));
223fae5c36eSMartin Matuska 		oterm.c_lflag |= ECHO;
224fae5c36eSMartin Matuska 	}
225fae5c36eSMartin Matuska 
226*e64fe029SMartin Matuska #ifdef HAVE_SIGACTION
227fae5c36eSMartin Matuska 	/*
228cdf63a70SMartin Matuska 	 * Catch signals that would otherwise cause the user to end
229cdf63a70SMartin Matuska 	 * up with echo turned off in the shell.  Don't worry about
230cdf63a70SMartin Matuska 	 * things like SIGXCPU and SIGVTALRM for now.
231cdf63a70SMartin Matuska 	 */
232cdf63a70SMartin Matuska 	sigemptyset(&sa.sa_mask);
233cdf63a70SMartin Matuska 	sa.sa_flags = 0;		/* don't restart system calls */
234cdf63a70SMartin Matuska 	sa.sa_handler = handler;
235f061a221SMartin Matuska 	/* Keep this list in sync with MAX_SIGNO! */
236cdf63a70SMartin Matuska 	(void)sigaction(SIGALRM, &sa, &savealrm);
237cdf63a70SMartin Matuska 	(void)sigaction(SIGHUP, &sa, &savehup);
238cdf63a70SMartin Matuska 	(void)sigaction(SIGINT, &sa, &saveint);
239cdf63a70SMartin Matuska 	(void)sigaction(SIGPIPE, &sa, &savepipe);
240cdf63a70SMartin Matuska 	(void)sigaction(SIGQUIT, &sa, &savequit);
241cdf63a70SMartin Matuska 	(void)sigaction(SIGTERM, &sa, &saveterm);
242cdf63a70SMartin Matuska 	(void)sigaction(SIGTSTP, &sa, &savetstp);
243cdf63a70SMartin Matuska 	(void)sigaction(SIGTTIN, &sa, &savettin);
244cdf63a70SMartin Matuska 	(void)sigaction(SIGTTOU, &sa, &savettou);
245*e64fe029SMartin Matuska #endif
246cdf63a70SMartin Matuska 
247cdf63a70SMartin Matuska 	if (!(flags & RPP_STDIN)) {
248cdf63a70SMartin Matuska 		int r = write(output, prompt, strlen(prompt));
249cdf63a70SMartin Matuska 		(void)r;
250cdf63a70SMartin Matuska 	}
251cdf63a70SMartin Matuska 	end = buf + bufsiz - 1;
252cdf63a70SMartin Matuska 	p = buf;
253cdf63a70SMartin Matuska 	while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
254cdf63a70SMartin Matuska 		if (p < end) {
255cdf63a70SMartin Matuska 			if ((flags & RPP_SEVENBIT))
256cdf63a70SMartin Matuska 				ch &= 0x7f;
257f061a221SMartin Matuska 			if (isalpha((unsigned char)ch)) {
258cdf63a70SMartin Matuska 				if ((flags & RPP_FORCELOWER))
259f061a221SMartin Matuska 					ch = (char)tolower((unsigned char)ch);
260cdf63a70SMartin Matuska 				if ((flags & RPP_FORCEUPPER))
261f061a221SMartin Matuska 					ch = (char)toupper((unsigned char)ch);
262cdf63a70SMartin Matuska 			}
263cdf63a70SMartin Matuska 			*p++ = ch;
264cdf63a70SMartin Matuska 		}
265cdf63a70SMartin Matuska 	}
266cdf63a70SMartin Matuska 	*p = '\0';
267cdf63a70SMartin Matuska 	save_errno = errno;
268cdf63a70SMartin Matuska 	if (!(term.c_lflag & ECHO)) {
269cdf63a70SMartin Matuska 		int r = write(output, "\n", 1);
270cdf63a70SMartin Matuska 		(void)r;
271cdf63a70SMartin Matuska 	}
272cdf63a70SMartin Matuska 
273cdf63a70SMartin Matuska 	/* Restore old terminal settings and signals. */
274cdf63a70SMartin Matuska 	if (memcmp(&term, &oterm, sizeof(term)) != 0) {
275fae5c36eSMartin Matuska 		const int sigttou = signo[SIGTTOU];
276fae5c36eSMartin Matuska 
277fae5c36eSMartin Matuska 		/* Ignore SIGTTOU generated when we are not the fg pgrp. */
278cdf63a70SMartin Matuska 		while (tcsetattr(input, _T_FLUSH, &oterm) == -1 &&
279fae5c36eSMartin Matuska 		    errno == EINTR && !signo[SIGTTOU])
280cdf63a70SMartin Matuska 			continue;
281fae5c36eSMartin Matuska 		signo[SIGTTOU] = sigttou;
282cdf63a70SMartin Matuska 	}
283*e64fe029SMartin Matuska #ifdef HAVE_SIGACTION
284cdf63a70SMartin Matuska 	(void)sigaction(SIGALRM, &savealrm, NULL);
285cdf63a70SMartin Matuska 	(void)sigaction(SIGHUP, &savehup, NULL);
286cdf63a70SMartin Matuska 	(void)sigaction(SIGINT, &saveint, NULL);
287cdf63a70SMartin Matuska 	(void)sigaction(SIGQUIT, &savequit, NULL);
288cdf63a70SMartin Matuska 	(void)sigaction(SIGPIPE, &savepipe, NULL);
289cdf63a70SMartin Matuska 	(void)sigaction(SIGTERM, &saveterm, NULL);
290cdf63a70SMartin Matuska 	(void)sigaction(SIGTSTP, &savetstp, NULL);
291cdf63a70SMartin Matuska 	(void)sigaction(SIGTTIN, &savettin, NULL);
292cdf63a70SMartin Matuska 	(void)sigaction(SIGTTOU, &savettou, NULL);
293*e64fe029SMartin Matuska #endif
294cdf63a70SMartin Matuska 	if (input != STDIN_FILENO)
295cdf63a70SMartin Matuska 		(void)close(input);
296cdf63a70SMartin Matuska 
297cdf63a70SMartin Matuska 	/*
298cdf63a70SMartin Matuska 	 * If we were interrupted by a signal, resend it to ourselves
299cdf63a70SMartin Matuska 	 * now that we have restored the signal handlers.
300cdf63a70SMartin Matuska 	 */
301f061a221SMartin Matuska 	for (i = 0; i <= MAX_SIGNO; i++) {
302cdf63a70SMartin Matuska 		if (signo[i]) {
303cdf63a70SMartin Matuska 			kill(getpid(), i);
304cdf63a70SMartin Matuska 			switch (i) {
305cdf63a70SMartin Matuska 			case SIGTSTP:
306cdf63a70SMartin Matuska 			case SIGTTIN:
307cdf63a70SMartin Matuska 			case SIGTTOU:
308cdf63a70SMartin Matuska 				need_restart = 1;
309cdf63a70SMartin Matuska 			}
310cdf63a70SMartin Matuska 		}
311cdf63a70SMartin Matuska 	}
312cdf63a70SMartin Matuska 	if (need_restart)
313cdf63a70SMartin Matuska 		goto restart;
314cdf63a70SMartin Matuska 
315cdf63a70SMartin Matuska 	if (save_errno)
316cdf63a70SMartin Matuska 		errno = save_errno;
317cdf63a70SMartin Matuska 	return(nr == -1 ? NULL : buf);
318cdf63a70SMartin Matuska }
319cdf63a70SMartin Matuska #endif /* _WIN32 && !__CYGWIN__ */
320cdf63a70SMartin Matuska #endif /* HAVE_READPASSPHRASE */
321cdf63a70SMartin Matuska 
322cdf63a70SMartin Matuska char *
323cdf63a70SMartin Matuska lafe_readpassphrase(const char *prompt, char *buf, size_t bufsiz)
324cdf63a70SMartin Matuska {
325cdf63a70SMartin Matuska 	char *p;
326cdf63a70SMartin Matuska 
327cdf63a70SMartin Matuska 	p = readpassphrase(prompt, buf, bufsiz, RPP_ECHO_OFF);
328cdf63a70SMartin Matuska 	if (p == NULL) {
329cdf63a70SMartin Matuska 		switch (errno) {
330cdf63a70SMartin Matuska 		case EINTR:
331cdf63a70SMartin Matuska 			break;
332cdf63a70SMartin Matuska 		default:
333cdf63a70SMartin Matuska 			lafe_errc(1, errno, "Couldn't read passphrase");
334cdf63a70SMartin Matuska 			break;
335cdf63a70SMartin Matuska 		}
336cdf63a70SMartin Matuska 	}
337cdf63a70SMartin Matuska 	return (p);
338cdf63a70SMartin Matuska }
339cdf63a70SMartin Matuska 
340