diff options
-rw-r--r-- | openbsd-compat/bsd-openpty.c | 67 | ||||
-rw-r--r-- | sshd.c | 7 |
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; @@ -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", |