Print this page
14249 pseudo-terminal nomenclature should reflect POSIX
Change-Id: Ib4a3cef899ff4c71b09cb0dc6878863c5e8357bc
*** 240,250 ****
#define TS_WONT 6 /* wont " */
#define TS_DO 7 /* do " */
#define TS_DONT 8 /* dont " */
static int ncc;
! static int master; /* master side of pty */
static int pty; /* side of pty that gets ioctls */
static int net;
static int inter;
extern char **environ;
static char *line;
--- 240,250 ----
#define TS_WONT 6 /* wont " */
#define TS_DO 7 /* do " */
#define TS_DONT 8 /* dont " */
static int ncc;
! static int manager; /* manager side of pty */
static int pty; /* side of pty that gets ioctls */
static int net;
static int inter;
extern char **environ;
static char *line;
*** 2752,2783 ****
struct sockaddr_in6 *sin6;
socklen_t wholen;
char username[MAXUSERNAMELEN];
int len;
uchar_t passthru;
! char *slavename;
if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
fatalperror(f, "open /dev/ptmx", errno);
}
if (grantpt(p) == -1)
! fatal(f, "could not grant slave pty");
if (unlockpt(p) == -1)
! fatal(f, "could not unlock slave pty");
! if ((slavename = ptsname(p)) == NULL)
! fatal(f, "could not enable slave pty");
(void) dup2(f, 0);
! if ((t = open(slavename, O_RDWR | O_NOCTTY)) == -1)
! fatal(f, "could not open slave pty");
if (ioctl(t, I_PUSH, "ptem") == -1)
fatalperror(f, "ioctl I_PUSH ptem", errno);
if (ioctl(t, I_PUSH, "ldterm") == -1)
fatalperror(f, "ioctl I_PUSH ldterm", errno);
if (ioctl(t, I_PUSH, "ttcompat") == -1)
fatalperror(f, "ioctl I_PUSH ttcompat", errno);
! line = slavename;
pty = t;
if (ioctl(t, TIOCGETP, &b) == -1)
syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
--- 2752,2783 ----
struct sockaddr_in6 *sin6;
socklen_t wholen;
char username[MAXUSERNAMELEN];
int len;
uchar_t passthru;
! char *subsidname;
if ((p = open("/dev/ptmx", O_RDWR | O_NOCTTY)) == -1) {
fatalperror(f, "open /dev/ptmx", errno);
}
if (grantpt(p) == -1)
! fatal(f, "could not grant subsidiary pty");
if (unlockpt(p) == -1)
! fatal(f, "could not unlock subsidiary pty");
! if ((subsidname = ptsname(p)) == NULL)
! fatal(f, "could not enable subsidiary pty");
(void) dup2(f, 0);
! if ((t = open(subsidname, O_RDWR | O_NOCTTY)) == -1)
! fatal(f, "could not open subsidiary pty");
if (ioctl(t, I_PUSH, "ptem") == -1)
fatalperror(f, "ioctl I_PUSH ptem", errno);
if (ioctl(t, I_PUSH, "ldterm") == -1)
fatalperror(f, "ioctl I_PUSH ldterm", errno);
if (ioctl(t, I_PUSH, "ttcompat") == -1)
fatalperror(f, "ioctl I_PUSH ttcompat", errno);
! line = subsidname;
pty = t;
if (ioctl(t, TIOCGETP, &b) == -1)
syslog(LOG_INFO, "ioctl TIOCGETP pty t: %m\n");
*** 3037,3047 ****
if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
net = netfd;
! master = ptmfd;
cryptmod_fd = netfd;
/*
* Show banner that getty never gave, but
* only if the user did not automatically authenticate.
--- 3037,3047 ----
if (ioctl(ptmfd, I_STR, &telnetmod) < 0)
fatal(netfd, "ioctl LOGDMX_IOC_QEXCHANGE of ptmfd failed\n");
net = netfd;
! manager = ptmfd;
cryptmod_fd = netfd;
/*
* Show banner that getty never gave, but
* only if the user did not automatically authenticate.
*** 3098,3112 ****
remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
if ((pid = fork()) < 0)
fatalperror(netfd, "fork", errno);
if (pid)
! telnet(net, master);
/*
* The child process needs to be the session leader
* and have the pty as its controlling tty. Thus we need
! * to re-open the slave side of the pty no without
* the O_NOCTTY flag that we have been careful to
* use up to this point.
*/
(void) setsid();
--- 3098,3112 ----
remopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;
if ((pid = fork()) < 0)
fatalperror(netfd, "fork", errno);
if (pid)
! telnet(net, manager);
/*
* The child process needs to be the session leader
* and have the pty as its controlling tty. Thus we need
! * to re-open the subsidiary side of the pty no without
* the O_NOCTTY flag that we have been careful to
* use up to this point.
*/
(void) setsid();
*** 3190,3200 ****
(auth_status == AUTH_VALID || auth_status == AUTH_USER) &&
((krb5_name != NULL) && strlen(krb5_name)) &&
((AuthenticatingUser != NULL) && strlen(AuthenticatingUser))) {
(void) execl(LOGIN_PROGRAM, "login",
"-p",
! "-d", slavename,
"-h", host,
"-u", krb5_name,
"-s", pam_svc_name,
"-R", KRB5_REPOSITORY_NAME,
AuthenticatingUser, 0);
--- 3190,3200 ----
(auth_status == AUTH_VALID || auth_status == AUTH_USER) &&
((krb5_name != NULL) && strlen(krb5_name)) &&
((AuthenticatingUser != NULL) && strlen(AuthenticatingUser))) {
(void) execl(LOGIN_PROGRAM, "login",
"-p",
! "-d", subsidname,
"-h", host,
"-u", krb5_name,
"-s", pam_svc_name,
"-R", KRB5_REPOSITORY_NAME,
AuthenticatingUser, 0);
*** 3206,3224 ****
* If we only know the name but not the principal,
* login will have to authenticate further.
*/
(void) execl(LOGIN_PROGRAM, "login",
"-p",
! "-d", slavename,
"-h", host,
"-s", pam_svc_name, "--",
(AuthenticatingUser != NULL ? AuthenticatingUser :
getenv("USER")), 0);
} else /* default, no auth. info available, login does it all */ {
(void) execl(LOGIN_PROGRAM, "login",
! "-p", "-h", host, "-d", slavename, "--",
getenv("USER"), 0);
}
fatalperror(netfd, LOGIN_PROGRAM, errno);
/*NOTREACHED*/
--- 3206,3224 ----
* If we only know the name but not the principal,
* login will have to authenticate further.
*/
(void) execl(LOGIN_PROGRAM, "login",
"-p",
! "-d", subsidname,
"-h", host,
"-s", pam_svc_name, "--",
(AuthenticatingUser != NULL ? AuthenticatingUser :
getenv("USER")), 0);
} else /* default, no auth. info available, login does it all */ {
(void) execl(LOGIN_PROGRAM, "login",
! "-p", "-h", host, "-d", subsidname, "--",
getenv("USER"), 0);
}
fatalperror(netfd, LOGIN_PROGRAM, errno);
/*NOTREACHED*/
*** 3252,3262 ****
* when it receives telnet protocol. Regular data
* flow between pty and network takes place through
* inkernel telnet streams module (telmod).
*/
static void
! telnet(int net, int master)
{
int on = 1;
char mode;
struct strioctl telnetmod;
int nsize = 0;
--- 3252,3262 ----
* when it receives telnet protocol. Regular data
* flow between pty and network takes place through
* inkernel telnet streams module (telmod).
*/
static void
! telnet(int net, int manager)
{
int on = 1;
char mode;
struct strioctl telnetmod;
int nsize = 0;
*** 3263,3273 ****
char binary_in = 0;
char binary_out = 0;
if (ioctl(net, FIONBIO, &on) == -1)
syslog(LOG_INFO, "ioctl FIONBIO net: %m\n");
! if (ioctl(master, FIONBIO, &on) == -1)
syslog(LOG_INFO, "ioctl FIONBIO pty p: %m\n");
(void) signal(SIGTSTP, SIG_IGN);
(void) signal(SIGCHLD, (void (*)())cleanup);
(void) setpgrp();
--- 3263,3273 ----
char binary_in = 0;
char binary_out = 0;
if (ioctl(net, FIONBIO, &on) == -1)
syslog(LOG_INFO, "ioctl FIONBIO net: %m\n");
! if (ioctl(manager, FIONBIO, &on) == -1)
syslog(LOG_INFO, "ioctl FIONBIO pty p: %m\n");
(void) signal(SIGTSTP, SIG_IGN);
(void) signal(SIGCHLD, (void (*)())cleanup);
(void) setpgrp();
*** 3300,3310 ****
/*
* Never look for input if there's still
* stuff in the corresponding output buffer
*/
if (pfrontp - pbackp) {
! FD_SET(master, &obits);
} else {
FD_SET(net, &ibits);
}
if (!SYNCHing) {
FD_SET(net, &xbits);
--- 3300,3310 ----
/*
* Never look for input if there's still
* stuff in the corresponding output buffer
*/
if (pfrontp - pbackp) {
! FD_SET(manager, &obits);
} else {
FD_SET(net, &ibits);
}
if (!SYNCHing) {
FD_SET(net, &xbits);
*** 3388,3398 ****
if (ioctl(net, I_STR, &telnetmod) < 0)
fatal(net, "ioctl TEL_IOC_GETBLK failed\n");
}
! if ((c = select(max(net, master) + 1, &ibits, &obits, &xbits,
(struct timeval *)0)) < 1) {
if (c == -1) {
if (errno == EINTR) {
continue;
}
--- 3388,3398 ----
if (ioctl(net, I_STR, &telnetmod) < 0)
fatal(net, "ioctl TEL_IOC_GETBLK failed\n");
}
! if ((c = select(max(net, manager) + 1, &ibits, &obits, &xbits,
(struct timeval *)0)) < 1) {
if (c == -1) {
if (errno == EINTR) {
continue;
}
*** 3425,3435 ****
if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
netflush();
if (ncc > 0)
telrcv();
! if (FD_ISSET(master, &obits) && (pfrontp - pbackp) > 0)
ptyflush();
}
cleanup(0);
}
--- 3425,3435 ----
if (FD_ISSET(net, &obits) && (nfrontp - nbackp) > 0)
netflush();
if (ncc > 0)
telrcv();
! if (FD_ISSET(manager, &obits) && (pfrontp - pbackp) > 0)
ptyflush();
}
cleanup(0);
}
*** 4277,4287 ****
ptyflush(void)
{
int n;
if ((n = pfrontp - pbackp) > 0)
! n = write(master, pbackp, n);
if (n < 0)
return;
pbackp += n;
if (pbackp == pfrontp)
pbackp = pfrontp = ptyobuf;
--- 4277,4287 ----
ptyflush(void)
{
int n;
if ((n = pfrontp - pbackp) > 0)
! n = write(manager, pbackp, n);
if (n < 0)
return;
pbackp += n;
if (pbackp == pfrontp)
pbackp = pfrontp = ptyobuf;
*** 4445,4457 ****
cleanup(int signum)
{
/*
* If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
* handle closing differently. We close "net" first and then
! * "master" in that order. We do close(net) first because
* we have no other way to disconnect forwarding between the network
! * and master. So by issuing the close()'s we ensure that no further
* data rises from TCP. A more complex fix would be adding proper
* support for throwing a "stop" switch for forwarding data between
* logindmux peers. It's possible to block in the close of the tty
* while the network still receives data and the telmod module is
* TEL_STOPPED. A denial-of-service attack generates this case,
--- 4445,4457 ----
cleanup(int signum)
{
/*
* If the TEL_IOC_ENABLE ioctl hasn't completed, then we need to
* handle closing differently. We close "net" first and then
! * "manager" in that order. We do close(net) first because
* we have no other way to disconnect forwarding between the network
! * and manager. So by issuing the close()'s we ensure that no further
* data rises from TCP. A more complex fix would be adding proper
* support for throwing a "stop" switch for forwarding data between
* logindmux peers. It's possible to block in the close of the tty
* while the network still receives data and the telmod module is
* TEL_STOPPED. A denial-of-service attack generates this case,
*** 4458,4468 ****
* see 4102102.
*/
if (!telmod_init_done) {
(void) close(net);
! (void) close(master);
}
rmut();
exit(EXIT_FAILURE);
}
--- 4458,4468 ----
* see 4102102.
*/
if (!telmod_init_done) {
(void) close(net);
! (void) close(manager);
}
rmut();
exit(EXIT_FAILURE);
}