[alt.security] BSD tty security, part 3: How to Fix It

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/25/91)

Here's one way to fix the BSD 4.[234] tty system, i.e., to provide some
strong guarantees that pty and tty sessions are safe and not subject to
corruption or denial of service, with minimal changes to the kernel and
to application programs. This is also meant to apply to systems derived
from BSD, such as SunOS, Ultrix, etc.

I've included quite a bit of sample code here, as well as evaluations of
what effect these changes will have on users and old programs. Thanks in
particular to Marc Teitelbaum for his extensive comments. The second
half of the article includes a bunch of optional recommendations that
may make your life easier but are not necessary for security.

Quick summary of kernel changes required: Make /dev/tty ioctls work on
/dev/tty??, make a /dev/stdtty driver which simply dup()s fd 3, and add
an ioctl, TIOCOPENCT, which returns the number of active references to a
given inode. That's it.

Quick summary of application changes required: Have certain programs do
an extra open() of the slave side to fd 3, move two device drivers, add
about fifteen lines of code (forty with complete error checks) to those
programs, add a new uid and group, make /dev/[pt]ty* world-inaccessible,
change chmod()s in those programs so that /dev/[pt]ty* remain
world-inaccessible, and make various programs setuid or setgid. That's
it.

1. Make all /dev/tty-specific ioctls work upon /dev/tty??. If the only
such ioctl is TIOCNOTTY, this is not necessary unless you want to
preserve the programmer's interface to detachment (which is probably
necessary). This may take some work. This step is safe, in that it will
not break working code.

2. Set up a /dev/stdtty driver that dup()s fd 3. This is tedious but not
difficult in principle. On systems with /dev/fd/3, all you have to do is
ln /dev/fd/3 /dev/stdtty. This step is safe.

3. Add an ioctl---I propose ioctl(fd,TIOCOPENCT,&x)---which *reliably*
sets x to the number of references to the *file* (not open file: I mean
file on disk, i.e., dev/inode pair, i.e., [igv]node) given by fd, or -1
if fd is not a disk file. Here ``reference'' means open file (i.e., the
thing in the file table). Under NFS I believe it is sufficient to report
v->v_count of the vnode. ``Reliably'' means that no matter what is going
on---swapped processes, locks of all sorts on the inode, file descriptor
passing, opening and closing---the returned information will be
absolutely correct starting from when ioctl() finishes and continuing as
long as no process opens or closes the file in question. This step is
safe.

4. Make sure that each of the tty-handling programs---getty, telnetd,
rlogind, script, etc.---opens /dev/ttyxx again in the master process and
leaves it open for use in #9 below. ``Master process'' means the process
in charge of the master side of the pty---telnetd, for instance. This is
easy:

	int fdttyagain; /* global variable */
	...
	/* in the parent right after fork */
	fdttyagain = open(line,O_RDWR);
	if (fdttyagain == -1)
	  syslog(LOG_CRIT,"cannot open %s again: %m",line);
	  /* or whatever your favorite error reporting method is */

This step is safe.

5. Make a new uid, pty. Make each of the non-root tty-handling programs
(that means script, as well as programs like atty, mtty, pty, etc. if
you have them installed) setuid pty, and make sure they reset uids
before executing anything. Do not make pty the same as root, unless your
system handles MAXUPRC by effective userid (ugh)---in that case you
can't safely run anything setuid to any user but root, and you should
complain to your vendor. (The latter is true under, e.g. Ultrix 3.1.)
This step is safe, but will take some work if you have many non-root
tty-handling programs.

6. Change the root tty-handling programs (e.g., telnetd) so that they
reset ttys to owner pty mode 600 rather than owner root mode 666. This
step will break any user programs that allocate ttys dynamically and
that you didn't take care of in #5. It is safe otherwise.

7. Have each of the tty-handling programs---getty, telnetd, rlogind,
script, etc.---open file descriptor 3 to the tty. This is trivial:

	{ /* after closing other descriptors, right before exec'ing the slave */
	 int fdtty;
	 fdtty = open(line,O_RDWR); /* line is, e.g., "/dev/ttyp7" */
	 if (fdtty == -1)
	   ; /* XXX: complain to the user, or exit */
	 else if (fdtty != 3)
	  {
	   if (dup2(fdtty,3) == -1)
	     ; /* XXX: complain to the user, or exit */
	   close(fdtty);
	  }
	}

This step will break any old code that assumes the first open() will
return 3. (Such code is disgusting, but this is beside the point.)

8. ln /dev/tty /dev/oldtty; rm /dev/tty; ln /dev/stdtty /dev/tty;
chmod 600 /dev/oldtty. This is the first change that will affect users
directly. However, if you have done steps 1, 2, and 7 correctly, nobody
will notice. Marc comments that any programs which redirect or close fd
3 will be affected if they later use /dev/tty; he couldn't think offhand
of any such programs except ksh, which isn't installed on most BSD
machines. If you do find further examples of such programs or scripts,
please post the fixes here. An alternative is to use fd 11 instead of
fd 3 throughout these changes; this won't help ksh, but I've never seen
a script use fd 11.

9. In each of the tty-handling programs, do the following upon slave
exit: (a) Clean up everything except (if it is convenient) [uw]tmp.
Close 0, 1, 2, and any other random descriptors lying around, except
/dev/ptyxx and /dev/ttyxx. (b) Test /dev/ttyxx with TIOCOPEN*. If
someone else still has it open, continue to step (c); otherwise skip to
step (d). (c) Fork, and exit in the parent. Repeatedly test /dev/ttyxx
(a five-second sleep is fine) until it is closed. (d) Clean up [uw]tmp
and exit. Note that steps (b) and (c) can fit into a simple library
routine. Here's sample code, with paranoid error checking:

	/* after cleaning up mostly everything */
	if (fdttyagain != -1)
	 {
	   /* Assumption: /dev/ttyxx is back to mode 600 owner pty. */
	  int count;
	  close(0); close(1); close(2);
	  ... /* close any other descriptors previously opened */
	      /* _except_ /dev/ptyxx (``fdpty'', perhaps) and fdttyagain */
	  (void) ioctl(fdttyagain,TIOCEXCL,(char *) 0);
	    /* entirely optional, but better safe than racing */
	    /* if TIOCOPENCT is not completely reliable */
	  if (ioctl(fdttyagain,TIOCOPENCT,&count) == -1)
	    syslog(LOG_CRIT,"cannot count open references to %s: %m",line);
	    /* or whatever your favorite error reporting method is */
	  else
	    if (count > 1)
	     {
	      syslog(LOG_INFO,"waiting on %s",line);
	      switch(fork())
	       {
	        case -1:
	 	  syslog(LOG_CRIT,"cannot fork to wait on %s: %m",line);
	 	  break;
	        case 0:
	 	   {
	 	    int i;
	 	    i = 0;
	 	    for (;;)
	 	     {
		      sleep(5);
		      if (ioctl(fdttyagain,TIOCOPENCT,&count) == -1)
	                syslog(LOG_CRIT,"weird: cannot count open references to %s: %m",line);
		      else
		        if (count == 1)
		 	  break;
		      ++i;
		      if (!(i % 1000))
		        syslog(LOG_INFO,"waited %d secs on %s",i * 5,line);
		      /* XXX: If i gets large enough, you may want to take */
		      /* desperate measures at this point. Example: */
		      /* vhangup(); fcntl(fdpty,F_SETFL,FNDELAY); */
		      /* vhangup(); write(fdpty,"x",1); vhangup(); */
		      /* read(fdpty,"y",1); vhangup(); */
		      /* And then break. */
		     }
		   }
		  syslog(LOG_INFO,"done waiting on %s",line);
		  break;
	        default:
	  	  exit(0);
 	       }
	     }
	  /* now finish cleaning up everything, and exit */
	 }

It doesn't really matter where the above code comes inside a cleanup
routine, as long as the tty already has the right modes. I think it's
aesthetically better to leave the utmp entry alone until the tty is
deallocated; but if this isn't convenient for some program, feel free to
ignore aesthetics and put the code right before exit().

Marc notes that this change will leave a pseudo-tty allocated to a user
as long as the user has a background process on the tty. Religious types
will say ``yes, that's how it should be.'' I say that at sites I'm
familiar with, this isn't a problem, because users don't run very many
background jobs, and there are more than enough pseudo-ttys. If this is
a problem for you, you will have to do step #20 below and educate your
users to detach background jobs, meanwhile killing any runaways. Sorry,
but this is the price you pay for security. You may prefer the
``desperate measures'' mentioned in the sample code to simply cut off
tty access after a few hours; any use of vhangup() is chock-full of race
conditions, but it would be exceedingly difficult for a process to make
it past all the races.

10. chown pty /dev/[pt]ty*; chmod 600 /dev/[pt]ty*. This is the big step.
Nonprivileged programs will no longer be able to open any ttys or ptys,
so nobody can deny service to other users without executing a privileged
program that will later show up in acct. Furthermore, the TIOCOPENCT
code guarantees that if a tty-handling program exits, absolutely nobody
is using that tty, so it is safe for immediate use by the next
tty-handling program. This throws a huge wrench into all the fundamental
tty security holes I know.

11. If you're using a Sun, make sure to chmod 600 /etc/utmp, or these
changes will go to waste. You may find it convenient to make certain
programs setgid or setuid here so that they can still write utmp, though
I consider this a mistake---you are bound to slip up when a hundred
different tools all manage one supposedly secure file. (But anything is
better than what Sun currently ships.)

12. Support the BSD 4.3 tty group model: make a new group, tty, chgrp
all /dev/tty* to it, and make ``talk'' and ``write'' setgid tty. Of
course, you don't need to do this if you already have the tty group.

It's possible to accomplish similar results with fewer changes. In fact,
my next version of pty will almost guarantee safety on stock BSD 4.2
systems with no kernel support except read access to /dev/kmem. (It is,
unfortunately, not possible to avoid race conditions from user code.)
You can, for example, place the burden of TIOCOPENCT checking upon the
program opening the tty, rather than the program closing it, so that
it's not a problem if one tty handler fails to do its job; but this
increases turnaround time for the users and allows denial-of-service
attacks. The above changes should be straightforward enough that halfway
solutions are not worthwhile.

(POSIX fans will note that using TIOCOPENCT to keep the tty allocated
past session leader exit *is* compliant: it only affects the secure BSD
exclusive lock on the master side, and does not prevent reassignment of
the slave tty to a new session---not that such a reassignment will ever
occur.)

Why must tty-handling programs be setuid rather than setgid? Because the
user must not be allowed to kill them---he would be able to retain tty
access that way.

There are many further changes you can make to eliminate minor security
holes or improve accounting. EVERYTHING BELOW THIS POINT IS COMPLETELY
OPTIONAL. Here are some of the most important:

13. Fix write. Many people don't appreciate how poor write's security
is; I quote from my pty paper's description of a write clone:

: Finally, write is a vastly improved clone. The old write had several big
: security holes: 1. Control characters were passed through. This version
: converts anything unprintable into a caret. 2. Lines were not
: distinctively marked. A user could manually simulate the ``EOT'' or
: ``EOF'' sequence, wait a few minutes, then start sending anything to the
: other tty without identification. This version precedes each line with
: the name of the sending user, and prints something more informative than
: EOT for an ended message. 3. write could be used to flood a terminal.
: (This is an accident waiting to happen.) This version puts a one-second
: pause between each line and restricts line length. 4. Originally, write
: would only check the protection on the tty being written to. But this
: meant that a user could be interrupted by someone hiding behind mesg n
: and have no recourse. (Footnote: Remember that UNIX has no enforce()
: call to enforce new permissions on an object. Setting mesg n does not
: stop a write in progress.) So many versions of write included
: ``revenge'': X was allowed to write to Y only if Y could write back.
: However, these versions tested tty protection only at the beginning of a
: message---which was useless. This version does the correct test: it
: simply checks write permission before sending each new line.

My write clone is public-domain, so I invite you---I beg you---to steal
code from it. Don't even give me any credit, just fix the bugs. Please.

14. Make script grok utmp and wtmp. (You may have to rethink certain
wtmp-based accounting schemes to do this.) Users constantly complain
that they can't ``talk'' within script, and the lack of accounting
is annoying. This doesn't matter under #18.

15. Change the chown() and fchown() system calls so that files can be
chowned between uid and euid. This opens up chown() for lots of secure
services without forcing the servers to run as root. In this case, it
lets script change the tty owner properly. This doesn't matter, though,
if you implement #16.

16. Don't even bother chowning ttys to the users who own them. (At this
point they might as well not be in the filesystem.) Yes, you can make
biff and mesg setuid pty, and no, nothing breaks except nroff's mesg n.

17. Make sure that telnetd, rlogind, etc. leave ttys with messages *off*
by default. Since UNIX has no way to enforce new access permissions on a
file, the usual default leaves all users open to instant attack. This is
a huge problem in the real world (at universities, at least), and while
there may be a sane argument for having messages on by default, it
cannot justify what amounts to unrestricted output to any and all ttys.

Finally, here are some optional changes that will make the above changes
much easier, or that will add basic features to your system. Do them
first and you'll never regret it.

18. Provide a program that spawns another program under a pseudo-tty,
handling I/O and job control transparently, and obeying all the rules
for tty handlers mentioned above. In fact, the program already exists by
the name of ``pty'' (see, e.g., comp.sources.unix volume 23), and its
author is quite willing to negotiate distribution terms. pty also
supports session management. (Isn't it embarrassing to explain UNIX to a
long-time VMS user? ``No, sorry, Bob, you can't get back to that shell
after your modem went on the fritz. The shell is gone.'' ``vi -r? Oh,
yeah, Bob, that means your connection got hung up.'' ``Nope, sorry, Bob,
you can't start recording a `talk' session without hanging up and
talking again.'' ``No, Bob. This is not VMS. Your process is stuck to
that terminal, right there. Yes, I understand, the terminal screen just
exploded, and you can't see your output. No, you cannot move to the next
terminal and continue work. Sorry, Bob, you're out of luck. Bye, Bob.'')

19. Rewrite all other tty handlers (it's easy---trust me) to invoke that
single, modular program. Don't you find it strange that a dozen programs
all have the same pty allocation code? Don't you find it unreasonable,
at least from a ``software engineering'' standpoint, that since people
are too lazy to do (e.g.) random tty searching every time they recopy
the same code, your average tty handler wastes several dozen open()s on
a big machine when it could use just two? In fact, I'll be glad to do
all the work of conversion for you, provided that you agree to make the
final version available for people to use.

20. Provide a program that detaches from its controlling tty and spawns
another program. The program is usually called ``detach'' and has no
options of note. It should also seek out and reopen("/dev/null") any
file descriptors pointing to any tty.

21. Delete /dev/oldtty and remove the /dev/tty driver from your kernel.
Also remove controlling ttys entirely. Also remove POSIX sessions if you
have them: make setsid() a no-op, and return an implementation-defined
error upon the pointless POSIX SIGCONT special case, and you even retain
POSIX compatibility if you had it. (Well, with one exception: POSIX
defines a foreground process in terms of its controlling terminal,
rather than the terminal it's trying to access as in BSD. Beg the POSIX
folks to make this rule optional---what do they lose?) Notice how much
extra space users get for running programs.

22. Make a stdio stream for stdtty, descriptor 3---after all, programs
do want to use it. Change csh and more to read from stdtty rather than
stderr. Someday you may even be able to open stderr write-only [gasp!].

23. Have accounting record the dev/inode pair on descriptor 3. In fact,
while you're making accounting work sensibly, record the pid, as well as
the dev/inode pair of the program run (if you can get that information).

24. Change getty to spawn the pty-handling program, and to disconnect
that session when it receives BREAK. Guess what? You've just set up a
trusted path.

Most of the recommendations here come from my pty paper, various drafts
of which have been available for many months. (TIOCOPEN* is new.) The
basic ideas come from Bellovin's ``Session Tty'' paper, which has been
available for years. If you get through all of the above and still want
to improve the tty system, you might get some further ideas out of those
papers. See pub/hier/pty/paper.9 on stealth.acf.nyu.edu and its
references for details.

---Dan

jef@ee.lbl.gov (Jef Poskanzer) (04/26/91)

In the referenced message, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote:
}13. Fix write. Many people don't appreciate how poor write's security
}is; I quote from my pty paper's description of a write clone:
}: Finally, write is a vastly improved clone. The old write had several big
}: security holes: 1. Control characters were passed through. This version
}: converts anything unprintable into a caret. 2. Lines were not
}: distinctively marked. A user could manually simulate the ``EOT'' or
}: ``EOF'' sequence, wait a few minutes, then start sending anything to the
}: other tty without identification. This version precedes each line with
}: the name of the sending user, and prints something more informative than
}: EOT for an ended message. 3. write could be used to flood a terminal.
}: (This is an accident waiting to happen.) This version puts a one-second
}: pause between each line and restricts line length. 4. Originally, write
}: would only check the protection on the tty being written to. But this
}: meant that a user could be interrupted by someone hiding behind mesg n
}: and have no recourse. (Footnote: Remember that UNIX has no enforce()
}: call to enforce new permissions on an object. Setting mesg n does not
}: stop a write in progress.) So many versions of write included
}: ``revenge'': X was allowed to write to Y only if Y could write back.
}: However, these versions tested tty protection only at the beginning of a
}: message---which was useless. This version does the correct test: it
}: simply checks write permission before sending each new line.
}My write clone is public-domain, so I invite you---I beg you---to steal
}code from it. Don't even give me any credit, just fix the bugs. Please.

As the co-author of the current BSD write, I can respond to this.
Our version does make control chars visible.  Checking the permissions
on the recipient before each line is a good idea.  The rest of your
changes are disgusting.
---
Jef

  Jef Poskanzer  jef@well.sf.ca.us  {apple, ucbvax, hplabs}!well!jef
  "In my poor, lean, lank face nobody has ever seen that any cabbages
                were sprouting out." -- Abraham Lincoln

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (04/27/91)

(Note that the changes to ``write'' being discussed here are entirely
optional suggestions; only steps 1-12 are necessary to fix the basic
problems.)

In article <12535@dog.ee.lbl.gov> Jef Poskanzer <jef@well.sf.ca.us> writes:
> Our version does make control chars visible.  Checking the permissions
> on the recipient before each line is a good idea.  The rest of your
> changes are disgusting.

Well, I'm glad you agree with two of them, but I'd like to ask the net's
opinion on the other two. Let me split this into three questions:

1. Do people think it's a problem that lines from ``write'' are not
identified? If nothing else, I like the ability to carry on two or three
write conversations at once without getting totally confused. If others
don't like this, though, then I'll stop pushing for it.

2. Do people think it's a problem that someone can start a ``write'',
then just type EOF or EOT to simulate ending it, then continue typing
without identification? While most experienced users will guess exactly
what's going on, novice users are really up the creek. Does anyone agree
with Jef that it's ``disgusting'' to see

	Message from operator@kramden on ttyp7 at 10:24 ...
	operator: this is where the text goes
	operator: and so on
	End of message from operator@kramden on ttyp7 at 10:25

instead of

	Message from operator@kramden on ttyp7 at 10:24 ...
	this is where the text goes
	and so on
	EOF

Maybe I'm biased from my RELAY days, but I really find the first format
more informative.

3. Do people think it's a problem that ``write'' can flood a terminal
with output before the recipient has a chance to react? My version
limits output to 500 characters per line and one line a second. Does
anyone think that this affects legitimate uses of ``write''? If not, is
there any harm in adding the protection against accidents and abuse?

---Dan

rickert@mp.cs.niu.edu (Neil Rickert) (04/28/91)

In article <15896:Apr2714:35:3991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Well, I'm glad you agree with two of them, but I'd like to ask the net's
>opinion on the other two. Let me split this into three questions:

 I, for one, like your changes.  Until they are in place I will continue
my practice of putting 'mesg n' in my .login file

>3. Do people think it's a problem that ``write'' can flood a terminal
>with output before the recipient has a chance to react? My version
>limits output to 500 characters per line and one line a second. Does
>anyone think that this affects legitimate uses of ``write''? If not, is
>there any harm in adding the protection against accidents and abuse?

 We had one user here who wrote a daemon to do this to every new person who
logged on.  I was sure glad I had 'mesg n' in my .login .  Even so I had to
wait a while for the end of his buffer before I could get in and kill
his daemon and suspend his account.  (Just as well he was a novice user, or
he could have made things more difficult.)


-- 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  Northern Illinois Univ.
  DeKalb, IL 60115                                   +1-815-753-6940

cadp01@vaxa.strath.ac.uk (04/28/91)

In article <15896:Apr2714:35:3991@kramden.acf.nyu.edu>, 
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

[stuff deleted]
 
> 1. Do people think it's a problem that lines from ``write'' are not
> identified? If nothing else, I like the ability to carry on two or three
> write conversations at once without getting totally confused. If others
> don't like this, though, then I'll stop pushing for it.

Me too, but I would rather have it as an option (mesg i ?) instead of
being forced to see this identification on every line I get. That way you
would satisfy both parts. This should of course be at the recepient end. 
Would this be too messy?

> 2. Do people think it's a problem that someone can start a ``write'',
> then just type EOF or EOT to simulate ending it, then continue typing
> without identification? While most experienced users will guess exactly
> what's going on, novice users are really up the creek. Does anyone agree
> with Jef that it's ``disgusting'' to see
> 
> 	Message from operator@kramden on ttyp7 at 10:24 ...
> 	operator: this is where the text goes
> 	operator: and so on
> 	End of message from operator@kramden on ttyp7 at 10:25
> 
> instead of
> 
> 	Message from operator@kramden on ttyp7 at 10:24 ...
> 	this is where the text goes
> 	and so on
> 	EOF
> 
> Maybe I'm biased from my RELAY days, but I really find the first format
> more informative.

