From: Todd C. Miller Date: Tue, 9 Oct 2018 19:25:52 +0000 (-0600) Subject: Print a warning for password read issues. X-Git-Tag: SUDO_1_8_26^2~60 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ab2cba0f5d8b286e8e52c06076efd32434f538ae;p=sudo Print a warning for password read issues. Issues include: timeout at the password prompt, read error while reading the password, and EOF reading the password. --- diff --git a/src/tgetpass.c b/src/tgetpass.c index 939fe48ad..655e69f75 100644 --- a/src/tgetpass.c +++ b/src/tgetpass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2016 + * Copyright (c) 1996, 1998-2005, 2007-2018 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -44,11 +44,18 @@ #include "sudo.h" #include "sudo_plugin.h" +enum tgetpass_errval { + TGP_ERRVAL_NOERROR, + TGP_ERRVAL_TIMEOUT, + TGP_ERRVAL_NOPASSWORD, + TGP_ERRVAL_READERROR +}; + static volatile sig_atomic_t signo[NSIG]; static bool tty_present(void); static void tgetpass_handler(int); -static char *getln(int, char *, size_t, int); +static char *getln(int, char *, size_t, int, enum tgetpass_errval *); static char *sudo_askpass(const char *, const char *); static int @@ -77,6 +84,27 @@ suspend(int signo, struct sudo_conv_callback *callback) debug_return_int(ret); } +static void +tgetpass_display_error(enum tgetpass_errval errval) +{ + debug_decl(tgetpass_display_error, SUDO_DEBUG_CONV) + + switch (errval) { + case TGP_ERRVAL_NOERROR: + break; + case TGP_ERRVAL_TIMEOUT: + sudo_warnx(U_("timed out reading password")); + break; + case TGP_ERRVAL_NOPASSWORD: + sudo_warnx(U_("no password was provided")); + break; + case TGP_ERRVAL_READERROR: + sudo_warn(U_("unable to read password")); + break; + } + debug_return; +} + /* * Like getpass(3) but with timeout and echo flags. */ @@ -90,6 +118,7 @@ tgetpass(const char *prompt, int timeout, int flags, static const char *askpass; static char buf[SUDO_CONV_REPL_MAX + 1]; int i, input, output, save_errno, neednl = 0, need_restart; + enum tgetpass_errval errval; debug_decl(tgetpass, SUDO_DEBUG_CONV) (void) fflush(stdout); @@ -175,7 +204,7 @@ restart: if (timeout > 0) alarm(timeout); - pass = getln(input, buf, sizeof(buf), ISSET(flags, TGP_MASK)); + pass = getln(input, buf, sizeof(buf), ISSET(flags, TGP_MASK), &errval); alarm(0); save_errno = errno; @@ -183,6 +212,7 @@ restart: if (write(output, "\n", 1) == -1) goto restore; } + tgetpass_display_error(errval); restore: /* Restore old signal handlers. */ @@ -210,6 +240,8 @@ restore: for (i = 0; i < NSIG; i++) { if (signo[i]) { switch (i) { + case SIGALRM: + break; case SIGTSTP: case SIGTTIN: case SIGTTOU: @@ -239,6 +271,7 @@ sudo_askpass(const char *askpass, const char *prompt) { static char buf[SUDO_CONV_REPL_MAX + 1], *pass; struct sigaction sa, savechld; + enum tgetpass_errval errval; int pfd[2], status; pid_t child; debug_decl(sudo_askpass, SUDO_DEBUG_CONV) @@ -281,9 +314,11 @@ sudo_askpass(const char *askpass, const char *prompt) /* Get response from child (askpass). */ (void) close(pfd[1]); - pass = getln(pfd[0], buf, sizeof(buf), 0); + pass = getln(pfd[0], buf, sizeof(buf), 0, &errval); (void) close(pfd[0]); + tgetpass_display_error(errval); + /* Wait for child to exit. */ for (;;) { pid_t rv = waitpid(child, &status, 0); @@ -305,7 +340,8 @@ sudo_askpass(const char *askpass, const char *prompt) extern int sudo_term_eof, sudo_term_erase, sudo_term_kill; static char * -getln(int fd, char *buf, size_t bufsiz, int feedback) +getln(int fd, char *buf, size_t bufsiz, int feedback, + enum tgetpass_errval *errval) { size_t left = bufsiz; ssize_t nr = -1; @@ -313,7 +349,10 @@ getln(int fd, char *buf, size_t bufsiz, int feedback) char c = '\0'; debug_decl(getln, SUDO_DEBUG_CONV) + *errval = TGP_ERRVAL_NOERROR; + if (left == 0) { + *errval = TGP_ERRVAL_READERROR; errno = EINVAL; debug_return_str(NULL); /* sanity */ } @@ -357,14 +396,27 @@ getln(int fd, char *buf, size_t bufsiz, int feedback) } } - debug_return_str_masked(nr == 1 ? buf : NULL); + if (nr != 1) { + if (nr == 0) { + *errval = TGP_ERRVAL_NOPASSWORD; + } else if (nr == -1) { + if (errno == EINTR) { + if (signo[SIGALRM] == 1) + *errval = TGP_ERRVAL_TIMEOUT; + } else { + *errval = TGP_ERRVAL_READERROR; + } + } + debug_return_str(NULL); + } + + debug_return_str_masked(buf); } static void tgetpass_handler(int s) { - if (s != SIGALRM) - signo[s] = 1; + signo[s] = 1; } static bool