]> granicus.if.org Git - sudo/commitdiff
Add pwstars sudoers option that causes sudo to print a star every
authorTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 8 Feb 2009 00:50:48 +0000 (00:50 +0000)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Sun, 8 Feb 2009 00:50:48 +0000 (00:50 +0000)
time the user presses a key.

Makefile.in
def_data.c
def_data.h
def_data.in
sudoers.pod
tgetpass.c

index 82883bb9c180876a152fadd79f72f7d5078bea5c..98c3e3933683aa9ebac723dccf334c22b010f37c 100644 (file)
@@ -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)
index 72c14c9f1f3f5de22b5489cc2a9941a0aee3e532..6910a436180175d2cd4b94e4cb34717b1d94a9f5 100644 (file)
@@ -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
     }
index afa78e0b5fc29b6f8ded5c4d491a22942a454465..0f661c2f132d1188d8544c1c9c0e8be1b26360f7 100644 (file)
 #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,
index 0a0a3b86deb6a741121cc306f15e67c69191a539..8419933c5a9418386e834267c3badb46765a6e65 100644 (file)
@@ -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"
index 132d538ee37e84959d3dc46d8341bbf3f360df4e..c3256bc43a524c35c5cf2b2e7d226d5b71dd3b8d 100644 (file)
@@ -653,12 +653,23 @@ will always be used.  This flag is I<off> by default.
 
 =item preserve_groups
 
-By default B<sudo> will initialize the group vector to the list of
+By default, B<sudo> will initialize the group vector to the list of
 groups the target user is in.  When I<preserve_groups> 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<off> by default.
 
+=item pwstars
+
+By default, B<sudo> 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<sudo>
+has hung at this point.  When I<pwstars> is set, B<sudo> 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<off> by default.
+
 =item requiretty
 
 If set, B<sudo> will only run when the user is logged in to a real
index c8dacd6ffe4d545a5265d1a6e8b4cdbd71c7b56f..9bc68b7a79248b2f52d304fef22ffd2d8771077e 100644 (file)
 
 #include <sys/types.h>
 #include <sys/param.h>
-#ifdef HAVE_SYS_BSDTYPES_H
-# include <sys/bsdtypes.h>
-#endif /* HAVE_SYS_BSDTYPES_H */
-#include <sys/time.h>
 #include <stdio.h>
 #ifdef STDC_HEADERS
 # include <stdlib.h>
 #include <errno.h>
 #include <signal.h>
 #include <fcntl.h>
-#ifdef HAVE_TERMIOS_H
-# include <termios.h>
-#else
-# ifdef HAVE_TERMIO_H
-#  include <termio.h>
-# else
-#  include <sgtty.h>
-#  include <sys/ioctl.h>
-# endif /* HAVE_TERMIO_H */
-#endif /* HAVE_TERMIOS_H */
 
 #include "sudo.h"
 
 __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';