sudo/SOURCES/sudo-1.8.29-CVE-2019-18634-...

159 lines
4.0 KiB
Diff

diff -up ./src/tgetpass.c.bla ./src/tgetpass.c
--- ./src/tgetpass.c.bla 2018-08-18 16:10:15.000000000 +0200
+++ ./src/tgetpass.c 2020-02-05 17:15:16.216904891 +0100
@@ -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_call
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
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
{
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
/* 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
extern int 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,
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 */
}
@@ -354,14 +393,27 @@ getln(int fd, char *buf, size_t bufsiz,
}
}
- 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