ssh-add bug
Andrew Pimlott
andrew at pimlott.ne.mediaone.net
Thu Jan 18 12:19:07 EST 2001
There is an amusing bug in ssh-add that causes it to go into an
infinite loop. I am using openssh 1.2.3, and noticed that when I
ran "ssh-add < /dev/null" in my X startup scripts, but didn't have
ssh-askpass installed, ssh-add started spewing errors into my
.xsession-errors and didn't stop.
I found that what happens is: ssh-add forks and attempts to exec
ssh-askpass. The exec-ed process is supposed to pass back the
passphrase on stdout. However, when the exec fails, the child
ssh-add process exits and--if stdout was not a terminal--flushes its
stdio buffers, which happen to contain a "Need passphrase" message.
As a result, the parent ssh-add sees what it interprets as a
passphrase coming back from the child. It tries to use this to
decript the key, fails, and tries the whole thing over again.
You can reproduce by moving ssh-askpass to another name (setting
SSH_ASKPASS=nowhere should also do) and running "ssh-add < /dev/null
> /dev/null". A strace showing this folly is at the end. I think a
patch that fixes this is
--- ssh-add.c.orig Wed Jan 17 20:09:29 2001
+++ ssh-add.c Wed Jan 17 20:14:07 2001
@@ -59,6 +59,9 @@
int p[2], status;
char buf[1024];
+ /* make sure child doesn't accidentally blab to stdout */
+ if (fflush(stdout) != 0)
+ fatal("ssh_askpass: fflush: %s", strerror(errno));
if (askpass == NULL)
fatal("internal error: askpass undefined");
if (pipe(p) < 0)
(untested because I don't have all the libraries on this machine to
recompile).
Andrew
Strace output:
pipe([4, 5]) = 0
fork() = 16582
[pid 19607] close(5) = 0
[pid 19607] read(4, <unfinished ...>
[pid 16582] close(4) = 0
[pid 16582] dup2(5, 1) = 1
[pid 16582] execve("/usr/bin/ssh-askpass", ["/usr/bin/ssh-askpass", "Bad passphr
ase, try again"], [/* 20 vars */]) = -1 ENOENT (No such file or directory)
[pid 16582] write(2, "ssh_askpass: exec(/usr/bin/ssh-a"..., 66) = 66
[pid 16582] write(2, "\r\n", 2) = 2
[pid 16582] write(1, "Need passphrase for /home/pimlot"..., 48) = 48
[pid 16582] munmap(0x40018000, 4096) = 0
[pid 16582] _exit(255) = ?
<... read resumed> "Need passphrase for /home/pimlot"..., 1024) = 48
--- SIGCHLD (Child exited) ---
close(4) = 0
wait4(16582, [WIFEXITED(s) && WEXITSTATUS(s) == 255], 0, NULL) = 16582
open("/home/pimlott/.ssh/identity", O_RDONLY) = 4
fstat(4, {st_mode=S_IFREG|0600, st_size=529, ...}) = 0
getuid() = 1000
getuid() = 1000
lseek(4, 0, SEEK_END) = 529
lseek(4, 0, SEEK_SET) = 0
read(4, "SSH PRIVATE KEY FILE FORMAT 1.1\n"..., 529) = 529
close(4) = 0
pipe([4, 5]) = 0
fork() = 16583
More information about the openssh-unix-dev
mailing list