Some people want it and some don't, make it an option and keep everyone 
happy. I would have like a 'End of message from foo@bar on ...' instead
of the EOT/EOF but this would just have a purely informative purpose in a
system that didn't enforce identification of lines.

> 3. Do people think it's a problem that ``write'' can flood a terminal
> with output before the recipient has a chance to react? My version
> limits output to 500 characters per line and one line a second. Does
> anyone think that this affects legitimate uses of ``write''? If not, is
> there any harm in adding the protection against accidents and abuse?
> 
> ---Dan

If you want to give someone a piece of code or something similar over 
write, then one second per line might be a bit too much. Of course, the
identification on each line would already have messed it up so you couldn't
grab the lot with a mouse and store it somewhere without a search-and-
replace...

					OK

o.kolbu@uk.ac.strath.vaxa - Reverse where necessary.   Olav Kolbu
Life is full of standards, just grab one that suits you.

lyda@acsu.buffalo.edu (kevin lyda) (04/29/91)

i'm not a wizard... the reason i'm responding to this is because i got a
rather annoying message from a friend (he was bored at the time) while i
was trying to show a user how to do something (i'm a student consultant).
he did a cat file | write lyda and the file was ~26 lines long.... just
enough so that i couldn't see who'd done it. now, from that perspective....

In article <15896:Apr2714:35:3991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>1. Do people think it's a problem that lines from ``write'' are not
>identified? If nothing else, I like the ability to carry on two or three
>write conversations at once without getting totally confused. If others
>don't like this, though, then I'll stop pushing for it.

personally, i like unix because of it's flexibility. i think it should be
up to the recipient of the write message whether or not they see the
username of the sender.

>2. Do people think it's a problem that someone can start a ``write'',
>then just type EOF or EOT to simulate ending it, then continue typing
>without identification? While most experienced users will guess exactly
>what's going on, novice users are really up the creek.

yeah... write dufus
EOF
^Z
and then scroll his screen from time to time... :) that gets real dry when
you're already pissed at a bug in your project that's due in 10 mins.

>Does anyone agree
>with Jef that it's ``disgusting'' to see

well.... it looks like vms.... :)

>3. Do people think it's a problem that ``write'' can flood a terminal
>with output before the recipient has a chance to react? My version
>limits output to 500 characters per line and one line a second. Does
>anyone think that this affects legitimate uses of ``write''? If not, is
>there any harm in adding the protection against accidents and abuse?

again... i'm in favor of flexibility. i do think that that is too
restricive, and just because you or i or anyone else doesn't think that
there's a use for it, doesn't mean there isn't one. (like, there was this
really useless adhesive floating about 3m for awhile... it didn't seem to
stick very well.... now those annoying post-it notes are everywhere...)

i think a good solution, though harder, would be a .writerc file. get rid
of the .canwrite file and replace it with a file that tells write what it's
allowed to do to *my* tty. if i want the user identified on each line, let
me say that. if i want the writes logged to a file, let me say that. etc...
it just seems to me that i can specify how my editor and more and talk
output to my screen.... why can't i do the same for write?

kevin

cudcv@warwick.ac.uk (Rob McMahon) (04/29/91)

In article <15896:Apr2714:35:3991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>1. Do people think it's a problem that lines from ``write'' are not
>identified? If nothing else, I like the ability to carry on two or three
>write conversations at once without getting totally confused.

I think it's a problem if the formatting is different on both ends.  I tend to
press RETURN when I'm getting near the end of a line, and it's messy if this
gets broken up at the other end.  I often type code, or cut&paste text or code
into the write session, and it's a pain if this gets broken, or they can't
themselves cut&paste it into an editor without having to strip out the junk.

I've never seriously held more than one write session at a time in a single
window, but not because the messages get mixed up, but rather because of all
that switching between write commands.  I have no trouble keeping two windows
active.

>2. Do people think it's a problem that someone can start a ``write'', then
>just type EOF or EOT to simulate ending it, then continue typing without
>identification?

