From 38c225af03d666d393c72dc0e35651dfaba70582 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sun, 8 Feb 2009 00:50:48 +0000 Subject: [PATCH] Add pwstars sudoers option that causes sudo to print a star every time the user presses a key. --- Makefile.in | 8 ++-- def_data.c | 4 ++ def_data.h | 2 + def_data.in | 3 ++ sudoers.pod | 13 +++++- tgetpass.c | 113 ++++++++++++++++------------------------------------ 6 files changed, 61 insertions(+), 82 deletions(-) diff --git a/Makefile.in b/Makefile.in index 82883bb9c..98c3e3933 100644 --- a/Makefile.in +++ b/Makefile.in @@ -108,8 +108,8 @@ SRCS = aix.c alias.c alloc.c check.c closefrom.c def_data.c defaults.c env.c \ isblank.c lbuf.c ldap.c list.c logging.c match.c mkstemp.c memrchr.c \ parse.c pwutil.c set_perms.c sigaction.c snprintf.c strcasecmp.c \ strerror.c strlcat.c strlcpy.c sudo.c sudo_noexec.c sudo_edit.c \ - sudo_nss.c testsudoers.c tgetpass.c toke.c toke.l tsgetgrpw.c utimes.c \ - visudo.c zero_bytes.c redblack.c selinux.c sesh.c $(AUTH_SRCS) + sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l tsgetgrpw.c \ + utimes.c visudo.c zero_bytes.c redblack.c selinux.c sesh.c $(AUTH_SRCS) AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ auth/kerb4.c auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \ @@ -131,7 +131,7 @@ COMMON_OBJS = gram.o alias.o alloc.o defaults.o error.o list.o match.o \ SUDO_OBJS = $(COMMON_OBJS) $(AUTH_OBJS) @SUDO_OBJS@ check.o env.o \ getspwuid.o gettime.o goodpath.o fileops.o find_path.o \ interfaces.o lbuf.o logging.o parse.o pwutil.o set_perms.o \ - sudo.o sudo_edit.o sudo_nss.o tgetpass.o + sudo.o sudo_edit.o sudo_nss.o term.o tgetpass.o VISUDO_OBJS = $(COMMON_OBJS) visudo.o fileops.o gettime.o goodpath.o \ find_path.o pwutil.o @@ -304,6 +304,8 @@ sudo_noexec.o: $(srcdir)/sudo_noexec.c $(srcdir)/compat.h config.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c sudo_nss.o: $(srcdir)/sudo_nss.c $(SUDODEP) $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_nss.c +term.o: $(srcdir)/term.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/term.c testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/testsudoers.c tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP) diff --git a/def_data.c b/def_data.c index 72c14c9f1..6910a4361 100644 --- a/def_data.c +++ b/def_data.c @@ -302,6 +302,10 @@ struct sudo_defs_types sudo_defs_table[] = { "visiblepw", T_FLAG, "Allow sudo to prompt for a password even if it would be visisble", NULL, + }, { + "pwstars", T_FLAG, + "Print a stars at the password prompt when there is user input", + NULL, }, { NULL, 0, NULL } diff --git a/def_data.h b/def_data.h index afa78e0b5..0f661c2f1 100644 --- a/def_data.h +++ b/def_data.h @@ -138,6 +138,8 @@ #define I_SUDOERS_LOCALE 68 #define def_visiblepw (sudo_defs_table[69].sd_un.flag) #define I_VISIBLEPW 69 +#define def_pwstars (sudo_defs_table[70].sd_un.flag) +#define I_PWSTARS 70 enum def_tupple { never, diff --git a/def_data.in b/def_data.in index 0a0a3b86d..8419933c5 100644 --- a/def_data.in +++ b/def_data.in @@ -223,3 +223,6 @@ sudoers_locale visiblepw T_FLAG "Allow sudo to prompt for a password even if it would be visisble" +pwstars + T_FLAG + "Print a stars at the password prompt when there is user input" diff --git a/sudoers.pod b/sudoers.pod index 132d538ee..c3256bc43 100644 --- a/sudoers.pod +++ b/sudoers.pod @@ -653,12 +653,23 @@ will always be used. This flag is I by default. =item preserve_groups -By default B will initialize the group vector to the list of +By default, B will initialize the group vector to the list of groups the target user is in. When I is set, the user's existing group vector is left unaltered. The real and effective group IDs, however, are still set to match the target user. This flag is I by default. +=item pwstars + +By default, B reads the password like most other Unix programs, +by turning off echo until the user hits the return (or enter) key. +Some users become confused by this as it appears to them that B +has hung at this point. When I is set, B will print +a star for each character of the password the user enters. Note +that this does have a security impact, as an onlooker will be able +to determine the length of the password being entered. +This flag is I by default. + =item requiretty If set, B will only run when the user is logged in to a real diff --git a/tgetpass.c b/tgetpass.c index c8dacd6ff..9bc68b7a7 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -27,10 +27,6 @@ #include #include -#ifdef HAVE_SYS_BSDTYPES_H -# include -#endif /* HAVE_SYS_BSDTYPES_H */ -#include #include #ifdef STDC_HEADERS # include @@ -57,16 +53,6 @@ #include #include #include -#ifdef HAVE_TERMIOS_H -# include -#else -# ifdef HAVE_TERMIO_H -# include -# else -# include -# include -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ #include "sudo.h" @@ -74,47 +60,10 @@ __unused static const char rcsid[] = "$Sudo$"; #endif /* lint */ -#ifndef TCSASOFT -# define TCSASOFT 0 -#endif -#ifndef ECHONL -# define ECHONL 0 -#endif - -#ifndef _POSIX_VDISABLE -# ifdef VDISABLE -# define _POSIX_VDISABLE VDISABLE -# else -# define _POSIX_VDISABLE 0 -# endif -#endif - -/* - * Compat macros for non-termios systems. - */ -#ifndef HAVE_TERMIOS_H -# ifdef HAVE_TERMIO_H -# undef termios -# define termios termio -# define tcgetattr(f, t) ioctl(f, TCGETA, t) -# define tcsetattr(f, a, t) ioctl(f, a, t) -# undef TCSAFLUSH -# define TCSAFLUSH TCSETAF -# else -# undef termios -# define termios sgttyb -# define c_lflag sg_flags -# define tcgetattr(f, t) ioctl(f, TIOCGETP, t) -# define tcsetattr(f, a, t) ioctl(f, a, t) -# undef TCSAFLUSH -# define TCSAFLUSH TIOCSETP -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ - static volatile sig_atomic_t signo; static void handler __P((int)); -static char *getln __P((int, char *, size_t)); +static char *getln __P((int, char *, size_t, int)); static char *sudo_askpass __P((const char *)); /* @@ -128,10 +77,9 @@ tgetpass(prompt, timeout, flags) { sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm; sigaction_t savetstp, savettin, savettou; - struct termios term, oterm; char *pass; static char buf[SUDO_PASS_MAX + 1]; - int input, output, save_errno; + int input, output, save_errno, neednl;; (void) fflush(stdout); @@ -167,19 +115,10 @@ restart: (void) sigaction(SIGTTIN, &sa, &savettin); (void) sigaction(SIGTTOU, &sa, &savettou); - /* Turn echo off/on as specified by flags. */ - if (tcgetattr(input, &oterm) == 0) { - (void) memcpy(&term, &oterm, sizeof(term)); - if (!ISSET(flags, TGP_ECHO)) - CLR(term.c_lflag, ECHO|ECHONL); -#ifdef VSTATUS - term.c_cc[VSTATUS] = _POSIX_VDISABLE; -#endif - (void) tcsetattr(input, TCSAFLUSH|TCSASOFT, &term); - } else { - zero_bytes(&term, sizeof(term)); - zero_bytes(&oterm, sizeof(oterm)); - } + if (def_pwstars) + neednl = term_raw(input); + else + neednl = term_noecho(input); /* No output if we are already backgrounded. */ if (signo != SIGTTOU && signo != SIGTTIN) { @@ -188,20 +127,16 @@ restart: if (timeout > 0) alarm(timeout); - pass = getln(input, buf, sizeof(buf)); + pass = getln(input, buf, sizeof(buf), def_pwstars); alarm(0); save_errno = errno; - if (!ISSET(term.c_lflag, ECHO)) + if (neednl) (void) write(output, "\n", 1); } /* Restore old tty settings and signals. */ - if (memcmp(&term, &oterm, sizeof(term)) != 0) { - while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 && - errno == EINTR) - continue; - } + term_restore(input); (void) sigaction(SIGALRM, &savealrm, NULL); (void) sigaction(SIGINT, &saveint, NULL); (void) sigaction(SIGHUP, &savehup, NULL); @@ -269,32 +204,54 @@ sudo_askpass(prompt) /* Get response from child (askpass) and restore SIGPIPE handler */ (void) close(pfd[1]); - pass = getln(pfd[0], buf, sizeof(buf)); + pass = getln(pfd[0], buf, sizeof(buf), 0); (void) close(pfd[0]); (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL); return(pass); } +extern int term_erase, term_kill; + static char * -getln(fd, buf, bufsiz) +getln(fd, buf, bufsiz, stars) int fd; char *buf; size_t bufsiz; + int stars; { + size_t left = bufsiz; ssize_t nr = -1; char *cp = buf; char c = '\0'; - if (bufsiz == 0) { + if (left == 0) { errno = EINVAL; return(NULL); /* sanity */ } - while (--bufsiz) { + while (--left) { nr = read(fd, &c, 1); if (nr != 1 || c == '\n' || c == '\r') break; + if (stars) { + if (c == term_kill) { + while (cp > buf) { + (void) write(fd, "\b \b", 3); + --cp; + } + left = bufsiz; + continue; + } else if (c == term_erase) { + if (cp > buf) { + (void) write(fd, "\b \b", 3); + --cp; + left++; + } + continue; + } + (void) write(fd, "*", 1); + } *cp++ = c; } *cp = '\0'; -- 2.40.0