diff options
-rw-r--r-- | include/readpassphrase.h | 46 | ||||
-rw-r--r-- | lib/libc/gen/getpass.3 | 3 | ||||
-rw-r--r-- | lib/libc/gen/getpass.c | 96 | ||||
-rw-r--r-- | lib/libc/gen/readpassphrase.3 | 115 | ||||
-rw-r--r-- | lib/libc/gen/readpassphrase.c | 128 |
5 files changed, 291 insertions, 97 deletions
diff --git a/include/readpassphrase.h b/include/readpassphrase.h new file mode 100644 index 00000000000..f32c464f75b --- /dev/null +++ b/include/readpassphrase.h @@ -0,0 +1,46 @@ +/* $OpenBSD: readpassphrase.h,v 1.1 2000/11/21 00:48:38 millert Exp $ */ + +/* + * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _READPASSPHRASE_H_ +#define _READPASSPHRASE_H_ + +#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */ +#define RPP_ECHO_ON 0x01 /* Leave echo on. */ +#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */ +#define RPP_FORCELOWER 0x04 /* Force input to lower case. */ +#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */ +#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */ + +#include <sys/cdefs.h> + +__BEGIN_DECLS +char * readpassphrase __P((const char *, char *, size_t, int)); +__END_DECLS + +#endif /* !_READPASSPHRASE_H_ */ diff --git a/lib/libc/gen/getpass.3 b/lib/libc/gen/getpass.3 index 70e84f592fe..b00f2d73299 100644 --- a/lib/libc/gen/getpass.3 +++ b/lib/libc/gen/getpass.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: getpass.3,v 1.6 1999/06/04 01:30:11 aaron Exp $ +.\" $OpenBSD: getpass.3,v 1.7 2000/11/21 00:48:37 millert Exp $ .\" .\" Copyright (c) 1989, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -74,6 +74,7 @@ returns a pointer to the null-terminated password. .El .Sh SEE ALSO .Xr crypt 3 +.Xr readpassphrase 3 .Sh HISTORY A .Fn getpass diff --git a/lib/libc/gen/getpass.c b/lib/libc/gen/getpass.c deleted file mode 100644 index 325c40c2b22..00000000000 --- a/lib/libc/gen/getpass.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char rcsid[] = "$OpenBSD: getpass.c,v 1.7 2000/01/13 19:36:21 millert Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <fcntl.h> -#include <paths.h> -#include <pwd.h> -#include <signal.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -char * -getpass(prompt) - const char *prompt; -{ - struct termios term; - char ch, *p; - int echo, input, output; - static char buf[_PASSWORD_LEN + 1]; - sigset_t oset, nset; - - /* - * Read and write to /dev/tty if possible; else read from - * stdin and write to stderr. - */ - if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) { - input = STDIN_FILENO; - output = STDERR_FILENO; - } - - /* - * Note - blocking signals isn't necessarily the - * right thing, but we leave it for now. - */ - sigemptyset(&nset); - sigaddset(&nset, SIGINT); - sigaddset(&nset, SIGTSTP); - (void)sigprocmask(SIG_BLOCK, &nset, &oset); - - /* Turn off echo if possible. */ - if (tcgetattr(input, &term) == 0 && (term.c_lflag & ECHO)) { - echo = 1; - term.c_lflag &= ~ECHO; - (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); - } else - echo = 0; - - (void)write(output, prompt, strlen(prompt)); - for (p = buf; read(input, &ch, 1) == 1 && ch != '\n';) - if (p < buf + _PASSWORD_LEN) - *p++ = ch; - *p = '\0'; - (void)write(output, "\n", 1); - if (echo) { - term.c_lflag |= ECHO; - (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); - } - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - if (input != STDIN_FILENO) - (void)close(input); - return(buf); -} diff --git a/lib/libc/gen/readpassphrase.3 b/lib/libc/gen/readpassphrase.3 new file mode 100644 index 00000000000..4d7018759a0 --- /dev/null +++ b/lib/libc/gen/readpassphrase.3 @@ -0,0 +1,115 @@ +.\" $OpenBSD: readpassphrase.3,v 1.1 2000/11/21 00:48:37 millert Exp $ +.\" +.\" Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd November 20, 2000 +.Dt READPASSPHRASE 3 +.Os +.Sh NAME +.Nm readpassphrase +.Nd get a passphrase from the user +.Sh SYNOPSIS +.Fd #include <readpassphrase.h> +.Ft char * +.Fn readpassphrase "const char *prompt" "char *buf" "size_t bufsiz" "int flags" +.Sh DESCRIPTION +The +.Fn readpassphrase +function displays a prompt to, and reads in a passphrase from, +.Pa /dev/tty . +If this file is inaccessible +and the +.Dv RPP_REQUIRE_TTY +flag is not set, +.Fn readpassphrase +displays the prompt on the standard error output and reads from the standard +input. In this case it is generally not possible to turn off echo. +.Pp +Up to +.Fa bufsiz +- 1 characters (one is for the NUL) are read into the provided buffer +.Fa buf . +Any additional +characters and the terminating newline (or return) character are discarded. +.Pp +.Fn readpassphrase +takes the following optional +.Fa flags : +.Pp +.Bd -literal -offset indent -compact +RPP_ECHO_OFF turn off echo (default behavior) +RPP_ECHO_ON leave echo on +RPP_REQUIRE_TTY fail if there is no tty +RPP_FORCELOWER force input to lower case +RPP_FORCEUPPER force input to upper case +RPP_SEVENBIT strip the high bit from input +.Ed +.Pp +The calling process should zero the passphrase as soon as possible to +avoid leaving the cleartext passphrase visible in the process's address +space. +.Sh RETURN VALUES +On success, +.Fn readpassphrase +returns a pointer to the NUL-terminated passphrase. If the +.Dv RPP_REQUIRE_TTY +flag is set and +.Pa /dev/tty +is inaccessible, +.Fn readpassphrase +returns the +.Dv NULL pointer. +.Sh EXAMPLES +The following code fragment will read a passphrase from +.Pa /dev/tty +into the buffer +.Fa passbuf. +.Bd -literal -offset indent +char passbuf[1024]; + +\&... + +if (readpassphrase("Response: ", passbuf, sizeof(passbuf), + RPP_REQUIRE_TTY) == NULL) + errx(1, "unable to read passphrase"); + +if (compare(transform(passbuf), epass) != 0) + errx(1, "bad passphrase"); + +\&... + +memset(passbuf, 0, sizeof(passbuf)); +.Sh FILES +.Bl -tag -width /dev/tty -compact +.It Pa /dev/tty +.El +.Sh SEE ALSO +.Xr getpass 3 +.Sh HISTORY +The +.Fn readpassphrase +function first appeared in +.Ox 2.9 . diff --git a/lib/libc/gen/readpassphrase.c b/lib/libc/gen/readpassphrase.c new file mode 100644 index 00000000000..8804dd4e8ad --- /dev/null +++ b/lib/libc/gen/readpassphrase.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.1 2000/11/21 00:48:37 millert Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <pwd.h> +#include <signal.h> +#include <string.h> +#include <termios.h> +#include <unistd.h> +#include <readpassphrase.h> + +char * +readpassphrase(prompt, buf, bufsiz, flags) + const char *prompt; + char *buf; + size_t bufsiz; + int flags; +{ + struct termios term; + char ch, *p, *end; + int echo, input, output; + sigset_t oset, nset; + + /* I suppose we could alloc on demand in this case (XXX). */ + if (bufsiz == 0) { + errno = EINVAL; + return(NULL); + } + + /* + * Read and write to /dev/tty if available. If not, read from + * stdin and write to stderr unless a tty is required. + */ + if ((input = output = open(_PATH_TTY, O_RDWR)) == -1) { + if (flags & RPP_REQUIRE_TTY) { + errno = ENOTTY; + return(NULL); + } + input = STDIN_FILENO; + output = STDERR_FILENO; + } + + /* + * We block SIGINT and SIGTSTP so the terminal is not left + * in an inconsistent state (ie: no echo). It would probably + * be better to simply catch these though. + */ + sigemptyset(&nset); + sigaddset(&nset, SIGINT); + sigaddset(&nset, SIGTSTP); + (void)sigprocmask(SIG_BLOCK, &nset, &oset); + + /* Turn off echo if possible. */ + echo = 0; + if (!(flags & RPP_ECHO_ON)) { + if (tcgetattr(input, &term) == 0 && (term.c_lflag & ECHO)) { + echo = 1; + term.c_lflag &= ~ECHO; + (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); + } + } + + (void)write(output, prompt, strlen(prompt)); + end = buf + bufsiz - 1; + for (p = buf; read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) { + if (p < end) { + if ((flags & RPP_SEVENBIT)) + ch = ch &= 0x7f; + if (isalpha(ch)) { + if ((flags & RPP_FORCELOWER)) + ch = tolower(ch); + if ((flags & RPP_FORCEUPPER)) + ch = toupper(ch); + } + *p++ = ch; + } + } + *p = '\0'; + (void)write(output, "\n", 1); + if (echo) { + term.c_lflag |= ECHO; + (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); + } + (void)sigprocmask(SIG_SETMASK, &oset, NULL); + if (input != STDIN_FILENO) + (void)close(input); + return(buf); +} + +char * +getpass(prompt) + const char *prompt; +{ + static char buf[_PASSWORD_LEN + 1]; + + return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); +} |