I think it's more important to keep the formatting intact, and the longer
message is of no use without the identifying `user: ' at the beginning of
typed lines (because I can obviously just type `End of message from ...'
instead of EOF).  Maybe I've just been lucky, but I've never been attacked
with this one.  If `mesg n' worked after the event I don't think it's a
problem.

>3. Do people think it's a problem that ``write'' can flood a terminal with
>output before the recipient has a chance to react?  My version limits output
>to 500 characters per line and one line a second.  Does anyone think that
>this affects legitimate uses of ``write''?

This idea seems to have more merit.  I have seen people doing `worms | write'
or `write < /usr/dict/words'.  Against that, I often send people a quick
message of a few lines using

	write user << 'eof'
	...
	'eof'

So that they don't have to sit there waiting for me to correct my typos.  It
would be a shame if the output only came out at one line a second.  Maybe
there's a compromise solution ... can I have 500 free characters before the
one line a second clunks in ?

Cheers,

Rob
-- 
UUCP:   ...!mcsun!ukc!warwick!cudcv	PHONE:  +44 203 523037
JANET:  cudcv@uk.ac.warwick             INET:   cudcv@warwick.ac.uk
Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England

kre@cs.mu.oz.au (Robert Elz) (04/29/91)

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

>1. Do people think it's a problem that lines from ``write'' are not
>identified?
>2. Do people think it's a problem that someone can start a ``write'',
>then just type EOF or EOT to simulate ending it,
>3. Do people think it's a problem that ``write'' can flood a terminal
>with output before the recipient has a chance to react?

The real problem is that the whole model used by "write" is simply
wrong - sure its simple, and in a sense, elegant, but its simply
not the way that things should be done.

The whole concept of some other random process, owned by some other
random user, being able to open a direct channel onto my terminal,
however the output is massaged, or identified, or restricted, is
simply silly.

The "traditional" way, where /dev/ttyX is mode 622, and anything can
dump anything it likes onto my terminal is just a giant hole, as
everyone knows by now I expect.

The "modern" way where /dev/ttyX is mode 620 and "write" is setgid "tty"
is safer, but now means that I can't create my own "write" like program
with my own preferred user interface, I can only use one of the standard
ones.

What's worse, the appearance of the message that I get to see depends
on the interface that the sending user has decided to select.

This is all absurd - clearly the intelligent way to run things is for
messages that come from another user to be displayed the way I want them
using a process I control - then I can have the message displayed using
whatever interface I desire (in practice, the way it happens is that
I have a window popped up on my display if I'm using a window system
at the time, or I have something very much like traditional "write"
if I'm on a dumb terminal).   Similarly, the user sending the message
can use whatever interface he desires, and there's no reason at all
that the interfaces need be similar - he can be sending a message from
a "talk" like X windows interface, and I can be receiving and responding
on my trusty old ASR33 using something just like 6th edition write,
and the whole thing can be traversing the world.

While part of what I have described is still fantasy (I don't really
have an asr33), much of it is in use here now - we still have to
integrate it with talk, and do some reasonable X interfaces, etc,
but this stuff all works, and is a much better way to operate (obviously
misc other message to the terminal schemes like comsat, wall, ... get
integrated as well).

Basically, there's a daemon process, to send a message you connect
to it, it becomes the destination user, and runs a user supplied
process (shell script commonly) which determines who is sending
the message, and what kind of message it is, and based on that
info, what should be done with the message.  Messages can be
forwarded to other hosts, rejected out of hand, transferred to
mail, ... whatever your process decides to do with it.  All a little
more fine grained than "mesg [yn]"!  Clearly the daemon process needs
to be trusted, and needs a methor to authenticate processes connecting
to it to get accurate user identification, but onto that anyone can
add whatever kind of user interface they prefer.

This stuff is not available (yet) so don't bother asking - the guy
who is actually writing the code has other things to do as well.
(My role is largely to tell him just why its not quite right yet...)

kre

mrc@milton.u.washington.edu (Mark Crispin) (04/29/91)

In article <kre.672866069@mundamutti.cs.mu.OZ.AU> kre@cs.mu.oz.au (Robert Elz) writes:
>The real problem is that the whole model used by "write" is simply
>wrong - sure its simple, and in a sense, elegant, but its simply
>not the way that things should be done.
>
>The whole concept of some other random process, owned by some other
>random user, being able to open a direct channel onto my terminal,
>however the output is massaged, or identified, or restricted, is
>simply silly.

Hopefully this is well understood by now.

Fortunately I never worry about it, since I rarely use multi-user Unix
systems.  The only thing I use our departmental Unix engine for is as
a mail drop, and even then I read the mail remotely.

>The "modern" way where /dev/ttyX is mode 620 and "write" is setgid "tty"
>is safer, but now means that I can't create my own "write" like program
>with my own preferred user interface, I can only use one of the standard
>ones.
>
>What's worse, the appearance of the message that I get to see depends
>on the interface that the sending user has decided to select.

On TOPS-20, you could create your own "write" like program, but it had
to go through either a system call or daemon that enforced various
restrictions on the contents and length of the text.  The call/daemon
also wrapped the message with header/trailer text so there was only
one way for text to display.

>This is all absurd - clearly the intelligent way to run things is for
>messages that come from another user to be displayed the way I want them
>using a process I control - then I can have the message displayed using
>whatever interface I desire

This is exactly how ITS worked.  You opened a core-link (pipe) to the
destination HACTRN (shell) and sent it a string.  The receiving HACTRN
could decide what, if anything, it wanted to do with the string
including refuse to open its end of the core-link if the user didn't
want to receive sends (writes).

It is so wonderful to find that in the 1990's we are rediscovering
technology of the late 60's/early 70's.  1/2 ;-)

psl@segue.segue.com (Peter Langston) (04/29/91)

In article <12535@dog.ee.lbl.gov> Jef Poskanzer <jef@well.sf.ca.us> writes:
>In the referenced message, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote:
>}13. Fix write. Many people don't appreciate how poor write's security
>}is; I quote from my pty paper's description of a write clone:
>}: ... blah, blah ...
>}code from it. Don't even give me any credit, just fix the bugs. Please.
>
>As the co-author of the current BSD write, I can respond to this.
>Our version does make control chars visible.  Checking the permissions
>on the recipient before each line is a good idea.  The rest of your
>changes are disgusting.

Jef is being too kind.  Agreed, the rest of the changes are disgusting in
their protect-the-user-from-her/himself presumption, but checking the
permissions on the recipient before each line is NOT such a good idea.
As it stands now, you can allow write access long enough for a friend to
initiate a write(1) and then turn off write access and discourage any other
interruption, (i.e. you can discriminate among users temporally).
Changing write to do continued checking of write permission would only
further frustrate users attempts to control their own environments.
It is hard to believe that the write program is the best place to solve the
problems of antisocial behaviour in one's community...

navarra@casbah.acns.nwu.edu (John 'tms' Navarra) (04/29/91)

In article <15896:Apr2714:35:3991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>(Note that the changes to ``write'' being discussed here are entirely
>optional suggestions; only steps 1-12 are necessary to fix the basic
>problems.)
>
>
>Well, I'm glad you agree with two of them, but I'd like to ask the net's
>opinion on the other two. Let me split this into three questions:
>
>1. Do people think it's a problem that lines from ``write'' are not
>identified? If nothing else, I like the ability to carry on two or three
>write conversations at once without getting totally confused. If others
>don't like this, though, then I'll stop pushing for it.

     I don't really have a problem with this. But I suppose it is no 
 big deal to include a username: message 
 at the begining of each line.                                       
 As far as making write multi-user -- THAT would be useful and then you
 would need this utility to identify users. I guess you are pretty much
 writing a local irc?

>
>2. Do people think it's a problem that someone can start a ``write'',
>then just type EOF or EOT to simulate ending it, then continue typing
>without identification? While most experienced users will guess exactly
>what's going on, novice users are really up the creek. Does anyone agree
>with Jef that it's ``disgusting'' to see
>
>	Message from operator@kramden on ttyp7 at 10:24 ...
>	operator: this is where the text goes
>	operator: and so on
>	End of message from operator@kramden on ttyp7 at 10:25
>
>instead of
>
>	Message from operator@kramden on ttyp7 at 10:24 ...
>	this is where the text goes
>	and so on
>	EOF

      Again, this is an EASY thing to do. You could do some checking to see
 if the string eof (EOF) is passed and then exit automatically and in 
 addition, print out the username of the person sending the message at the 
 end of the session. 
>
>Maybe I'm biased from my RELAY days, but I really find the first format
>more informative.
>
>3. Do people think it's a problem that ``write'' can flood a terminal
>with output before the recipient has a chance to react? My version
>limits output to 500 characters per line and one line a second. Does
>anyone think that this affects legitimate uses of ``write''? If not, is
>there any harm in adding the protection against accidents and abuse?

 Another good point. I once (along with a friend of mine) just swamped our
 super users terminal whenever he logged in. Write should have some limit
 to the number of characters it sends at a time. Or perhaps a better way
 to deal with large amounts of characters being transferred at one time --
 like if a char/min ratio was too big, write would pause a coupla seconds
 to accept a kill signal from the receiver. 
>
>---Dan



         Good luck with your program.

-- 
From the Lab of the MaD ScIenTiST:
      
navarra@casbah.acns.nwu.edu

flee@cs.psu.edu (Felix Lee) (04/29/91)

> 3. Do people think it's a problem that ``write'' can flood a terminal
> with output before the recipient has a chance to react? My version
> limits output to 500 characters per line and one line a second.

It's a form of noise ordinance.  Perhaps there are better noise
ordinances, but that one seems reasonable to me.

Of course, write-like programs shouldn't use tty devices for
rendezvous.  They should rendezvous at a service or port advertised by
the user.  I believe Zephyr does something like this.
--
Felix Lee	flee@cs.psu.edu

lm@slovax.Eng.Sun.COM (Larry McVoy) (04/29/91)

In the referenced message, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) wrote:
}13. Fix write. Many people don't appreciate how poor write's security
}is; I quote from my pty paper's description of a write clone:
}: ... blah, blah ...
}code from it. Don't even give me any credit, just fix the bugs. Please.

Is all this fuss really worth it?  I hate to appear caveliar and I
don't speak for Sun, just as a user, but does anyone really care?  OK,
anyone except the Feds?  Yeah, the system is insecure.  In many
places.  It seems to me that worrying about anti-social behavior
through tty's is the least of our problems.

I would much rather see all this energy going into making the system
secure enough that ``bad'' people can't login, rather then worrying
about the annoying write messages from people who have been given an
account.  Seems to me that you are in much worse trouble if you let an
outsider into your network/machine.  As long as we manage to prevent
that from happening, I think most admins can deal with people
misbehaving.

I dunno, maybe I'm missing some important point, but it seems rather
paranoid to me to worry about the people who have accounts on your
machine.  You trusted them enough to give them an account, where did
that trust go?
---
Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm@sun.com

jik@athena.mit.edu (Jonathan I. Kamens) (04/29/91)

In article <kre.672866069@mundamutti.cs.mu.OZ.AU>, kre@cs.mu.oz.au (Robert Elz) writes:
|> [description of a daemon-based message service]
|> 
|> This stuff is not available (yet) so don't bother asking - the guy
|> who is actually writing the code has other things to do as well.
|> (My role is largely to tell him just why its not quite right yet...)

  Your code may not be available yet, but Project Athena's Zephyr is.

\begin{plug}

  It is distributed (it works for us in an environment with over 1000
workstations), it supports Kerberos authentication (if you want it), it
supports multiple interfaces both for message senders and message recipients,
and all functionality is encapsulated in a library, so people can write their
own interfaces if they want (I know someone who has implemented much of the
Zephyr library in perl :-).

  For more information, you can anonymous ftp to athena-dist.mit.edu
[18.71.0.38] and look in /pub/usenix/zephyr.PS for a (PostScript) paper about
Zephyr that was presented at Usenix, or look in /pub/zephyr for the source
code et al.

  If you don't have anonymous ftp access, you can send mail to
"archive-server@athena-dist.mit.edu" with "help" in the body to find out how
to get the stuff via E-mail.

\end{plug}

  If you have questions about Zephyr, I'd be glad to answer them, but please
read the Usenix paper before asking them in E-mail (unless you can't read
PostScript; I don't know where the text version of the paper is, or I'd say).

-- 
Jonathan Kamens			              USnail:
MIT Project Athena				11 Ashford Terrace
jik@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

car@trux.UUCP (Chris Rende) (04/30/91)

From article <15896:Apr2714:35:3991@kramden.acf.nyu.edu>, by brnstnd@kramden.acf.nyu.edu (Dan Bernstein):

Anyone who has ever used Multics should find this thread quite amusing since
Multics handles user to user messages quite nicely and consistently.

> 1. Do people think it's a problem that lines from ``write'' are not
> identified?

Yes.

When a user sends a 'write' type message to another user, it appears like this:

From: Chris Rende (car.user) tty11 Mon Apr 29 13:36:24 EDT 1991:
Line of text

Subsequent lines from the same user appear like this:
:= Line of text

This tells you that the line of text came form the last message sender.

If another person sends you a message, you get another full header like above.

Let's say that you have more than one user sending you messages...
If a new message comes in, and it is from the last identified sender, then
you get the ':=' prefix.
If a new message comes in, and it is not from the last identified sender,
then you get this:
(Chris Rende) := Line of text

> If nothing else, I like the ability to carry on two or three
> write conversations at once without getting totally confused. If others
> don't like this, though, then I'll stop pushing for it.

I like it too! See the above example.

> 2. Do people think it's a problem that someone can start a ``write'',
> then just type EOF or EOT to simulate ending it, then continue typing
> without identification? While most experienced users will guess exactly
> what's going on, novice users are really up the creek. Does anyone agree
> with Jef that it's ``disgusting'' to see
> 
> 	Message from operator@kramden on ttyp7 at 10:24 ...
> 	operator: this is where the text goes
> 	operator: and so on
> 	End of message from operator@kramden on ttyp7 at 10:25

I like this because you can tell where each line comes from.

That's why Multics preceeds a message line with ":=" so you know where it
came from.

> 3. Do people think it's a problem that ``write'' can flood a terminal
> with output before the recipient has a chance to react?

Kinda - but it's too bothersome to do anything about it. Having the ability
to switch messages off is sufficient. (mesg n).

> My version
> limits output to 500 characters per line and one line a second.

What if I'm using 300 baud? The meter of "what is too much data" changes
based on a number of factors...

> Does
> anyone think that this affects legitimate uses of ``write''? If not, is
> there any harm in adding the protection against accidents and abuse?

I don't think that it's worth the bother. And yes, in my college days we
used to 'zap' people by flooding them with messages - it's all part of the
fun. :-)

Actually, I think that there is a more fundamental problem: I think that
it is a crime for anyone to be able to open the device file which I am
connected to.

I would rather see messages implemented via a signal to my shell. The
shell can gather messages, format and identify them as above, and output
them when I am ready to see them. That's another nice thing about Multics:
polite mode.

Don't you just love it when lp (or whoever) sends you a message which
wipes out what you are typing? I hate that.

On Multics you can issue the command "stty polite". Now, messages are
not sent to the terminal unless/until the user hits return. (Or until/while
the keyboard input buffer is empty).

Multics also has a "stty replay" mode. If Multics does interrupt you while
you are typing then it will re-display the line which you were typing
so that you can continue from where you left off.

car.
-- 
Christopher A. Rende           Central Cartage (Nixdorf/Pyramid/SysVR2/BSD4.3)
uunet!edsews!rphroy!trux!car   Multics,DTSS,Unix,Shortwave,Scanners,UnixPC/3B1
car@trux.mi.org                Minix 1.2,PC/XT,Mac+,TRS-80 Model I,1802 ELF
trux!ramecs!car     "I don't ever remember forgetting anything." - Chris Rende

ssd@engr.ucf.edu (Steven S. Dick) (05/01/91)

In article <15896:Apr2714:35:3991@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>	Message from operator@kramden on ttyp7 at 10:24 ...
>	operator: this is where the text goes
>	operator: and so on
>	End of message from operator@kramden on ttyp7 at 10:25

Well, personally, I don't like this style or the standard style.
The format is OK....it's the timing I detest.

I've written my own write replacement [which I probably should release
to the net] that lets you type your whole message before it sends it.
I HATE getting the write start message, and then waiting to get the rest.

The name at the beginning of the line isn't needed if the message is sent
as one chunk.  

A few security additions I put in my program right away...
It limits the message to 20 lines.  This could, I suppose, ioctl the
remote terminal and check its actual height.  (Assume 20 otherwise.)
It doesn't make sure the input is coming from a tty--maybe it should.

I didn't think of putting in a pause before sending the next 20
lines...  This might be useful.  I wouldn't actually pause--just record
the time, and make sure that some decent amount of time (like at least
1 sec per line) has passed before sending anything more.  Nobody can
actually type that fast anyway.  :-)

	Steve
ssd@engr.ucf.edu

cks@hawkwind.utcs.toronto.edu (Chris Siebenmann) (05/02/91)

lm@slovax.Eng.Sun.COM (Larry McVoy) writes:
| Is all this fuss really worth it?  I hate to appear caveliar and I
| don't speak for Sun, just as a user, but does anyone really care?  OK,
| anyone except the Feds?  Yeah, the system is insecure.  In many
| places.  It seems to me that worrying about anti-social behavior
| through tty's is the least of our problems.

 This is only true if you trust (or mostly trust) your user population.
This is probably true at most commercial and research sites, less true
at educational machines used by professors and graduate students, and
not necessarily true at all for undergraduate machines. I'd like to
trust the undergraduates, and to a certain extent I do, but not to this
extent. 

 Worse yet, it is VERY hard to have any sort of control over who gets
accounts and access; students come and go, accounts are left inactive
when people drop the course, people share their passwords with others,
and people use easy to guess passwords. With some work, just about
anyone could walk off the street here and log onto one of our
undergraduate systems, and I have every reason to believe that some
people do. All I can do is to make sure that once someone has managed
to log on, the amount of damage they can do is minimized and easy to
fix.

--
	"This is what separates us system programmers from the
	 application programmers: we can ruin an entire machine and
	 then recover it, they can only ruin their own files and then
	 get someone else to restore them"	- Geoff Collyer
cks@hawkwind.utcs.toronto.edu	           ...!{utgpu,utzoo,watmath}!utgpu!cks

rodney@tyrell.stgt.sub.org (Rodney Volz) (05/02/91)

In article <*WC_6A$@warwick.ac.uk> cudcv@warwick.ac.uk (Rob McMahon) writes:
>
> [ problems concerning write(1) ]
>

Sorry for interfering, but I really don't see the point in discussing
"write". Write does not have any S-Bit, so if you e.g. choose to make
write reject messages > 20 lines, I'll just compile my own write.

Well, I don't even have to compile it...

$ cat > /dev/console < `eof`
foo...
eof
$

-Rodney
-- 
                     Rodney Volz - 7000 Stuttgart 1 - FRG
 ============> ...uunet!mcsun!unido!gtc!aragon!tyrell!rodney <=============
  rodney@tyrell.gtc.de * rodney@delos.stgt.sub.org * rodney@mcshh.hanse.de 
  \_____________ May your children and mine live in peace. ______________/

muller@sdcc10.ucsd.edu (Keith Muller) (05/02/91)

In article <7299:Apr2510:22:2091@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Here's one way to fix the BSD 4.[234] tty system, i.e., to provide some
>strong guarantees that pty and tty sessions are safe and not subject to
>corruption or denial of service, with minimal changes to the kernel and
>to application programs. This is also meant to apply to systems derived
>from BSD, such as SunOS, Ultrix, etc.

.....

>9. In each of the tty-handling programs, do the following upon slave
>exit: (a) Clean up everything except (if it is convenient) [uw]tmp.
>Close 0, 1, 2, and any other random descriptors lying around, except
>/dev/ptyxx and /dev/ttyxx. (b) Test /dev/ttyxx with TIOCOPEN*. If
>someone else still has it open, continue to step (c); otherwise skip to
>step (d). (c) Fork, and exit in the parent. Repeatedly test /dev/ttyxx
>(a five-second sleep is fine) until it is closed. (d) Clean up [uw]tmp
>and exit. Note that steps (b) and (c) can fit into a simple library

.....

While this may look useful for patching an existing system, it might be more
profitable in the long term to step back from the details of the current
problem and investigate the underlying problem with ttys. I really do not want
to depend on the actions of step 9 (especially step 9c....) to promote
security (what if the master side process dies prematurely for example; not
all servers can be that robust all the time). This also greatly increases
the complexity of servers (even if it is in a library) and divides the task
of resource protection between the kernel and numerous user processes in
a complex way. If not all tty allocators are robust 100% of the time
security is lost. --- Since kernel changes are being proposed in the above
solution, maybe a different approach would provide a less complex solution.

In simple terms a major problem with ttys has always been the semantics
of the revocation of access rights to a tty (pseudo or real). The difficulty
is created by both "valid" processes and "revoked" processes sharing access
to common data structures (inode and device tty structures) and the
routines which implement tty semantics. 

The technique described below is based on controlling access rights through
the system open file table. This method adds a system call I shall
call revoke(tty) just for the context of this description.
Revoke(tty) has the semantics where all other open file references (except
for the one passed as an arg) to a tty (real or slave side of a pty) are
revoked.  Clearly this is a root only syscall. Revoke() can be expanded to
support any semantics required for i/o requests by jobs on file descriptors
pointing to invalidated ttys as required. It can also function as a way to
attach background jobs after a tty session is terminated.

The most basic implementation of revoke() (for tty protection only)
would be to add a flag to the f_flag field in the open file table which will be
set whenever access rights are revoked. Revoke() will set this flag in all
other entries in the open file table (except the one passed as an arg) that
point to the same tty as the arg (you check by same inode and major/minor
in all active inodes if ttys have multiple nodes in the file system).
The revoked access flag is then checked whenever a tty related routine is
entered (like ttread(), ttwrite()) and before performing an operation on the
tty (like fchmod()). Whenever a process awakes from sleeping in one of these
tty routines, the flag is checked. If the flag is found set, the appropriate
errno is set (if that is what is required) and the system call returns (you
could even return EOF on a read, with a -1 on later calls). To check this flag
in the tty routines requires that a pointer to the open file table related to
this tty system call must be passed to the device and on to the tty routines
as an arg (a simple change from the current code). This simple implementation
of revoke() is NOT a major kernel mod.

A more complex implementation of revoke() would address the two issues of
last close on a tty not being called when background jobs are hung and
the ability to attach background jobs. In this case revoke() could be
called as the result of a close on the master side of a pty, or by init
when a login shell dies. In addition to the flag in the open file table,
revoke() would be expanded to function similar to a dup2() to modify the
f_fileops and f_data fields in each open file table structure being modified.
Revoke() modifies f_data to point at a memory structure that would be
used to contain information for later re-attachment of the tty
(it could contain a description of tty modes for example). By changing f_data,
the references to the ttys inode in the active inode table is decremented
(which is what f_data used to point at). This allows the device close routines
to be called. F_fileops are changed to point at a collection of routines
which implement the "required" semantics of a detached terminal (allows you to
specify more complex ops other than failing i/o from background jobs).
These new f_fileops could use the new structure pointed to by f_data for
current use and/or future attachment needs. So when a background process does 
a read for example, rwuio() would call these new routines instead of the
device (and then the line discipline) routines. In this method wakeups in
tty routines would find the revoke flag set in f_flags and return to the
kernel entry point routine such as rwuio() (with an indication they detected
the revoke flag). The kernel entry routine would then call the new f_fileops
routine (they were reset when the flag was set) (Future calls will always
call the f_fileops routines directly).

The use of the open file table allows revocation of a tty access regardless
of the state of the process (even if it is swapped). It is the single data
structure which represent a processes (or several peer processes) specific
reference to a tty that is not shared by future access to the tty device or
by any other unrelated processes.

This method eliminates "terrorist" techniques like allocating all
ptys, it stops hanging background jobs from grabbing plain text passwords, etc.
It also provides a mechanism for supporting whatever semantics are deemed
necessary for tty operations from detached processes (e.g. do reads block or
does the new routines set EOF state....). The reattachment of background jobs
would use the f_data before pointing it at the inode table entry of the new
tty and would replace the f_fileops back to the tty routines (clearing the
revoke flag in f_flags also). 

---- How to use this call for tty allocation only (protection from prior
     references to ttys. Done as root.) ----

	a) open the master side (for pty allocation only)
	   If this succeeds, then no other process is using the pty. This
	   assumes the current semantics of on a single reference to
	   the master side.

	b) open slave side (entry point for "real" tty allocation also)

	c) set exclusive use on (slave) tty.

	d) revoke(tty) -- where revoke() is described above

	e) set owner,group and access bits on (slave) tty (following
	   current techniques like group tty etc).

	f) clear exclusive use on (slave) tty.

	g) at this point the tty is secure from prior reference attacks.
	   Future reference can then be controlled via owner,group.
	   No looping ioctls to check for link count. No wedged ptys. No
	   complex utmp hacking etc... (Of course write etc still have to
	   be fixed as dan and other have already described...)

Some of this technique has already been tried on a production system.
Part of the tty protection phase stuff was implemented last year 
on a 4.3BSD Tahoe system (I needed to stop some bozo user from stealing
plaintext passwords. We cannot limit our user population, nor can we easily
remove "aggressive" users from the machines).  In my simple implementation I
defaulted to semantics that made revoked access equate to a failed system
call (similar to the results of what the old vhangup() would do. This may
not be the right thing in all cases).  I need to look at how this works with
sessions as implemented into 4.3 Reno before saying more. Clearly I
haven't implemented reattaching ttys...

Keith Muller
University of California
kmuller@ucsd.edu

(Copyright 1991 University of California)

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/03/91)

In article <18924@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:
> While this may look useful for patching an existing system, it might be more
> profitable in the long term to step back from the details of the current
> problem and investigate the underlying problem with ttys.

The only unusual aspect of my solution is TIOCOPENCT, which is
sufficient to simulate dynamic ttys with static ttys. Making the tty
files inaccessible and making programs setuid is a standard technique.
Replacing /dev/tty with my /dev/stdtty is necessary (on systems without
u_ttyvp, anyway) to close the avenue that gets around most ``fixes.''
Together these changes *do* solve the underlying problems of statically
allocated ttys, though I would prefer that ptys be as dynamic as pipes
in the first place.

> I really do not want
> to depend on the actions of step 9 (especially step 9c....) to promote
> security (what if the master side process dies prematurely for example; not
> all servers can be that robust all the time).

I address this in the comments after step 12. You can, for instance,
arrange for each process to skip a tty during allocation if TIOCOPENCT
indicates that the file is in use. However, this added complexity is not
strictly necessary, and on most machines the servers really don't crash.
If you have the time and energy, by all means add TIOCOPENCT checks at
the beginning of each session.

> This also greatly increases
> the complexity of servers (even if it is in a library) and divides the task
> of resource protection between the kernel and numerous user processes in
> a complex way.

The complexity is already there! A typical BSD system has a dozen
programs managing the pseudo-tty resources. This type of decentralized
management is stupid, and it makes any tty fix much harder to apply, but
my fixes certainly don't make the situation any worse.

If someone takes the time to rewrite telnetd (well, I've done this
already) and rlogind and expect and so on to use a single, modular pty
manager (e.g., my ``pty'' program), then he'll be able to implement my
fixes just by adding TIOCOPENCT and changing that manager in the way
I've described. But this is way too complex for a minimal fix.

> Since kernel changes are being proposed in the above
> solution, maybe a different approach would provide a less complex solution.

Your solution requires many more changes than mine, and most of them in
the kernel. It does not provide or simulate a simple model like dynamic
ttys. It is not spelled out in sufficient detail for someone to
implement, and the effects of each change are not explained.

Most importantly, your changes don't close the holes on anything but
Suns and very recent BSD releases. Should I explain this? All your
revoke() does is stop access through the open file table (and it's not
entirely clear that it will work any better than vhangup() for that).
But p_ttyd (or u_ttyd) doesn't *go* through the open file table. Poof,
there goes your security.

You also require that a flag be added to the file structure and that
every single tty I/O operation be changed to pay attention to that flag
and take special action if it is set. So far (not to mention replacing
u_ttyd with u_ttyvp or the equivalent) we're talking about some hundreds
of extra lines of kernel code---far more than required to implement
/dev/fd/3 (to replace /dev/tty) or TIOCOPENCT.

You require that all tty-handling programs be setuid root. Setuid to
some other uid would be much safer---but you can't do that without
letting unprivileged users abuse revoke().

I'm sorry to criticize your changes in such harsh terms, but they remind
me too much of the kludge upon kludge that vendors like Convex have
tried. You don't stop the problems at their source; you let two
independent user programs have a tty simultaneously open; your changes
don't even work as advertised on most machines, because you missed a
fundamental avenue around your revoke(). Even if your fix were simpler
or less fragile than mine, these flaws would condemn it.

---Dan

muller@sdcc10.ucsd.edu (Keith Muller) (05/03/91)

In article <15369:May219:46:0491@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>The only unusual aspect of my solution is TIOCOPENCT, which is
>sufficient to simulate dynamic ttys with static ttys. Making the tty
>files inaccessible and making programs setuid is a standard technique.
>Replacing /dev/tty with my /dev/stdtty is necessary (on systems without
>u_ttyvp, anyway) to close the avenue that gets around most ``fixes.''
>Together these changes *do* solve the underlying problems of statically
>allocated ttys, though I would prefer that ptys be as dynamic as pipes
>in the first place.

You missed the point. Your method boils down to avoiding using ptys (and only
works for ptys it will not work for real hardware ttys) that have background
jobs still using them. my discussion was to outline a technique to deal
with background jobs access to ttys in general to make people
think about what to do about background jobs that still have
access to real ttys once a user logs out or the master side process terminates
on a pty. Better solutions are gained when alternative solutions are
investigated.

->Remember your article title was BSD tty security (not sunos pty security).<-

>I address this in the comments after step 12. You can, for instance,
>arrange for each process to skip a tty during allocation if TIOCOPENCT
>indicates that the file is in use. However, this added complexity is not
>strictly necessary, and on most machines the servers really don't crash.
>If you have the time and energy, by all means add TIOCOPENCT checks at
>the beginning of each session.

On very active system with lots of background (or hung jobs) you eventually
run out of ptys. Without your {sleep, TIOCOPENCT ... loop} the service denial
hole is still present. This is something that is fairly important in
many environments. Legitimate background jobs deny service to that pty
in your scheme (unless you go the vahangup() route you suggested in you
comments (resulting is doing a similar action as revoke()... ah but then your
allocation would have to run as root....)

>The complexity is already there! A typical BSD system has a dozen
>programs managing the pseudo-tty resources. This type of decentralized
>management is stupid, and it makes any tty fix much harder to apply, but
>my fixes certainly don't make the situation any worse.

Again you need to address both hardware and ptys. My point is there a
an alternative to pty allocation that is less complex (the revoke() 
suggestion encased in "exclusive use" ioctls is a lot simplier than the
complex setup and cleanup you are suggesting. It is easily stuck in
a library routine also and is a lot less code).

>Your solution requires many more changes than mine, and most of them in
>the kernel. It does not provide or simulate a simple model like dynamic
>ttys. It is not spelled out in sufficient detail for someone to
>implement, and the effects of each change are not explained.

The number of changes is not a lot of code nor is it any more complex. 
Tracking down all those references to a pty (or tty) is the SAME for
both your TIOCOPENCT and the revoke(). Clearing and/or setting a flag
once you have found the references is trival.

Most of the framework for revoke() is in the kernel already exists as most
i/o related system calls already make an access check on the open file table
flags at each entry into the kernel (at least 4.3 tahoe and earlier does).
Code (a small amount) is added to handle sleeping processes (a failure of
vhangup()) I wasn't giving a "cookbook" but drafting an alternative to
provoke discussion on the topic (of access rights to ttys). The discussion
simply addresses the protection of ttys from prior reference attacks and not
how to implement what you call "dynamic" ttys. (Do you mean dynamic creation
of ptys....????).  Again I was addressing (p)tys as they current exisist in
BSD unix (a static device).

>Most importantly, your changes don't close the holes on anything but
>Suns and very recent BSD releases. Should I explain this? All your
>revoke() does is stop access through the open file table (and it's not
>entirely clear that it will work any better than vhangup() for that).
>But p_ttyd (or u_ttyd) doesn't *go* through the open file table. Poof,
>there goes your security.

Neither p_ttyd (or u_ttyd) are in 4.3 RENO or earlier (and you did call
this a BSD tty security fix). I did state this concept was only tried on a
4.3 tahoe system. The difference from vhangup() is that the checks are
carried down into those routines that sleep(). vhangup() fails to protect
due to the fact that it removes read/write access in another process context.
Jobs that sleep through this in the tty routines can complete when they
run (performing a single I/O that should NOT occur). You may not need
the extra flag if you simply want to kill off access the way vhangup()
does. Of course this destroys access right state you may want to consider on
future operations by that process (like what kind of errno to return etc).

>You also require that a flag be added to the file structure and that
>every single tty I/O operation be changed to pay attention to that flag
>and take special action if it is set. So far (not to mention replacing
>u_ttyd with u_ttyvp or the equivalent) we're talking about some hundreds
>of extra lines of kernel code---far more than required to implement
>/dev/fd/3 (to replace /dev/tty) or TIOCOPENCT.

As stated above access rights are already checked on i/o ops, adding 
a check for the revoke flag (or if you have revoke strip off read/write flags
like vhangup() then there is little extra code besides revoke() itself).
On 4.3 RENO and earlier there is only u_ttyvp, so that replacement
is not needed.

>You require that all tty-handling programs be setuid root. Setuid to
>some other uid would be much safer---but you can't do that without
>letting unprivileged users abuse revoke().

It is as easy (or easier) to make a setuid() program safe as it is to
preventing a server from crashing before it cleans up (so you state).
Having a pty "allocation" running as non-root causes problems. It this case the
slave side would be owned by pty and not the user. This eliminates redirects
to/from the tty by the valid user of the pty. Things like mesg etc would
have to be setuid() pty to work. What about movement of data between two
ptys owned by the same user? A single user would be unable to access
another pty he was assigned by pty. This is asymmetric to the allocation
of real ttys (and the allocation or actions by setuid root clients that
use ptys... rlogind). Running as nonroot also eliminates the use of
vhangup() which you suggest using under those conditions where ptys are
held up by background jobs. Besides vhangup is easily spoofed and also
works only on the open file table. What about REAL ttys....???
They also are subject to the similar attacks, how do you protect them?

>I'm sorry to criticize your changes in such harsh terms, but they remind
>me too much of the kludge upon kludge that vendors like Convex have
>tried. You don't stop the problems at their source; you let two
>independent user programs have a tty simultaneously open; your changes
>don't even work as advertised on most machines, because you missed a
>fundamental avenue around your revoke(). Even if your fix were simpler
>or less fragile than mine, these flaws would condemn it.
>

Sorry you are so sensitive about your design (I suspect many people
consider your proposal a kludge...). On BSD (not SunOS based
machines) up to 4.3 RENO (which do not have p_ttyd (or u_ttyd))
the basic revoke() works with simple client mods and simple
kernel mods. In the environment BSD prior to 4.3 RENO revoke() works as
advertised (no process remains with any access after the revoke()),
so your objections are misdirected. If you read my discussion more carefully
you would have seen that I was careful to state this was an idea tested on
4.3 tahoe only as a proof of concept. My only goal was to show an alternative
to your user mode based allocation could work and not stomp on your ego...
This is why i dicussed the topic rather than casting a single solution
in concrete as THE ONLY WAY.

What your solution fails to address are problems with real ttys which
have problems similar to ptys (And the title IS security of BSD ttys...)
and should have the benefit of similar protections.

Keith Muller
University of California
kmuller@ucsd.edu

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/04/91)

In article <18953@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:
> You missed the point. Your method boils down to avoiding using ptys (and only
> works for ptys it will not work for real hardware ttys) that have background
> jobs still using them.

(It will work for hardwired ttys if you make the outlined changes to
getty's initialization routine. But without a secure break key [as you
can implement with my suggestion #24], hardwired ttys are completely
insecure anyway.)

Yes. Isn't it nice that the system also avoids using pipes that have
background jobs still using them?

> Better solutions are gained when alternative solutions are
> investigated.

I agree that it is worthwhile to investigate alternative solutions. But
I really, really, really don't want to see someone call something a
``fix'' when it does not solve the problem on the vast majority of
available systems. That's what you've been doing.

I agree that vhangup(), revoke(), etc. would make a more useful (though
more complex) security model, if they worked (which they don't in most
current systems). That's why I've been pushing for an enforce() syscall.
The problem is that to make vhangup() actually work as documented, you
have to reorganize every file access in the system to go through the
mechanism that vhangup() controls. Similarly for revoke() and enforce().
This is a worthwhile long-term project, not something you can reasonably
require in a minimal fix.

> ->Remember your article title was BSD tty security (not sunos pty security).<-

Yes. The majority of BSD-derived multiuser systems ``out there'' are not
SunOS machines.

> On very active system with lots of background (or hung jobs) you eventually
> run out of ptys. Without your {sleep, TIOCOPENCT ... loop} the service denial
> hole is still present. This is something that is fairly important in
> many environments.

Again, I address this in the comments after step 12, as well as in step
7. For most environments it is not a problem, as there are typically ten
times more ptys than background jobs. For the environments where this is
not true, you will have to pay attention to my other suggestions.

> My point is there a
> an alternative to pty allocation that is less complex (the revoke() 
> suggestion encased in "exclusive use" ioctls is a lot simplier than the
> complex setup and cleanup you are suggesting.

Less complex? Less complex? Do you believe what you're saying?

Would it be ``less complex'' if the system had a static pool of pipes?
You pick a pipe, revoke() any current users of it, and then use it for
yourself?

Would it be ``less complex'' if the system had a static pool of pids?
You pick a process id, fork(), revoke() any other processes with the
same pid, and then use it for yourself?

Would it be ``less complex'' if the system had a static pool of files?
You pick an inode, revoke() any other users of that inode, and then use
it for yourself?

Sorry, but you're not being realistic. UNIX pipe management is simple
because UNIX allocates pipes dynamically. UNIX pid management is simple
because UNIX allocates pids dynamically. UNIX file management is simple
because UNIX allocates files dynamically. Do you see anyone worrying
about the security of pipes?

That's why my solution effectively implements dynamically allocated
ptys. ``Dynamically allocated'' doesn't imply infinitely many---you can
run out of pipes or processes or files if you try hard enough---but it
makes management and security much, much simpler.

> It is easily stuck in
> a library routine also and is a lot less code).

How about we stop arguing, you write up a complete description at the
same level of detail as mine, and then we see which solution is simpler
and requires less code.

> Tracking down all those references to a pty (or tty) is the SAME for
> both your TIOCOPENCT and the revoke().

Incorrect. On a Sun, for instance, to handle TIOCOPENCT you just go from
file descriptor to open file description to vnode, then report v->count
of the vnode. Done. Your revoke() requires going through the entire file
table and setting flags here and there. (That's what you said...)

> Clearing and/or setting a flag
> once you have found the references is trival.

And once you have included special treatment of that flag in every
single tty operation. This is a lot of kernel work. Why do you refuse to
write out these changes at a sufficiently low level of detail that
people can implement them? If it's so few lines of code, why don't you
write out the code?

> >Most importantly, your changes don't close the holes on anything but
> >Suns and very recent BSD releases. Should I explain this? All your
> >revoke() does is stop access through the open file table (and it's not
> >entirely clear that it will work any better than vhangup() for that).
> >But p_ttyd (or u_ttyd) doesn't *go* through the open file table. Poof,
> >there goes your security.
> Neither p_ttyd (or u_ttyd) are in 4.3 RENO or earlier (and you did call
> this a BSD tty security fix).

Do you know what you're talking about?

ttyd is standard BSD, and is on the vast majority of BSD-derived
systems. ttyvp only appears on Suns, very recent (i.e. non-production)
BSD releases, and possibly some obscure or extremely recently released
systems that I'm not familiar with.

I repeat my claim: your changes don't close the holes on anything but
Suns and very recent BSD releases (such as Reno). In fact, unless you
know you've changed every single tty operation to check that flag and
behave properly, including when coming out of sleep, your changes are
insecure even on those systems.

> >You also require that a flag be added to the file structure and that
> >every single tty I/O operation be changed to pay attention to that flag
> >and take special action if it is set. So far (not to mention replacing
> >u_ttyd with u_ttyvp or the equivalent) we're talking about some hundreds
> >of extra lines of kernel code---far more than required to implement
> >/dev/fd/3 (to replace /dev/tty) or TIOCOPENCT.
> As stated above access rights are already checked on i/o ops,

But you want people to add an extra check, plus have it handled for
blocking processes. I repeat my claim.

> On 4.3 RENO and earlier there is only u_ttyvp, so that replacement
> is not needed.

This statement is simply incorrect. On BSD 4.3 Reno and LATER there is
u_ttyvp. I believe that they took the name and idea from SunOS, though
I'll have to check this with Marc Teitelbaum.

Damn it, I can't stay polite about this. You obviously aren't familiar
with a wide range of machines---your statements about u_ttyvp prove
that. Your fixes do not work on most machines, but you say they do
because you don't know what you're doing. This is exactly the kind of
sheer idiocy that has let to the current situation: nobody fixes the
problem at its source, but people like you keep claiming that the latest
kludge really does solve the problem, and fewer and fewer people realize
that the problem still exists. I can't tolerate this! You are damaging
security on present and future systems by claiming that an insecure
solution is a solution. Don't you realize how stupid this is?

When the problem is SOLVED, feel free to advocate further complexity in
the security mechanism. In the meantime, don't be an ass. If you're
going to propose a solution, check with more experienced people (like
those at BSD) who can tell you whether it really will work.

> >You require that all tty-handling programs be setuid root. Setuid to
> >some other uid would be much safer---but you can't do that without
> >letting unprivileged users abuse revoke().
> It is as easy (or easier) to make a setuid() program safe as it is to
> preventing a server from crashing before it cleans up (so you state).

That's what they said about Emacs. Ever hear of move-mail?

> Having a pty "allocation" running as non-root causes problems.

Perhaps you did not read my proposal. I require that *non-root*
tty-handling programs be made setuid pty. This means programs like
script. script already doesn't chown ttys; my changes don't affect this
situation at all.

This is the third time you've claimed that my changes break something
when in fact they don't. Please read my proposal before criticizing it!

> Things like mesg etc would
> have to be setuid() pty to work.

Again, please read my proposal before criticizing it! I have addressed
practically every issue you've brought up.

> A single user would be unable to access
> another pty he was assigned by pty.

There are many ways to pass data and descriptors. Furthermore, your
statement about pty is incorrect; please read the pty interface
definition in my pty paper, particularly the definition of -xc.

> >I'm sorry to criticize your changes in such harsh terms, but they remind
> >me too much of the kludge upon kludge that vendors like Convex have
> >tried. You don't stop the problems at their source; you let two
> >independent user programs have a tty simultaneously open; your changes
> >don't even work as advertised on most machines, because you missed a
> >fundamental avenue around your revoke(). Even if your fix were simpler
> >or less fragile than mine, these flaws would condemn it.
> Sorry you are so sensitive about your design

I'm not sensitive about it. I welcome constructive criticism of it. I'd
love to see it made simpler without compromising its security.

But I am extremely sensitive to your claims that you have a fix, when in
fact YOUR CHANGES DO NOT SOLVE THE PROBLEM ON THE VAST MAJORITY OF
SYSTEMS. This is the worst kind of security through obscurity: by
claiming that your changes work, you might delude other people into
believing you, and then they won't implement real fixes WHEN THE SYSTEM
WITH YOUR CHANGES IS JUST AS INSECURE AS IT WAS BEFORE.

Simplicity is a side issue when you can't even make correct fixes.

> (I suspect many people
> consider your proposal a kludge...).

It is a kludge, albeit a reliable one. It's a kludge to fix a kludge.

> In the environment BSD prior to 4.3 RENO revoke() works as
> advertised (no process remains with any access after the revoke()),

You are wrong.

---Dan

kre@cs.mu.oz.au (Robert Elz) (05/04/91)

jik@athena.mit.edu (Jonathan I. Kamens) writes:

>  Your code may not be available yet, but Project Athena's Zephyr is.

Yes, I know about Zephyr, and probably should have mentioned it
explicitly - several other people brought it to my attention, for
which I thank you all.

However, these things aren't quite the same - Zephyr is solving a
much bigger problem than most of us need solved, and at least doesn't
seem to solve all of the problem that we actually do want to solve, it
would seem that the stuff being done here could adequately be turned
into Zephyr clients though.  Or, perhaps, might be able to be.

In particular, we're only interested in interactive messaging (that
stuff that currently opens /dev/ttyXX and blats noise onto it).  User
location, ... are outside our scope, and unnecessary in our environment
(its just not that big - furthermore, its not often necessary, you can
usually address a user on your local node, he will have arranged for
the message to go wherever he wants to reveive messages).

But we are very interested in user presentation - the way that the
user actually gets to control the way that messages are shown and
which particular messages get shown at all (eg: I like a window to
appear showing me "biff" (comsat) type output from new messages that
arrive, then vanish a couple of minutes later - but I don't want
that for "noise" messages I get - where my definition of what is
noise changes from minute to minute).   That type of control is
the heart of the stuff here, and at least from the paper (which
I saw in the usenix proceedings originally, and just fetched and
read again - using the net is an easier way to find it than hunting
through shelves looking for proceedings...) it doesn't appear that
this is really what zephyr is doing.

Finally - the place I log in (my workstation) is not where I want
messages processed, ie: running a "zwgc" process here would be a
basic waste of (extremely) scarce workstation resources.  Our stuff
requires no permanently running processes at all - apart from inetd
which is going to be there anyway.  Inetd starts a daemon when a message
arrives, that daemon becomes me, and does my will to the message.
Should someone actually send a message to my workstation (as I said,
no user location stuff, people can do that if they desire), that
daemon will run for just a short while, redirect the message off
to the host where I want to do the processing for it, and tell the
sender they sent to the wrong place and are being forwarded.

Maybe I should grab zephyr and have a more detailed look at it??

kre

kre@cs.mu.oz.au (Robert Elz) (05/04/91)

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

>--far more than required to implement
>/dev/fd/3 (to replace /dev/tty) or TIOCOPENCT.

The problem with using /dev/fd/3 and using that instead of /dev/tty
is that you lose the ability to guarantee to be able to open the
terminal where your user is sitting, assuming that there is one.

First, there's the obvious "prog 3</dev/null" which probably isn't
worth worrying about too much (if users explicitly want to have
the prog not be able to use the controlling tty that's OK, and
possible with /dev/tty anyway).

But worse, there are zillions of progs currently that do, more or
less

	for (fd = 3; fd < ENOUGH; fd++)
		close(fd);

(where ENOUGH is calculated different ways in different progs).

All of those are going to need to be fixed to start at 4 instead
of 3, or they're all going to lose their tty access, not just
for themselves, which often won't matter much, but for all of their
decendant processes as well.

The one big advantage of /dev/ttyd (u.u_ttyd) is that its very difficult
to accidentally give it away, you really have to try very very hard
to do it.

kre

ps: you may just as well post the code to exploit the bugs now, if
there's anyone around who can't figure out how to do it now, they're
not likely to be able to figure out how to compile your code either...

kre@cs.mu.oz.au (Robert Elz) (05/04/91)

ssd@engr.ucf.edu (Steven S. Dick) writes:

>I've written my own write replacement [which I probably should release
>to the net] that lets you type your whole message before it sends it.

You don't need to write a "write" replacement to do that, you just
do

	write user <<!
	message
	!

	or

	cat | write user

but while that's sometimes useful it's not what write is meant for, you're
not supposed to sit and wait for the rest of the message after you see the
line with the sender's name on it - you're supposed to write back, write
is basically intended for interactive conversations, if your write makes
you finish the whole thing before the recipient gets to see any of it,
how can you possibly respond to his thoughts if your write has already
completed?

kre

rickert@mp.cs.niu.edu (Neil Rickert) (05/04/91)

In article <1991May1.121058.20933@osceola.cs.ucf.edu> ssd@engr.ucf.edu (Steven S. Dick) writes:
>I didn't think of putting in a pause before sending the next 20
>lines...  This might be useful.  I wouldn't actually pause--just record
>the time, and make sure that some decent amount of time (like at least
>1 sec per line) has passed before sending anything more.  Nobody can
>actually type that fast anyway.  :-)

 How about not just 'pausing', but also closing and re-opening the file
descriptor before sending any more.  This would honor any change in
permissions.

-- 
=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
  Neil W. Rickert, Computer Science               <rickert@cs.niu.edu>
  Northern Illinois Univ.
  DeKalb, IL 60115                                   +1-815-753-6940

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/04/91)

In article <kre.673345687@mundamutti.cs.mu.OZ.AU> kre@cs.mu.oz.au (Robert Elz) writes:
> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >--far more than required to implement
> >/dev/fd/3 (to replace /dev/tty) or TIOCOPENCT.
> The problem with using /dev/fd/3 and using that instead of /dev/tty

Let me note that I addressed these issues fully in the original
proposal. I would love to hear from someone who can come up with (and
write out) a simpler solution to the /dev/tty problem.

> is that you lose the ability to guarantee to be able to open the
> terminal where your user is sitting, assuming that there is one.

But that guarantee was never there. If you set TIOCEXCL on your tty
under most BSD-derived systems, you won't be able to open /dev/tty
either.

In fact, that's a good way to see how many programs depend on /dev/tty.
Try it. You'll be surprised at the results.

> But worse, there are zillions of progs currently that do, more or
> less
> 	for (fd = 3; fd < ENOUGH; fd++)
> 		close(fd);

I pointed this out in the proposal. I also pointed out that it only
affects programs which change fd 3 and then want to open /dev/tty (or
really old programs that assume the first open() will return 3). Most of
the programs that close all descriptors also want to stay in the
background, or are already dissociated from the ctty, or simply don't
care about the tty.

As I also pointed out in the proposal, the most important example of
such a program is ksh, which isn't installed on most BSD machines and is
also easily fixed. The other big class is scripts which might redirect
fd 3 somewhere and then want to use /dev/tty; as I also pointed out in
the proposal, you can solve this by using fd 11 instead of fd 3.

If anyone has actual examples of programs that redirect fd 3 and then
use /dev/tty, I expect that he'll do the sensible thing and post the
necessary fixes to the net, so as to save work on everyone else's part.

> The one big advantage of /dev/ttyd (u.u_ttyd) is that its very difficult
> to accidentally give it away, you really have to try very very hard
> to do it.

(One might ask whether this is the ``right'' situation---should it be
``very very hard'' to redirect stdin or stdout or stderr? Do you think
that the file descriptor model somehow isn't adequate for cttys?)

I addressed this in the proposal, notably with the fd 11 suggestion.
Steve Bellovin says that file descriptor -1 would preserve backwards
compatibility. Unfortunately, it would also require changes throughout
the kernel. The research UNIX people considered using 127, then decided
that there wasn't anything so special about stdtty and made it 3.

---Dan

pww@bnr.ca (Peter Whittaker) (05/05/91)

In article <kre.673349595@mundamutti.cs.mu.OZ.AU> kre@cs.mu.oz.au (Robert Elz) writes:
>ssd@engr.ucf.edu (Steven S. Dick) writes:
>
>>I've written my own write replacement [which I probably should release
>>to the net] that lets you type your whole message before it sends it.
>
(a bit deleted...)

>not supposed to sit and wait for the rest of the message after you see the
>line with the sender's name on it - you're supposed to write back, write

(This may be strictly off the alt.security path, but if "write" was made to 
behave as "msg" or "tm" - descrived below, these security might become
academic....)

Hmm, I dunno - seems you are letting the current form of "write" drive your
expectations of what "write" should be, rather that deciding what you want
then giving "write" that form (i.e. you are letting the technology drive 
your requriements rather than vice-versa).

How about an example from the (shudder) ibemm world (ibemm is the 
pronounciation of a well known and much dumped-upon TLA company name,
for those of you who don't know.....):  the "msg" and "tm" commands.

msg is a system command with syntax

msg USERNAME [AT HOSTNAME] [message text] RETURN

msg sends one line (up to ~120 character messages to the indicated recipient;
tm is an EXEC (i.e. a mainframe shell script) that packages msg messages in
a configurable border, with configurable line lengths, and prefixes the
FROM_USERID_AT_HOSTNAME info to each line.  If you want a multiline message,
you type a continuation character (also configurable) at the end of the line
of text you wish to continue.

When you hit the RETURN key in msh, or in tm without having specified a
continuatiuon character, the message is sent; and each line is prefixed 
with FROM_USERID_AT_HOSTNAME information.

There is NO WAY to flood someone's tty without them knowing who is doing
the flooding, as each line output to the tty is identified with the sender's
userid.  (examples below)

This allows you to "chat" interactively with one person (and a "chat" 
facility that sits on top of "msg" and allows a multi-party conversation
with private message capability exists as well) without them being able
to flood your tty, or otherwise boggle your mind without you knowing who 
is doing it.

The easiest way to fix some of the write-related security holes that have
been under discussion?  Implement msg, tm, and chat, and remove write.
(To avoid problem like the redirection one seen above, do not let "msg" 
read from stdin - though "tm" and "chat" could, seeing has how they will
exist on top of "msg".)  Further, restrict "msg" to sending non-CTRL
characters only.

What about programs that currently use write?  Well, they are generally
shell scripts, right?  It may be a headache to fix them all, but if the
write command was replaced by a script that notified the user to switch to
"msg", then it wouldn;t take long for people to fix things up, especially
if they were given advance warning of the changeover.

Perhaps eliminating write and implementing a better solution is a more 
appropriate way of fixing the problems with write?
(I am not volunteering for this.... :->).


Peter W.
pww@bnr.ca


(Examples of "msg" and "tm" below)

So, if I type "msg QQQ@bnr.ca Hi Q, how ya doin'? <RETURN>", QQQ@bnr.ca
sees (in bold, by the way)

MSG FROM QQQ@bnr.ca : Hi Q, how ya doin'?

If I use "tm", with its very tailorable output behavior, with "\" as my 
continuation character, the following results:

tm QQQ@bnr.ca Hi Q, ho ya doin'?  We are going to the \ <RETURN>
CONT:  beach this afternoon, wanna come?  MJ and SP \ <RETURN>
CONT:  will be there!!! <RETURN>

(CONT: is a bold/highlighted prompt from "tm")

QQQ@bnr.ca sees:

MSG FROM QQQ@bnr.ca : /=============================\
MSG FROM QQQ@bnr.ca : | Hi Q, how ya doin'?  We are |
MSG FROM QQQ@bnr.ca : | going to the beach this     |
MSG FROM QQQ@bnr.ca : | afternoon, wanna come?      |
MSG FROM QQQ@bnr.ca : | MJ and SP will be there!!!  /
MSG FROM QQQ@bnr.ca : \=============================/

--
Peter Whittaker      [~~~~~~~~~~~~~~~~~~~~~~~~~~]   Open Systems Integration
pww@bnr.ca           [       DSA's'R'Us!        ]   Bell Northern Research 
Ph: +1 613 765 2064  [                          ]   P.O. Box 3511, Station C
FAX:+1 613 763 3283  [__________________________]   Ottawa, Ontario, K1Y 4H7

muller@sdcc10.ucsd.edu (Keith Muller) (05/05/91)

In article <1237:May321:05:0191@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> 
> (It will work for hardwired ttys if you make the outlined changes to
> getty's initialization routine. But without a secure break key [as you
> can implement with my suggestion #24], hardwired ttys are completely
> insecure anyway.)

Why should hardwire ttys be insecure? Login session terminal termination
occurs when either the login shell exits or dcd drops (assuming -nohang
is set). Preventing login just because a background job is referencing a
tty is not acceptable.

If I read #24 correctly you want to force ttys through ptys? (connecting
the master side with a pipe through the hardwire port). So ptys are
the only thing used for login sessions.... Sure is a lot
of overhead (in and out of user mode multiple times to move data). 

> And once you have included special treatment of that flag in every
> single tty operation. This is a lot of kernel work. Why do you refuse to
> write out these changes at a sufficiently low level of detail that
> people can implement them? If it's so few lines of code, why don't you
> write out the code?

I am not trying to promote a fix, but promote a discussion on how to 
address tty semantics . The only reason I even answer your postings is to
point out that other METHODS exsist.

The code to check access is simple and the majority of the tests are already
is in the kernel. 

I am looking at the code (4.3 reno) right now.  On entry point in the
kernel for read() for example we see:

	if (((unsigned)uap->fdes) >= NOFILE ||
		    (fp = u.u_ofile[uap->fdes]) == NULL ||
			(fp->f_flag & FREAD) == 0)
			return (EBADF);

Now tell me the open file table access rights for the read isn't being
done here....

Traversing the open file table on device deallocation
is not a lot of code. Vhangup() (aka forceclose()) does it already (from
4.3 tahoe):

forceclose(dev)
	dev_t dev;
{
	register struct file *fp;
	register struct inode *ip;

	for (fp = file; fp < fileNFILE; fp++) {
		if (fp->f_count == 0)
			continue;
		if (fp->f_type != DTYPE_INODE)
			continue;
		ip = (struct inode *)fp->f_data;
		if (ip == 0)
			continue;
		if ((ip->i_mode & IFMT) != IFCHR)
			continue;
		if (ip->i_rdev != dev)
			continue;
		fp->f_flag &= ~(FREAD|FWRITE);
	}
}

So even by revoking access the way vhangup does (by removind read/write
access and not using an additional flag) the code is small. Deallocation
of ttys is not a very highly called occurance to consider the above loop
"intensive". (it is certainly a lot less load than what I think you
want to do to the data flow on herdware ttys). Actually in both this and
your method the case where multiple (v)(i)nodes reference the same device
probably should be addressed (even if it is a questionable thing to do)..

> ttyd is standard BSD, and is on the vast majority of BSD-derived
> systems. ttyvp only appears on Suns, very recent (i.e. non-production)
> BSD releases, and possibly some obscure or extremely recently released
> systems that I'm not familiar with.

Looking at the source for 4.3 tahoe there is no p_ttyd or u_ttyd.  All tty
references use the open file table. Access removed there terminates access
to the tty. If f_flag permissions (or a revoked flag if you want to do it
that way) (or even more strongly if f_data does not reference the
active inode in the kernel), that fd cannot do i/o.

In the 4.3 reno you get from CSRG, ttyvp does exsist (see kern/tty_tty.c).

> I repeat my claim: your changes don't close the holes on anything but
> Suns and very recent BSD releases (such as Reno). In fact, unless you
> know you've changed every single tty operation to check that flag and
> behave properly, including when coming out of sleep, your changes are
> insecure even on those systems.

There about 17 places where you sleep on read/write and ioctl for
tty ops. All in tty.c and tty_pty.c (all have  similar code fragments,
many of which relate to hanging background operations). In most places
the sleep is followed by a goto to the top (entry point) of the routine.
At the top is one place the check could be done. For example the
sleep() fragment in ttread() (from 4.3 tahoe) looks like:

 if (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) {
	 if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) ||
	    (u.u_procp->p_sigmask & sigmask(SIGTTIN)) ||
		u.u_procp->p_flag&SVFORK)
			return (EIO);
	  gsignal(u.u_procp->p_pgrp, SIGTTIN);
	  sleep((caddr_t)&lbolt, TTIPRI);
	  goto loop;
	}

Now loop is at the top of the routine. Adding the following line (assuming
you pass the tty struct to the routines) does the check for read for
example. (the if statement after the loop: is what is added).This uses
a access restriction scheme like vhangup (not an added flag but removing the
read/write flags as demonstrated in forceclose() above.

loop:
	if ((fp->f_flag & FREAD) == 0)
		return(EBADF);

> 
> But you want people to add an extra check, plus have it handled for
> blocking processes. I repeat my claim.

This is the only check added. Not a significant consumption of time.
(You could just make it a macro and put it after each sleep if you want
to trade space for time).

>> On 4.3 RENO and earlier there is only u_ttyvp, so that replacement
>> is not needed.

> This statement is simply incorrect. On BSD 4.3 Reno and LATER there is
> u_ttyvp. I believe that they took the name and idea from SunOS, though
> I'll have to check this with Marc Teitelbaum.

Yes a typo on my part. (The earlier should be later, the surrounding
paragraphs did support the corrected statement).

> 
> Damn it, I can't stay polite about this. You obviously aren't familiar
> with a wide range of machines---your statements about u_ttyvp prove
> that. Your fixes do not work on most machines, but you say they do
> because you don't know what you're doing. This is exactly the kind of
> sheer idiocy that has let to the current situation: nobody fixes the
> .... 
  
Excuse me but I am only illustrating a different technique does exsist
and never stated I was providing a fix to all variants of UNIX..
I simply used BSD as a counter example in my posting as an alternate
to what you start out saying when you descibe your fixes:

>Here's one way to fix the BSD 4.[234] tty system, i.e., to provide some

And thats what I desribed, a technique for the BSD 4.[234] tty system.
If some vendor adds a tty device or tty access method in THEIR operating
system that does not use the open file table like 4.[234] does then
they should rethink the reasons why it was done. (maybe throwing
out the open file table is a reasonable thing and should be done, but that
is not what this discussion is about).

Unless you are looking at a different BSD kernel source than I, your
statements about tty i/o access in BSD (tahoe or reno) is in error.
Please look at the actual kernel code before "shooting from the hip".

Keith Muller
University of California

kre@cs.mu.oz.au (Robert Elz) (05/05/91)

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

>> 	for (fd = 3; fd < ENOUGH; fd++)
>> 		close(fd);

>I pointed this out in the proposal. I also pointed out that it only
>affects programs which change fd 3 and then want to open /dev/tty

No, this is not true - it affects programs that close fd 3, then
exec any program that wants to open /dev/tty - the most common case
perhaps being those progs that have a '!' or 'shell' command, to
fork/exec an interactive shell, from which anything can be run.  This
is a much harder problem to fix - essentially it means that all progs
that close(3) and allow any other prog to be exec'd need to be fixed.

>The research UNIX people considered using 127, then decided
>that there wasn't anything so special about stdtty and made it 3.

Yes, I know - they have the luxury of fixing their entire environment.
Very few others do - vendors don't, they can't fix code supplied by
customers, or independant code suppliers.  Breaking code that customers
have written, or even worse, bought, is not something any vendor is
going to want to undertake lightly.

On the other hand, using fd -2 (not -1, that will cause stupid progs
that attempt to reference fd's after an open error to do weird things)
or 65535, or any other "unusual" number would not have these drawbacks.
Its much more work for the vendors in their kernels, but at least its
work that is mostly compatible with their current offerings.

kre

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/06/91)

In article <19002@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:
> In article <1237:May321:05:0191@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> > (It will work for hardwired ttys if you make the outlined changes to
> > getty's initialization routine. But without a secure break key [as you
> > can implement with my suggestion #24], hardwired ttys are completely
> > insecure anyway.)
> Why should hardwire ttys be insecure?

For all the reasons that Bellovin outlines in his session tty paper.

> Preventing login just because a background job is referencing a
> tty is not acceptable.

But leaving the tty insecure isn't acceptable either. That's why the
logical compromise is to allow login on a dynamically allocated tty, or
to simulate dynamic allocation the way that I've been recommending. I
notice that you deleted my explanation of the analogy between ttys and
pipes/pids/etc.; I'd appreciate it if you responded to that analogy
before continuing to talk about ``acceptable'' ways to handle tty
security.

> If I read #24 correctly you want to force ttys through ptys?

Yes, though this is not a required step. It just makes sense, and gives
you features like a secure break key. I'd say that severing the link
between modem connections and tty handling is the heart of Bellovin's
session tty idea.

> Sure is a lot
> of overhead (in and out of user mode multiple times to move data). 

There's a lot of conceptual overhead too---all the tty processing,
forwarding the data to a physical device like a modem, etc. With streams
(or, I assume, bstreams), there's no user-mode switch anyway, and going
through both a /dev/modem and /dev/ptyxx would be almost as fast as the
current hardwired ttys.

> > And once you have included special treatment of that flag in every
> > single tty operation. This is a lot of kernel work. Why do you refuse to
> > write out these changes at a sufficiently low level of detail that
> > people can implement them? If it's so few lines of code, why don't you
> > write out the code?
> I am not trying to promote a fix, but promote a discussion on how to 
> address tty semantics. The only reason I even answer your postings is to
> point out that other METHODS exsist.

Okay, I'm sorry for flaming. I just don't want to see people proposing
non-solutions as solutions, because that's exactly what's caused all the
previous screwups.

In particular, your ``fixes'' do not work on any system that has
p_ttyd/u_ttyd instead of u_ttyvp. This includes most BSD releases,
Ultrix through at least 4.1, Convex UNIX through at least 9.0, and many
other systems. So if you're going to continue talking about your
``solution'', please try to be accurate: ``solution for BSD 4.3-Reno''.

> 	if (((unsigned)uap->fdes) >= NOFILE ||
> 		    (fp = u.u_ofile[uap->fdes]) == NULL ||
> 			(fp->f_flag & FREAD) == 0)
> 			return (EBADF);
> Now tell me the open file table access rights for the read isn't being
> done here....

It isn't. Again, what makes UNIX security so simple is that there's the
file protection firewall, and once you're past that wall there's nothing
to check. One of vhangup()'s problems, as you noted, is that a process
blocking on I/O won't check for access rights again.

Doesn't it strike you as odd that you have to introduce access checks at
so many extra spots to make your revoke() work even marginally better
than vhangup()? Don't you realize that you're proposing a fundamental
change to the security mechanism? There's no precedent in UNIX for
revoking file access!

> Deallocation
> of ttys is not a very highly called occurance to consider the above loop
> "intensive".

I care very little about the efficiency of tty allocation, though
scanning the file table on allocation increases turnaround time, while
actions on deallocation don't. I care much more about the amount of code
that has to be changed.

> Actually in both this and
> your method the case where multiple (v)(i)nodes reference the same device
> probably should be addressed (even if it is a questionable thing to do)..

Again, please stop criticizing my proposal before you've read it. My
method handles this case correctly---it's not even a special case,
because unlike you I'm not mucking around with vnodes and the file
table. I agree that you have to address such issues.

> All tty
> references use the open file table. Access removed there terminates access
> to the tty.

No. That's a common blunder. In a multitasking system there are several
operations going on at once. You have terminated FUTURE access to the
tty ONLY IF there are no current operations.

Don't you understand that this ``termination'' idea is foreign to UNIX?
Don't you think that you'd better have a whole bunch of people think
through it and reimplement the kernel around it before deciding that it
works?

> In the 4.3 reno you get from CSRG, ttyvp does exsist (see kern/tty_tty.c).

Yes. That's what I said.

> > But you want people to add an extra check, plus have it handled for
> > blocking processes. I repeat my claim.
> This is the only check added. Not a significant consumption of time.

When did you suddenly become so fixated on time? What I care about is
simplicity. People (and vendors) should have to make as few changes as
possible to the system, with as little of it as possible in the kernel.

Here, let's review my required kernel changes again:

: Quick summary of kernel changes required: Make /dev/tty ioctls work on
: /dev/tty??, make a /dev/stdtty driver which simply dup()s fd 3, and add
: an ioctl, TIOCOPENCT, which returns the number of active references to a
: given inode. That's it.

Would you like to give a paragraph stating your required changes, at the
same level of detail?

  [ ... ]
> And thats what I desribed, a technique for the BSD 4.[234] tty system.

But, once again, your technique does not work on most BSD 4.3-based
systems and will work on absolutely no BSD 4.2 systems. Rather than
arguing with me, why don't you ask Marc Teitelbaum at Berkeley whether
there exist standard systems supporting u_ttyd. You apparently don't
believe they do.

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/06/91)

In article <kre.673430200@mundamutti.cs.mu.OZ.AU> kre@cs.mu.oz.au (Robert Elz) writes:
> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >> 	for (fd = 3; fd < ENOUGH; fd++)
> >> 		close(fd);
> >I pointed this out in the proposal. I also pointed out that it only
> >affects programs which change fd 3 and then want to open /dev/tty
> No, this is not true - it affects programs that close fd 3, then
> exec any program that wants to open /dev/tty

(That's the same thing; program != process.) Right, which is why Marc
pointed out ksh. If you find other examples of such programs, please say
so here. If you can post patches too, great!

  [ using descriptors other than 3 ]
> Its much more work for the vendors in their kernels, but at least its
> work that is mostly compatible with their current offerings.

It won't be any extra work if they pick the current maximum fd and
kludge getdtablesize() to subtract 1 from its answer. In any case, all
that's important for security is that *some* file descriptor be used
rather than the old /dev/tty driver.

---Dan

jfh@rpp386.cactus.org (John F Haugh II) (05/06/91)

In article <17790:May522:37:5591@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>In article <19002@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:
>> Why should hardwire ttys be insecure?
>
>For all the reasons that Bellovin outlines in his session tty paper.

There is absolutely =no= reason to consider hardware tty's to be
insecure simply because they are hardware tty's.  All that is required
to make hardware tty's secure is for some operation to exist which
insures that all current references to the device are legitimate.

This could be implemented as a hardware signal (Secure Attention Key)
which kills all processes on the list of processes having the device
open directly or indirectly but not possessing some privilege or
belonging to some set or processes.

>In particular, your ``fixes'' do not work on any system that has
>p_ttyd/u_ttyd instead of u_ttyvp. This includes most BSD releases,
>Ultrix through at least 4.1, Convex UNIX through at least 9.0, and many
>other systems. So if you're going to continue talking about your
>``solution'', please try to be accurate: ``solution for BSD 4.3-Reno''.

It is very possible to have u.u_ttyd and still have secure hardware
tty ports.  The system could very easily maintain a list of every
process which has any reference to that specific device.  A system
call could then traverse that list and kill any process not permitted
to still have a reference to that device, or it could be nice and
merely invalidate the access to that device.

>Don't you understand that this ``termination'' idea is foreign to UNIX?
>Don't you think that you'd better have a whole bunch of people think
>through it and reimplement the kernel around it before deciding that it
>works?

This has already been done several times.  If you can find a way past
the revoke() and frevoke() system calls in AIX v3, send me a note.  I
don't care for how it was implemented (which I consider to be a gross
hack of the first order), but it works very completely.

The complaints you have about "future" termination are really very
easy to address.  There are only so many places a process can sleep
in a device driver.  Go fix them.

>Here, let's review my required kernel changes again:

[ List deleted ]

>Would you like to give a paragraph stating your required changes, at the
>same level of detail?

Provide a mechanism within the kernel for tracking processes with
current access to any inode table entry.  Define a system call or
ioctl command which terminates all processes, except the current
process, which have references to that inode table entry.  Define
it such that operations on character and block devices affect all
inode table entries that refer to the same major and minor device
number pair.  This gives access revocation ability for files and
filesystems, as well as tty's.  It also doesn't require streams
or dynamic pty allocation or copying all manner of data all over
the inside of the kernel.

The first part is time and space consuming, and does more than
what is needed to solve the tty problem.  If you care about all
those things, limit it to tty devices only.  The nature of the
problem is that there is no reverse mapping from inode to process.
Create a reverse map from inode to process, and the problem
goes away.
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

jfh@rpp386.cactus.org (John F Haugh II) (05/06/91)

In article <17916:May522:46:2091@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>It won't be any extra work if they pick the current maximum fd and
>kludge getdtablesize() to subtract 1 from its answer. In any case, all
>that's important for security is that *some* file descriptor be used
>rather than the old /dev/tty driver.

Naw, this is still more than you have to do.  What happens if I move
u.u_ttyd from the u-page to the process table?  The reason you want to
use a file descriptor is because the file table is accessible - u_ttyd
isn't.  How about fixing that problem instead of creating another
hack?
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/07/91)

In article <19249@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> There is absolutely =no= reason to consider hardware tty's to be
> insecure simply because they are hardware tty's.  All that is required
> to make hardware tty's secure is for some operation to exist which
> insures that all current references to the device are legitimate.

Agreed. Since UNIX doesn't provide for revoking a valid file descriptor,
the obvious solution is to make sure that no user program ever gets to
touch a modem driver. A privileged program can control the driver and
route I/O through a pipe or pseudo-tty or socket or any other basically
dynamic object. It can also drop its control of the driver whenever the
user types break.

> This could be implemented as a hardware signal (Secure Attention Key)
> which kills all processes on the list of processes having the device
> open directly or indirectly but not possessing some privilege or
> belonging to some set or processes.

The problem is that, once again, UNIX doesn't have this concept of
terminating current access. The last time that people tried to add it to
BSD was vhangup(), and that was a complete failure.

I find it conceptually much simpler to just make sure that unprivileged
programs never open /dev/modem*.

> >In particular, your ``fixes'' do not work on any system that has
> >p_ttyd/u_ttyd instead of u_ttyvp. This includes most BSD releases,
> >Ultrix through at least 4.1, Convex UNIX through at least 9.0, and many
> >other systems. So if you're going to continue talking about your
> >``solution'', please try to be accurate: ``solution for BSD 4.3-Reno''.
> It is very possible to have u.u_ttyd and still have secure hardware
> tty ports.  The system could very easily maintain a list of every
> process which has any reference to that specific device.

Well, sure, but that's even more work that Muller hasn't outlined in
detail. Again it seems much simpler to put this control at the user
level.

> >Don't you understand that this ``termination'' idea is foreign to UNIX?
> >Don't you think that you'd better have a whole bunch of people think
> >through it and reimplement the kernel around it before deciding that it
> >works?
> This has already been done several times.

Fine. If it works in AIX then that's good for AIX. Unfortunately, most
machines out there don't have kernels supporting termination.

> The complaints you have about "future" termination are really very
> easy to address.  There are only so many places a process can sleep
> in a device driver.  Go fix them.

And how about file descriptor passing, which is yet another path for a
file to stay open past revocation?

The basic problem here is that inside the kernel valid file access can
be represented in many different forms. The *only* time access
permissions are checked is when the access goes through an open file
table entry. To chop off file access, you have to chop off every
possible form of that access---even if it's hidden inside a blocked
syscall or a message.

One way to fix this in the long term is to have permissions at a lower
level than open file descriptions---permissions at such a low level that
*every* file operation will check them in every time slice where they
apply. In a vnode-based system, one example of such permissions is the
filesystem pointer, and BSD 4.3-Reno has a working (though not very
fine-grained) revoke() that simply trashes that pointer.

Switching to vnodes is, unfortunately, too much to require in a minimal
fix. In the long term it would seem wise to consider exactly what sort
of permissions should apply at a lower level than open file access, how
those permissions should be controlled, etc.

> >Here, let's review my required kernel changes again:
> [ List deleted ]
> >Would you like to give a paragraph stating your required changes, at the
> >same level of detail?
> Provide a mechanism within the kernel for tracking processes with
> current access to any inode table entry.

C'mon, that's not at the same level of detail as ``Make /dev/tty ioctls
work on /dev/tty??''. *What* is the mechanism? You obviously have to
introduce some new structures or add fields to the old ones; where are
those fields?

To make this work on current systems you also have to make sure that
u_ttyd access is tracked. This would require that an entirely separate
set of kernel routines be changed, and I don't think a whole bunch of
people would figure this out from your description.

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/07/91)

In article <19250@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> In article <17916:May522:46:2091@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >It won't be any extra work if they pick the current maximum fd and
> >kludge getdtablesize() to subtract 1 from its answer. In any case, all
> >that's important for security is that *some* file descriptor be used
> >rather than the old /dev/tty driver.
> Naw, this is still more than you have to do.  What happens if I move
> u.u_ttyd from the u-page to the process table?

Yeah, I think you can make vhangup() chop /dev/tty without races if you
change u_ttyd to p_ttyd throughout, fix all your process-status programs
so that they don't crash with this change, and add some lines inside the
vhangup() syscall. That doesn't do anything about current operations.

> How about fixing that problem instead of creating another
> hack?

``Creating another hack''? Sheesh. The entire idea of having a separate
tty security mechanism is a hack. /dev/tty represents an alternate
method of file access, and as such makes security a whole lot more
complicated than when there was only open(). That's the problem that
/dev/stdtty fixes.

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/07/91)

In article <19045@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:
> In article <17790:May522:37:5591@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >> Why should hard-wire ttys be insecure?
> >For all the reasons that Bellovin outlines in his session tty paper.
> I was making an "open question". A design that leaves a device as hopelessly
> insecure really need to be reevaluated. If the technique used for
> security on ptys cannot be extended to hard-wired ttys,

Are you referring to mine? As I pointed out, you can perfectly well use
TIOCOPENCT at the beginning of a hardwired tty session (i.e., in getty).
If someone is still using the tty, getty will (I presume) give a message
to the user and sleep.

> I have no special interest in any specific
> technique for solving tty security on BSD for the LONG TERM.

Right. It's interesting to discuss long-term solutions, but the current
topic is a minimal correct fix for BSD 4.[234] as well as all systems
derived from them. Let's make sure to keep these topics separate.

> No one ever objected to dynamic allocation, but you do not
> have dynamic allocation in your solution,

This can be argued---would you say that files are not dynamically
allocated because there's only a finite pool of possible inodes on each
disk? Would you say that processes are not dynamically allocated because
the process table is finite?

> This might be a fine quick fix, but ignoring alternative
> solutions is short-sighted.

All I want people to ignore is non-solutions. What you've proposed is
not a short-term solution for most systems.

Here's what I said at the beginning of this thread:

: Here's one way to fix the BSD 4.[234] tty system, i.e., to provide some
: strong guarantees that pty and tty sessions are safe and not subject to
: corruption or denial of service, with minimal changes to the kernel and
: to application programs. This is also meant to apply to systems derived
: from BSD, such as SunOS, Ultrix, etc.

If you want to talk about changes that don't make those guarantees, or
if you want to talk about changes that only apply to BSD 4.3-Reno, or if
you want to talk about extensive, long-term changes, feel free. Just
don't do it in this thread.

> Creation of completely dynamic ttys (probably more than just
> cloning ptys) for both hardware tty ports and network based ports would
> require a long term project to be done on a pure BSD system.

Well, BSD 4.4 is going to implement ptys with bstreams, and your
concerns about the speed of data flow are answered by any proper streams
system. (Putting I/O through a stream doesn't involve a context switch.)

> Your analogy to pipes/pids is basic operating system concepts, nothing is
> there to comment on....

But you keep saying that revoking access is somehow simpler or better
than dynamic allocation. If you believe that, why don't you extend the
analogy to pids and pipes and inodes?

> >In particular, your ``fixes'' do not work on any system that has
> >p_ttyd/u_ttyd instead of u_ttyvp. This includes most BSD releases,
> >Ultrix through at least 4.1, Convex UNIX through at least 9.0, and many
> >other systems. So if you're going to continue talking about your
> >``solution'', please try to be accurate: ``solution for BSD 4.3-Reno''.
> To quote (loosely) Chris Torek "... they are not BSD...".

Fine. In case you didn't notice, I'm talking about solutions that the
rest of the world can use. This was part of the very first paragraph in
this thread, and I don't like the way that you neither take the steps to
make your solution portable, nor admit in public that it's not portable,
given that the thread started on a portable note.

And as for BSD, the official BSD 4.2 had u_ttyp. Official BSD 4.3 had
u_ttyp. Official BSD 4.3-Tahoe had u_ttyp. It is only in BSD 4.3-Reno,
which is only a beta of 4.4 and is not a production system, that
Berkeley picked up u_ttyvp.

> I keep saying
> this is discussion of BSD UNIX as from UCB

But you don't even take 4.2, 4.3, or 4.3-Tahoe into account.

> I have been accurate in my statements, you just keep ignoring the text... 

No, I've been taking your statements as you say them. For example:

> Both p_ttyd/u_ttyd have never existed in a UCB release).

This is incorrect. I'm sorry, but I can no longer take seriously what
you say about standard BSD code, and it's obvious that you don't care
about any of the BSD variants.

  [ read() example ]
> So at entry point access rights are
> checked.

Sure, but that's not sufficient to check access rights at all times once
you allow those flags to be turned off.

> >Doesn't it strike you as odd that you have to introduce access checks at
> >so many extra spots to make your revoke() work even marginally better
> >than vhangup()? Don't you realize that you're proposing a fundamental
> >change to the security mechanism? There's no precedent in UNIX for
> >revoking file access!
> Sure looks like vhangup() (which has been around for years) revokes
> access.

No, it does not. As a syscall it is useless; as an experiment it failed
miserably.

> access protection by rights is part of unix and
> is not a fundamental change.

Terminating access rights is a fundamental change. How about we drop
this issue until one of the original UNIX developers has given his
opinion.

> The special case (though it is not a bright thing for a admin to do) is
> have two ttys with different names but the same major/minor number.

I can't stop someone from giving all usernames the same userid either.

> >> All tty
> >> references use the open file table. Access removed there terminates access
> >> to the tty.
> >No. That's a common blunder. In a multitasking system there are several
> >operations going on at once. You have terminated FUTURE access to the
> >tty ONLY IF there are no current operations.
> You had better sit down with 4.3 tahoe source for example (and again
> I am talking about pure UCB BSD again). And look. If the code is too complex
> use McKusicks et al Operating System book, a very good reference.
> There are no way a file descriptor can do i/o if its open file table
> reference is invalidated (where invalidation means FREAD etc flags are
> removed).

Obviously you don't understand what an I/O operation is. If someone is
performing a read operation or write operation on a tty, he has already
gotten past the access checks in the open file table, and terminating
permission there doesn't stop the operations in progress.

> In a multitaking system on a single cpu, there really only one section of
> code (either kernel or user, ignoring dma and i/o bus stuff) executing
> at a given instance.

And this is the most useless way to look at an operating system. Unless
every atomic user operation completes instantly, the OS will have to
handle several operations in progress at once.

> A very good basic text is Silberschatz et al
> Operating System Concepts for a description of these fundamental techniques.

Why don't you read it?

> Second guessing what changes a vendor made to the basic BSD system
> is not being discussed.

Who are you to dictate what's being discussed? I'm worrying about
security on all the BSD-derived systems out there, and only a small
percentage of them are straight from Berkeley. I *have* to know what
vendors are doing. You don't, but your fixes also don't work on most
machines.

> > > But you want people to add an extra check, plus have it handled for
> > > blocking processes. I repeat my claim.
> > This is the only check added. Not a significant consumption of time.
> >When did you suddenly become so fixated on time? What I care about is
> >simplicity. People (and vendors) should have to make as few changes as
> >possible to the system, with as little of it as possible in the kernel.
> A fix that slows a kernel down because it is easy is probably a poor
> design.

Perhaps.

> >Here, let's review my required kernel changes again:
> >: Quick summary of kernel changes required: Make /dev/tty ioctls work on
> >: /dev/tty??, make a /dev/stdtty driver which simply dup()s fd 3, and add
> >: an ioctl, TIOCOPENCT, which returns the number of active references to a
> >: given inode. That's it.
> You forgot

I didn't forget anything. See the word ``kernel.'' I again request that
you outline the kernel changes you require, in at least sufficient
detail that someone familiar with what each kernel routine does can
implement the changes. ``fix the wakeup cases'' has no detail at all.
Then try to claim that changing code throughout the kernel is more
robust than adding a couple of syscalls.

> But in all
> fairness, I would not be concerned about the size, but the performance
> (read this as execution speed) of the solution.

Fine. My solution involves absolutely zero change in user turnaround
time for pty allocation, and nearly zero time total. Yours?

> >> And thats what I described, a technique for the BSD 4.[234] tty system.
> >But, once again, your technique does not work on most BSD 4.3-based
> >systems and will work on absolutely no BSD 4.2 systems.
  [ accuses me of misreading something ... ]
> Please stop trying to expand this to non BSD systems (Sunos
> is NOT BSD....).

You're the one who tried to take the phrase ``BSD 4.[234] tty system''
out of context. The complete paragraph is quoted above; as anyone can
see, I have from the beginning been referring to *all* BSD-derived
systems.

  [ after once again claiming that BSD releases have never included u_ttyd ]
> Please go and study operating systems in more detail. If you comment on
> 4.3 Tahoe or reno look at the code, (dropping names does not make a
> statement correct) and say nothing about the code until you understand it.
> You may want to consider taking a few graduate level courses in
> operating systems...

I think this is a classic case of someone making an absolutely false
statement, then giving several pieces of advice that obviously would be
better applied to himself.

---Dan

beede@sctc.com (Mike Beede) (05/07/91)

psl@segue.segue.com (Peter Langston) writes:

>As it stands now, you can allow write access long enough for a friend to
>initiate a write(1) and then turn off write access and discourage any other
>interruption, (i.e. you can discriminate among users temporally).

If you want to descriminte between users, why not _do_ that instead of
using the kludge of turning message access on and off?  Have a
mechanism with smaller granularity (users instead of yes/no).

-- 
Mike Beede         SCTC
beede@sctc.com     1210 W. County Rd E, Suite 100           
			Arden Hills, MN  55112
                         (612) 482-7420

muller@sdcc10.ucsd.edu (Keith Muller) (05/08/91)

In article <3739:May701:40:0591@kramden.acf.nyu.edu>, brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> In article <19045@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:

For the sake of reducing net noise only one part of Dans message bears
comment.....

> Obviously you don't understand what an I/O operation is. If someone is
> performing a read operation or write operation on a tty, he has already
> gotten past the access checks in the open file table, and terminating
> permission there doesn't stop the operations in progress.

Wrong. You failed to read my suggestion. The file pointer has to be carried down
with the io op from all points. This means adding the file pointer as a
single arg. all along the path from the ssyscall to the line disc. (This is
a simple change).

For example here is a partial sample of the code. This will
work with the unmodified 4.3 Tahoe vhangup().

In routine ino_rw() from sys_inode.c This shows the file pointer addition
for read/writes
48c48
< 	error = rwip(ip, uio, rw);
---
> 	error = rwip(ip, uio, rw, fp);
83c83
< rwip(ip, uio, rw)
---
> rwip(ip, uio, rw, fp)
86a87
> 	struct file *fp;
111c112
< 			error = (*cdevsw[major(dev)].d_read)(dev, uio);
---
> 			error = (*cdevsw[major(dev)].d_read)(dev, uio, fp);
114c115
< 			error = (*cdevsw[major(dev)].d_write)(dev, uio);
---
> 			error = (*cdevsw[major(dev)].d_write)(dev, uio, fp);

-----------------------------
Partial sample diffs for tty_tty.c (tahoe)
This shows how the fp is added as an arg to pass to the device ( from
the indirect controlling tty device). (only read is shown).
22a23
> #include "file.h"
36c37
< syread(dev, uio)
---
> syread(dev, uio, fp)
38a40
> 	struct file *fp;
43c45
< 	return ((*cdevsw[major(u.u_ttyd)].d_read)(u.u_ttyd, uio));
---
> 	return ((*cdevsw[major(u.u_ttyd)].d_read)(u.u_ttyd, uio, fp));
--------------------------------
-------------------------
partial diffs for tty_pty.c This also shows the extra arg being passed along by
a tty device to the line disp.
***************
*** 95,103 ****
  	ptcwakeup(tp, FREAD|FWRITE);
  }
  
! ptsread(dev, uio)
  	dev_t dev;
  	struct uio *uio;
  {
  	register struct tty *tp = &pt_tty[minor(dev)];
  	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
--- 95,104 ----
  	ptcwakeup(tp, FREAD|FWRITE);
  }
  
! ptsread(dev, uio, fp)
  	dev_t dev;
  	struct uio *uio;
+ 	struct file *fp;
  {
  	register struct tty *tp = &pt_tty[minor(dev)];
  	register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
***************
*** 130,136 ****
  			return (error);
  	} else
  		if (tp->t_oproc)
! 			error = (*linesw[tp->t_line].l_read)(tp, uio);
  	ptcwakeup(tp, FWRITE);
  	return (error);
  }
--- 131,137 ----
  			return (error);
  	} else
  		if (tp->t_oproc)
! 			error = (*linesw[tp->t_line].l_read)(tp, uio, fp);
  	ptcwakeup(tp, FWRITE);
  	return (error);
  }

-------------
Partial sample diffs for tty.c (tahoe)
*** /tmp/,RCSt1007772	Tue May  7 16:06:21 1991
--- tty.c	Fri Jun 15 14:14:57 1990
***************
*** 1129,1137 ****
   * Called from device's read routine after it has
   * calculated the tty-structure given as argument.
   */
! ttread(tp, uio)
  	register struct tty *tp;
  	struct uio *uio;
  {
  	register struct clist *qp;
  	register c, t_flags;
--- 1129,1138 ----
   * Called from device's read routine after it has
   * calculated the tty-structure given as argument.
   */
! ttread(tp, uio, fp)
  	register struct tty *tp;
  	struct uio *uio;
+ 	struct file *fp;
  {
  	register struct clist *qp;
  	register c, t_flags;
***************
*** 1138,1143 ****
--- 1139,1147 ----
  	int s, first, error = 0;
  
  loop:
+ 	if ((fp != (struct file *)0) && ((fp->f_flag & FREAD) == 0))
+ 		return(EBADF);
+ 
  	/*
  	 * Take any pending input first.
  	 */


-----------------------------------------------------

Now on every ttread the CURRENT file pointer access rights are checked (this
uses the off the shelf vhangup().  The same change appiles ttwrite(), etc.
This catches sleepers as they come back up to the top of the "loop:" on
wakeup. (vhangup() will modify f_flag)

Keith Muller
University of California

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/08/91)

I apologize to the rest of the net for Muller's attempts to drag this
thread into issues only relevant to the latest non-production release
from Berkeley. There are no technical points in this article, and I have
set followups appropriately. Hopefully the rest of us can continue to
discuss issues of some importance under this subject line.

In article <19105@sdcc6.ucsd.edu> muller@sdcc10.ucsd.edu (Keith Muller) writes:
> For the sake of reducing net noise only one part of Dans message bears
> comment.....

``Net noise''? For someone who's claimed in public that no BSD release
has included u_ttyp when in fact they all have until Reno, you should
learn to be both more careful and more polite.

> > Obviously you don't understand what an I/O operation is. If someone is
> > performing a read operation or write operation on a tty, he has already
> > gotten past the access checks in the open file table, and terminating
> > permission there doesn't stop the operations in progress.
> Wrong. You failed to read my suggestion.

The context, which you deleted, was your quote of *current* kernel code,
and I responded likewise.

I have been reading your suggestions. I do not find them relevant to
this thread, because they do not fix tty problems on the vast majority
of BSD-derived systems. If you wish to continue talking about changes
that only have a positive effect under BSD 4.3-Reno, please start a new
thread with an accurate subject line. Or, if you want your changes to be
adopted, talk to Berkeley directly. As they are redoing the tty system
anyway I doubt they'll listen.

> For example here is a partial sample of the code. This will
> work with the unmodified 4.3 Tahoe vhangup().

Sorry, but after your comments about u_ttyp I have to assume that when
you say ``work'' you are referring to little more than proper syntax.

---Dan

wcs) (05/08/91)

In article <kre.672866069@mundamutti.cs.mu.OZ.AU> kre@cs.mu.oz.au (Robert Elz) writes:
]The real problem is that the whole model used by "write" is simply
]wrong - sure its simple, and in a sense, elegant, but its simply
]not the way that things should be done.
]The whole concept of some other random process, owned by some other
]random user, being able to open a direct channel onto my terminal,
.....
]This is all absurd - clearly the intelligent way to run things is for
]messages that come from another user to be displayed the way I want them

I disagree - you have to remember what "write" is supposed to be for:
* "mail" is for sending people messgaes with potentially structured
	content that they can read with their favorite interface
	program when they want.  For people who want to know right
	away if they have mail, you can use a window-thingie or have
	biff bark at you when mail arrives, or whatever you want.
* "talk" is for coordinated real-time conversations between people,
	but by definition is a cooperative activity - you have to
	write to somebody using THEIR program, whether it's
	sockets-based, fifo-based, file-based, or whatever.
* "write" is for rudely interrupting people who haven't pre-arranged 
	some kind of talk program.  The standard write programs let
	you prevent people (other than root) from interrupting you
	if you want.  It also works as a crude "talk".

The main problem with write is that it doesn't work well if you're
not using a standard tty-like terminal session.  But in that case, you
can use 'mesg n', and use your favorite mail-notifier to let you
know when you have mail, or advertise your favorite 'talk' program
for people to call you with.  If people still want to rudely interrupt you,
they can use 'finger' to find your telephone number.
The other aspect to this problem is that sometimes root really does
need to interrupt you, and that can easily get lost in a window system
or an editing or graphics session.  Any suggestions here?

-- 
				Pray for peace;		  Bill
# Bill Stewart 908-949-0705 erebus.att.com!wcs AT&T Bell Labs 4M-312 Holmdel NJ
# I never wanted to be a hacker!  I wanted to be --- a lumberjack!

gsh7w@astsun9.astro.Virginia.EDU (Greg Hennessy) (05/08/91)

Dan Bernstein writes: 
#There are no technical points in this article, and I have
#set followups appropriately.

Is it correct to assume that setting followups to "misc.test" gives
you a warm fuzzy feeling Dan?

--
-Greg Hennessy, University of Virginia
 USPS Mail:     Astronomy Department, Charlottesville, VA 22903-2475 USA
 Internet:      gsh7w@virginia.edu  
 UUCP:		...!uunet!virginia!gsh7w

sef@kithrup.COM (Sean Eric Fagan) (05/09/91)

In article <1991May8.050005.26963@cbnewsh.att.com> wcs@cbnewsh.att.com (Bill Stewart 908-949-0705 erebus.att.com!wcs) writes:
>* "write" is for rudely interrupting people who haven't pre-arranged 
>	some kind of talk program.  The standard write programs let
>	you prevent people (other than root) from interrupting you
>	if you want.  It also works as a crude "talk".

talk doesn't work too well a) when talking from a non-sun to a sun, b) when
network bandwidth is on the order of 30 bytes a second, and c) when you
don't have a terminal capable of running a full-screen program.  While write
works for all three cases (for (b) I use 'mode l' from telnet, it helps a
lot), you need to have an account on the target machine.

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.

bombman@diku.dk (Hans-Henrik St{rfeldt) (05/09/91)

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

>(Note that the changes to ``write'' being discussed here are entirely
>optional suggestions; only steps 1-12 are necessary to fix the basic
>problems.)

>In article <12535@dog.ee.lbl.gov> Jef Poskanzer <jef@well.sf.ca.us> writes:
>> Our version does make control chars visible.  Checking the permissions
>> on the recipient before each line is a good idea.  The rest of your
>> changes are disgusting.

>Well, I'm glad you agree with two of them, but I'd like to ask the net's
>opinion on the other two. Let me split this into three questions:

Another problem pops up, using write with X-windows, it is possible to hide
yourself entirely, from the person you write to. This is done by making a
'non-login-shell' from your mail session (xterm). Then you can write to other
users, who gets following message:

Message from ???@freja on ttyp7 at 10:24 ...
typed message here....
EOF

This, i think is one of the greater problems with write.

--Hans Henrik Staerfeldt

ps. I am a user, not a sysop
-- 
____________________________________________________________
DK_  |  |         Bombman the mad bomber                    |
 // .|{}|         Bombman@freja.diku.dk                     |
/-|  |__|         Hans Henrik Staerfeldt                    |

kre@cs.mu.oz.au (Robert Elz) (05/09/91)

wcs@cbnewsh.att.com (Bill Stewart 908-949-0705 erebus.att.com!wcs) writes:

>I disagree - you have to remember what "write" is supposed to be for:

I'm quite aware what its supposed to be for ...

>* "mail" is for sending people messgaes with potentially structured
(and is irrelevant here)

>* "talk" is for coordinated real-time conversations between people,
>* "write" is for rudely interrupting people who haven't pre-arranged 

I disagree with this .. both initiate conversations, both rudely
interrupt, the sole difference there is that with talk I cannot
see any hint of the other person's message until I respond, and
both have a very fixed interface style, that I can't alter.

The interface we have does not require any pre-arrangement in order
for someone to write to you, a user who does nothing at all will
see nothing different from current practice.  No users need to more
than put a shell script in their login directory to be able to
selectively permit selected users to "rudely interrupt", while
totally ignoring others, and directing others to a less intrusive
communication mechanism.

Unless you have operated in an academic environment with lots of
moronic undergrad students you may not appreciate the usefulness of
selective message control - I don't want to prevent messages from
colleagues, nor necessarily from all but a few known people, but
I do want to be able to make messages from known obnoxious twerps
vanish into a bit bucket.   "Mesg n" simply isn't enough.

It also allows that want to take the effort (which need not be very
great) to create any kind of interface they desire - there is no
particularly good reason why just because someone chooses to use
"write" to initiate a conversation I can't use an interface that
looks like talk, with his message appearing in one window, and
my replies being typed in another - I will still see his lines one
at a time, as he types them, rather than character by character,
as that's te interface he has chosen - he will get my reply lines
line by line as well.  My "talk" interface may be an X application,
or it may just be on a regular terminal using curses.   If the guy
at the other end is using an intelligent interface too, that may
buffer my reply lines until he types 'o' along the typical lines
of a traditional write type conversation.

>The other aspect to this problem is that sometimes root really does
>need to interrupt you, and that can easily get lost in a window system
>or an editing or graphics session.  Any suggestions here?

The same one - obviously how easy it is to provide an unambiguous
but not overly intrusive interrupt mechanism depends on the details
of your particular situation.  On a typical 80x24 terminal there isn't
much possible beyond blatting characters onto the terminal, but given
that its your terminal, so you know its characteristics, you could
make an interface that clears the screen and puts the message in the
middle.   If you have a slightly smarter terminal, it may have switched
to analternate memory page, or something, then restore your work when
you have seen the message - in any case, the point is that its up to
the user to decide just how, and when, if at all, he wants to be interrupted.

kre

jfh@rpp386.cactus.org (John F Haugh II) (05/10/91)

In article <28949:May620:55:5391@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Agreed. Since UNIX doesn't provide for revoking a valid file descriptor,
>the obvious solution is to make sure that no user program ever gets to
>touch a modem driver. A privileged program can control the driver and
>route I/O through a pipe or pseudo-tty or socket or any other basically
>dynamic object. It can also drop its control of the driver whenever the
>user types break.

No, the obvious solution is to provide for file access revocation.  What
do you do to assure (because, remember, we have to provide assurances
that our solution really works - handwaving doesn't cut it) that there
isn't some process on the other side of the "privileged program" that
is reading our hardware tty?  Under all the suggestions I've seen for
this hack, there is still a hardware tty device whose privilege bits
we must very carefully watch out for lest anyone ever get access to it.

>The problem is that, once again, UNIX doesn't have this concept of
>terminating current access. The last time that people tried to add it to
>BSD was vhangup(), and that was a complete failure.

Then fix vhangup().

>I find it conceptually much simpler to just make sure that unprivileged
>programs never open /dev/modem*.

I find it conceptually much simpler to not have one extra process per
active tty port.

>Well, sure, but that's even more work that Muller hasn't outlined in
>detail. Again it seems much simpler to put this control at the user
>level.

Well, I have a real job.  I'd love to wander about the Reno sources
I've got laying around and make the fixes, but I've got other things
that those people that sign my checks keep telling me are more
important ...

>C'mon, that's not at the same level of detail as ``Make /dev/tty ioctls
>work on /dev/tty??''. *What* is the mechanism? You obviously have to
>introduce some new structures or add fields to the old ones; where are
>those fields?
>
>To make this work on current systems you also have to make sure that
>u_ttyd access is tracked. This would require that an entirely separate
>set of kernel routines be changed, and I don't think a whole bunch of
>people would figure this out from your description.

Whenever I come up with a way to bill my employer for hours spent in
USENET consultation, then I'll spend the time and provide the exact
details.

But I will tell you this much - the changes that are required are not
that difficult to make.  Your suggestions are the grossest hack I've
seen to date for solving this problem, and it doesn't even provide
any assurance that it has been solved, while at the same time adding
its own collection of deficiencies.
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

jfh@rpp386.cactus.org (John F Haugh II) (05/10/91)

In article <29117:May621:05:1391@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Yeah, I think you can make vhangup() chop /dev/tty without races if you
>change u_ttyd to p_ttyd throughout, fix all your process-status programs
>so that they don't crash with this change, and add some lines inside the
>vhangup() syscall. That doesn't do anything about current operations.

Like I said, the current operations can be fixed by finding all the
places that sleep waiting for an I/O operation to complete.  Add a
generation number or some such to the tty structure.  Save your
generation number before sleeping, and if they match when you wake
up, you win the prize.  There are zillions of ways to solve this
problem.

>> How about fixing that problem instead of creating another
>> hack?
>
>``Creating another hack''? Sheesh. The entire idea of having a separate
>tty security mechanism is a hack. /dev/tty represents an alternate
>method of file access, and as such makes security a whole lot more
>complicated than when there was only open(). That's the problem that
>/dev/stdtty fixes.

That's utter nonsense.  AIX supports /dev/tty and tty device
revocation, and the code to support both is no big deal.  It even
manages to get access via /dev/tty correct ...
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

mjr@uther.calvin.edu (Matt Ranney) (05/11/91)

I've just joined this groups a few days ago, so I missed most of the
other things that were said, but the "write" program doesn't even need
to be used to fire anonymous messages to people.  You can just cat a
core dump > their tty.  

I'm sure this has been said before, but could someone please enlighten
me on a few things?  I still don't see why tty security is such a difficult
problem to resolve.  Why not make programs that need to spam the
user's tty setuid root, and change the default permissions on user's
ttys so that only they (and root, of course) have read/write.  And
make the write program, as was said before, spew data at a slower rate,
and prepend each line with the writer's id.  The login program is
already setuid root, so the permissions could stay at root r/w only.
This would fix programs like "cover" from working.

So why wouldn't this work?  If some other naive person like myself has
already asked this question and had it answered, please respond via Email.

Thanks
--
Matt Ranney -- t22918@ursa.calvin.edu  
sendmail: error reading file /home/t22918/.signature     (core dumped)

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/11/91)

Since John expressed some doubts, enclosed here is an informal but
reasonably detailed proof of the security of my proposed solution. Also
here is a justification of each of the required steps in my solution.
Someone who reads through this should understand why each step is
necessary and why in combination they are sufficient; if there's any
misunderstanding, send me e-mail, and I'll post a clarification.

In article <19253@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> No, the obvious solution is to provide for file access revocation.  What
> do you do to assure (because, remember, we have to provide assurances
> that our solution really works - handwaving doesn't cut it) that there
> isn't some process on the other side of the "privileged program" that
> is reading our hardware tty?

Huh? Under suggestion #24, no user process will ever open hardwired
/dev/tty* or /dev/modem* or whatever you want to call those devices.
Provided that the normal UNIX security mechanisms are in place, and
provided that /dev/modem* always have their permission bits properly
set, the system guarantees that no user program can ever open those
files. Are you doubting the concept of file permissions?

> Your suggestions are the grossest hack I've
> seen to date for solving this problem, and it doesn't even provide
> any assurance that it has been solved,

Wtf are you talking about? As I said at first, my solution provides
strong guarantees that the problem has been solved. Witness a proof of
security:

1. All /dev/pty* are initially group- and world-inaccessible, and owned
   by user pty, as required by the solution. Hence, at the outset, only
   programs running as root or pty may open those files. Provided that
   none of those programs ever changes the mode of /dev/pty*, they will
   continue to be group- and world-inaccessible.

2. A file may only be open in a process if it is (1) opened directly by
   that process, (2) passed in from another process, e.g., via fork().
   Provided that none of those root/pty programs ever passes an open
   /dev/ptyxx descriptor to another process, and given #1, we conclude
   that no process can have /dev/pty* open unless it is a root/pty
   program. (This means, more precisely, that it has at some point had
   root or pty permissions. Even more precisely, by ``process'' I
   distinguish between processes with the same pid and process state but
   separated by an exec(), and by ``passing'' I mean to include leaving
   the descriptor open through an exec().)

3. Provided that none of those root/pty programs ever passes an open
   /dev/ptyxx descriptor to another process, and because /dev/ptyxx may
   only be opened once, there always exists at most one process with
   /dev/ptyxx open.

4. I claim that if /dev/ptyxx is not open in any process, then
   /dev/ttyxx is not (group- or world-) accessible, and is owned by pty,
   provided that no root/pty process changes an inaccessible /dev/ttyxx
   to an accessible one (or one with a different owner) without having
   /dev/ptyxx open. Proof: The claim is true at first, as all /dev/tty*
   are initially inaccessible as required by the solution. By #2,
   /dev/ptyxx may only be open in a root/pty process. So by hypothesis
   we must only check that when such a process closes /dev/ptyxx,
   /dev/ttyxx is not accessible. But, as required by my solution, such a
   process must change /dev/ttyxx to be owner pty mode 600 before it
   closes /dev/ptyxx. Hence the claim is always true.
   
5. If /dev/ptyxx is not open in any process, then /dev/ttyxx is not open
   in any process except possibly a root/pty process. Proof: The claim
   is true at first. As in #4, /dev/ptyxx may only be open in a root/pty
   process. So we must only check that when a root/pty process closes
   /dev/ptyxx, /dev/ttyxx is not open except possibly in a root/pty
   process (which, in fact, can only be itself). But, as required by my
   solution, the process must open a separate open file description to
   /dev/ttyxx which it does not pass to any other process. Furthermore,
   also as required by my solution, before closing /dev/ptyxx, and after
   changing /dev/ttyxx to be owner pty mode 600, the process must be
   told by TIOCOPENCT that the only open file description to /dev/ttyxx
   is that separate descriptor, which again it has not passed to any
   other process. Hence the claim is true.

That's the basic idea. From these guarantees you can draw further
conclusions. If, for example, telnetd opens /dev/ptyxx and /dev/ttyxx
and then passes the descriptors to login, then by #5 we see that no
other process can have had /dev/ttyxx open from when /dev/ptyxx was last
open, and by #4 we see that no other process can have opened /dev/ttyxx
during the last period in which /dev/ptyxx was not open. Hence no other
process has /dev/ttyxx open.

Now, John, would you like to repeat your statement about assurances?

Sure, a stupid superuser (or a buggy root/pty program) can invalidate
any of the assumptions mentioned above: for example, he can change
/dev/ptyxx and /dev/ttyxx to mode 666 owner shmoe, and (guess what?)
it's insecure. There's no way to solve problems like this without adding
mandatory access controls.

At the top of this article I promised to explain why each of the
required steps in my solution was necessary. Well, steps 3, 4, and 9 are
used in guarantee #5, and steps 5, 6, and 10 are used in guarantees #1
and #4. I don't see any way to eliminate those steps without breaking
at least one of the guarantees; conversely, those steps together with
normal UNIX security do make the proofs work.

Steps 1, 2, 7, and 8 fix a separate problem. The above guarantees only
address the issue of having /dev/ttyxx open directly. Unfortunately,
today's UNIX systems have alternative ways of affecting the device
through a different mechanism than opening it: for example, /dev/tty.
Those steps eliminate the current /dev/tty and reduce that alternative
access mechanism to the original mechanism, namely file descriptors. I
should note that there are many other alternative access mechanisms
(e.g., process groups) that in some systems introduce their own sets of
security problems, but the only universal mechanism allowing complete
data corruption is /dev/tty. (Having two ptys with the same minor number
would be just as dangerous, but I have never seen anyone do that, and it
would certainly break the usual pty allocation code.)

Do I need to explain step 11, namely protecting /etc/utmp on Suns? This
is what I call a SCINUP---a Security Compromise Introduced in the Name
of User Power. I suppose it's like the example of a superuser making all
the tty files world-writable, but /etc/utmp is so easy to fix that I
felt compelled to mention it.

Finally, step 12 fixes an old SCINUP, namely having users leave their
ttys world-usable in order to allow user-to-user communication. This is
also only somewhat related to the basic problems of tty access. I leave
it to everyone else to seek out and destroy further SCINUPS embedded in
common programs.

There. Is there anyone left who doesn't understand why a particular step
is necessary, or who doesn't believe that my solution guarantees rather
strong security? (Again, if I need to clarify anything above, send me
some e-mail.) Those of you who've been shouting religious stupidities
about how you absolutely need to see break code to be convinced that my
fixes work---can you see the difference now between a proof of security
by logic and a ``proof'' of security by testing? (I will address this
point in detail in a coming message.)

---Dan

lyda@acsu.buffalo.edu (kevin lyda) (05/11/91)

In article <21553:May1020:06:0791@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Those of you who've been shouting religious stupidities
>about how you absolutely need to see break code to be convinced that my
>fixes work---can you see the difference now between a proof of security
>by logic and a ``proof'' of security by testing? (I will address this
>point in detail in a coming message.)

good point....  :)  a file that one of my professors was kind enough to
distribute... sadly, none of these proofs receive credit...

			HOW TO PROVE IT

proof by example:
	The author gives only the case n = 2 and suggests that it 
	contains most of the ideas of the general proof.

proof by intimidation:
	'Trivial'.

proof by vigorous handwaving:
	Works well in a classroom or seminar setting.

proof by cumbersome notation:
	Best done with access to at least four alphabets and special
	symbols.

proof by exhaustion:
	An issue or two of a journal devoted to your proof is useful.

proof by omission:
	'The reader may easily supply the details'
	'The other 253 cases are analogous'
	'...' 

proof by obfuscation:
	A long plotless sequence of true and/or meaningless 
	syntactically related statements.

proof by wishful citation:
	The author cites the negation, converse, or generalization of 
	a theorem from the literature to support his claims.

proof by funding:
	How could three different government agencies be wrong?

proof by eminent authority:
	'I saw Karp in the elevator and he said it was probably NP-
	complete.' 

proof by personal communication:
	'Eight-dimensional colored cycle stripping is NP-complete 
	[Karp, personal communication].' 

proof by reduction to the wrong problem:
	'To see that infinite-dimensional colored cycle stripping is 
	decidable, we reduce it to the halting problem.' 

proof by reference to inaccessible literature:
	The author cites a simple corollary of a theorem to be found 
	in a privately circulated memoir of the Slovenian 
	Philological Society, 1883.

proof by importance:
	A large body of useful consequences all follow from the 
	proposition in question.

proof by accumulated evidence:
	Long and diligent search has not revealed a counterexample.

proof by cosmology:
	The negation of the proposition is unimaginable or 
	meaningless. Popular for proofs of the existence of God.

proof by mutual reference:
	In reference A, Theorem 5 is said to follow from Theorem 3 in 
	reference B, which is shown to follow from Corollary 6.2 in 
	reference C, which is an easy consequence of Theorem 5 in 
	reference A.

proof by metaproof:
	A method is given to construct the desired proof. The 
	correctness of the method is proved by any of these 
	techniques.

proof by picture:
	A more convincing form of proof by example. Combines well 
	with proof by omission.

proof by vehement assertion:
	It is useful to have some kind of authority relation to the 
	audience.

proof by ghost reference:
	Nothing even remotely resembling the cited theorem appears in 
	the reference given.

proof by forward reference:
	Reference is usually to a forthcoming paper of the author, 
	which is often not as forthcoming as at first.

proof by semantic shift:
	Some of the standard but inconvenient definitions are changed 
	for the statement of the result.

proof by appeal to intuition:
	Cloud-shaped drawings frequently help here.

jfh@rpp386.cactus.org (John F Haugh II) (05/13/91)

In article <21553:May1020:06:0791@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Since John expressed some doubts, enclosed here is an informal but
>reasonably detailed proof of the security of my proposed solution. Also
>here is a justification of each of the required steps in my solution.
>Someone who reads through this should understand why each step is
>necessary and why in combination they are sufficient; if there's any
>misunderstanding, send me e-mail, and I'll post a clarification.

None of that is "an assurance" that I have a clean port.  What does
the system do to "assure" the application that the pty port is clean?
What can the application do to gain some assurance that the pty port
server it is talking to is really the right thing to be talking to?

There are only two things needed to guarantee you have the only
open file descriptor - TIOCOCNT (or whatever) and fchmod().  If you
want to bump everyone off, add a "revoke()"-like system call.  All
this tty copying nonsense defers the problem to the administration,
which had better never let the permissions get messed up, or a new
device node created.  Yes, kernel changes are needed as well.

The ability to "clean" a hard or soft tty with a "revoke()" system
call guarantees that the tty port you are talking to is yours and
yours alone, file permissions or no.  What you do is to defer the
issue for another level - nothing has prevented me from setting up
my trojan horse on the pty side and walking away.  You'll also
find the business with the <BREAK> key is pretty costly when you
start getting framing errors on your modem ports and your users
get logged out.
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/13/91)

In article <19262@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> None of that is "an assurance" that I have a clean port.  What does
> the system do to "assure" the application that the pty port is clean?
> What can the application do to gain some assurance that the pty port
> server it is talking to is really the right thing to be talking to?

I don't understand this. Why should the application need such assurance?
It's just an unprivileged program. Are you saying that whenever someone
forks ls, it's ls's job to make sure that it's talking to the ``right
thing'' (whatever that is) before it runs? How is it supposed to behave
differently if it's not talking to the ``right thing''?

If the system supports normal UNIX security, my changes guarantee that
when a user starts a program through telnet or rlogin or script or
whatever, no other program initially has access to the same tty. It's
not the program's job to make such checks, just as it's not the job of
each new process to check at user level that it has a unique pid.

> What you do is to defer the
> issue for another level - nothing has prevented me from setting up
> my trojan horse on the pty side and walking away.

Every new telnet or rlogin or script will skip that pty, so who cares?
In the meantime the session will be accounted to you.

> You'll also
> find the business with the <BREAK> key is pretty costly when you
> start getting framing errors on your modem ports and your users
> get logged out.

So use a different secure attention key. The point is that if getty is
the only program with a hardwired tty open, then there's no way for user
programs to mangle that tty except as getty allows.

---Dan

jfh@rpp386.cactus.org (John F Haugh II) (05/14/91)

In article <10581:May1315:01:2891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>I don't understand this. Why should the application need such assurance?
>It's just an unprivileged program.

OK, how would a privileged application get the assurances it wants that
the port it is talking to is the real port.  For example, how does
"passwd" know that it really has the real user, and isn't being run in
some pipeline with a little expect script that looks for "Old Password"
and then keeps anything else that comes along, including the new
password?  Oh.

>If the system supports normal UNIX security, my changes guarantee that
>when a user starts a program through telnet or rlogin or script or
>whatever, no other program initially has access to the same tty. It's
>not the program's job to make such checks, just as it's not the job of
>each new process to check at user level that it has a unique pid.

BZZZT.  Wrong answer.  Your scam does nothing to protect against
applications that start on non-network ports.  I can always emulate the
login sequence (unless you dream up some exotic login sequence to add
as the next layer of hacks).  I can login and start my little trojan
horse then walk away from the screen with a login banner displayed.
How do you insure that there are no programs, including trojan horses,
running on that port?

>Every new telnet or rlogin or script will skip that pty, so who cares?
>In the meantime the session will be accounted to you.

Sure.  And I'll have your password.  How do you know that I was 
actually the person that started the trojan horse once I can
demostrate that I can break an account?  Program gets your password,
pretends you entered it wrong, exits, and gives you the real banner.
Move on to next victim, signed on as first victim ...

>So use a different secure attention key. The point is that if getty is
>the only program with a hardwired tty open, then there's no way for user
>programs to mangle that tty except as getty allows.

What is the difference between getty having a hardwired port open, and
clone-of-getty sitting on a pty that you just handed me when I logged in?
Or do we throw out all the glass tubes being used today?  As for using
different SAK keys, what to do about UUCP, etc?
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/14/91)

In article <19270@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> In article <10581:May1315:01:2891@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >I don't understand this. Why should the application need such assurance?
> >It's just an unprivileged program.
> OK, how would a privileged application get the assurances it wants that
> the port it is talking to is the real port.  For example, how does
> "passwd" know that it really has the real user,

Okay, now I understand what you're getting at. The answer is that passwd
doesn't know who it's talking to. If a user wants to run it in a
situation where every keystroke could be monitored---e.g., over an
Ethernet---you can't realistically say that passwd should refuse to
function. Or are you going to restrict use of passwd to people who can
walk up to the console? (In a few environments this is reasonable.)

Eavesdropping (and data corruption) is no worse a problem for passwd
than it is for any user program. If you want to solve those essentially
physical problems, encrypt your data.

> BZZZT.  Wrong answer.  Your scam does nothing to protect against
> applications that start on non-network ports.

Sure it does. Please read suggestion #24.

> >Every new telnet or rlogin or script will skip that pty, so who cares?
> >In the meantime the session will be accounted to you.
> Sure.  And I'll have your password.

Perhaps you missed the first sentence. Every new telnet or rlogin or
script will skip that pty, so who cares? Under suggestion #24, getty
will skip it too. You will never get a password, because no user will
ever be talking to your program while logging in.

> >So use a different secure attention key. The point is that if getty is
> >the only program with a hardwired tty open, then there's no way for user
> >programs to mangle that tty except as getty allows.
> What is the difference between getty having a hardwired port open, and
> clone-of-getty sitting on a pty that you just handed me when I logged in?

No user will ever get his clone ``sitting on a pty that you just handed
me when I logged in'' because the login process will skip all used ptys.
End of argument.

> Or do we throw out all the glass tubes being used today? 

That would be silly. Why would you suggest such a thing?

> As for using
> different SAK keys, what to do about UUCP, etc?

This is a non-issue.

---Dan

jfh@rpp386.cactus.org (John F Haugh II) (05/15/91)

In article <25833:May1416:43:4291@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Okay, now I understand what you're getting at. The answer is that passwd
>doesn't know who it's talking to. If a user wants to run it in a
>situation where every keystroke could be monitored---e.g., over an
>Ethernet---you can't realistically say that passwd should refuse to
>function. Or are you going to restrict use of passwd to people who can
>walk up to the console? (In a few environments this is reasonable.)

Glad you finally got that point.

Now, given that passwd can't verify who it is talking to, how can it
possibly meet the assurances required to state that it isn't talking
to a trojan horse?

>Eavesdropping (and data corruption) is no worse a problem for passwd
>than it is for any user program. If you want to solve those essentially
>physical problems, encrypt your data.

Sure.  But I'm not even talking about eavesdropping, I'm talking
about really simple stuff, like trojan horses.  What about a case
where my application looks just like "passwd", but is really just
a pipe or somesuch (like the "pty" command) from your keyboard to
the real passwd command.

>Sure it does. Please read suggestion #24.

I log in as "jfh", and start my trojan horse.  It displays a login
banner.  You type "brnstnd".  I prompt for your passwd.  You enter
it.  I stuff the username and password in a file and exit.  What
does your scheme do to prevent that from happening on a hardwired
terminal?

>> As for using
>> different SAK keys, what to do about UUCP, etc?
>
>This is a non-issue.

It just goes to show that you've never bothered thinking about what
the issues are.  How exactly would an application turn off the SAK
key under your system?
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/16/91)

In article <19276@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> Now, given that passwd can't verify who it is talking to, how can it
> possibly meet the assurances required to state that it isn't talking
> to a trojan horse?

You didn't answer my question. Are you going to restrict use of passwd
to people who can walk up to the console? If not, then you are always
vulnerable to eavesdropping, and it's the user's responsibility, not
passwd's, to make sure that nobody's looking over his shoulder.

It doesn't matter whether passwd can make your statement. All that's
necessary is that a normal user, under normal operation of the system,
will be able to start passwd in a safe way. That's what I've guaranteed.
If he later wants to do something stupid and start passwd in an unsafe
way, I can't stop him, and I see no reason that passwd should stop him.

> >Eavesdropping (and data corruption) is no worse a problem for passwd
> >than it is for any user program. If you want to solve those essentially
> >physical problems, encrypt your data.
> Sure.  But I'm not even talking about eavesdropping, I'm talking
> about really simple stuff, like trojan horses.  What about a case
> where my application looks just like "passwd", but is really just
> a pipe or somesuch (like the "pty" command) from your keyboard to
> the real passwd command.

Who tf cares? A sane user will never invoke such a pipe. It's not
passwd's responsibility to check that the user is sane.

Somehow we're failing to communicate here. My model is that the user
walks up to a console or makes a network connection, then types
something that (as the OS documentation guarantees) sends his future
keystrokes directly to the system and nobody else. If he then types his
username and password, nobody else gets the password. If he then types
passwd and changes his password, nobody else gets the password.

The problem right now is that there are all these security holes---the
system doesn't guarantee that nobody's looking on. My changes make that
guarantee, at least for the tty subsystem.

You seem to be in this fantasy world where the user intentionally
invokes a pipe to your recording wrapper around passwd. That's stupid.
He's going to do that about as often as he sends you his password by
e-mail. What problem are you trying to fix?

> >Sure it does. Please read suggestion #24.
> I log in as "jfh", and start my trojan horse.  It displays a login
> banner.  You type "brnstnd".  I prompt for your passwd.  You enter
> it.

Perhaps you didn't read the suggestion. I don't just type my username
and password; I press the secure attention key, then my username and
password. Surely you're familiar with Multics?

> >> As for using
> >> different SAK keys, what to do about UUCP, etc?
> >This is a non-issue.
> It just goes to show that you've never bothered thinking about what
> the issues are.  How exactly would an application turn off the SAK
> key under your system?

Be serious. The whole point of a SECURE attention key is that it cannot
be violated by unprivileged applications (i.e., things outside the TCB).
And, as Bellovin told you, there's no need for an application to turn
off the SAK---you just make the SAK a variable-length signal if normal
data is fixed-length, and vice versa. This is a non-issue.

---Dan

jfh@rpp386.cactus.org (John F Haugh II) (05/16/91)

In article <14021:May1521:56:2291@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>In article <19276@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
>> Now, given that passwd can't verify who it is talking to, how can it
>> possibly meet the assurances required to state that it isn't talking
>> to a trojan horse?
>
>You didn't answer my question. Are you going to restrict use of passwd
>to people who can walk up to the console? If not, then you are always
>vulnerable to eavesdropping, and it's the user's responsibility, not
>passwd's, to make sure that nobody's looking over his shoulder.

I got news for you, bud, talking to the console doesn't buy you anything
either.  Besides, physical security falls outside the scope of software
security.  All the clever hacks can't keep someone from taking the cover
off the machine and removing the disk drives.

>Who tf cares? A sane user will never invoke such a pipe. It's not
>passwd's responsibility to check that the user is sane.

Actually, it is passwd's responsibility to insure that it is talking
to the user that is has authenticated.  That includes not talking to
a trojan horse.

>Somehow we're failing to communicate here. My model is that the user
>walks up to a console or makes a network connection, then types
>something that (as the OS documentation guarantees) sends his future
>keystrokes directly to the system and nobody else. If he then types his
>username and password, nobody else gets the password. If he then types
>passwd and changes his password, nobody else gets the password.
>
>The problem right now is that there are all these security holes---the
>system doesn't guarantee that nobody's looking on. My changes make that
>guarantee, at least for the tty subsystem.

But your system doesn't do what you claim it does - sure, it prevents
someone else from logging out, keeping a /dev/tty file descriptor
laying around, and doing what it prevents them from doing.  It does
not prevent them from having trusted code (the passwd command) from
being executed by a trojan horse.  How many times a day does the user
type this "something that sends his future keystrokes directly to the
system and nobody else."

>Be serious. The whole point of a SECURE attention key is that it cannot
>be violated by unprivileged applications (i.e., things outside the TCB).
>And, as Bellovin told you, there's no need for an application to turn
>off the SAK---you just make the SAK a variable-length signal if normal
>data is fixed-length, and vice versa. This is a non-issue.

Can I change my baud rate while waiting for the SAK sequence?  Of
course there's a need to turn off the SAK key - how long is a UUCP
packet this week?  Once you permit an application to change any
way in which the SAK sequence is processed (variable v. fixed length)
or affect its being recognized (baud rates), you no longer have a
reliable SAK sequence, and all the SAK warm fuzzies won't make SAK
usable.  The system itself =must= have a way to insure that you and
you alone are out there.  Not just "you have a way", but "it has a
way" too.  Please don't answer that the stty command is going to
have to be privileged so you can't change parity or character length
or baud rate or whatnot.

I'm not saying your entire concept is wrong, or useless or anything,
just that you are missing some very crucial parts.  SAK alone is
not enough, it helps a great deal, but it ignores other entire
classes of problems that you are waving off.  As for your changes,
as Bellovin pointed out, they are overly complex in, what I think
he called, "the wrong places."  Implementing revoke() and a decent
SAK probably shouldn't take more than one or two weeks, and it
closes all the real interesting holes.  Adding "trusted path"
should get rid of the rest of the things affecting tty security.
The hardest part to trusted path is figuring out what needs to
run on the trusted path.  The reason that the NCSC criteria are
presented in the fashion they are, is that parts of the criteria
are often useless without other parts.  SAK without trusted path
is just a nice way to kill things when you log in.  Trusted path
keeps trojan horse from springing up once you logged in, but
doesn't let you kill any trojan running off the trusted path.  It's
the bigger picture you are missing.  Like, what good is object
reuse if you don't have access control, or vice versa?

I have to run - the movers are coming in a few minutes to deliver
some furniture and maybe I'll find the Orange Book if I shuffle
some of the junk around ...
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (05/17/91)

In <19281@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:

>Can I change my baud rate while waiting for the SAK sequence?  Of
>course there's a need to turn off the SAK key - how long is a UUCP
>packet this week?

A secure attention key sequence, to be secure, must use an out-of-band
channel.  As an analogous example, the DTR line to a modem is
out-of-band and cannot be defeated no matter what you send on the data
lines.
--
Rahul Dhesi <dhesi@cirrus.COM>
UUCP:  oliveb!cirrusl!dhesi

jfh@rpp386.cactus.org (John F Haugh II) (05/17/91)

In article <3136@cirrusl.UUCP>, dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
> In <19281@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> 
> >Can I change my baud rate while waiting for the SAK sequence?  Of
> >course there's a need to turn off the SAK key - how long is a UUCP
> >packet this week?
> 
> A secure attention key sequence, to be secure, must use an out-of-band
> channel.  As an analogous example, the DTR line to a modem is
> out-of-band and cannot be defeated no matter what you send on the data
> lines.

Yes.  Not everything has an out of band channel to send a SAK sequence
along on.  For example, what would you use as the SAK sequence on a 3
wire dumb ASCII terminal that is hardwired to a port switch that is
used by any number of other terminals with various baud rates and
keyboards?  There are no spare lines to dork with.  Send a break?  Do
all dumb ASCII keyboards include a BREAK key?  It can't be defeated,
but no every keyboard has one.  Waving "SAK" in front of the problem
does not make the issue of authenticating the login process to you any
more secure.  The issue I keep trying to raise is that it is nice if
both the computer and the user clean the line.  Dan assures us that
for a properly started login process (which he can't guarantee the
user is going to press SAK to start) we get a clean line.  I say,
remove the dependency on the user pressing SAK to start with - let
the system clean the line off itself.  If the user wants to clean the
line, let her nail the SAK key and kill any trojans lurking in the
wings.  If a system application (for example, passwd) wants to make
certain it is talking directly to the authenticated user, let it
execute some revoke() process which kills off all untrusted (non-TCB)
applications using that port (or some other grotesque action).
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (05/18/91)

In the discussion, Dan mentioned using a secure attention key (SAK)
sequence for security.  John objected, saying that the SAK sequence
would have to be disabled for some purposes, such as UUCP.  I
responded:

   A secure attention key sequence, to be secure, must use an
   out-of-band channel.  As an analogous example, the DTR line to a
   modem is out-of-band and cannot be defeated no matter what you send
   on the data lines.

John F Haugh II responds (quite correctly):

   Not everything has an out of band channel to send a SAK sequence
   along on.  For example, what would you use as the SAK sequence on a
   3 wire dumb ASCII terminal that is hardwired to a port switch that
   is used by any number of other terminals with various baud rates and
   keyboards?  There are no spare lines to dork with.  Send a break?
   Do all dumb ASCII keyboards include a BREAK key?  It can't be
   defeated, but not every keyboard has one.

Dan will, of course, have his own response to this (as he always
does :-).  Although it's true that not all hardware guarantees an
out-of-band channel to support a secure attention key, it turns out
that there is a simple method of using in-band signalling that is
*virtually* foolproof.  The good folks at Bizcomp patented this some
years ago.  (Maybe I should say the "bad" folks, because they then
proceeded to sue everybody in sight.)  The idea is to have a secure
attention sequence that includes guard pauses before and after.  In the
case of the most popular application of this patent, the sequence used
is:

     (1 second pause) +++ (1 second pause)

When the above happens on the data line, a modem that understands it
goes into command mode.

I said *virtually* foolproof because there is a finite, though
infinitesimal, chance that a genuine data stream will include the same
sequence.  If it does, you are in trouble.  It doesn't happen in
practice, probably for the same reason that an ideal gas in a box never
collects all in one corner, though the quantum mechanics (mechanicists?
machinists?) will tell you that, given enough time, it *will* happen.

Probably 99.9% of dumb terminals have a real break key.  Users of the
remaining 0.1% may have to do something like this:

     1.   pause for 3 to 5 seconds
     2.   rapidly hit the + key 10 times
     3.   pause for 3 to 5 seconds
     4.   hit the return key

The chances of the pauses accidentally occuring in the same way in a
data stream are probably very small.  To make the sequence even more
foolproof you can increase the pauses, or require a longer
sequence like:

     (pause) +++ (pause) --- (pause) &&& (pause)
--
Rahul Dhesi <dhesi@cirrus.COM>
UUCP:  oliveb!cirrusl!dhesi

scs@lokkur.dexter.mi.us (Steve Simmons) (05/18/91)

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

>In article <19276@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:

>> What about a case
>> where my application looks just like "passwd", but is really just
>> a pipe or somesuch (like the "pty" command) from your keyboard to
>> the real passwd command.

>Who tf cares? A sane user will never invoke such a pipe. It's not
>passwd's responsibility to check that the user is sane.

There are one hell of a lot of insane users out there.  I've seen them
regularly for the past ten years.
-- 
 "FACT: less than 10% of the psychiatrists in the US are actually
  practicing cannibals."  Rod Johnson

jfh@rpp386.cactus.org (John F Haugh II) (05/19/91)

In article <3140@cirrusl.UUCP> Rahul Dhesi <dhesi@cirrus.COM> writes:
>Dan will, of course, have his own response to this (as he always
>does :-).

Yes, I have read the specification for the Dan Bernstein Window
Manager.  It argues with your for 15 minutes and still doesn't
resize the window ...

>          Although it's true that not all hardware guarantees an
>out-of-band channel to support a secure attention key, it turns out
>that there is a simple method of using in-band signalling that is
>*virtually* foolproof.

The problem is that it must be =absolutely= foolproof.  If I can
come up with even one way to circumvent it, it isn't usable as a
SAK sequence.  AT&T with the SV/MLS product uses DTR as the
out-of-band signal.  What about three-wire terminals?  [ The answer
there is that if you don't use exactly the set up the NCSC evaluated,
your milage may vary ;-) ]

>     (1 second pause) +++ (1 second pause)
>
>When the above happens on the data line, a modem that understands it
>goes into command mode.

Every second I send an answer-back request to your terminal.  Once a
second I receive the answer-back, strip it out from whatever you type,
and pass that along unchanged to the rest of the system.  You never
notice anything funny because you aren't talking to the hardware
anyhow, but rather my little trojan horse that is pretending to be
the login program.

It's obvious that you are thinking a lot harder than Dan, but it
isn't clear that you understand the nature of the problem.  A SAK
squence must be absolutely uninteruptable (for lack of a better
word).  I don't think it is possible for a single SAK sequence to
apply to all possible login session types for more than the smallest
collection of hardware.  I think it takes a multiple choice approach.

But SAK alone is not the end-all to security.  You also need an
application that can do useful things with SAK, and Dan's suggestion
that every SAK kills everything on the line is just too gross.  If
the user can't SAK at any time, they will never SAK.  And that means
any need for the SAK key during crucial operations (like changing
your password) will not be met - what, press SAK and kill my XBIFF?
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/19/91)

In article <19306@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> Yes.  Not everything has an out of band channel to send a SAK sequence
> along on.

Then the sequence must be in-band. For the sake of argument, let's say
that getty (or whatever process does the I/O on a hardwired line) checks
for ^K everywhere in the input stream. ^K<space> is translated into a ^K
for the underlying session, and ^K<anything else> disconnects the
session for later reconnection and provides a login prompt. That's a
secure attention key, and one which cannot be defeated on most
terminals. (The exceptions are those terminals which can somehow be
forced to silently transmit a space right after the user types ^K, and
those in which the ^K key itself can be reprogrammed.)

> Dan assures us that
> for a properly started login process (which he can't guarantee the
> user is going to press SAK to start) we get a clean line.

What's the point of your parenthetical comment? The system documentation
will tell users that they should press ^K a few times to get a login
prompt. Otherwise, sayeth the docs, some other user might be faking the
login prompt, and that's a Bad Thing. In any case, yes, I assert that my
solution provides a secure tty, and I've explained in another article
exactly why this is true.

> I say,
> remove the dependency on the user pressing SAK to start with - let
> the system clean the line off itself.  If the user wants to clean the
> line, let her nail the SAK key and kill any trojans lurking in the
> wings.

Frankly, John, that is one of the most idiotic statements I've ever
heard from you. You complain about my solution because it can't stop
stupid users from telling other users their passwords, but you want to
trust the user to press SAK after he's given away the password? Wake up.
Revoking tty access does not solve any more problems than my solution
does, and your ridiculous ideas about how a SAK can be implemented have
nothing to do with tty security.

---Dan

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/19/91)

In article <19309@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> It's obvious that you are thinking a lot harder than Dan, but it
> isn't clear that you understand the nature of the problem.  A SAK
> squence must be absolutely uninteruptable (for lack of a better
> word).

John, I am assuming the existence of a well-known SAK for a given line,
and pointing out how it can be used to increase security. You're
attacking the mere concept of an SAK. As Multics and several other
operating systems showed quite clearly, SAKs do exist, so any arguments
to the contrary are wrong.

> But SAK alone is not the end-all to security.  You also need an
> application that can do useful things with SAK, and Dan's suggestion
> that every SAK kills everything on the line is just too gross.

I have never made any such suggestion, and I despise the way that you
have misrepresented my proposals. I advise readers to check my postings
rather than believing John's statements about them.

(What I actually suggested is that SAK disconnect the current session.
This means that the user can later log in again and reconnect, resuming
work where he left off. For further details on session management, see
my pty paper, Bellovin's session manager paper, or VMS documentation.)

---Dan

jfh@rpp386.cactus.org (John F Haugh II) (05/20/91)

In article <23893:May1901:19:2191@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>(What I actually suggested is that SAK disconnect the current session.
>This means that the user can later log in again and reconnect, resuming
>work where he left off. For further details on session management, see
>my pty paper, Bellovin's session manager paper, or VMS documentation.)

[ I was going to respond to the other article from Dan.  I'm on a
  "responding to Dan" diet ...  This last paragraph was too juicy to
  pass up. ]

Which means that your SAK scheme is actually less secure than I had
originally thought.  What are you going to do to revoke TTY access to
a process that =somehow= has illicitly gained access to the TTY?  Multics
and AIX v3 (and others ...) have a SAK key that gets it right - if you
don't have any authorization to attach to the port, you die when the
user presses SAK.  Your scam lets the trojan or whatever lurk about in
the background, and never kills it because you've been too kind hearted
and let it live.

Now I realize that SAK and trusted path really come into the NCSC
criteria somewheres up around B2 and B3, but really, either implement
it so that SAK does what it should (revoke unauthorized access to the
TTY) or don't bother at all.  Your suggestion is akin to the apparent
AT&T implementation of SAK for SV/MLS - /etc/getty interprets the DTR
falling, and goes and kills the jobs that have the port open.  But
what if /etc/getty isn't running?  [ This is a real question ... ]

All I want to know is what do you do to get rid of trojan horses after
they have gained access to your tty line.  Could you please answer
that one simple little question?
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/20/91)

This article includes a series of diagrams showing how I think hardwired
ttys should work. This has all been explained before, both in my pty
paper and in Steve Bellovin's session manager paper, but John refuses to
accept the fact that dynamically allocated ttys are secure. So here goes.

In article <19313@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> In article <23893:May1901:19:2191@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
> >(What I actually suggested is that SAK disconnect the current session.
> >This means that the user can later log in again and reconnect, resuming
> >work where he left off. For further details on session management, see
> >my pty paper, Bellovin's session manager paper, or VMS documentation.)
> [ I was going to respond to the other article from Dan.  I'm on a
>   "responding to Dan" diet ...  This last paragraph was too juicy to
>   pass up. ]
> Which means that your SAK scheme is actually less secure than I had
> originally thought.  What are you going to do to revoke TTY access to
> a process that =somehow= has illicitly gained access to the TTY?

``What are you going to do to revoke pipe access to a process that
=somehow= has illicitly gained access to the pipe?'' You don't do
anything. You create the pipe dynamically, and there is absolutely no
way that another process is going to have access to it.

I'm getting sick of explaining this to you again and again. So let me
draw you a picture of what the system looks like after suggestion #24:
                ___
     /^\       |abc|
     | <)      |def|
     | -  ---- |ghi| ---- /dev/tty00 ---- getty ---- /dev/ptyq7 ---- sh
     \_/       |___|
                          hardwired       system      pseudo-        user
    John      terminal      device        process       tty         process

Here getty never lets a user program access /dev/tty00; it forwards all
I/O through a pseudo-tty. Let's say you start a Trojan Horse:
                ___
     /^\       |abc|
     | <)      |def|
     | -  ---- |ghi| ---- /dev/tty00 ---- getty ---- /dev/ptyq7 ---- TROJAN
     \_/       |___|
                          hardwired       system      pseudo-        user
    John      terminal      device        process       tty         process

Now you leave the terminal alone, and another user comes along.
                ___
     /^\       |abc|
     | <       |def|
     | |  ---- |ghi| ---- /dev/tty00 ---- getty ---- /dev/ptyq7 ---- TROJAN
     \_/       |___|
                          hardwired       system      pseudo-        user
    Sally     terminal      device        process       tty         process

Sally bangs on ^K a few times. As I explained before, getty notices the
SAK and disconnects the current session:
                ___
     /^\       |abc|
     | <       |def|
     | |  ---- |ghi| ---- /dev/tty00 ---- getty    
     \_/       |___|
                          hardwired       system     
    Sally     terminal      device        process      


                                                   /dev/ptyq7 ---- TROJAN
						
                                                     pseudo-        user
                                                       tty         process

Notice that the link between the terminal and the Trojan Horse has been
completely severed. No process has access to /dev/tty00 other than
getty. Now Sally logs in, on an unused pseudo-tty allocated by getty:
                ___
     /^\       |abc|
     | <       |def|
     | |  ---- |ghi| ---- /dev/tty00 ---- getty ---- /dev/ptysb ---- login
     \_/       |___|
                          hardwired       system      pseudo-        safe
    Sally     terminal      device        process       tty         process


                                                   /dev/ptyq7 ---- TROJAN
						
                                                     pseudo-        user
                                                       tty         process

Your fake login program is still running, but it's inside a session that
Sally isn't talking to. Sally is talking to /dev/ptysb, which is
guaranteed clean. I explained in detail in a previous article why my
solution makes that guarantee.

Now do you understand why allocating an unused tty stops Trojans?

> Your scam lets the trojan or whatever lurk about in
> the background, and never kills it because you've been too kind hearted
> and let it live.

You have no idea what you are talking about.

> But
> what if /etc/getty isn't running?

Under my proposal, no I/O will happen at all if getty isn't talking to
the port. Note that all hardwired ttys are only accessible to root.

> All I want to know is what do you do to get rid of trojan horses after
> they have gained access to your tty line.  Could you please answer
> that one simple little question?

Can you please stop repeating the same stupid little question? If you
can't understand Bellovin's explanations or my explanations or the
series of diagrams above, I give up.

---Dan

jh4o+@andrew.cmu.edu (Jeffrey T. Hutzelman) (05/20/91)

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>      (pause) +++ (pause) --- (pause) &&& (pause)
> --
> Rahul Dhesi <dhesi@cirrus.COM>
> UUCP:  oliveb!cirrusl!dhesi

Of course, you actually don't want to use the sequence (pause) +++
(pause), because that will produce really confusing results if someone
ever tries to invoke it over a modem that recognizes that.  Of course,
a modem connection isn't all that secure anyway because it's easy to
tap, but someone might still consider themselves secure enough despite
that.  On the other hand, an in-band SAK sequence over the phone would
be a dead giveaway to someone wathing that you're about to type
something sensitive, like a password.
--------------------
Jeffrey Hutzelman			America Online: JeffreyH11
Internet: jh4o+@andrew.cmu.edu		BITNET: JHUTZ@DRYCAS
>> Apple // Forever!!! <<

jfh@rpp386.cactus.org (John F Haugh II) (05/20/91)

In article <3690:May1921:22:5191@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
>Can you please stop repeating the same stupid little question? If you
>can't understand Bellovin's explanations or my explanations or the
>series of diagrams above, I give up.

No.  Not until you figure out that I don't care about the TTY line
and I don't care about what happens before the user logs in.  What
happens to a trojan horse that gains access to the =PTY= =AFTER=
the user logs in?  The purpose (go read the Orange Book if you
don't believe me) of Trusted Path and SAK and so on is to insure
positive TCB to User (and vice versa) communication.  If you change
the point of attack from the hardwired tty port to the PTY device
and don't make it any more difficult to violate, all you've done
is moved the problem.  You diagram completely and totally misses
the point.
-- 
John F. Haugh II        | Distribution to  | UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) |  Domain: jfh@rpp386.cactus.org
"If liberals interpreted the 2nd Amendment the same way they interpret the
 rest of the Constitution, gun ownership would be mandatory."

wes@harem.clydeunix.com (Barnacle Wes) (05/20/91)

Trojan horses:

In article <25833:May1416:43:4291@kramden.acf.nyu.edu> brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:
% Eavesdropping (and data corruption) is no worse a problem for passwd
% than it is for any user program. If you want to solve those essentially
% physical problems, encrypt your data.

In article <19276@rpp386.cactus.org>, jfh@rpp386.cactus.org (John F Haugh II) replies:
> Sure.  But I'm not even talking about eavesdropping, I'm talking
> about really simple stuff, like trojan horses.  What about a case
> where my application looks just like "passwd", but is really just
> a pipe or somesuch (like the "pty" command) from your keyboard to
> the real passwd command.

% Sure it does. Please read suggestion #24.

> I log in as "jfh", and start my trojan horse.  It displays a login
> banner.  You type "brnstnd".  I prompt for your passwd.  You enter
> it.  I stuff the username and password in a file and exit.  What
> does your scheme do to prevent that from happening on a hardwired
> terminal?

It doesn't.  Of course, there is no way you can really prevent such
things from happening unless you have only local terminals with physical
control.  Case in point:

I worked with a man several years ago who was such a pest on the
(VAX/VMS) system we used that I and several friends decided to take
away the privileges on his account.  Our accounts didn't have the
privilege to change his account, but his did, so we dragged a PC with
two serial ports into the wiring closet and spliced it into his
terminal line.  We wrote a simple program for the PC that passed data
back and forth between COM1: and COM2: while looking for the login and
password prompts and recording his responses.  That night, we logged
into his account, ran authorize, and took away all his privileges.  We
continued doing this for every privileged account he logged into for
the next several days.  Everything was quiet on the system for about 3
months after this attack, until he managed to get SETPRIV back.

Secure Attention Keys:

> As for using
> different SAK keys, what to do about UUCP, etc?

% This is a non-issue.

> It just goes to show that you've never bothered thinking about what
> the issues are.  How exactly would an application turn off the SAK
> key under your system?

Just make the SAK SEQUENCE a break (framing error).  This solves any
problems with UUCP, and if you have a ""-BREAK-in: sequence in your
send-expect strings, you'll get the secure port on login.  This may, of
course, disagree with any terminal servers you're using, but they can
usually be reconfigured to support a "local" key other than break.

	Wes Peters
-- 
#include <std/disclaimer.h>                               The worst day sailing
My opinions, your screen.                                   is much better than
Raxco had nothing to do with this!                        the best day at work.
     Wes Peters:  wes@harem.clydeunix.com   ...!sun!unislc!harem!wes

rockwell@socrates.umd.edu (Raul Rockwell) (05/21/91)

Dan Bernstein;
   >It's not passwd's responsibility to check that the user is sane.

Steve Simmons:
   There are one hell of a lot of insane users out there.  I've seen
   them regularly for the past ten years.

"It doesn't matter how smart the program is, a dumb user will always
 find a way to screw it up."  -- Joanne Byrd


Raul Rockwell

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (05/22/91)

In article <19317@rpp386.cactus.org> jfh@rpp386.cactus.org (John F Haugh II) writes:
> What
> happens to a trojan horse that gains access to the =PTY= =AFTER=
> the user logs in?

If that can happen, then you're not talking about a Trojan Horse; you're
talking about a complete failure in security. If a program can do that,
it can redirect all further input from and output to the terminal, and
the user is up the creek. Why do you care what happens past that?

What I'm doing is making sure that such programs won't get access to the
pseudo-tty in the first place. *That's* security.

---Dan

seebs@thor.acc.stolaf.edu (The Laughing Prophet) (05/22/91)

In article <1991May9.145536.20002@odin.diku.dk> bombman@diku.dk (Hans-Henrik St{rfeldt) writes:
>Another problem pops up, using write with X-windows, it is possible to hide
>yourself entirely, from the person you write to. This is done by making a
>'non-login-shell' from your mail session (xterm). Then you can write to other
>users, who gets following message:

>Message from ???@freja on ttyp7 at 10:24 ...
>typed message here....
>EOF

Hmm... I know a way, on most unix systems, to duplicate this wrt a
normal user (i.e., someone who doesn't quite have the background to
use 'ps' instinctively)...

write <foo>
<type message here>
<*type* "EOF">
^Z out of the job and wait. About 5 minutes later, they will have forgotten
about you. Then, fg the job, and:
^V^GMessage from root@gopher.rodent.generic.com on ttyl4 at 16:32 ...
>type message here<
EOF

and repeat as often as desired. Most people will be fooled by this
one...

And I have *no* idea how to stop it in any reasonable way.

>--Hans Henrik Staerfeldt
>ps. I am a user, not a sysop

Hmm. I sort of run a NeXT, but really I'm just a user. I want to be
a sysop some day, though...

> // .|{}|         Bombman@freja.diku.dk                     |
>/-|  |__|         Hans Henrik Staerfeldt                    |

--SeebS--
--
Peter Seebach - The Laughing Prophet     |     |        Anonymous Posting Here!
I don't speak for St. Olaf, St. Olaf     |     |           seebs@acc.stolaf.edu
doesn't speak for me, and Marcel Marceau |     | "Forgive them Father, for they
speaks for no one.                       |     |        do not get the joke..."