no tty is present (or when specified with the -A flag). TODO: docs.
/*
- * Copyright (c) 1999-2005 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1999-2005, 2008 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
break;
}
- pass_warn(stderr);
+ if (!ISSET(tgetpass_flags, TGP_ASKPASS))
+ pass_warn(stderr);
}
cleanup:
/*
- * Copyright (c) 1993-1996,1998-2005 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1993-1996,1998-2005, 2007-2008
+ * Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
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,
--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
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 <<EOF
+#define _PATH_SUDO_ASKPASS "$with_askpass"
+EOF
+
+
{ echo "$as_me:$LINENO: checking whether to do user authentication by default" >&5
echo $ECHO_N "checking whether to do user authentication by default... $ECHO_C" >&6; }
;;
*-*-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=$?
-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.
-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.
-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
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10466 "configure"
+#line 10489 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10566 "configure"
+#line 10589 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
;;
esac], AC_MSG_RESULT(no))
+AC_MSG_CHECKING(path to sudo-askpass)
+AC_ARG_WITH(askpass, [ --with-askpass=PATH Fully qualified pathname of sudo-askpass],
+[case $with_askpass in
+ yes) with_askpass="$libexecdir/sudo-askpass"
+ ;;
+ no) ;;
+ *) ;;
+esac], [with_askpass="$libexecdir/sudo-askpass"])
+AC_MSG_RESULT($with_askpass)
+SUDO_DEFINE_UNQUOTED(_PATH_SUDO_ASKPASS, "$with_askpass")
+
dnl
dnl Options for --enable
dnl
"type", T_STR,
"SELinux type to use in the new security context: %s",
NULL,
+ }, {
+ "askpass", T_STR|T_PATH,
+ "Path to the askpass helper program: %s",
+ NULL,
}, {
NULL, 0, NULL
}
#define I_ROLE 63
#define def_type (sudo_defs_table[64].sd_un.str)
#define I_TYPE 64
+#define def_askpass (sudo_defs_table[65].sd_un.str)
+#define I_ASKPASS 65
enum def_tupple {
never,
type
T_STR
"SELinux type to use in the new security context: %s"
+askpass
+ T_STR|T_PATH
+ "Path to the askpass helper program: %s"
#endif
#ifdef ENV_EDITOR
def_env_editor = TRUE;
+#endif
+#ifdef _PATH_SUDO_ASKPASS
+ def_askpass = _PATH_SUDO_ASKPASS;
#endif
def_env_reset = TRUE;
def_set_logname = TRUE;
#undef _PATH_SUDO_NOEXEC
#endif /* _PATH_SUDO_NOEXEC */
+#ifndef _PATH_SUDO_ASKPASS
+#undef _PATH_SUDO_ASKPASS
+#endif /* _PATH_SUDO_ASKPASS */
+
#ifndef _PATH_VI
#undef _PATH_VI
#endif /* _PATH_VI */
(void) close(fd);
}
+ /* Use askpass value from sudoers unless specified by the user. */
+ if (def_askpass && !user_askpass)
+ user_askpass = def_askpass;
+
+ /* If no tty is present but DISPLAY is set, use askpass if we have it. */
+ if (user_askpass && !ISSET(tgetpass_flags, TGP_STDIN) &&
+ user_ttypath == NULL && user_display != NULL && *user_display != '\0')
+ SET(tgetpass_flags, TGP_ASKPASS);
+
/* User may have overriden environment resetting via the -E flag. */
if (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv)
def_env_reset = FALSE;
user_tty = "unknown";
for (ep = envp; *ep; ep++) {
+ /* XXX - don't fill in if empty string */
switch (**ep) {
+ case 'D':
+ if (strncmp("DISPLAY=", *ep, 8) == 0)
+ user_display = *ep + 8;
+ break;
case 'K':
if (strncmp("KRB5CCNAME=", *ep, 11) == 0)
user_ccname = *ep + 11;
user_prompt = *ep + 12;
else if (strncmp("SUDO_USER=", *ep, 10) == 0)
prev_user = *ep + 10;
+ else if (strncmp("SUDO_ASKPASS=", *ep, 13) == 0)
+ user_askpass = *ep + 13;
break;
-
}
}
}
switch (NewArgv[0][1]) {
+ case 'A':
+ SET(tgetpass_flags, TGP_ASKPASS);
+ break;
case 'p':
/* Must have an associated prompt. */
if (NewArgv[1] == NULL)
/*
- * Copyright (c) 1993-1996, 1998-2005, 2007
+ * Copyright (c) 1993-1996, 1998-2005, 2007-2008
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
char *cmnd_safe;
char *class_name;
char *krb5_ccname;
+ char *display;
+ char *askpass;
int ngroups;
GETGROUPS_T *groups;
struct list_member *env_vars;
#define user_host (sudo_user.host)
#define user_shost (sudo_user.shost)
#define user_ccname (sudo_user.krb5_ccname)
+#define user_display (sudo_user.display)
+#define user_askpass (sudo_user.askpass)
#define safe_cmnd (sudo_user.cmnd_safe)
#define login_class (sudo_user.class_name)
#define runas_pw (sudo_user._runas_pw)
*/
#define TGP_ECHO 0x01 /* leave echo on when reading passwd */
#define TGP_STDIN 0x02 /* read from stdin, not /dev/tty */
+#define TGP_ASKPASS 0x03 /* read from askpass helper program */
struct lbuf;
struct passwd;
* Usage strings for sudo. These are here because we
* need to be able to substitute values from configure.
*/
-#define SUDO_USAGE1 " -h | -K | -k | -L | -V | -v"
-#define SUDO_USAGE2 " -l[l] [-g groupname|#gid] [-U username] [-u username|#uid] [-g groupname|#gid] [command]"
-#define SUDO_USAGE3 " [-bEHPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] [<command>]"
-#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] [<command>]"
+#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 */
/*
- * Copyright (c) 1996, 1998-2005 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 1996, 1998-2005, 2007-2008
+ * Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
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.
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;
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;