Patch for hanging ssh-add under Solaris CDE

Dave Dykstra dwd at bell-labs.com
Fri Oct 19 05:15:57 EST 2001


One of my users found that the new ssh-add, from the portable OpenSSH CVS
as of October 12, was hanging in his .profile while trying to start up CDE
(Common Desktop Environment) on Solaris 2.6.  The previous one, which was
from OpenSSH 2.9p2, did not hang.  It turns out that CDE, at least on
Solaris 2.6, 7 and 8, runs the user's .profile with a special startup shell
that allocates a pseudo-tty (I assume so people can use "stty" to set their
preferred settings) but is not attached to anything that can actually
accept user input.   Those of you with Solaris can reproduce with

    DTSOURCEPROFILE=true /usr/dt/bin/sdt_shell -c ssh-add

I discovered that the problem was that the new readpassphrase() function is
flushing (that is, discarding) the terminal input but the old function
cli_read_passphrase() did not.  When input is not flushed, then ssh-add
gets an immediate end of file and exits.  When the input is flushed, a 
subsequent read from stdin hangs.  I see by truss that sdt_shell is actually
write an end-of-file character (^D) to the pseudo-tty, and apparently that
results in a single zero-length read on the other side if it isn't flushed.

You may wonder why the user was calling ssh-add from his .profile; it's
because after CDE comes up the user runs an xterm (dtterm actually) with
"-C -ls", which means a console window running as a login shell, which
executes .profile again, and he goes to that console window to type in his
passphrase.  And actually the user was not following the documented way of
using CDE, in that a comment in ~/.dtprofile says that anything which is
going to result in reading from the user is supposed to be surrounded by a

    if [ ! "$DT" ]; then 
	... read data ...
    fi

On the other hand, the old ssh-add used to work and the new one doesn't
so it may cause problems for more people.

A patch to go back to the old way is attached in case it is wanted.  You
might think that because readpassphrase() usually turns off echoing, that
flushing the input is a good idea.  If that's desired, I suggest either
adding another flag or using the existing RPP_REQUIRE_TTY flag and using
_T_FLUSH only if that is set.  That flag is not set for ssh-add, but it is
set for other things.

- Dave Dykstra


--- openbsd-compat/readpassphrase.c.O	Fri Oct 12 17:12:22 2001
+++ openbsd-compat/readpassphrase.c	Thu Oct 18 13:59:25 2001
@@ -36,12 +36,6 @@
 #include <termios.h>
 #include <readpassphrase.h>
 
-#ifdef TCSASOFT
-# define _T_FLUSH	(TCSAFLUSH|TCSASOFT)
-#else
-# define _T_FLUSH	(TCSAFLUSH)
-#endif
-
 char *
 readpassphrase(prompt, buf, bufsiz, flags)
 	const char *prompt;
@@ -102,13 +96,13 @@
 			term.c_cc[VSTATUS] = _POSIX_VDISABLE;
 		}
 #endif
-		(void)tcsetattr(input, _T_FLUSH, &term);
+		(void)tcsetattr(input, TCSANOW, &term);
 	}
 	if (!(flags & RPP_ECHO_ON)) {
 		if (tcgetattr(input, &term) == 0 && (term.c_lflag & ECHO)) {
 			echo = 1;
 			term.c_lflag &= ~ECHO;
-			(void)tcsetattr(input, _T_FLUSH, &term);
+			(void)tcsetattr(input, TCSANOW, &term);
 		}
 	}
 
@@ -141,7 +135,7 @@
 		if (status != _POSIX_VDISABLE)
 			term.c_cc[VSTATUS] = status;
 #endif
-		(void)tcsetattr(input, _T_FLUSH, &term);
+		(void)tcsetattr(input, TCSANOW, &term);
 	}
 	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
 	if (input != STDIN_FILENO)



More information about the openssh-unix-dev mailing list