[comp.unix.wizards] Session management

tchrist@convex.COM (Tom Christiansen) (08/27/90)

In article <8319:Aug2617:20:3690@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>This is the correct behavior. The difficulties with locking up tty ports
>are reflections of two different problems: first, that ptys aren't
>dynamically allocated in 4BSD; and second, that standard ttys exist at
>all. Hardwired /dev/tty* should be replaced with raw /dev/modem* and so
>on; *all* tty use should go through a common interface provided by a
>pseudo-terminal session manager. This would solve many problems at once.

I think there is a crying need such a thing because the same code gets
written again and again to do essentially the same thin How would you like
to see a pty session manager work?  I'm going to throw out some
off-the-cuff ideas, plus a lot of for-thought questions, to see what the
net thinks.

I'd like to solve at least these problems:

    1. getting the pty name right (varies system to system)
    2. race condition between choosing a name and trying the open
    3. the need to be suid to get a pty
    4. the need to chown the pty appropriately
    5. the need to properly update utmp and wtmp

Many programs (script, window, xterm) would no longer need to be
setuid to munge utmp or chown ptys, which would be a nice plus.

Off the top of my head, here are some ideas that are implementable on a
BSD system.  

I would make a daemon server that everyone talked to in order to get
the session.  You could instead put it in the kernel as a special 
"/dev/pty" pseudo-driver that did the allocation for you, but I don't
see much that having it in the kernel might gain you considering
the cost.

How might it actually work?

