From e3fc19a176c1ed2c266aca03cb5bcc17d0192630 Mon Sep 17 00:00:00 2001 From: Sadrul Habib Chowdhury Date: Mon, 11 Aug 2008 23:11:58 -0400 Subject: [PATCH] Require password, when applicable, for remote detach If a session has a password set, then it should be necessary for the user to enter the password before a remote detach. This change achieves that behaviour. A small change in the messaging system is necessary, thus bumping the message version, for the first time since it has been introduced, it seems. But I don't think it's going to break anything. Discussion at #24029 --- src/attacher.c | 21 +++- src/screen.c | 3 +- src/screen.h | 4 +- src/socket.c | 328 ++++++++++++++++++++++++++++++++++++++------------------- 4 files changed, 242 insertions(+), 114 deletions(-) diff --git a/src/attacher.c b/src/attacher.c index edba8d0..fe3956e 100644 --- a/src/attacher.c +++ b/src/attacher.c @@ -306,7 +306,7 @@ int how; Panic(0, "That screen is %sdetached.", dflag ? "already " : "not "); #ifdef REMOTE_DETACH if (dflag && - (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH)) + (how == MSG_DETACH || how == MSG_POW_DETACH)) { m.m.detach.dpid = getpid(); strncpy(m.m.detach.duser, LoginName, sizeof(m.m.detach.duser) - 1); @@ -317,9 +317,16 @@ int how; else # endif m.type = MSG_DETACH; + /* If there is no password for the session, or the user enters the correct + * password, then we get a SIGCONT. Otherwise we get a SIG_BYE */ + signal(SIGCONT, AttachSigCont); if (WriteMessage(lasts, &m)) Panic(errno, "WriteMessage"); close(lasts); + while (!ContinuePlease) + pause(); /* wait for SIGCONT */ + signal(SIGCONT, SIG_DFL); + ContinuePlease = 0; if (how != MSG_ATTACH) return 0; /* we detached it. jw. */ sleep(1); /* we dont want to overrun our poor backend. jw. */ @@ -348,6 +355,18 @@ int how; m.m.attach.columns = atoi(s); m.m.attach.encoding = nwin_options.encoding > 0 ? nwin_options.encoding + 1 : 0; +#ifdef REMOTE_DETACH +#ifdef POW_DETACH + if (dflag == 2) + m.m.attach.detachfirst = MSG_POW_DETACH; + else +#endif + if (dflag) + m.m.attach.detachfirst = MSG_DETACH; + else +#endif + m.m.attach.detachfirst = MSG_ATTACH; + #ifdef MULTIUSER /* setup CONT signal handler to repair the terminal mode */ if (multi && (how == MSG_ATTACH || how == MSG_CONT)) diff --git a/src/screen.c b/src/screen.c index 1a0646c..20954ba 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1160,7 +1160,8 @@ char **av; } else if (dflag && !mflag) { - (void) Attach(MSG_DETACH); + SET_TTYNAME(0); + Attach(MSG_DETACH); Msg(0, "[%s %sdetached.]\n", SockName, (dflag > 1 ? "power " : "")); eexit(0); /* NOTREACHED */ diff --git a/src/screen.h b/src/screen.h index 633f948..3798b33 100644 --- a/src/screen.h +++ b/src/screen.h @@ -171,8 +171,9 @@ struct mode /* * versions of struct msg: * 0: screen version 3.6.6 (version count introduced) + * 1: screen version 4.1.0 */ -#define MSG_VERSION 0 +#define MSG_VERSION 1 #define MSG_REVISION (('m'<<24) | ('s'<<16) | ('g'<<8) | MSG_VERSION) struct msg { @@ -204,6 +205,7 @@ struct msg int meta_esc; /* his new meta esc character unless -1 */ char envterm[20 + 1]; /* terminal type */ int encoding; /* encoding of display */ + int detachfirst; /* whether to detach remote sessions first */ } attach; struct diff --git a/src/socket.c b/src/socket.c index 4ac85de..09aa73d 100644 --- a/src/socket.c +++ b/src/socket.c @@ -53,6 +53,7 @@ static void DoCommandMsg __P((struct msg *)); static int sconnect __P((int, struct sockaddr *, int)); #endif static void FinishAttach __P((struct msg *)); +static void FinishDetach __P((struct msg *)); static void AskPassword __P((struct msg *)); @@ -777,6 +778,150 @@ char *s1, *s2; # define TTYCMP(a, b) strcmp(a, b) #endif +static int +CreateTempDisplay(m, recvfd, wi) +struct msg *m; +int recvfd; +struct win *wi; +{ + int pid; + int attach; + char *user; + int i; + struct mode Mode; + struct display *olddisplays = displays; + + switch (m->type) + { + case MSG_ATTACH: + pid = m->m.attach.apid; + user = m->m.attach.auser; + attach = 1; + break; +#ifdef REMOTE_DETACH + case MSG_DETACH: +# ifdef POW_DETACH + case MSG_POW_DETACH: +# endif /* POW_DETACH */ + pid = m->m.detach.dpid; + user = m->m.detach.duser; + attach = 0; + break; +#endif + default: + return -1; + } + + if (CheckPid(pid)) + { + Msg(0, "Attach attempt with bad pid(%d)!", pid); + return -1; + } + if (recvfd != -1) + { + char *myttyname; + i = recvfd; + recvfd = -1; + myttyname = ttyname(i); + if (myttyname == 0 || strcmp(myttyname, m->m_tty)) + { + Msg(errno, "Attach: passed fd does not match tty: %s - %s!", m->m_tty, myttyname ? myttyname : "NULL"); + close(i); + Kill(pid, SIG_BYE); + return -1; + } + } + else if ((i = secopen(m->m_tty, O_RDWR | O_NONBLOCK, 0)) < 0) + { + Msg(errno, "Attach: Could not open %s!", m->m_tty); + Kill(pid, SIG_BYE); + return -1; + } +#ifdef MULTIUSER + if (attach) + Kill(pid, SIGCONT); +#endif + +#if defined(ultrix) || defined(pyr) || defined(NeXT) + brktty(i); /* for some strange reason this must be done */ +#endif + + if (attach) + { + if (display || wi) + { + write(i, "Attaching from inside of screen?\n", 33); + close(i); + Kill(pid, SIG_BYE); + Msg(0, "Attach msg ignored: coming from inside."); + return -1; + } + +#ifdef MULTIUSER + if (strcmp(user, LoginName)) + if (*FindUserPtr(user) == 0) + { + write(i, "Access to session denied.\n", 26); + close(i); + Kill(pid, SIG_BYE); + Msg(0, "Attach: access denied for user %s.", user); + return -1; + } +#endif + + debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", pid, m->m_tty); +#ifndef MULTI + if (displays) + { + write(i, "Screen session in use.\n", 23); + close(i); + Kill(pid, SIG_BYE); + return -1; + } +#endif + } + + /* create new display */ + GetTTY(i, &Mode); + if (MakeDisplay(user, m->m_tty, attach ? m->m.attach.envterm : "", i, pid, &Mode) == 0) + { + write(i, "Could not make display.\n", 24); + close(i); + Msg(0, "Attach: could not make display for user %s", user); + Kill(pid, SIG_BYE); + return -1; + } +#ifdef ENCODINGS + if (attach) + { +# ifdef UTF8 + D_encoding = m->m.attach.encoding == 1 ? UTF8 : m->m.attach.encoding ? m->m.attach.encoding - 1 : 0; +# else + D_encoding = m->m.attach.encoding ? m->m.attach.encoding - 1 : 0; +# endif + if (D_encoding < 0 || !EncodingName(D_encoding)) + D_encoding = 0; +#endif + } + + if (iflag && olddisplays) + { + iflag = 0; +#if defined(TERMIO) || defined(POSIX) + olddisplays->d_NewMode.tio.c_cc[VINTR] = VDISABLE; + olddisplays->d_NewMode.tio.c_lflag &= ~ISIG; +#else /* TERMIO || POSIX */ + olddisplays->d_NewMode.m_tchars.t_intrc = -1; +#endif /* TERMIO || POSIX */ + SetTTY(olddisplays->d_userfd, &olddisplays->d_NewMode); + } + SetMode(&D_OldMode, &D_NewMode, D_flow, iflag); + SetTTY(D_userfd, &D_NewMode); + if (fcntl(D_userfd, F_SETFL, FNBLOCK)) + Msg(errno, "Warning: NBLOCK fcntl failed"); + return 0; +} + void ReceiveMsg() { @@ -791,6 +936,7 @@ ReceiveMsg() #endif struct display *olddisplays = displays; int recvfd = -1; + struct acluser *user; #ifdef NAMEDPIPE debug("Ha, there was someone knocking on my fifo??\n"); @@ -970,107 +1116,8 @@ ReceiveMsg() /* FALLTHROUGH */ case MSG_ATTACH: - if (CheckPid(m.m.attach.apid)) - { - Msg(0, "Attach attempt with bad pid(%d)!", m.m.attach.apid); - break; - } - if (recvfd != -1) - { - char *myttyname; - i = recvfd; - recvfd = -1; - myttyname = ttyname(i); - if (myttyname == 0 || strcmp(myttyname, m.m_tty)) - { - Msg(errno, "Attach: passed fd does not match tty: %s - %s!", m.m_tty, myttyname ? myttyname : "NULL"); - close(i); - Kill(m.m.attach.apid, SIG_BYE); - break; - } - } - else if ((i = secopen(m.m_tty, O_RDWR | O_NONBLOCK, 0)) < 0) - { - Msg(errno, "Attach: Could not open %s!", m.m_tty); - Kill(m.m.attach.apid, SIG_BYE); - break; - } -# ifdef MULTIUSER - Kill(m.m.attach.apid, SIGCONT); -# endif - -#if defined(ultrix) || defined(pyr) || defined(NeXT) - brktty(i); /* for some strange reason this must be done */ -#endif - - if (display || wi) - { - write(i, "Attaching from inside of screen?\n", 33); - close(i); - Kill(m.m.attach.apid, SIG_BYE); - Msg(0, "Attach msg ignored: coming from inside."); - break; - } - -#ifdef MULTIUSER - if (strcmp(m.m.attach.auser, LoginName)) - if (*FindUserPtr(m.m.attach.auser) == 0) - { - write(i, "Access to session denied.\n", 26); - close(i); - Kill(m.m.attach.apid, SIG_BYE); - Msg(0, "Attach: access denied for user %s.", m.m.attach.auser); - break; - } -#endif - - debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m_tty); -#ifndef MULTI - if (displays) - { - write(i, "Screen session in use.\n", 23); - close(i); - Kill(m.m.attach.apid, SIG_BYE); - break; - } -#endif - - /* create new display */ - GetTTY(i, &Mode); - if (MakeDisplay(m.m.attach.auser, m.m_tty, m.m.attach.envterm, i, m.m.attach.apid, &Mode) == 0) - { - write(i, "Could not make display.\n", 24); - close(i); - Msg(0, "Attach: could not make display for user %s", m.m.attach.auser); - Kill(m.m.attach.apid, SIG_BYE); - break; - } -#ifdef ENCODINGS -# ifdef UTF8 - D_encoding = m.m.attach.encoding == 1 ? UTF8 : m.m.attach.encoding ? m.m.attach.encoding - 1 : 0; -# else - D_encoding = m.m.attach.encoding ? m.m.attach.encoding - 1 : 0; -# endif - if (D_encoding < 0 || !EncodingName(D_encoding)) - D_encoding = 0; -#endif - /* turn off iflag on a multi-attach... */ - if (iflag && olddisplays) - { - iflag = 0; -#if defined(TERMIO) || defined(POSIX) - olddisplays->d_NewMode.tio.c_cc[VINTR] = VDISABLE; - olddisplays->d_NewMode.tio.c_lflag &= ~ISIG; -#else /* TERMIO || POSIX */ - olddisplays->d_NewMode.m_tchars.t_intrc = -1; -#endif /* TERMIO || POSIX */ - SetTTY(olddisplays->d_userfd, &olddisplays->d_NewMode); - } - SetMode(&D_OldMode, &D_NewMode, D_flow, iflag); - SetTTY(D_userfd, &D_NewMode); - if (fcntl(D_userfd, F_SETFL, FNBLOCK)) - Msg(errno, "Warning: NBLOCK fcntl failed"); - + if (CreateTempDisplay(&m, recvfd, wi)) + break; #ifdef PASSWORD if (D_user->u_password && *D_user->u_password) AskPassword(&m); @@ -1090,17 +1137,17 @@ ReceiveMsg() # ifdef POW_DETACH case MSG_POW_DETACH: # endif /* POW_DETACH */ - for (display = displays; display; display = next) +#ifdef PASSWORD + user = *FindUserPtr(m.m.detach.duser); + if (user && user->u_password && *user->u_password) { - next = display->d_next; -# ifdef POW_DETACH - if (m.type == MSG_POW_DETACH) - Detach(D_REMOTE_POWER); - else -# endif /* POW_DETACH */ - if (m.type == MSG_DETACH) - Detach(D_REMOTE); + if (CreateTempDisplay(&m, recvfd, 0)) + break; + AskPassword(&m); } + else +#endif /* PASSWORD */ + FinishDetach(&m); break; #endif case MSG_COMMAND: @@ -1198,6 +1245,9 @@ struct msg *m; ASSERT(display); pid = D_userpid; + if (m->m.attach.detachfirst != MSG_ATTACH) + FinishDetach(m); + #if defined(pyr) || defined(xelos) || defined(sequent) /* * Kludge for systems with braindamaged termcap routines, @@ -1342,6 +1392,59 @@ struct msg *m; # endif /* SIG_NODEBUG */ } +static void +FinishDetach(m) +struct msg *m; +{ + struct display *next, **d, *det; + int pid; + + if (m->type == MSG_ATTACH) + pid = D_userpid; + else + pid = m->m.detach.dpid; + + /* Remove the temporary display prompting for the password from the list */ + for (d = &displays; (det = *d); d = &det->d_next) + { + if (det->d_userpid == pid) + break; + } + if (det) + { + *d = det->d_next; + det->d_next = 0; + } + + for (display = displays; display; display = next) + { + next = display->d_next; +# ifdef POW_DETACH + if (m->type == MSG_POW_DETACH) + Detach(D_REMOTE_POWER); + else +# endif /* POW_DETACH */ + if (m->type == MSG_DETACH) + Detach(D_REMOTE); + else if (m->type == MSG_ATTACH) + { +#ifdef POW_DETACH + if (m->m.attach.detachfirst == MSG_POW_DETACH) + Detach(D_REMOTE_POWER); + else +#endif + if (m->m.attach.detachfirst == MSG_DETACH) + Detach(D_REMOTE); + } + } + display = displays = det; + if (m->type != MSG_ATTACH) + { + if (display) + FreeDisplay(); + Kill(pid, SIGCONT); + } +} #ifdef PASSWORD static void PasswordProcessInput __P((char *, int)); @@ -1404,7 +1507,10 @@ int ilen; AddStr("\r\n"); D_processinputdata = 0; D_processinput = ProcessInput; - FinishAttach(&pwdata->m); + if (pwdata->m.type == MSG_ATTACH) + FinishAttach(&pwdata->m); + else + FinishDetach(&pwdata->m); free(pwdata); return; } -- 2.11.4.GIT