]> granicus.if.org Git - sudo/commitdiff
Print a warning for password read issues.
authorTodd C. Miller <Todd.Miller@sudo.ws>
Tue, 9 Oct 2018 19:25:52 +0000 (13:25 -0600)
committerTodd C. Miller <Todd.Miller@sudo.ws>
Tue, 9 Oct 2018 19:25:52 +0000 (13:25 -0600)
Issues include: timeout at the password prompt, read error while
reading the password, and EOF reading the password.

src/tgetpass.c

index 939fe48ad728b26c1724d5e8ed53a6aa6bb6ed05..655e69f7505ad3dc045d292696a2b9ead286bdab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1998-2005, 2007-2016
+ * Copyright (c) 1996, 1998-2005, 2007-2018
  *     Todd C. Miller <Todd.Miller@sudo.ws>
  *
  * Permission to use, copy, modify, and distribute this software for any
 #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