If we used a UNIX-domain UDP socket, we could pass file descriptors
between processes.  Let the daemon do all the work of finding, opening,
and chowning the pty, plus the [wu]tmp munging.  He could just call

    if (getpty(&master_fd, &slave_fd) != -1) {

and have the fd's filled in.  Would we want to know the name?  If so, 
we could something like this do this:

    if ((ptyname = getpty(&master_fd, &slave_fd)) != (char *)0) {

You say, but wait, you might want to be able to make this work for remote
logins, so I can't use UNIX domain sockets.  Perhaps this is a valid
point: if we did that, could we get rid of rlogind, telnetd, Then how
would the file-descriptor hand-off take place?  What about urgent data and
stderr?  Can the pty model really be adopted to the socket and connect
method?  Since telnet, rlogin, DECNET-style sethost, and Sun's "on -i"
program all use different protocols, I suspect this is infeasible.  Maybe
we better leave it as is and keep and rlogind and friends around, but this
is mildly unsettling.

How would the daemon know that when the pty was free so that it could
return the pty to the free pool and fix up utmp and wtmp?  

Rlogind knows because the login process is his child whom he waits on, but
the session manager deals with unrelated processes.   If the function were
to actually spawn a login-shell on a pty, then it could wait for the kid
to do the cleanup, but that sort of behavior wouldn't always be
appropriate.

If we placed it in the kernel, I supposed the close routine could know to
do the right thing, but I wouldn't like to have the kernel mucking with
[wu]tmp files.  Maybe a stronger interaction with the kernel, as in Suns'
lock daemon and its kernel RPC calls.

Do you ever NOT want an entry in utmp?  Sometimes ptys are used to run
processes that just want a tty but aren't really a login session.  Should
they be?  xterm (sometimes) and emacs don't currently put lines there, but
I'm not sure whether this is a feature or not.  If we really wanted it, we
could have either two entry points or else an extra parameter.

Could this be made to work using non-BSD systems?  Would it eventually
go in a POSIX spec, and if so, which one?  Certainly system calls and
library functions, but what of networking or system administration?

Has this been done yet?  Attempted?  Contemplated?  

--tom
--
 "UNIX was never designed to keep people from doing stupid things, because 
  that policy would also keep them from doing clever things." [Doug Gwyn]

moss@cs.umass.edu (Eliot Moss) (08/27/90)

An additional feature I definitely want is for the session manager to retain a
session for some user-selectable time (with a system chosen upper bound) if
the remote end drops before logout. I lose modem connections because of noise
frequently, and it is really annoying to have to reconstruct my whole job tree
when that happens. (The VMS pty stuff keeps sessions around as described, and
when you relogin you get the option of connecting to your abandoned job or
creating a new one.)
--

		J. Eliot B. Moss, Assistant Professor
		Department of Computer and Information Science
		Lederle Graduate Research Center
		University of Massachusetts
		Amherst, MA  01003
		(413) 545-4206; Moss@cs.umass.edu

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (08/27/90)

In article <105387@convex.convex.com> tchrist@convex.COM (Tom Christiansen) writes:
> In article <8319:Aug2617:20:3690@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >This is the correct behavior. The difficulties with locking up tty ports
> >are reflections of two different problems: first, that ptys aren't
> >dynamically allocated in 4BSD; and second, that standard ttys exist at
> >all. Hardwired /dev/tty* should be replaced with raw /dev/modem* and so
> >on; *all* tty use should go through a common interface provided by a
> >pseudo-terminal session manager. This would solve many problems at once.
> I think there is a crying need such a thing because the same code gets
> written again and again to do essentially the same thing

I agree. That's why pty 3.001, the ultimate pseudo-terminal manager, is
about to come out in c.s.unix. It provides every good feature that
Steve Bellovin mentions for his session manager, without the fuss.
It's already been reported to work on a huge variety of BSD-based
machines.

> How would you like
> to see a pty session manager work?

The way pty works, with some support of course.

> I'd like to solve at least these problems:
>     1. getting the pty name right (varies system to system)

pty solves this basically by hiding it from the user. ptys should not be
tied to the filesystem; they should be allocated dynamically. pty makes
sure that the user doesn't have to depend on filesystem ptys or static
ptys. Anyway, as is it supports any pty bank names, e.g., /dev/fooXY for
the master and /dev/boinkXY for the slave, with X from [54y-!] and Y
from [01234treuio].

>     2. race condition between choosing a name and trying the open

pty solves this (along with a host of other pty security problems). See
the code in getfreepty().

>     3. the need to be suid to get a pty

pty solves this. (Of course, it can be compiled and installed by
unprivileged users on current insecure systems; I wouldn't want to
take this away.)

>     4. the need to chown the pty appropriately

pty solves this, with a host of related options.

>     5. the need to properly update utmp and wtmp

pty supports both utmp and wtmp, again with a host of configuration
options.

> Many programs (script, window, xterm) would no longer need to be
> setuid to munge utmp or chown ptys, which would be a nice plus.

An improved clone of script is provided along with pty. It's a tiny
shell script. It's just one of twenty-one free public-domain utilities
provided with pty.

> I would make a daemon server that everyone talked to in order to get
> the session.

I disagree. The right interface is pty's program-based interface. As an
illustration of the power of the interface, the pty package includes
patches for telnetd. The patches integrate pty session support into
telnetd, so that users can disconnect and reconnect sessions with no
effort. The interface is so good that the patched telnetd is just as
efficient as the original version, believe it or not.

Under pty's interface, there could be such a daemon, but the user
shouldn't care.

Also, you cannot achieve security unless you have a separate (setuid)
process.

> You say, but wait, you might want to be able to make this work for remote
> logins, so I can't use UNIX domain sockets.  Perhaps this is a valid
> point: if we did that, could we get rid of rlogind, telnetd, Then how
> would the file-descriptor hand-off take place?  What about urgent data and
> stderr?

I'm not sure what you're asking here. pty's telnet patches aren't
enough?

> How would the daemon know that when the pty was free so that it could
> return the pty to the free pool and fix up utmp and wtmp?  

pty handles this by just waiting for the child to exit. Note that it
keeps output around for a disconnected session until you get a chance to
reconnect.

> Rlogind knows because the login process is his child whom he waits on, but
> the session manager deals with unrelated processes.   If the function were
> to actually spawn a login-shell on a pty, then it could wait for the kid
> to do the cleanup, but that sort of behavior wouldn't always be
> appropriate.

True. In fact, the right model for logins is as follows: You connect
to (say) telnetd; telnetd starts a login process, *without* a pty; if
you get in, your shell is (say) ``pty /bin/csh'', so that you get a pty.

> Do you ever NOT want an entry in utmp?  Sometimes ptys are used to run
> processes that just want a tty but aren't really a login session.

My interpretation of utmp is that it should reflect interactive sessions
only. My PD wall clone uses utmp this way, as do talk programs. Anyway,
pty has -xu and -xU options to turn utmp on and off; the sysadmin can
require or disable utmp use, of course.

> Could this be made to work using non-BSD systems?

Well, I'm (slowly) working on a streams-based version, but I've never
been very close to System V. (Help?) The pty interface would remain
almost exactly the same.

> Would it eventually
> go in a POSIX spec, and if so, which one?  Certainly system calls and
> library functions, but what of networking or system administration?

None of the above: it should be a separate program. Hooray for program
modularity! Hooray for interface design!

> Has this been done yet?  Attempted?  Contemplated?  

Attempted and completed. pty.3.001.shar will appear on c.s.unix very
soon. If you're desperate, complain at rsalz@bbn.com. If you're really
desperate, anon ftp a copy from the pub/ directory on 128.122.128.22.

To repeat the paragraph prompting this thread: Under pty, hardwired
/dev/tty* should be replaced with /dev/modem* and so on. *All* pty use
should go through the pty program. (Of course, administrators would
have a special non-pty shell just in case something went wrong.) This
provides a trusted path between incoming connections and the login
program, with obvious methods; it makes all sessions disconnectable,
as per Steve Bellovin's session manager; and so on.

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (08/27/90)

In article <MOSS.90Aug27081600@ibis.cs.umass.edu> moss@cs.umass.edu writes:
> An additional feature I definitely want is for the session manager to retain a
> session for some user-selectable time (with a system chosen upper bound) if
> the remote end drops before logout.

I agree, and pty does this too! It's very nice to be able to just flip
my terminal off in case of trouble, then reconnect later from anywhere.
I don't know how I lived without this feature.

pty doesn't implement the time limit: I was thinking of including it in
the code, but it's easy enough to do manually. (Under the session, check
every once in a while through sesslist. If the session is disconnected
and has the same signaller at two successive checks, kill -HUP all the
processes and sesskill the session.)

> I lose modem connections because of noise
> frequently, and it is really annoying to have to reconstruct my whole job tree
> when that happens.

Agreed. pty also lets you manually disconnect. This machine had to be
taken down a couple of days ago, but before that I had a single shell
running for a month. I just disconnected and reconnected every time,
saving on shell startup time, eliminating the need for vi -r, and
generally reducing angst.

> (The VMS pty stuff keeps sessions around as described, and
> when you relogin you get the option of connecting to your abandoned job or
> creating a new one.)

I source this script early in my login sequence (before aliases):

$HOME/links/sesslist
$HOME/links/sesslist | grep -s disconnected \
  && ( echo -n 'Reconnect to session (return to ignore): '; \
       set reconnect="$<"; \
       if ( a"$reconnect"b != ab ) exec sess reconnect "$reconnect"; \
     )

Primitive, but it gets the job done. A few minutes ago I just typed qf
and popped back into this session.

Once again, pty 3.001, the ultimate pseudo-terminal manager (implemented
for BSD variants only at the moment), will appear soon on c.s.unix. If
you're desperate, ask rsalz@bbn.com. If you're really desperate, anon
ftp to the pub/ directory on 128.122.128.22.

---Dan

mmcg@bruce.cs.monash.OZ.AU (Mike McGaughey) (08/28/90)

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>I agree, and pty does this too! [and a zillion other things]

But do you get a free set of steak knives?

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (08/28/90)

In article <2976@bruce.cs.monash.OZ.AU> mmcg@bruce.cs.monash.OZ.AU (Mike McGaughey) writes:
> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >I agree, and pty does this too! [and a zillion other things]
> But do you get a free set of steak knives?

Yes! Just call 1-900-PTY-STKN and order your set TODAY! :-)

