diff options
author | green <green@FreeBSD.org> | 2002-03-08 21:14:00 +0000 |
---|---|---|
committer | green <green@FreeBSD.org> | 2002-03-08 21:14:00 +0000 |
commit | e81a222988987c911063a4420ec7ec6521da4836 (patch) | |
tree | 36829c674b6805dcd4b99f5436746d023c60065b /lib/libc | |
parent | 3f54e70a538644a9a3b5f1162e911dde602bd4ff (diff) | |
download | FreeBSD-src-e81a222988987c911063a4420ec7ec6521da4836.zip FreeBSD-src-e81a222988987c911063a4420ec7ec6521da4836.tar.gz |
Update readpassphrase(3)to the latest revisions. Changes are mainly due
to return value constraints now changing as well as more intelligent
handling of signals.
Obtained from: OpenBSD
Diffstat (limited to 'lib/libc')
-rw-r--r-- | lib/libc/gen/readpassphrase.3 | 111 | ||||
-rw-r--r-- | lib/libc/gen/readpassphrase.c | 92 |
2 files changed, 146 insertions, 57 deletions
diff --git a/lib/libc/gen/readpassphrase.3 b/lib/libc/gen/readpassphrase.3 index 3b03c10..3c0aea4 100644 --- a/lib/libc/gen/readpassphrase.3 +++ b/lib/libc/gen/readpassphrase.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: readpassphrase.3,v 1.3 2001/08/06 10:42:25 mpech Exp $ +.\" $OpenBSD: /usr/local/www/cvsroot/OpenBSD/src/lib/libc/gen/readpassphrase.3,v 1.7 2001/12/15 15:37:51 millert Exp $ .\" .\" Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> .\" All rights reserved. @@ -27,15 +27,15 @@ .\" .\" $FreeBSD$ .\" -.Dd November 20, 2000 +.Dd December 7, 2001 .Dt READPASSPHRASE 3 .Os .Sh NAME .Nm readpassphrase .Nd get a passphrase from the user .Sh SYNOPSIS -.In readpassphrase.h -.Ft "char *" +.Fd #include <readpassphrase.h> +.Ft char * .Fn readpassphrase "const char *prompt" "char *buf" "size_t bufsiz" "int flags" .Sh DESCRIPTION The @@ -53,9 +53,7 @@ In this case it is generally not possible to turn off echo. .Pp Up to .Fa bufsiz -\- 1 characters (one is for the -.Dv NUL ) -are read into the provided buffer +- 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. @@ -64,42 +62,52 @@ characters and the terminating newline (or return) character are discarded. takes the following optional .Fa flags : .Pp -.Bl -tag -width ".Dv RPP_REQUIRE_TTY" -compact -.It Dv RPP_ECHO_OFF -turn off echo (default behavior) -.It Dv RPP_ECHO_ON -leave echo on -.It Dv RPP_REQUIRE_TTY -fail if there is no tty -.It Dv RPP_FORCELOWER -force input to lower case -.It Dv RPP_FORCEUPPER -force input to upper case -.It Dv RPP_SEVENBIT -strip the high bit from input -.El +.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, +Upon successful completion, .Fn readpassphrase returns a pointer to the null-terminated passphrase. -If the -.Dv RPP_REQUIRE_TTY -flag is set and -.Pa /dev/tty -is inaccessible, +If an error is encountered, the terminal state is restored and +a null pointer is returned. +.Sh ERRORS +.Bl -tag -width Er +.It Bq Er EINTR +The .Fn readpassphrase -returns a -.Dv NULL -pointer. +function was interrupted by a signal. +.It Bq Er EINVAL +The +.Ar bufsiz +argument was zero. +.It Bq Er EIO +The process is a member of a background process attempting to read +from its controlling terminal, the process is ignoring or blocking +the SIGTTIN signal or the process group is orphaned. +.It Bq Er EMFILE +The process has already reached its limit for open file descriptors. +.It Bq Er ENFILE +The system file table is full. +.It Bq Er ENOTTY +There is no controlling terminal and the +.Dv RPP_REQUIRE_TTY +flag was specified. +.El .Sh EXAMPLES The following code fragment will read a passphrase from .Pa /dev/tty into the buffer -.Fa passbuf . +.Fa passbuf. .Bd -literal -offset indent char passbuf[1024]; @@ -116,12 +124,51 @@ if (compare(transform(passbuf), epass) != 0) memset(passbuf, 0, sizeof(passbuf)); .Ed +.Sh SIGNALS +.Fn readpassphrase +will catch the following signals: +.Pp +.Bd -literal -offset indent -compact +SIGINT +SIGHUP +SIGQUIT +SIGTERM +SIGTSTP +SIGTTIN +SIGTTOU +.Ed +.Pp +When one of the above signals is intercepted, terminal echo will +be restored if it had previously been turned off. +If a signal handler was installed for the signal when +.Fn readpassphrase +was called that handler is then executed. +If no handler was previously installed for the signal then the +default action is taken as per +.Xr sigaction 2 . +.Pp +The +.Dv SIGTSTP , +.Dv SIGTTIN , +.Dv SIGTTOU , +signals (stop signal generated from keyboard or due to terminal I/O +from a background proccess) are treated specially. +When the process is resumed after it has been stopped, +.Fn readpassphrase +will reprint the prompt and the user may then enter a passphrase. .Sh FILES -.Bl -tag -width ".Pa /dev/tty" -compact +.Bl -tag -width /dev/tty -compact .It Pa /dev/tty .El .Sh SEE ALSO +.Xr sigaction 2 , .Xr getpass 3 +.Sh STANDARDS +The +.Fn readpassphrase +function is an +.Ox +extension and should not be used if portability is desired. .Sh HISTORY The .Fn readpassphrase diff --git a/lib/libc/gen/readpassphrase.c b/lib/libc/gen/readpassphrase.c index 2f70232..1812354 100644 --- a/lib/libc/gen/readpassphrase.c +++ b/lib/libc/gen/readpassphrase.c @@ -1,3 +1,5 @@ +/* $OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $ */ + /* * Copyright (c) 2000 Todd C. Miller <Todd.Miller@courtesan.com> * All rights reserved. @@ -26,7 +28,7 @@ */ #if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.7 2001/08/07 19:34:11 millert Exp $"; +static const char rcsid[] = "$OpenBSD: readpassphrase.c,v 1.12 2001/12/15 05:41:00 millert Exp $"; #endif /* LIBC_SCCS and not lint */ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -44,17 +46,19 @@ __FBSDID("$FreeBSD$"); #include <readpassphrase.h> #include "un-namespace.h" +static volatile sig_atomic_t signo; + +static void handler(int); + char * -readpassphrase(prompt, buf, bufsiz, flags) - const char *prompt; - char *buf; - size_t bufsiz; - int flags; +readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags) { - struct termios term, oterm; + ssize_t nr; + int input, output, save_errno; char ch, *p, *end; - int input, output; - sigset_t oset, nset; + struct termios term, oterm; + struct sigaction sa, saveint, savehup, savequit, saveterm; + struct sigaction savetstp, savettin, savettou; /* I suppose we could alloc on demand in this case (XXX). */ if (bufsiz == 0) { @@ -62,6 +66,7 @@ readpassphrase(prompt, buf, bufsiz, flags) return(NULL); } +restart: /* * Read and write to /dev/tty if available. If not, read from * stdin and write to stderr unless a tty is required. @@ -76,20 +81,26 @@ readpassphrase(prompt, buf, bufsiz, flags) } /* - * 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. + * Catch signals that would otherwise cause the user to end + * up with echo turned off in the shell. Don't worry about + * things like SIGALRM and SIGPIPE for now. */ - sigemptyset(&nset); - sigaddset(&nset, SIGINT); - sigaddset(&nset, SIGTSTP); - (void)_sigprocmask(SIG_BLOCK, &nset, &oset); + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; /* don't restart system calls */ + sa.sa_handler = handler; + (void)_sigaction(SIGINT, &sa, &saveint); + (void)_sigaction(SIGHUP, &sa, &savehup); + (void)_sigaction(SIGQUIT, &sa, &savequit); + (void)_sigaction(SIGTERM, &sa, &saveterm); + (void)_sigaction(SIGTSTP, &sa, &savetstp); + (void)_sigaction(SIGTTIN, &sa, &savettin); + (void)_sigaction(SIGTTOU, &sa, &savettou); /* Turn off echo if possible. */ if (tcgetattr(input, &oterm) == 0) { memcpy(&term, &oterm, sizeof(term)); - if (!(flags & RPP_ECHO_ON) && (term.c_lflag & ECHO)) - term.c_lflag &= ~ECHO; + if (!(flags & RPP_ECHO_ON)) + term.c_lflag &= ~(ECHO | ECHONL); if (term.c_cc[VSTATUS] != _POSIX_VDISABLE) term.c_cc[VSTATUS] = _POSIX_VDISABLE; (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); @@ -100,7 +111,7 @@ readpassphrase(prompt, buf, bufsiz, flags) (void)_write(output, prompt, strlen(prompt)); end = buf + bufsiz - 1; - for (p = buf; _read(input, &ch, 1) == 1 && ch != '\n' && ch != '\r';) { + for (p = buf; (nr = _read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r';) { if (p < end) { if ((flags & RPP_SEVENBIT)) ch &= 0x7f; @@ -114,23 +125,54 @@ readpassphrase(prompt, buf, bufsiz, flags) } } *p = '\0'; + save_errno = errno; if (!(term.c_lflag & ECHO)) (void)_write(output, "\n", 1); - /* Restore old terminal settings and signal mask. */ + /* Restore old terminal settings and signals. */ if (memcmp(&term, &oterm, sizeof(term)) != 0) - (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm); - (void)_sigprocmask(SIG_SETMASK, &oset, NULL); + (void)tcsetattr(input, TCSANOW|TCSASOFT, &oterm); + (void)_sigaction(SIGINT, &saveint, NULL); + (void)_sigaction(SIGHUP, &savehup, NULL); + (void)_sigaction(SIGQUIT, &savequit, NULL); + (void)_sigaction(SIGTERM, &saveterm, NULL); + (void)_sigaction(SIGTSTP, &savetstp, NULL); + (void)_sigaction(SIGTTIN, &savettin, NULL); + (void)_sigaction(SIGTTOU, &savettou, NULL); if (input != STDIN_FILENO) (void)_close(input); - return(buf); + + /* + * If we were interrupted by a signal, resend it to ourselves + * now that we have restored the signal handlers. + */ + if (signo) { + kill(getpid(), signo); + switch (signo) { + case SIGTSTP: + case SIGTTIN: + case SIGTTOU: + signo = 0; + goto restart; + } + } + + errno = save_errno; + return(nr == -1 ? NULL : buf); } +#if 0 char * -getpass(prompt) - const char *prompt; +getpass(const char *prompt) { static char buf[_PASSWORD_LEN + 1]; return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF)); } +#endif + +static void handler(int s) +{ + + signo = s; +} |