From: Todd C. Miller Date: Sun, 2 Mar 2008 14:31:57 +0000 (+0000) Subject: Add support for running a helper program to read the password when X-Git-Tag: SUDO_1_7_0~173 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee04914164c24012c3d996a841c0f88754e9bb82;p=sudo Add support for running a helper program to read the password when no tty is present (or when specified with the -A flag). TODO: docs. --- diff --git a/auth/sudo_auth.c b/auth/sudo_auth.c index 11860bafd..4ee39c1d1 100644 --- a/auth/sudo_auth.c +++ b/auth/sudo_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005 Todd C. Miller + * Copyright (c) 1999-2005, 2008 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -195,7 +195,8 @@ verify_user(pw, prompt) break; } - pass_warn(stderr); + if (!ISSET(tgetpass_flags, TGP_ASKPASS)) + pass_warn(stderr); } cleanup: diff --git a/check.c b/check.c index cc6c80823..0297df5c3 100644 --- a/check.c +++ b/check.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1993-1996,1998-2005 Todd C. Miller + * Copyright (c) 1993-1996,1998-2005, 2007-2008 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -98,7 +99,8 @@ check_user(validated) status = timestamp_status(timestampdir, timestampfile, user_name, TS_MAKE_DIRS); if (status != TS_CURRENT || ISSET(validated, FLAG_CHECK_USER)) { - lecture(status); + if (!ISSET(tgetpass_flags, TGP_ASKPASS)) + lecture(status); /* Expand any escapes in the prompt. */ prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt, diff --git a/configure b/configure index ce1ddf9f2..73494ed0f 100755 --- a/configure +++ b/configure @@ -1581,6 +1581,7 @@ Optional Packages: --with-secure-path override the user's path with a built-in one --without-interfaces don't try to read the ip addr of ether interfaces --with-stow properly handle GNU stow packaging + --with-askpass=PATH Fully qualified pathname of sudo-askpass --with-selinux enable SELinux support --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use @@ -3740,6 +3741,28 @@ echo "${ECHO_T}no" >&6; } fi +{ echo "$as_me:$LINENO: checking path to sudo-askpass" >&5 +echo $ECHO_N "checking path to sudo-askpass... $ECHO_C" >&6; } + +# Check whether --with-askpass was given. +if test "${with_askpass+set}" = set; then + withval=$with_askpass; case $with_askpass in + yes) with_askpass="$libexecdir/sudo-askpass" + ;; + no) ;; + *) ;; +esac +else + with_askpass="$libexecdir/sudo-askpass" +fi + +{ echo "$as_me:$LINENO: result: $with_askpass" >&5 +echo "${ECHO_T}$with_askpass" >&6; } +cat >>confdefs.h <&5 echo $ECHO_N "checking whether to do user authentication by default... $ECHO_C" >&6; } @@ -6180,7 +6203,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6183 "configure"' > conftest.$ac_ext + echo '#line 6206 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -7724,11 +7747,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7727: $lt_compile\"" >&5) + (eval echo "\"\$as_me:7750: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7731: \$? = $ac_status" >&5 + echo "$as_me:7754: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8014,11 +8037,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8017: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8040: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8021: \$? = $ac_status" >&5 + echo "$as_me:8044: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -8118,11 +8141,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8121: $lt_compile\"" >&5) + (eval echo "\"\$as_me:8144: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8125: \$? = $ac_status" >&5 + echo "$as_me:8148: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -10463,7 +10486,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < conftest.$ac_ext <]" -#define SUDO_USAGE4 " -e [-S] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..." +#define SUDO_USAGE1 " [-A] -h | -K | -k | -L | -V | -v" +#define SUDO_USAGE2 " -l[l] [-A] [-g groupname|#gid] [-U username] [-u username|#uid] [-g groupname|#gid] [command]" +#define SUDO_USAGE3 " [-AbEHPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []" +#define SUDO_USAGE4 " -e [-AS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..." #endif /* _SUDO_USAGE_H */ diff --git a/tgetpass.c b/tgetpass.c index bb7cf3c27..3b6031f6f 100644 --- a/tgetpass.c +++ b/tgetpass.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2007-2008 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -122,6 +123,7 @@ static volatile sig_atomic_t signo; static void handler __P((int)); static char *getln __P((int, char *, size_t)); +static char *sudo_askpass(const char *); /* * Like getpass(3) but with timeout and echo flags. @@ -140,6 +142,11 @@ tgetpass(prompt, timeout, flags) int input, output, save_errno; (void) fflush(stdout); + + /* If using a helper program to get the password, run it instead. */ + if (ISSET(flags, TGP_ASKPASS) && user_askpass) + return(sudo_askpass(prompt)); + restart: signo = 0; pass = NULL; @@ -232,6 +239,49 @@ restart: return(pass); } +/* + * Fork a child and exec sudo-askpass to get the password from the user. + */ +static char * +sudo_askpass(prompt) + const char *prompt; +{ + static char buf[SUDO_PASS_MAX + 1], *pass; + sigaction_t sa, saved_sa_pipe; + int pfd[2]; + pid_t pid; + + if (pipe(pfd) == -1) + error(1, "unable to create pipe"); + + if ((pid = fork()) == -1) + error(1, "unable to fork"); + + if (pid == 0) { + /* child, point stdout to output side of the pipe and exec askpass */ + (void) dup2(pfd[1], STDOUT_FILENO); + set_perms(PERM_FULL_USER); + closefrom(STDERR_FILENO + 1); + execl(user_askpass, user_askpass, prompt, (char *)NULL); + warning("unable to run %s", user_askpass); + _exit(255); + } + + /* Ignore SIGPIPE in case child exits prematurely */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = SIG_IGN; + (void) sigaction(SIGPIPE, &sa, &saved_sa_pipe); + + /* Get response from child (askpass) and restore SIGPIPE handler */ + (void) close(pfd[1]); + pass = getln(pfd[0], buf, sizeof(buf)); + (void) close(pfd[0]); + (void) sigaction(SIGPIPE, &saved_sa_pipe, NULL); + + return(pass); +} + static char * getln(fd, buf, bufsiz) int fd;