11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: sshpty.c,v 1.28 2007/09/11 23:49:09 stevesk Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Author: Tatu Ylonen <ylo@cs.hut.fi>
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *                    All rights reserved
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Allocating a pseudo-terminal, and making it the controlling tty.
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * As far as I am concerned, the code I have written for this software
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * can be used freely for any purpose.  Any derived versions of this
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * software must be clearly marked as such, and if the derived work is
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * incompatible with the protocol description in the RFC file, it must be
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * called by a name other than "ssh" or "Secure Shell".
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/ioctl.h>
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/stat.h>
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <signal.h>
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h>
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <fcntl.h>
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <grp.h>
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PATHS_H
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <paths.h>
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <pwd.h>
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <termios.h>
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_UTIL_H
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <util.h>
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h>
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "sshpty.h"
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h"
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_PTY_H
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <pty.h>
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef O_NOCTTY
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define O_NOCTTY 0
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef __APPLE__
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <AvailabilityMacros.h>
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#  define __APPLE_PRIVPTY__
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# endif
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Allocates and opens a pty.  Returns 0 if no pty could be allocated, or
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * nonzero if a pty was successfully allocated.  On success, open file
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * descriptors for the pty and tty sides and the name of the tty side are
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * returned (the buffer must be able to hold at least 64 characters).
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* openpty(3) exists in OSF/1 and some other os'es */
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *name;
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (i < 0) {
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("openpty: %.100s", strerror(errno));
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
751b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood#ifdef ANDROID
761b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood	/* Android does not have a working ttyname() */
771b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood	name = "/dev/ptmx";
781b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood#else
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	name = ttyname(*ttyfd);
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (!name)
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("openpty returns device for which ttyname fails.");
821b6cc98e30329f380546d5f22b1c9c975e3df4f8Mike Lockwood#endif
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	strlcpy(namebuf, name, namebuflen);	/* possible truncation */
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 1;
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Releases the tty.  Its ownership is returned to root, and permissions to 0666. */
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpty_release(const char *tty)
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifndef __APPLE_PRIVPTY__
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (chown(tty, (uid_t) 0, (gid_t) 0) < 0)
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("chown %.100s 0 0 failed: %.100s", tty, strerror(errno));
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (chmod(tty, (mode_t) 0666) < 0)
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("chmod %.100s 0666 failed: %.100s", tty, strerror(errno));
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* __APPLE_PRIVPTY__ */
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Makes the tty the process's controlling tty and sets it to sane modes. */
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpty_make_controlling_tty(int *ttyfd, const char *tty)
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int fd;
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_VHANGUP
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	void *old;
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_VHANGUP */
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef _UNICOS
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setsid() < 0)
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("setsid: %.100s", strerror(errno));
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd = open(tty, O_RDWR|O_NOCTTY);
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd != -1) {
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGHUP, SIG_IGN);
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		ioctl(fd, TCVHUP, (char *)NULL);
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		signal(SIGHUP, SIG_DFL);
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		setpgid(0, 0);
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Failed to disconnect from controlling tty.");
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Setting controlling tty using TCSETCTTY.");
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ioctl(*ttyfd, TCSETCTTY, NULL);
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd = open("/dev/tty", O_RDWR);
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd < 0)
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%.100s: %.100s", tty, strerror(errno));
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	close(*ttyfd);
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	*ttyfd = fd;
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* _UNICOS */
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* First disconnect from the old controlling tty. */
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef TIOCNOTTY
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd >= 0) {
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		(void) ioctl(fd, TIOCNOTTY, NULL);
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* TIOCNOTTY */
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setsid() < 0)
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("setsid: %.100s", strerror(errno));
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Verify that we are successfully disconnected from the controlling
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * tty.
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd >= 0) {
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("Failed to disconnect from controlling tty.");
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Make it our controlling tty. */
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef TIOCSCTTY
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	debug("Setting controlling tty using TIOCSCTTY.");
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("ioctl(TIOCSCTTY): %.100s", strerror(errno));
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* TIOCSCTTY */
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef NEED_SETPGRP
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (setpgrp(0,0) < 0)
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("SETPGRP %s",strerror(errno));
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* NEED_SETPGRP */
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_VHANGUP
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	old = signal(SIGHUP, SIG_IGN);
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	vhangup();
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	signal(SIGHUP, old);
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_VHANGUP */
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd = open(tty, O_RDWR);
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd < 0) {
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("%.100s: %.100s", tty, strerror(errno));
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef USE_VHANGUP
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(*ttyfd);
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*ttyfd = fd;
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* USE_VHANGUP */
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* USE_VHANGUP */
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Verify that we now have a controlling tty. */
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	fd = open(_PATH_TTY, O_WRONLY);
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (fd < 0)
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		error("open /dev/tty failed - could not set controlling tty: %.100s",
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	else
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		close(fd);
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* _UNICOS */
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* Changes the window size associated with the pty. */
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpty_change_window_size(int ptyfd, u_int row, u_int col,
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int xpixel, u_int ypixel)
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct winsize w;
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* may truncate u_int -> u_short */
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	w.ws_row = row;
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	w.ws_col = col;
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	w.ws_xpixel = xpixel;
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	w.ws_ypixel = ypixel;
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	(void) ioctl(ptyfd, TIOCSWINSZ, &w);
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodpty_setowner(struct passwd *pw, const char *tty)
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct group *grp;
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	gid_t gid;
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	mode_t mode;
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct stat st;
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Determine the group to make the owner of the tty. */
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	grp = getgrnam("tty");
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (grp) {
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		gid = grp->gr_gid;
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		mode = S_IRUSR | S_IWUSR | S_IWGRP;
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} else {
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		gid = pw->pw_gid;
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		mode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/*
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Change owner and mode of the tty as required.
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * Warn but continue if filesystem is read-only and the uids match/
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 * tty is owned by root.
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	 */
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (stat(tty, &st))
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		fatal("stat(%.100s) failed: %.100s", tty,
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		    strerror(errno));
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef WITH_SELINUX
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	ssh_selinux_setup_pty(pw->pw_name, tty);
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (chown(tty, pw->pw_uid, gid) < 0) {
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (errno == EROFS &&
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    (st.st_uid == pw->pw_uid || st.st_uid == 0))
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("chown(%.100s, %u, %u) failed: %.100s",
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    tty, (u_int)pw->pw_uid, (u_int)gid,
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    strerror(errno));
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("chown(%.100s, %u, %u) failed: %.100s",
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    tty, (u_int)pw->pw_uid, (u_int)gid,
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    strerror(errno));
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (chmod(tty, mode) < 0) {
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (errno == EROFS &&
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				debug("chmod(%.100s, 0%o) failed: %.100s",
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    tty, (u_int)mode, strerror(errno));
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			else
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				fatal("chmod(%.100s, 0%o) failed: %.100s",
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				    tty, (u_int)mode, strerror(errno));
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
264