summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsd-compat/bsd-openpty.c67
-rw-r--r--sshd.c7
2 files changed, 47 insertions, 27 deletions
diff --git a/openbsd-compat/bsd-openpty.c b/openbsd-compat/bsd-openpty.c
index 1ab41f42..078d666c 100644
--- a/openbsd-compat/bsd-openpty.c
+++ b/openbsd-compat/bsd-openpty.c
@@ -71,28 +71,11 @@
#define O_NOCTTY 0
#endif
-int
-openpty(int *amaster, int *aslave, char *name, struct termios *termp,
+#if defined(HAVE_DEV_PTMX) && !defined(HAVE__GETPTY)
+static int
+openpty_streams(int *amaster, int *aslave, char *name, struct termios *termp,
struct winsize *winp)
{
-#if defined(HAVE__GETPTY)
- /*
- * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
- * pty's automagically when needed
- */
- char *slave;
-
- if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
- return (-1);
-
- /* Open the slave side. */
- if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
- close(*amaster);
- return (-1);
- }
- return (0);
-
-#elif defined(HAVE_DEV_PTMX)
/*
* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
* also has bsd-style ptys, but they simply do not work.)
@@ -141,9 +124,53 @@ openpty(int *amaster, int *aslave, char *name, struct termios *termp,
# ifndef __hpux
ioctl(*aslave, I_PUSH, "ttcompat");
# endif /* __hpux */
+ return (0);
+}
+#endif
+
+int
+openpty(int *amaster, int *aslave, char *name, struct termios *termp,
+ struct winsize *winp)
+{
+#if defined(HAVE__GETPTY)
+ /*
+ * _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
+ * pty's automagically when needed
+ */
+ char *slave;
+
+ if ((slave = _getpty(amaster, O_RDWR, 0622, 0)) == NULL)
+ return (-1);
+ /* Open the slave side. */
+ if ((*aslave = open(slave, O_RDWR | O_NOCTTY)) == -1) {
+ close(*amaster);
+ return (-1);
+ }
return (0);
+#elif defined(HAVE_DEV_PTMX)
+
+#ifdef SSHD_ACQUIRES_CTTY
+ /*
+ * On some (most? all?) SysV based systems with STREAMS based terminals,
+ * sshd will acquire a controlling terminal when it pushes the "ptem"
+ * module. On such platforms, first allocate a sacrificial pty so
+ * that sshd already has a controlling terminal before allocating the
+ * one that will be passed back to the user process. This ensures
+ * the second pty is not already the controlling terminal for a
+ * different session and is available to become controlling terminal
+ * for the client's subprocess. See bugzilla #245 for details.
+ */
+ static int junk_ptyfd = -1, junk_ttyfd;
+
+ if (junk_ptyfd == -1)
+ (void)openpty_streams(&junk_ptyfd, &junk_ttyfd, NULL, NULL,
+ NULL);
+#endif
+
+ return openpty_streams(amaster, aslave, name, termp, winp);
+
#elif defined(HAVE_DEV_PTS_AND_PTC)
/* AIX-style pty code. */
const char *ttname;
diff --git a/sshd.c b/sshd.c
index 53526b59..ef18ba46 100644
--- a/sshd.c
+++ b/sshd.c
@@ -2080,15 +2080,8 @@ main(int ac, char **av)
* setlogin() affects the entire process group. We don't
* want the child to be able to affect the parent.
*/
-#if !defined(SSHD_ACQUIRES_CTTY)
- /*
- * If setsid is called, on some platforms sshd will later acquire a
- * controlling terminal which will result in "could not set
- * controlling tty" errors.
- */
if (!debug_flag && !inetd_flag && setsid() == -1)
error("setsid: %.100s", strerror(errno));
-#endif
if (rexec_flag) {
debug("rexec start in %d out %d newsock %d pipe %d sock %d",