Seriously, I haven't yet mentioned (in this thread, anyway) that pty
comes with twenty-one short public-domain utilities, including improved
clones of script (utmp support, extra flexibility), u (sort bug gone),
who (slightly faster, better who am i handling), write (fixes four
distinct security holes), lock (various bugs fixed, more obnoxious upon
failed password); straight clones of wall, tty, biff, mesg; and more!
Get your AT&T-free public domain clones TODAY!

---Dan

boyd@necisa.ho.necisa.oz (Boyd Roberts) (08/28/90)

In article <105387@convex.convex.com> tchrist@convex.COM (Tom Christiansen) writes:
>
>I would make a daemon server that everyone talked to in order to get
>the session.  You could instead put it in the kernel as a special 
>"/dev/pty" pseudo-driver that did the allocation for you, but I don't
>see much that having it in the kernel might gain you considering
>the cost.
>

You can do this stuff with a `mounted process', the connection line
discipline (conn_ld) and the message line discipline (mesg_ld) with V8/9/10.

When "/dev/service" is opened your user mode process gets a message
that something is requesting an open (via select() and read()) and you
then pass a file descriptor back across the stream (with the
right line discplines pushed) that refers to "/dev/serviceXX".

Your process, mounted on "/dev/service", manages a table of
"/dev/serviceXX" for some XX.  And, of course, you can deny the
service as well.  The message you get tells you who's on the
far end of the open -- but it's fairly UNIX specific  (uid, gid,
login name and process nice value -- from memory).

I think its a lot simpler with the V9 ipc library, but I don't have
my V9 manual to hand.  But the library hides some of the
intricacies of the implementation.   It's nice.

Hume will followup and catch me out -- just watch...


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

davidb@Pacer.UUCP (David Barts) (08/29/90)

In article <105387@convex.convex.com>, tchrist@convex.COM (Tom Christiansen) writes:
> :
> :
> I'd like to solve at least these problems:
> 
>     1. getting the pty name right (varies system to system)
>     2. race condition between choosing a name and trying the open
> . . .

I thought master pty's only allowed one open at a time (at least that's
what the HP-UX docs say).  So choosing a name is easy -- just read
through the /dev directory (or wherever the ptys are).  For each name
that matches the naming convention of a master pty, try to open it.  If
the open succeeds, you have your pty pair.  (You can't open a closed
master pty whose slave is still open, because that will fail also.)

The only possible problem that I see is if some other unwanted process
opens your slave pty.  But this can be solved by keeping all the ptys
owned by root and not world read- or writable (to limit use of ptys to
trusted programs that follow this opening protocol).  So I can see
where the need for suid programs and chown()ing comes in, but I can't
see the race condition, since choosing the name and trying the open are
the same step.

Am I missing something here?  (I looked in the man pages for our
Solbourne system, and couldn't find anything as detailed as the rules
laid out in the HP man pages for when a master pty will open.) Is this
behavior of master pty's unique to HP-UX?

The one time I wrote a program that used ptys, I used the above
approach and it seemed to work just fine.
-- 
David Barts			Pacer Corporation, Bothell, WA
davidb@pacer.uucp		...!uunet!pilchuck!pacer!davidb