On Sun, Mar 03, 2002 at 08:56:45PM -0500, Jeff Licquia wrote:
> I agree that there is a security impact to this, though; gnome-sudo
> would be better if it supported this. With all the flamage, I'm tempted
> to submit a patch to do this.
This seems difficult with support in sudo for it: there doesn't seem
to be any way for the launcher (gnome-sudo) to tell whether sudo's
asked for a password without the program being run telling the launcher
that it's running now. Which means the gnome-sudo-helper needs to be
in sudoers, which means the only option is running sudo twice somehow,
which I think still has problems (if your local config is to always ask
for passwords, eg).
So, here's one way of changing sudo. It essentially adds support for the
SSH_ASKPASS environment variable for querying passwords and such. Since
XAUTHORITY is passed through in the environment, this should do away
with the need for gnome-sudo-helper, and just let gnome-sudo call "sudo
<cmd>" directly.
It appears to work, and doesn't have at least one obvious security hole.
It doesn't do all its dialogue via ssh-askpass, though, which might be
considered a bug.
diff -urb sudo-1.6.5p1/debian/changelog sudo-1.6.5p1-aj/debian/changelog
--- sudo-1.6.5p1/debian/changelog Mon Mar 4 14:21:24 2002
+++ sudo-1.6.5p1-aj/debian/changelog Mon Mar 4 14:39:30 2002
@@ -1,3 +1,10 @@
+sudo (1.6.5p1-3.1) unstable; urgency=low
+
+ * Add support for getting passphrase from ssh-askpass.
+ * Fixes free-of-unallocated-memory bug in auth/pam.c (Closes: Bug#131235)
+
+ -- Anthony Towns <aj@azure.humbug.org.au> Mon, 4 Mar 2002 13:11:54 +1000
+
sudo (1.6.5p1-3) unstable; urgency=high
* ugly hack to add --disable-saved-ids when building on sparc in response
diff -urb sudo-1.6.5p1/auth/pam.c sudo-1.6.5p1-aj/auth/pam.c
--- sudo-1.6.5p1/auth/pam.c Mon Mar 4 14:21:24 2002
+++ sudo-1.6.5p1-aj/auth/pam.c Mon Mar 4 14:20:37 2002
@@ -220,7 +220,7 @@
pr->resp = estrdup((char *) tgetpass(p,
def_ival(I_PASSWD_TIMEOUT) * 60, tgetpass_flags));
if (pr->resp == NULL)
- pr->resp = "";
+ pr->resp = strdup(""); /* freed later */
if (*pr->resp == '\0')
nil_pw = 1; /* empty password */
break;
diff -urb sudo-1.6.5p1/env.c sudo-1.6.5p1-aj/env.c
--- sudo-1.6.5p1/env.c Wed Jan 16 09:43:58 2002
+++ sudo-1.6.5p1-aj/env.c Mon Mar 4 14:24:14 2002
@@ -154,6 +154,10 @@
for (ep = envp; *ep; ep++) {
switch (**ep) {
+ case 'D':
+ if (strncmp("DISPLAY=", *ep, 8) == 0)
+ break; /* needed for ssh-askpass to work */
+ continue;
case 'H':
if (strncmp("HOME=", *ep, 5) == 0)
break;
@@ -174,6 +178,8 @@
user_shell = *ep + 6;
else if (!user_prompt && !strncmp("SUDO_PROMPT=", *ep, 12))
user_prompt = *ep + 12;
+ else if (!user_sshaskpass && !strncmp("SSH_ASKPASS=", *ep, 12))
+ user_sshaskpass = *ep + 12;
continue;
case 'T':
if (strncmp("TZ=", *ep, 3) == 0)
Only in sudo-1.6.5p1-aj/: foo.sh
diff -urb sudo-1.6.5p1/sudo.c sudo-1.6.5p1-aj/sudo.c
--- sudo-1.6.5p1/sudo.c Wed Jan 16 09:43:59 2002
+++ sudo-1.6.5p1-aj/sudo.c Mon Mar 4 14:44:30 2002
@@ -736,6 +736,14 @@
case 'S':
tgetpass_flags |= TGP_STDIN;
break;
+ case 'A':
+ if (!user_sshaskpass) {
+ (void) fprintf(stderr,
+ "%s: -A requires SSH_ASKPASS\n", Argv[0]);
+ usage(1);
+ }
+ tgetpass_flags |= TGP_SSHASKPASS;
+ break;
case '-':
NewArgc--;
NewArgv++;
@@ -1022,7 +1030,7 @@
{
(void) fprintf(stderr, "usage: sudo -V | -h | -L | -l | -v | -k | -K | %s",
- "[-H] [-P] [-S] [-b] [-p prompt]\n [-u username/#uid] ");
+ "[-A] [-H] [-P] [-S] [-b]\n [-p prompt] [-u username/#uid] ");
#ifdef HAVE_LOGIN_CAP_H
(void) fprintf(stderr, "[-c class] ");
#endif
diff -urb sudo-1.6.5p1/sudo.h sudo-1.6.5p1-aj/sudo.h
--- sudo-1.6.5p1/sudo.h Thu Jan 17 07:27:09 2002
+++ sudo-1.6.5p1-aj/sudo.h Mon Mar 4 13:27:58 2002
@@ -60,6 +60,7 @@
char *cmnd;
char *cmnd_args;
char *class_name;
+ char *sshaskpass;
};
/*
@@ -135,6 +136,7 @@
#define user_prompt (sudo_user.prompt)
#define user_host (sudo_user.host)
#define user_shost (sudo_user.shost)
+#define user_sshaskpass (sudo_user.sshaskpass)
#define safe_cmnd (sudo_user.cmnd_safe)
#define login_class (sudo_user.class_name)
#define runas_pw (sudo_user._runas_pw)
@@ -171,6 +173,7 @@
*/
#define TGP_ECHO 0x01 /* leave echo on when reading passwd */
#define TGP_STDIN 0x02 /* read from stdin, not /dev/tty */
+#define TGP_SSHASKPASS 0x04 /* if set, use SSH_ASKPASS on DISPLAY */
/*
* Function prototypes
diff -urb sudo-1.6.5p1/sudo.man.in sudo-1.6.5p1-aj/sudo.man.in
--- sudo-1.6.5p1/sudo.man.in Thu Jan 17 09:36:09 2002
+++ sudo-1.6.5p1-aj/sudo.man.in Mon Mar 4 14:26:28 2002
@@ -145,7 +145,7 @@
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBsudo\fR \fB\-V\fR | \fB\-h\fR | \fB\-l\fR | \fB\-L\fR | \fB\-v\fR | \fB\-k\fR | \fB\-K\fR | \fB\-s\fR |
-[ \fB\-H\fR ] [\fB\-P\fR ] [\fB\-S\fR ] [ \fB\-b\fR ] | [ \fB\-p\fR \fIprompt\fR ]
+[ \fB-A\fR ] [ \fB\-H\fR ] [\fB\-P\fR ] [\fB\-S\fR ] [ \fB\-b\fR ] | [ \fB\-p\fR \fIprompt\fR ]
[ \fB\-c\fR \fIclass\fR|\fI-\fR ] [ \fB\-a\fR \fIauth_type\fR ]
[ \fB\-u\fR \fIusername\fR|\fI#uid\fR ] \fIcommand\fR
.SH "DESCRIPTION"
@@ -262,6 +262,13 @@
The \fB\-s\fR (\fIshell\fR) option runs the shell specified by the \fI\s-1SHELL\s0\fR
environment variable if it is set or the shell as specified
in \fIpasswd\fR\|(@mansectform@).
+.Ip "\-A" 4
+.IX Item "-A"
+The \fB\-A\fR option runs the program specified in the \fI\s-1SSH_ASKPASS\s0\fR
+envrionment variable to obtain the password. The program should accept a single
+argument for the prompt, and return a single line on stdout for the password.
+Note that most environment variables have been cleared before this program is
+run.
.Ip "\-H" 4
.IX Item "-H"
The \fB\-H\fR (\fI\s-1HOME\s0\fR) option sets the \f(CW\*(C`HOME\*(C'\fR environment variable
diff -urb sudo-1.6.5p1/tgetpass.c sudo-1.6.5p1-aj/tgetpass.c
--- sudo-1.6.5p1/tgetpass.c Tue Dec 18 09:56:47 2001
+++ sudo-1.6.5p1-aj/tgetpass.c Mon Mar 4 14:21:09 2002
@@ -36,6 +36,7 @@
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/wait.h>
#ifdef HAVE_SYS_BSDTYPES_H
# include <sys/bsdtypes.h>
#endif /* HAVE_SYS_BSDTYPES_H */
@@ -131,6 +132,59 @@
static void handler __P((int));
/*
+ * Call external command (ssh-askpass) to get password. Useful for GUIs.
+ */
+char *
+tsshaskpass(prompt, buf, bufsize)
+ const char *prompt;
+ char *buf;
+ int bufsize;
+{
+ int fromchild[2];
+ pid_t child;
+ int len, status;
+
+ if (0 != pipe(fromchild)) return NULL;
+
+ child = fork();
+ if (child < 0) {
+ close(fromchild[0]); close(fromchild[1]);
+ return NULL;
+ }
+
+ if (child == 0) { /* I'm the child */
+ set_perms(PERM_FULL_USER, 0);
+
+ close(fromchild[0]);
+
+ if (fromchild[1] != 1) {
+ dup2(fromchild[1], 1);
+ close(fromchild[1]);
+ }
+
+ execlp(user_sshaskpass, user_sshaskpass, prompt, NULL);
+ exit(1);
+ }
+
+ /* I'm the parent */
+ close(fromchild[1]);
+
+ /* Read the first line of output from the child */
+ len = read(fromchild[0], buf, bufsize - 1);
+ close(fromchild[0]);
+
+ while (waitpid(child, &status, 0) < 0)
+ if (errno != EINTR)
+ break;
+ if (len <= 1)
+ return NULL;
+ buf[len] = '\0';
+ buf[strcspn(buf, "\r\n")] = '\0';
+
+ return (buf[0] != '\0') ? buf : NULL;
+}
+
+/*
* Like getpass(3) but with timeout and echo flags.
*/
char *
@@ -145,6 +199,10 @@
int input, output, save_errno;
struct TERM term, oterm;
char *pass;
+
+ if (flags & TGP_SSHASKPASS) {
+ return tsshaskpass(prompt, buf, sizeof(buf));
+ }
restart:
/* Open /dev/tty for reading/writing if possible else use stdin/stderr. */
Cheers,
aj
--
Anthony Towns <aj@humbug.org.au> <http://azure.humbug.org.au/~aj/>
We came. We Saw. We Conferenced. http://linux.conf.au/
``Debian: giving you the power to shoot yourself in each
toe individually.'' -- with kudos to Greg Lehey
Attachment:
pgpuJlDtVOOz7.pgp
Description: PGP signature