rsalz@bbn.com (Rich Salz) (10/10/90)
Submitted-by: Dan Bernstein <brnstnd@kramden.acf.nyu.edu> Posting-number: Volume 23, Issue 31 Archive-name: pty/part01 [ This is the Ginsu knife (it slices, it dices, it never rusts) that Dan has been talking about in comp.unix.wixards/internals for some time now. It is a mind-blower. --r$ ] pty - run a program under a pty session pty is meant as the sole interface between pseudo-terminals and the rest of the system. Some features: improved security; over fifty options for precise control; session disconnecting and reconnecting; full efficiency after a reconnect; a gradual upgrade path so that all your old utilities will work without change; support for applications that need full pty control; and a reasonably smart install script. Also in this package are twenty-one utilities, including a ``script'' that actually works. pty has been thoroughly tested on several BSD 4.3-based machines and tested on several BSD 4.2-based machines. It should be easy to port to any system supporting pseudo-terminals and UNIX-domain sockets. If you know any application of ptys that this program can't handle, or if you have a different machine that would benefit from the modularity and power of a pty port, please let the author know. pty does not work under POSIX-based machines (such as SunOS 4.1), even when it works perfectly under their predecessors (such as SunOS 4.0.3). The main problem is POSIX's introduction of sessions and the way it kills a non-orphaned process in an orphaned process group. There are other incompatibilities, mostly minor but some (like accounting and setuid problems) important. The author is working on a POSIX port. #! /bin/sh # This is a shell archive. Remove anything before this line, then feed it # into a shell via "sh file" or similar. To overwrite existing files, # type "sh file -c". # The tool that generated this appeared in the comp.sources.unix newsgroup; # send mail to comp-sources-unix@uunet.uu.net if you want that tool. # Contents: PACKNOTES README MANIFEST FILES INSTALL patch # patch/telnetd.90.06.28.patch util # Wrapped by rsalz@litchi.bbn.com on Wed Oct 10 10:11:35 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo If this archive is complete, you will see the following message: echo ' "shar: End of archive 1 (of 6)."' if test -f 'PACKNOTES' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'PACKNOTES'\" else echo shar: Extracting \"'PACKNOTES'\" \(1756 characters\) sed "s/^X//" >'PACKNOTES' <<'END_OF_FILE' XBad character 010 in line 384 of "INSTALL". XBad character 010 in line 385 of "INSTALL". XBad character 010 in line 401 of "INSTALL". XBad character 010 in line 402 of "INSTALL". XBad character 010 in line 428 of "INSTALL". XBad character 010 in line 429 of "INSTALL". XBad character 010 in line 443 of "INSTALL". XBad character 010 in line 444 of "INSTALL". XBad character 010 in line 467 of "INSTALL". XBad character 010 in line 468 of "INSTALL". XFound 10 control chars in "INSTALL" X XBad character 07 in line 98 of "util/write.c". XFound 1 control char in "util/write.c" X XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 30 of "util/lock.c". XBad character 07 in line 34 of "util/lock.c". XBad character 07 in line 36 of "util/lock.c". XBad character 07 in line 38 of "util/lock.c". XFound 20 control chars in "util/lock.c" X XBad character 07 in line 53 of "util/wall.c". XFound 1 control char in "util/wall.c" X XBad character 010 in line 2 of "util/script.tidy". XBad character 010 in line 2 of "util/script.tidy". XFound 2 control chars in "util/script.tidy" END_OF_FILE if test 1756 -ne `wc -c <'PACKNOTES'`; then echo shar: \"'PACKNOTES'\" unpacked with wrong size! fi # end of 'PACKNOTES' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3922 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' Xpty - run a program under a pty session X Xpty is meant as the sole interface between pseudo-terminals and the rest Xof the system. Some features: improved security; over fifty options for Xprecise control; session disconnecting and reconnecting; full efficiency Xafter a reconnect; a gradual upgrade path so that all your old utilities Xwill work without change; support for applications that need full pty Xcontrol; and a reasonably smart install script. Also in this package are Xtwenty-one utilities, including a ``script'' that actually works. X Xpty has been thoroughly tested on several BSD 4.3-based machines and Xtested on several BSD 4.2-based machines. It should be easy to port to Xany system supporting pseudo-terminals and UNIX-domain sockets. If you Xknow any application of ptys that this program can't handle, or if you Xhave a different machine that would benefit from the modularity and Xpower of a pty port, please let the author know. X X Xpty does not work under POSIX-based machines (such as SunOS 4.1), even Xwhen it works perfectly under their predecessors (such as SunOS 4.0.3). XThe main problem is POSIX's introduction of sessions and the way it Xkills a non-orphaned process in an orphaned process group. There are Xother incompatibilities, mostly minor but some (like accounting and Xsetuid problems) important. The author is working on a POSIX port. X X Xpty version 3.001, August 21, 1990. XCopyright (c) 1990, Daniel J. Bernstein. XAll rights reserved. X XThis distribution packaged August 22, 1990. X XGeneral layout: XCHANGES Description of changes since first distributed version XCOPYRIGHT A comprehensible copyright notice XFILES File list (used by make shar) XINSTALL A script to guide you through compilation and installation XINSTALLREADABLE INSTALL's information, in a format you can reasonably edit XMANIFEST Shipping list XQUESTIONS Some questions that pty answers XREADME This document XTESTS A script to guide you through some tests XMakefile Installation commands X*.c Programs X*.h Header files Xpty.man Documentation Xpatch/* Patches to other programs to better use pty Xutil/* Utilities X XBefore you do anything else, run the INSTALL script. It'll guide you Xthrough compiling and installing pty and the utilities. Then run TESTS Xto exercise a few of pty's features on your system. patch/ is separate; Xread patch/README at your leisure. X XRead CHANGES for a list of changes. pty -C and pty -W give copyright and Xwarranty information; pty -H prints a help screen. X XNote that INSTALL, util/lock.c, util/script.tidy, util/write.c, and Xutil/wall.c all contain control characters. X X XKnown problems: X XPOSIX compatibility---might as well do complete rewrite Xlast was removed but is mentioned in INSTALL and INSTALLREADABLE XINSTALL's usleep test is not accurate in Ultrix 3.1C (aargh) Xchildsig = SIGCONT for TSTP in master.c? XPIPE should be handled by finish in sigler.c for NO_FDPASSING folks Xsesslist gives error for a session directory not yet created Xpty -H lists /etc/wtmp---guaranteed to confuse some people XQUESTIONS and TESTS list sed ... | more, race; more should be grep x Xon cannot chdir to session directory, pty does not restore correctly X (set up your session directory correctly!) X X XTODO list: X XINSTALLSU script, for the final stages of installation Xfix PTYDIR propagation into utilities Xvhangup()? this is a sticky issue. probably not but we'll see Xlocking on /etc/utmp and /usr/adm/wtmp? not necessary if APPEND works Xgenerally handle signals better in sigler Xclean up ``last'' and include it in package X``detach''? not yet, for reasons discussed in paper Xmust pty really stop on pty -T ... &? X``utmpinit'', so that pty and login will get along---generally useful X X XMore comprehensive discussion will be available soon in ``The Design, XImplementation, and Use of a Pseudo-Terminal Manager.'' END_OF_FILE if test 3922 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'MANIFEST' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'MANIFEST'\" else echo shar: Extracting \"'MANIFEST'\" \(2906 characters\) sed "s/^X//" >'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X---------------------------------------------------------- XPACKNOTES 1 XREADME 1 XMANIFEST 1 This shipping list XCHANGES 5 XCOPYRIGHT 4 XFILES 1 XINSTALL 1 XINSTALLREADABLE 2 XMakefile 5 XQUESTIONS 4 XTESTS 4 Xconfig.h 3 Xerr.c 5 Xerr.h 6 Xfile.h 6 Xfile.h.new 6 Xfile.h.old 5 Xgetopt.h 6 Xglobals.c 5 Xlogs.c 3 Xlogs.h 6 Xmaster.c 2 Xmaster.h 6 Xmisc.c 5 Xmisc.h 6 Xpatch 1 Xpatch/Makefile 4 Xpatch/README 4 Xpatch/TELNET.FTP 6 Xpatch/igntt.c 5 Xpatch/telnetd.90.06.28.patch 1 Xpty.1 3 Xpty.c 2 Xpty.h 5 Xsig.c 4 Xsig.h 5 Xsigler.c 3 Xsigler.h 6 Xslave.c 4 Xslave.h 6 Xsock.c 3 Xsock.h 5 Xtexts.c 4 Xtexts.h 6 Xtty.c 3 Xtty.h 5 Xutil 1 Xutil/Makefile 3 Xutil/biff.1 5 Xutil/biff.c 4 Xutil/condom 6 Xutil/condom.1 5 Xutil/disconnect.1 5 Xutil/disconnect.c 5 Xutil/excloff.1 6 Xutil/excloff.c 6 Xutil/exclon.1 5 Xutil/exclon.c 6 Xutil/lock.1 5 Xutil/lock.c 5 Xutil/mesg.1 5 Xutil/mesg.c 5 Xutil/reconnect.1 5 Xutil/reconnect.c 5 Xutil/script 6 Xutil/script.1 5 Xutil/script.tidy 6 Xutil/script.tidy.1 5 Xutil/sess 6 Xutil/sess.1 5 Xutil/sesskill.1 5 Xutil/sesskill.c 5 Xutil/sesslist.1 5 Xutil/sesslist.c 4 Xutil/sessname.1 5 Xutil/sessname.c 5 Xutil/sessuser.1 4 Xutil/sessuser.c 4 Xutil/sessutil.c 4 Xutil/sessutil.h 5 Xutil/tiocsti.1 6 Xutil/tiocsti.c 6 Xutil/tty.1 6 Xutil/tty.c 6 Xutil/u.1 5 Xutil/u.c 5 Xutil/wall.1 5 Xutil/wall.c 5 Xutil/who.1 5 Xutil/who.c 5 Xutil/write.1 5 Xutil/write.c 4 Xutil/xsessutil.c 4 END_OF_FILE if test 2906 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'FILES' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'FILES'\" else echo shar: Extracting \"'FILES'\" \(1052 characters\) sed "s/^X//" >'FILES' <<'END_OF_FILE' XCHANGES XREADME XFILES XCOPYRIGHT XMANIFEST XINSTALL XINSTALLREADABLE XTESTS XQUESTIONS XMakefile Xpty.1 Xconfig.h Xpty.h Xsigler.h Xmaster.h Xslave.h Xerr.h Xtty.h Xgetopt.h Xtexts.h Xsig.h Xlogs.h Xfile.h Xfile.h.old Xfile.h.new Xsock.h Xmisc.h Xpty.c Xsigler.c Xmaster.c Xslave.c Xerr.c Xtty.c Xtexts.c Xsig.c Xglobals.c Xlogs.c Xsock.c Xmisc.c Xpatch Xpatch/README Xpatch/TELNET.FTP Xpatch/Makefile Xpatch/telnetd.90.06.28.patch Xpatch/igntt.c Xutil Xutil/Makefile Xutil/biff.1 Xutil/biff.c Xutil/condom Xutil/condom.1 Xutil/disconnect.1 Xutil/disconnect.c Xutil/excloff.1 Xutil/excloff.c Xutil/exclon.1 Xutil/exclon.c Xutil/lock.1 Xutil/lock.c Xutil/mesg.1 Xutil/mesg.c Xutil/reconnect.1 Xutil/reconnect.c Xutil/script Xutil/script.1 Xutil/script.tidy Xutil/script.tidy.1 Xutil/sess Xutil/sess.1 Xutil/sesskill.1 Xutil/sesskill.c Xutil/sesslist.1 Xutil/sesslist.c Xutil/sessname.1 Xutil/sessname.c Xutil/sessuser.1 Xutil/sessuser.c Xutil/sessutil.c Xutil/sessutil.h Xutil/tiocsti.1 Xutil/tiocsti.c Xutil/tty.1 Xutil/tty.c Xutil/u.1 Xutil/u.c Xutil/wall.1 Xutil/wall.c Xutil/who.1 Xutil/who.c Xutil/write.1 Xutil/write.c Xutil/xsessutil.c END_OF_FILE if test 1052 -ne `wc -c <'FILES'`; then echo shar: \"'FILES'\" unpacked with wrong size! fi # end of 'FILES' fi if test -f 'INSTALL' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'INSTALL'\" else echo shar: Extracting \"'INSTALL'\" \(25242 characters\) sed "s/^X//" >'INSTALL' <<'END_OF_FILE' X#!/bin/sh X# This is a shell script. Feed it to sh. Xecho ' XHi, and welcome to the pty install script. Xpty is a program for managing pseudo-terminals. X XI'\''m not actually going to install anything. XI'\''ll just guide you through what has to be done, Xfrom compiling through installation. X XOne advantage of this hands-off philosophy is that Xyou can kill and restart this script at any time. XYou may prefer to read through INSTALLREADABLE, Xwhich has the same information. X XIn the first part of this script, I'\''ll lead you through configuration. XFor the moment, don'\''t actually change anything in your system. Just Xalternate between reading this script and fooling around with the XMakefile, and I'\''ll remind you later, after compilation, of what has Xto be changed elsewhere. X XI need the following programs: echo, tr [-d], man, sed [-n], grep, test. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XThe first versions of pty were designed on a BSD 4.2-based system. XDuring May 1990 pty 3.0 was written completely from scratch, Xon a BSD 4.3-based system. It has been thoroughly tested on Xseveral BSD 4.3-based systems, tested with a few Makefile changes Xon several BSD 4.2-based systems, and run on at least one mutant. X XIf you make it through installation and testing and get pty running, Xplease send a note to the author, Dan Bernstein, on the Internet Xat brnstnd@nyu.edu. Let him know your computer model, OS version, and Xwhat changes you had to make. If you have any trouble, please also get Xin touch with the author. If you have a different kind of system with Xpseudo-terminal support that could use a pty port, the author would Xlove to hear about it. X XOne note: Like all software, pty comes without warranty, to the extent Xpermitted by applicable law. Use it at your own risk. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XI assume that you don'\''t want to make any major changes Xto your computer just to take advantage of pty'\''s capabilities. XYou might not even have a privileged account, for all I know. X XThe first major decision you have to make is what privileges to give pty. XObviously if you don'\''t have privileges then pty won'\''t either; Xthis is Case UN. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XThere are several good reasons for giving programs privileges. XMost importantly, privileged programs can precisely control access Xto a shared resource. pty supports an interactive user list in X/etc/utmp, a login-logout record in /usr/adm/wtmp, and controlled Xaccess to the pseudo-terminal files themselves, including security and Xmode changing. None of these are possible if pty isn'\''t setuid. X XIf your system has a lot more tty security than usual, you probably Xwon'\''t be able to run pty without privileges. (However, if your system Xhas a lot more tty security than usual, it'\''s almost certainly running Xpty anyway.) X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XIf you do want pty to have privileges, you have to decide between Xsetting up pty as root (Case ROOT) or as some other user, say ``pty'\'\'' X(Case PTY). Staying away from root has the advantage that problems Xcan'\''t possibly destroy all security in one blow. However, root has Xseveral advantages, mainly because of BSD limitations: 1. A process Xcan'\''t change ownership of a file between its euid and uid. Only root Xcan change ownership. It shouldn'\''t be necessary to change ownership Xof ptys anyway, but that'\''s what many programs assume. 2. MAXUPRC in X<sys/param.h> limits the number of processes under a given *effective* Xuid. This absolutely idiotic behavior is a serious problem for programs Xsetuid to anything other than root. pty tries to work around this Xproblem, but there are no true solutions. 3. Despite the documentation Xin kill(2), many machines don'\''t allow non-root processes to send XCONT to children with a different uid. Unlike almost all other programs, Xpty sensibly handles its child stopping and restarting; but this won'\''t Xwork on those machines if pty isn'\''t root. X XYou should decide now between Case ROOT and Case PTY. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XWhether you'\''ve decided on ROOT, PTY, or UN, Xnow is the time to check the security of the entire pty package. XIt'\''d be difficult for anything to slip through the checks by the Xauthor, testers, and source group moderator, but you should take Xat least a moment to look for your pet security peeves. X XA couple of security notes: The only open(,O_CREAT) in pty is in Xmaster.c, at the top of master(), of a file with a very restricted Xform constructed from the filename of a /dev/ttyxx. There are no Xcreat()s. The only bind() is in sock.c'\''s pty_readsock(), which is Xcalled only from master.c'\''s master() to create a socket with a Xsimilarly restricted name. (fnsty is changed in sigler but not in Xmaster.) The only exec() is in slave.c, after a forced setreuid() Xto a uid that is only set to getuid(). unlink(), mkdir(), and rename() Xare only used with restricted pathnames. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XIn Case PTY, you have to set up a new uid, say ``pty'\'\'' (or whatever Xusername you want). pty should not allow logins. Its password should Xbe an asterisk; its home directory should be /nonexistent; its shell Xshould be /bin/true. In other words, the only access to user pty Xshould be through these setuid programs. X XIn any privileged case you should have group tty, Xwhich most BSD 4.3 systems have as gid 4. X' X Xecho 'Running '\ X'$ ttygroup="`sed -n '\''s/^tty:[^:]*:\(.*\):.*/\1/p'\'' < /etc/group`" ...' Xttygroup="`sed -n 's/^tty:[^:]*:\(.*\):.*/\1/p' < /etc/group`" X Xcase "$ttygroup" in X4) echo ' XI see that you have a tty group, 4 as usual. Good. X' ;; X'') echo ' XYou don'\''t have a tty group. Unless you have a suitable group under a Xdifferent name, you should add the line Xtty:*:4:root Xto /etc/group. X' ;; X*) echo ' XI see that you have a tty group, gid '"$ttygroup"' rather than 4. Okay. X' ;; Xesac X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XNext, we'\''re going to drudge through the config.h file. X XIn Cases ROOT or PTY, you have to set up a system-wide directory Xfor storing information about pty sessions. (A session is a program Xstuck under a pty that you can disconnect and reconnect.) Users can Xget around this directory, storing the information in ~/.pty and Xrevoking any privileges, with pty -xS; you can even make this default Xby setting flagxsetuid = 0 in globals.c. However, a single system-wide Xdirectory is safer. X XAnyway, that directory, PTYDIR, should be mode 0700, owner root in case XROOT or pty in case PTY, group irrelevant. PTYDIR is defined in config.h Xas /usr/etc/pty by default; if you choose a different directory, add X-DPTYDIR=\"/what/ever/dir/ect/ory\" to CCOPTS in the Makefile. X XIn Case UN, you may want to set up a directory ~/PTY inside your home Xdirectory, and set PTYDIR to that; you may want to set flagxsetuid = 0 Xin globals.c; or you may want to just type -xS to pty all the time. I Xrecommend the first strategy. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XNext come pseudo-terminal pathnames. I assume that your ptys are Xlabelled as /dev/ptyxx and /dev/ttyxx, where xx is any two-letter Xextension. pty can support any initial strings instead of these, Xbut some of the utilities have /dev/tty hardcoded, and lots of other Xprograms running around assume those names. If you'\''re desperate, Xdefine DEVMTY and DEVSTY in the Makefile, and figure out what has to Xbe changed in util/*. (Sorry.) X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XThe extension is traditionally [p-za-o][0-9a-f]. The first letter of the Xsecond string is special: if /dev/ttyq0 doesn'\''t exist, for example, then Xnone of /dev/ttyq[0-9a-f] will be used. (That'\''s called a pty bank.) X XYou can change those strings by defining, e.g., PTY1=\"ABCDEFG\" or XPTY2=\"02468abfq\" in the Makefile. You have at least four choices here: X1. Give pty its own, new, banks of new pseudo-terminals with weird bank Xnames not including a through z, and define PTY1 appropriately. pty will Xonly use those new ptys, and older programs will just use the old ptys. XThis may require reconfiguring your system for the larger number of Xterminals. 2. Give pty some new banks, and take out some old ones to Xmake up for it. 3. Give pty a chunk of the old banks. 4. Give pty all Xthe old banks. X XNote that pty searches randomly through PTY1 and PTY2 by default; for Xefficiency, PTY1 really should reflect exactly the pty banks you have. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XSo now you'\''ve decided on new ptys, or set aside some or all of your Xold ptys, and changed PTY1 and PTY2 appropriately. Because BSD gives a Xprocess very little control over its controlling terminal, pty has to Xpass a terminal name explicitly when it reconnects. If any of your tty X(not just pseudo-tty!) filenames are longer than 30 characters, you have Xto set -DTTYNAMELEN=60 (or whatever) in the Makefile. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' X/etc/utmp has traditionally listed all users logged on. XThis nebulous concept has evolved through the years; given the way Xthat most programs use utmp, utmp is probably better defined as a Xlist of all interactive sessions. Anyway, pty supports this file, Xand will make an entry in it when given -xu. If you have a different Xfile, add -DPTYUTMP_FILE=\"/foo/bar/utmp\" to DEFINES in the Makefile. X XNote that /etc/utmp is unprotected (mode 666) on Suns. This was Sun'\''s Xattempt to let unprivileged programs manage the file. Unforunately, this Xerror in judgment opens up a huge security hole, which even on Xsingle-user machines is an invitation to make mistakes. I advise you to Xmake /etc/utmp owned by root in Case ROOT or pty in Case PTY, mode 644. XThere aren'\''t many unprivileged programs that don'\''t understand the Xpty interface; people on non-Suns have survived so far, and there'\''s Xno reason for you to keep subscribing to an insecure model of resource Xsharing. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XAlthough pty will put an entry into utmp, it doesn'\''t really support Xthe remote-host field. There is no logical association between sessions Xand connections; why should a login require a pty, and why should a Xsession only stick around for one connection? So pty just puts "pty" in Xthe host field. You can change this with -DPTYUTMP_HOST=\"foo\"; you may Xeven want to make PTY_UTMPHOST call a function that you define. X X(Similar comments apply to PTYWTMP_HOST. There are also PTYUTMP_SWHOST Xand PTYWTMP_SWHOST, defaults PTYUTMP_HOST and "pty-sessuser" Xrespectively; see util/sessuser.1 for more information.) X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' X/usr/adm/wtmp has traditionally recorded all logins, logouts, reboots, Xftp sessions, and various other interesting events. (The entry for a Xline in utmp is the last entry for that line in wtmp.) pty supports wtmp Xfully, in the same way as utmp. You should make wtmp mode 644, owner Xroot or pty as appropriate. Change PTYWTMP_FILE if /usr/adm/wtmp is Xsomewhere else. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XYou can turn off utmp support by uncommenting the NO_UTMP line in Xconfig.h. (Just delete the initial /*.) You can also turn off support Xfor wtmp, disconnectable sessions, or changing pseudo-terminal file Xownership; just uncomment the appropriate line. You can force use of Xeach of these features by defining MUST_UTMP, etc., in the same way. X XNote that the usual login programs do their own wtmp management, and Xmany accounting programs incorrectly equate session time with connect Xtime, so users will rarely want wtmp. As more programs appear using the Xpty interface, and as login programs start using a more logical system Xfor accounting, MUST_WTMP may become an appropriate way to monitor Xpseudo-terminal usage. For the moment, I do not advise setting any NO Xor MUST. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' Xpty subscribes (not very willingly) to the BSD 4.3 model of pty Xprotection, with a few twists. All ptys are under group tty, at all Xtimes; if you don'\''t have a tty group, all ptys should be under some Xother protected group at all times. Anyway, pty will change the group of Xeach pseudo-terminal file to PTYGROUP, default 4, under -xc. X' X Xcase "$ttygroup" in X4) echo ' XSince you already have a tty group, gid 4, you'\''re fine. X' ;; X'') echo ' XYou don'\''t have a tty group. You should pick a gid and define X-DPTYGROUP=whatever in the Makefile. X' ;; X*) echo ' XYou have a tty group, but it'\''s not gid 4. You should define X-DPTYGROUP='"$ttygroup"' in the Makefile. X' ;; Xesac X Xecho ' X(Under Case UN, don'\''t worry about all this group stuff. Just leave XPTYGROUP alone.) X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XUnder -xc, pty changes the pseudo-terminal owner to the current real Xuid. The fact that terminals need to be in the file hierarchy reflects a Xserious failure in the BSD terminal model; but anyway, many programs Xexpect to be able to fool around with /dev/tty. After pty is done with Xthe terminal, it sets the owner back to its effective uid. You can Xmodify this behavior by changing PTYOWNER from euid to something else. X XUnder Case UN, PTYOWNER is irrelevant. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XWhile a tty is unused, BSD systems traditionally leave it unprotected. XUnfortunately, this leaves some huge security holes. Here'\''s one of Xthe biggest advantages of a privileged pty manager: unused ttys don'\''t Xhave to be left open for any random program to use. After it'\''s done Xwith a pseudo-terminal, pty changes it to mode UNUSEDPTYMODE, default X0600. (This is another case of a poor model for kludging pty support Xinto unprivileged programs. If you haven'\''t set up separate pty banks Xfor pty, and you really want to allow unprivileged access to unused Xptys, try mode 0660 and make those other programs setgid to tty.) X XA tty that someone'\''s using can be in many different modes. Typically XUSEDPTYMODE should be 0600, which means user-only access, messages off, Xbiff off. If you really, really, really want to make the mistake of Xhaving messages or biff on by default, try 0620, 0700, or 0720. Note Xthat the world protection should always be 0: the point of the tty group Xis that only setgid-tty programs can access ttys. X XAs usual, you can'\''t do anything about these in Case UN. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XNow we'\''re past generic configuration and down to your system'\''s Xnitty-gritty. X XFor purity, pty has SIGRET_TYPE, default int, as the type returned by a Xsignal handler. On Suns and ANSI-compliant machines, you should define XSIGRET_TYPE=void. Then you can admire the lint -haxc *.c output. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XOUTBUFSIZE, default 16384, is the size of the buffer pty keeps between Xthe incoming data and the pseudo-tty, and between the pseudo-tty and the Xoutgoing data. If you want to spare less than 32K per pty just for Xbuffer space, feel free to change this. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XGENERIC is another concession to ANSI taste. GENERIC * should be a Xpointer type that any other pointer can be safely converted to and back; XGENERIC is char by default, but on newer machines can be set to void. XAs it'\''ll be at least five years before ANSI manages to outlaw char *, Xand as void * is often invalid, I advise you to leave GENERIC alone. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' Xpty attempts to forward window-size changes transparently. It also Xsupports the auxiliary characters structure, which lets you type a Xsingle character to get system and tty status. X' X Xecho 'Running $ man 4 tty | sed '\''s/_//g'\'' | grep -s winsize' Xif man 4 tty | sed 's/_//g' | grep -s winsize Xthen havewin=y; echo ' XI see you have window sizes. X' Xelse havewin=n; echo ' XI see you don'\''t have window sizes. XYou'\''ll have to comment out #define TTY_WINSIZE in config.h. X(This may be inaccurate on Suns; try grep winsize /usr/include/sys/tt*.h.) X' X case "$ttygroup" in X 4) ;; X '') echo '(Let me guess: This isn'\''t a BSD 4.3 system.)' ;; X *) ;; X esac Xfi X Xecho 'Running $ man 4 tty | sed '\''s/_//g'\'' | grep -s auxchars' Xif man 4 tty | sed 's/_//g' | grep -s auxchars Xthen haveaux=y; echo ' XI see you have auxiliary characters. XYou should uncomment #define TTY_AUXCHARS in config.h. X' Xelse haveaux=n; echo ' XI see you don'\''t have auxiliary characters. X' Xfi X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' Xpty also puts siginterrupt() and usleep() to good use in working Xaround BSD limitations. Without siginterrupt(), there is absolutely Xno way to get per-process non-blocking I/O, so pty may block when it Xdoesn'\''t have to (namely, when it has N bytes to write to the output, Xthe output is a pipe with M bytes of space, and N > M > 0). If you Xdefine SIGINTERRUPT (as default), pty will take some extra effort to Xnever, ever, ever block when it doesn'\''t have to. X XAt one point, pty pauses to kludge around a common bug in UNIX-domain Xsockets. With usleep() it will pause much more briefly. This makes Xreconnects much faster. X' X Xecho 'Running $ man siginterrupt | sed '\''s/_//g'\'' | grep -s siginterrupt' Xif man siginterrupt | sed 's/_//g' | grep -s siginterrupt Xthen havesigintr=y; echo ' XI see you have siginterrupt(). Good. X' X case "$ttygroup$havewinsize" in X 4y) echo 'I'\''ll bet you'\''re a BSD 4.3 system.' ;; X *) echo 'Weird, are you BSD 4.3?' ;; X esac Xelse havesigintr=n; echo ' XI see you don'\''t have siginterrupt(). You have to comment out X#define SIGINTERRUPT in config.h. X' Xfi X Xecho 'Running $ man usleep | sed '\''s/_//g'\'' | grep -s usleep' Xif man usleep | sed 's/_//g' | grep -s usleep Xthen haveusleep=y; echo ' XI see you have usleep(). Good. X' Xelse haveusleep=n; echo ' XI see you don'\''t have usleep(). You have to comment out X#define USLEEP in config.h. X' Xfi X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XFinally (almost done with configuration!), we have to make sure that you Xhave UNIX-domain sockets, and check whether you have file descriptor Xpassing. X' X Xecho 'Running $ test -r /usr/include/sys/un.h' Xif test -r /usr/include/sys/un.h Xthen haveunsocks=y; echo ' XI see you have UNIX-domain sockets. Good. X' X echo 'Running $ man recvmsg | sed '\''s/_//g'\'' | grep -s rights' X if man recvmsg | sed 's/_//g' | grep -s rights X then havefdpass=y; echo ' XI see you have file descriptor passing. Good. (Your fd passing may be Xbuggy, as it'\''s a relatively new, powerful, and rarely exploited Xfeature. If you have trouble, try defining NO_FDPASSING.) X' X else havefdpass=n; echo ' XI see you don'\''t have file descriptor passing. This isn'\''t a Xdisaster, though it means that reconnected sessions will be as Xinefficient as they are in programs other than pty, boo hoo hoo. XUncomment NO_FDPASSING in config.h. X' X fi Xelse haveunsocks=n; echo ' XUh-oh. I don'\''t see <sys/un.h>, which means you probably don'\''t have XUNIX-domain sockets. Without sockets you can'\''t have disconnectable Xsessions. Sigh. I guess you have to define NO_UNIXSOCKS in config.h. X' Xfi X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XWhew! We'\''ve finally made it through configuration. If you want, try Xrunning lint -haxc *.c or whatever your favorite code checker is; the Xlint here gives some bogus errors about correct char * casts, an error Xbecause the SIG_IGN definition is unportable, and a couple of bzero Xcomplaints because FD_ZERO isn'\''t defined very well. X XIf you'\''re on an old system without FD_ZERO, FD_SET, and FD_ISSET in X<sys/types.h>, I recommend you upgrade. Try copying file.h.old to file.h X(the original version is in file.h.new). X XWe'\''re nearly at the end. Change CC and CCOPTS in the Makefile for any Xlast-minute additions; if you'\''re worried, change -s to -g for debugging. XNow compile! % (date; make) >>& Makelog & and come back to this script. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XWhile the program is compiling, let'\''s start providing some support. X(If the compile finishes or has an error, just ignore it for the Xmoment.) These are some real changes, so watch out! X XFirst---in Case PTY only!---make a new uid, pty, not allowing logins. X X/etc/passwd: pty:*:whatever:4:::/bin/true X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XSecond, make sure you have a tty group set up. X X/etc/group: tty:*:4:root X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XThird, make PTYDIR. X XROOT: # mkdir /usr/etc/pty; chmod 700 /usr/etc/pty XPTY: # mkdir /usr/etc/pty; chown pty /usr/etc/pty; chmod 700 /usr/etc/pty XUN: % mkdir ~/PTY; chmod 700 ~/PTY X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XFourth, make sure you have all the pseudo-terminal files set up and Xappropriately configured. X XChange each of them to group tty. X XChange each of them to owner pty in case PTY or root in case ROOT. X XChange each of them to mode UNUSEDPTYMODE (0600). X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XFifth, make sure /etc/utmp and /usr/adm/wtmp exist, owned by root in XCase ROOT or pty in Case PTY, each mode 644. (In Case UN, you probably Xwant to be working on a Sun with its insecure /etc/utmp, so that pty can Xtake advantage of it. Sigh.) X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XSixth, I advise that you make a special directory /usr/local/ptybin for Xpty and its associated utilities, with symbolic links in /usr/local. XThis choice isn'\''t too important, but it'\''s easier if you know a Xplace to put programs. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XOkay. You'\''ve done about all that can be done before compilation Xfinishes, so go do something else. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XThe compile should be done now. If all went well, the make should have Xexited normally, Makelog should show no errors, and you should have an Xexecutable pty program sitting in this directory. Unfortunately, life Xisn'\''t always so generous. Here are a few of the more common errors. X XThe loader complains about missing getopt(), optarg, and optind: These Xare all in the getopt library, available in the early volumes of Xcomp.sources.unix. If you use GNU getopt, please make sure you Xunderstand the implications of its license. X XThe loader complains about missing FD_ZERO, FD_SET, and FD_ISSET: Try Xcopying file.h.old to file.h and recompiling. If the compiler gives Xvarious further errors related to these macros, uncomment the Xcommented-out lines in file.h.old, copy to file.h, and try once again. X Xbcopy() isn'\''t defined: In pty.h, change bcopy(src,dst,num) to Xmemcpy(dst,src,num). (Note the order.) Try again. X XIf you still can'\''t get the code to compile, let the author know. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XNext, compile the utilities. There isn'\''t much to say about them; Xthey'\''re all public domain, some of them clones of or improvements Xover standard utilities, some of them clones with special features to Xwork with pty, some of them entirely new programs for pty'\''s new Xfeatures. Just glance at the top of util/Makefile; then X% cd util; (date; make) >>& Makelog & and wait. X XWarning: The pty session directory is hardcoded in util/sessutil.c. XIf you have changed PTYDIR, check through sessutil.c carefully. X' X Xecho '----- Press return to continue. ' | tr -d '\012'; read contline X Xecho ' XSo now you should have some executables sitting around collecting dust. XIn Cases ROOT and PTY, put {pty,biff,disconnect,mesg,reconnect,sesskill, Xsesslist,sessname,sessuser} into a system-wide directory, owner root or Xpty, mode 4755. Put wall and write into the same place, group tty, mode X2755. Put {condom,excloff,exclon,last,lock,script,script.tidy,sess,tiocsti, Xtty,u,who,xdisconnect,xreconnect,xsesskill,xsesslist,xsessname,xsessuser} Xinto the same place, mode 755. Make absolutely sure none of the shell Xscripts are setuid. X XIn Case UN, just put all the programs somewhere in your PATH. X XThat'\''s it! Try running TESTS now. X X(Two other things you have to do at some point: move your old script, Xbiff, mesg, and so on to script.old, biff.old, mesg.old, etc., with Xsymbolic links to the new versions in their place; and move the old X/usr/man/{script,biff,mesg,...}.1 somewhere else, copy all the *.1 Xhere to /usr/man/man1, and run /etc/catman.) X' END_OF_FILE echo shar: 10 control characters may be missing from \"'INSTALL'\" if test 25242 -ne `wc -c <'INSTALL'`; then echo shar: \"'INSTALL'\" unpacked with wrong size! fi chmod +x 'INSTALL' # end of 'INSTALL' fi if test ! -d 'patch' ; then echo shar: Creating directory \"'patch'\" mkdir 'patch' fi if test -f 'patch/telnetd.90.06.28.patch' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'patch/telnetd.90.06.28.patch'\" else echo shar: Extracting \"'patch/telnetd.90.06.28.patch'\" \(13647 characters\) sed "s/^X//" >'patch/telnetd.90.06.28.patch' <<'END_OF_FILE' X*** pathnames.h.original Tue Aug 21 15:45:25 1990 X--- pathnames.h Tue Aug 21 22:24:30 1990 X*************** X*** 35,37 **** X--- 35,40 ---- X #ifdef BFTPDAEMON X #define BFTPPATH "/usr/ucb/bftp" X #endif /* BFTPDAEMON */ X+ #ifdef USEPTY X+ #define _PATH_PTY "/usr/local/pty" X+ #endif X*** sys_term.c.original Tue Aug 21 15:45:31 1990 X--- sys_term.c Tue Aug 21 22:00:56 1990 X*************** X*** 23,28 **** X--- 23,32 ---- X X #include "telnetd.h" X #include "pathnames.h" X+ #ifdef USEPTY X+ #include "sock.h" X+ extern char *ttyname(); X+ #endif X X #ifdef NEWINIT X #include <initreq.h> X*************** X*** 354,359 **** X--- 358,364 ---- X X getpty() X { X+ #ifndef USEPTY X register int p; X #ifndef CRAY X register char c, *p1, *p2; X*************** X*** 398,403 **** X--- 403,416 ---- X } X #endif /* CRAY */ X return(-1); X+ #else USEPTY X+ /* In this new 'n' improved pty-based telnetd, we've already called */ X+ /* startslave, which in turn waited to grab pseudo-terminals from the */ X+ /* pty program. Global variable pty (grrrr) already has our tty. line */ X+ /* has already been filled in by startslave. In fact, there's no point */ X+ /* in calling getpty() at all. */ X+ return pty; X+ #endif USEPTY X } X X #ifdef LINEMODE X*************** X*** 764,772 **** X--- 777,788 ---- X */ X getptyslave() X { X+ #ifndef USEPTY X register int t = -1; X+ #endif X X #ifndef CRAY X+ #ifndef USEPTY X /* X * Disassociate self from control terminal and open ttyp side. X * Set important flags on ttyp and ptyp. X*************** X*** 791,796 **** X--- 807,815 ---- X fatalperror(net, line); X #endif X X+ #else USEPTY X+ /* In a pty-based world, this function is rendered similarly useless. */ X+ #endif USEPTY X init_termbuf(); X #ifndef USE_TERMIO X termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; X*************** X*** 812,821 **** X--- 831,846 ---- X #endif X set_termbuf(); X #else /* CRAY */ X+ #ifndef USEPTY X (void) chown(line, 0, 0); X (void) chmod(line, 0600); X+ #endif X #endif /* CRAY */ X+ #ifndef USEPTY X return(t); X+ #else USEPTY X+ /* What's there to return? We've thrown away fdsty. */ X+ #endif X } X X #ifdef NEWINIT X*************** X*** 829,842 **** X--- 854,891 ---- X * is necessary to startup the login process on the slave side of the pty. X */ X X+ #ifdef USEPTY X+ int fdpass[2]; X+ int siglerpid; X+ #endif USEPTY X /* ARGSUSED */ X+ #ifndef USEPTY X startslave(t, host) X int t; X+ #else USEPTY X+ startslave(host) X+ #endif USEPTY X char *host; X { X register int i; X long time(); X X+ #ifdef USEPTY X+ char strfdpass[10]; X+ char ch; X+ int fdmty; X+ int fdsty; X+ char *ttyn; X+ int pgrp; X+ int fd; X+ #endif USEPTY X+ #ifdef USEPTY X+ /* Prepare for receiving pseudo-terminal descriptors from pty. */ X+ if (socketpair(AF_UNIX,SOCK_STREAM,0,fdpass) == -1) /* virtually impossible */ X+ fatalperror(net,"pty-socketpair"); X+ (void) sprintf(strfdpass,"%d",fdpass[1]); X+ X+ #endif USEPTY X #ifndef NEWINIT X # ifdef CRAY X utmp_sig_init(); X*************** X*** 845,850 **** X--- 894,902 ---- X if ((i = fork()) < 0) X fatalperror(net, "fork"); X if (i) { X+ #ifdef USEPTY X+ siglerpid = i; X+ #endif X # ifdef CRAY X /* X * Cray parent will create utmp entry for child and send X*************** X*** 873,881 **** X--- 925,972 ---- X } X utmp_sig_notify(pid); X # endif /* CRAY */ X+ #ifndef USEPTY X (void) close(t); X+ #else USEPTY X+ /* Now we'll receive the descriptors. */ X+ (void) close(fdpass[1]); X+ (void) sprintf(line,"/NONexistent"); X+ fdmty = fdsty = -1; X+ if (pty_getch(fdpass[0],&ch) == -1) X+ cleanup(); /* XXX: telnetd's finishup handling really sucks. */ X+ if (pty_putgetint(fdpass[0],'G',&siglerpid) == -1) X+ cleanup(); X+ if (pty_getch(fdpass[0],&ch) == -1) X+ cleanup(); X+ if (pty_putgetfd(fdpass[0],'m',&fdmty) == -1) X+ cleanup(); X+ if (pty_getch(fdpass[0],&ch) == -1) X+ cleanup(); X+ if (pty_putgetfd(fdpass[0],'s',&fdsty) == -1) X+ cleanup(); X+ if (!(ttyn = ttyname(fdsty))) X+ cleanup(); X+ (void) strncpy(line,ttyn,14); X+ if ((fd = open("/dev/tty",O_RDWR)) != -1) X+ { X+ (void) ioctl(fd,TIOCNOTTY,0); /* detach */ X+ (void) close(fd); X+ } X+ (void) close(open(ttyn,O_RDWR)); /* attach ourselves to tty */ X+ pty = fdmty; X+ (void) ioctl(fdsty,TIOCGPGRP,&pgrp); X+ (void) setpgrp(0,pgrp); X+ (void) close(fdsty); /* we won't need it for anything else */ X+ (void) fcntl(fdpass[0],F_SETFL,FNDELAY); /* XXX */ X+ X+ #endif USEPTY X } else { X+ #ifndef USEPTY X start_login(t, host); X+ #else USEPTY X+ (void) close(fdpass[0]); X+ start_login(host,strfdpass); X+ #endif USEPTY X /*NOTREACHED*/ X } X #else /* NEWINIT */ X*************** X*** 986,994 **** X--- 1077,1095 ---- X * function will turn us into the login process. X */ X X+ #ifndef USEPTY X start_login(t, host) X int t; X+ #else USEPTY X+ /* Added parameter, for dealing with pty: strfdpass, a printable version */ X+ /* of the file descriptor for passing more descriptors up to us. */ X+ X+ start_login(host,strfdpass) X+ #endif USEPTY X char *host; X+ #ifdef USEPTY X+ char *strfdpass; X+ #endif USEPTY X { X register char *cp; X register char **argv; X*************** X*** 996,1001 **** X--- 1097,1103 ---- X #ifdef CRAY X register char **cpp, **cpp2; X utmp_sig_wait(); X+ #ifndef USEPTY X # ifndef TCVHUP X setpgrp(); X # endif X*************** X*** 1028,1038 **** X--- 1130,1142 ---- X termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; X termbuf.c_cflag = EXTB|HUPCL|CS8; X set_termbuf(); X+ #endif USEPTY X #endif /* CRAY */ X X /* X * set up standard paths before forking to login X */ X+ #ifndef USEPTY X #ifndef NO_SETSID X if (setsid() < 0) X fatalperror(net, "setsid"); X*************** X*** 1042,1053 **** X--- 1146,1167 ---- X if (ioctl(t, TIOCSCTTY, (char *)0) < 0) X fatalperror(net, "ioctl(sctty)"); X #endif X+ #else USEPTY X+ /* The POSIXish setsid() handling here is pty's responsibility. */ X+ #endif USEPTY X (void) close(net); X (void) close(pty); X+ #ifndef USEPTY X (void) dup2(t, 0); X (void) dup2(t, 1); X (void) dup2(t, 2); X (void) close(t); X+ #else USEPTY X+ (void) close(0); /* ahhh, life is easy */ X+ (void) close(1); X+ (void) close(2); X+ /* but absolutely don't close fdpass. */ X+ #endif USEPTY X /* X * -h : pass on name of host. X * WARNING: -h is accepted by login if and only if X*************** X*** 1054,1060 **** X--- 1168,1183 ---- X * getuid() == 0. X * -p : don't clobber the environment (so terminal type stays set). X */ X+ #ifdef USEPTY X+ /* Stick the pty magic in front. */ X+ argv = addarg(0, "pty"); /* this addarg stuff is stupid */ X+ argv = addarg(argv,"-sdf"); X+ argv = addarg(argv,strfdpass); X+ argv = addarg(argv,"-xRCUWX"); /* XXX: -xr? */ X+ argv = addarg(argv,_PATH_LOGIN); X+ #else X argv = addarg(0, "login"); X+ #endif X argv = addarg(argv, "-h"); X argv = addarg(argv, host); X #if !defined(CRAY) && !defined(NO_LOGIN_P) X*************** X*** 1084,1090 **** X--- 1207,1217 ---- X } X #endif X X+ #ifdef USEPTY X+ execv(_PATH_PTY,argv); X+ #else USEPTY X execv(_PATH_LOGIN, argv); X+ #endif USEPTY X X syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); X fatalperror(net, _PATH_LOGIN); X*************** X*** 1142,1155 **** X--- 1269,1294 ---- X p = line + sizeof("/dev/") - 1; X if (logout(p)) X logwtmp(p, "", ""); X+ #ifndef USEPTY X (void)chmod(line, 0666); X+ #else USEPTY X+ (void) chmod(line,0600); /* banish these security holes! */ X+ #endif USEPTY X (void)chown(line, 0, 0); X *p = 'p'; X+ #ifndef USEPTY X (void)chmod(line, 0666); X+ #else USEPTY X+ (void) chmod(line,0600); X+ #endif USEPTY X (void)chown(line, 0, 0); X # else X rmut(); X+ #ifndef USEPTY X vhangup(); /* XXX */ X+ #else USEPTY X+ /* vhangup(); XXX: This is also pty's responsibility. */ X+ #endif USEPTY X # endif X (void) shutdown(net, 2); X #else /* CRAY */ X*************** X*** 1156,1162 **** X--- 1295,1306 ---- X # ifndef NEWINIT X rmut(line); X (void) shutdown(net, 2); X+ #ifndef USEPTY X kill(0, SIGHUP); X+ #else USEPTY X+ /* kill(0, SIGHUP); The pty master makes this decision. */ X+ (void) kill(siglerpid,SIGHUP); /* but we do have to tell the sigler. */ X+ #endif USEPTY X # else /* NEWINIT */ X (void) shutdown(net, 2); X # endif /* NEWINT */ X*************** X*** 1273,1282 **** X--- 1417,1434 ---- X (void) close(f); X } X } X+ #ifndef USEPTY X (void) chmod(line, 0666); X+ #else USEPTY X+ (void) chmod(line, 0600); X+ #endif USEPTY X (void) chown(line, 0, 0); X line[strlen("/dev/")] = 'p'; X+ #ifndef USEPTY X (void) chmod(line, 0666); X+ #else USEPTY X+ (void) chmod(line, 0600); X+ #endif USEPTY X (void) chown(line, 0, 0); X } /* end of rmut */ X #endif /* CRAY */ X*** telnetd.c.original Tue Aug 21 15:45:36 1990 X--- telnetd.c Tue Aug 21 21:27:48 1990 X*************** X*** 28,33 **** X--- 28,37 ---- X #endif /* not lint */ X X #include "telnetd.h" X+ #ifdef USEPTY X+ #include "sock.h" X+ extern char *ttyname(); X+ #endif USEPTY X X /* X * I/O data buffers, X*************** X*** 462,467 **** X--- 466,472 ---- X int t; X struct hostent *hp; X X+ #ifndef USEPTY X /* X * Find an available pty to use. X */ X*************** X*** 470,475 **** X--- 475,481 ---- X fatal(net, "All network ports in use"); X X t = getptyslave(); X+ #endif USEPTY X X /* get name of connected client */ X hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), X*************** X*** 489,500 **** X--- 495,533 ---- X /* X * Start up the login process on the slave side of the terminal X */ X+ #ifndef USEPTY X startslave(t, host); X+ #else USEPTY X+ startslave(host); X+ #endif USEPTY X X+ #ifdef USEPTY X+ /* In this pty-based version of the world, life is easy. startslave() */ X+ /* actually dumps its process under the pty program, which handles all */ X+ /* those nasty details of finding a pty and getting it started. pty */ X+ /* then passes its pty master side up to telnetd (the ``controller'') */ X+ /* so that we have full control. Joy to the world. */ X+ X+ /* X+ * Find an available pty to use. X+ */ X+ pty = getpty(); /* noop */ X+ if (pty < 0) /* impossible */ X+ fatal(net, "All network ports in use"); X+ X+ getptyslave(); X+ X+ #endif USEPTY X telnet(net, pty); /* begin server processing */ X /*NOTREACHED*/ X } /* end of doit */ X X+ #ifdef USEPTY X+ extern int fdpass[2]; X+ extern int siglerpid; X+ char ch; X+ X+ #endif USEPTY X #ifndef MAXHOSTNAMELEN X #define MAXHOSTNAMELEN 64 X #endif MAXHOSTNAMELEN X*************** X*** 775,780 **** X--- 808,819 ---- X if (!SYNCHing) { X FD_SET(f, &xbits); X } X+ #ifdef USEPTY X+ FD_SET(fdpass[0],&ibits); X+ /* When we get input on fdpass, we're switching ttys. */ X+ /* This FD_SET seems logical, but it invites bugs under many */ X+ /* implementations. XXX. */ X+ #endif USEPTY X if ((c = select(16, &ibits, &obits, &xbits, X (struct timeval *)0)) < 1) { X if (c == -1) { X*************** X*** 785,791 **** X--- 824,899 ---- X sleep(5); X continue; X } X+ #ifdef USEPTY X+ if (pty_getch(fdpass[0],&ch) != -1) X+ { X+ /* reconnect... */ X+ int fdmty; X+ int fdsty; X+ char *ttyn; X+ int pgrp; X+ int fd; X X+ fdmty = fdsty = -1; X+ (void) fcntl(fdpass[0],F_SETFL,0); /*XXX*/ X+ if (ch != 'G') X+ if (pty_getch(fdpass[0],&ch) == -1) X+ ; X+ if (pty_putgetint(fdpass[0],'G',&siglerpid) == -1) X+ cleanup(); X+ if (pty_getch(fdpass[0],&ch) == -1) X+ cleanup(); X+ if (pty_putgetfd(fdpass[0],'m',&fdmty) == -1) X+ cleanup(); X+ if (pty_getch(fdpass[0],&ch) == -1) X+ cleanup(); X+ if (pty_putgetfd(fdpass[0],'s',&fdsty) == -1) X+ cleanup(); X+ if (!(ttyn = ttyname(fdsty))) X+ cleanup(); X+ /* It's impossible to do anything sensible with utmp; */ X+ /* this shows very clearly why utmp's remote field */ X+ /* is inconsistent. So we stick to the same ``line.'' */ X+ X+ fd = 0; X+ (void) ioctl(p, TIOCPKT, (char *)&fd); X+ /* Packet mode, like NDELAY, is not a polite thing to */ X+ /* give someone else. One of those unstated conventions */ X+ /* that people should learn... */ X+ X+ if ((fd = open("/dev/tty",O_RDWR)) != -1) X+ { X+ (void) ioctl(fd,TIOCNOTTY,0); /* detach */ X+ (void) close(fd); X+ } X+ (void) close(open(ttyn,O_RDWR)); /* attach */ X+ X+ (void) close(pty); X+ pty = fdmty; X+ p = pty; /* XXX: Blame DAB for this. Whither modularity? */ X+ X+ (void) ioctl(p, TIOCPKT, (char *)&on); X+ /* If we didn't do this, telnetd would become very */ X+ /* confused, because it's expecting packet-mode stuff. */ X+ X+ (void) fcntl(fdpass[0],F_SETFL,FNDELAY); /* XXX */ X+ (void) ioctl(fdsty,TIOCGPGRP,&pgrp); X+ (void) setpgrp(0,pgrp); X+ X+ /* XXX: If this messes up Linemode, TOUGH LUCK! */ X+ init_termbuf(); /* XXX */ X+ #ifdef LINEMODE X+ localstat(); /* XXX */ X+ #endif X+ X+ FD_ZERO(&xbits); X+ FD_ZERO(&ibits); /* XXX */ X+ FD_ZERO(&obits); X+ X+ /* XXX: anything else to do? */ X+ } X+ #endif USEPTY X+ X /* X * Any urgent data? X */ X*************** X*** 881,888 **** X--- 989,1004 ---- X if (pcc < 0 && errno == EWOULDBLOCK) X pcc = 0; X else { X+ #ifndef USEPTY X if (pcc <= 0) X break; X+ #else USEPTY X+ if (pcc <= 0) X+ { X+ pcc = 0; X+ goto wtfiseofpty; X+ } X+ #endif USEPTY X #if !defined(CRAY2) || !defined(UNICOS5) X #ifdef LINEMODE X /* X*************** X*** 932,937 **** X--- 1048,1056 ---- X ptyip = ptyibuf; X #endif /* defined(CRAY2) && defined(UNICOS5) */ X } X+ #ifdef USEPTY X+ wtfiseofpty: ; X+ #endif USEPTY X } X X while (pcc > 0) { END_OF_FILE if test 13647 -ne `wc -c <'patch/telnetd.90.06.28.patch'`; then echo shar: \"'patch/telnetd.90.06.28.patch'\" unpacked with wrong size! fi # end of 'patch/telnetd.90.06.28.patch' fi if test ! -d 'util' ; then echo shar: Creating directory \"'util'\" mkdir 'util' fi echo shar: End of archive 1 \(of 6\). cp /dev/null ark1isdone MISSING="" for I in 1 2 3 4 5 6 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 6 archives. rm -f ark[1-9]isdone else echo You still must unpack the following archives: echo " " ${MISSING} fi exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.