brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/07/91)
If host X supports RFC 931, and if joe@X and sally@Y are connected through TCP, then sally can find out the name of joe. This package includes authd, an RFC 931 server. Once you've installed it, your users can't escape the authentication: if they telnet or rlogin or send mail or do whatever to another host, that host can find out the username. This package also includes a library that acts as an RFC 931 client. You don't need privileges to use the library, which should compile and run without trouble on any BSD-derived system. (authd is not so portable; although it works without changes under SunOS and Ultrix, it might not work on other systems. The package includes a couple of test programs.) I've placed this code into the public domain because I think that everyone should support at least this level of security. I'm sick of seeing people forge mail and spoof NNTP and attack systems anonymously through the network. Now they won't be able to, because every connection will be tagged with the username with at least as much security as the TCP host address in each packet. I hope that every site will do its part to contribute to network security (and to help CERT trace intruders). It should take approximately 10 minutes to read the instructions and compile, install, and test authd on a new machine. It should take approximately 2 minutes on each new machine once you're familiar with the instructions. Send comments on these estimates to brnstnd@nyu.edu, cc the Office of Management and Budget, Paperwork Reduction Division. ---Dan #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: FILES README FORMLETTER CHANGES INSTALL Makefile authd.8 # authuser.3 tcpuid.8 tcpuname.8 authd.c authuser.h authuser.c # test.c netstatuid rfc931 # Wrapped by brnstnd@kramden on Wed Feb 6 23:19:18 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'FILES' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'FILES'\" else echo shar: Extracting \"'FILES'\" \(143 characters\) sed "s/^X//" >'FILES' <<'END_OF_FILE' XFILES XREADME XFORMLETTER XCHANGES XINSTALL XMakefile Xauthd.8 Xauthuser.3 Xtcpuid.8 Xtcpuname.8 Xauthd.c Xauthuser.h Xauthuser.c Xtest.c Xnetstatuid Xrfc931 END_OF_FILE if test 143 -ne `wc -c <'FILES'`; then echo shar: \"'FILES'\" unpacked with wrong size! fi # end of 'FILES' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(5011 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' Xauthd - authentication server daemon Xtcpuid, tcpuname - find out which user owns a connection Xauthuser - remote authentication library X Xauthd is a kernel-level implementation of RFC 931, the Authentication XServer. RFC 931 provides the name of the user owning a TCP connection. XThis helps network security: unless TCP itself is compromised, it is Ximpossible to forge mail or news between computers supporting RFC 931. XIt also becomes much easier to trace attackers than in the current, Xlargely anonymous, network. authd requires no changes to current code: Xevery connect() and accept() is authenticated automatically, with no Xloss of efficiency. X Xtcpuid and tcpuname are the same program, but more suitable for local Xuse from the command line by a user or system administrator. They show Xwhich local user created a given TCP connection. X Xauthuser is a library encapsulating client use of RFC 931. It talks to a Xremote Authentication Server to find out the username on the other side Xof a given connection. X XOnly root can install authd. However, most current systems are insecure Xenough that any user can run tcpuid and tcpuname. authuser is meant for Xuse by any program. X X X Xauthd version 3.0, February 5, 1991. XPlaced into the public domain by Daniel J. Bernstein. XSome of the code in authd was inspired by code written by XVic Abell, abe@mace.cc.purdue.edu, for the ofiles program. X X XOrganization of README: X X1. Files X2. Requirements X3. How to configure authd X4. How to compile authd X5. How to install authd X6. TODO list X X X1. Files: X XREADME this file XFORMLETTER form letter to send to the author XFILES file list XINSTALL friendly installation script XCHANGES description of changes since first distributed version XMakefile compilation commands Xauthd.c the authd program Xauthuser.h the authuser include file Xauthuser.c the authuser library Xauthd.8 documentation for authd Xtcpuid.8 documentation for tcpuid Xtcpuname.8 documentation for tcpuname Xauthuser.3 documentation for authuser Xtest.c program to test authuser and authd Xnetstatuid shell script to test tcpuname Xrfc931 RFC 931, Authentication Server X X X X2. Requirements X Xauthd requires netstat, and it pokes around in several BSD-specific Xkernel structures. It is not inherently portable code. Nevertheless, it Xhas been compiled under Ultrix, SunOS, and Convex UNIX, and it probably Xdoesn't take much work to get running under pretty much any BSD system. Xauthuser should compile and run without trouble on any BSD system. X XYou must be root to install authd. However, authd's sister utilities, Xtcpuid and tcpuname, will probably work anyway if /dev/kmem is readable. XAny program can use the authuser library. X Xauthd and authuser have been tested on the following systems. X X Sun 4/280, SunOS 4.0.3 X VAX 8650, Ultrix 4.1 X DECsystem-5820, Ultrix 4.0 X DECStation-5400, Ultrix 4.0 X XIf your machine isn't in this list, and you get the programs working, X*please* send a note to me at brnstnd@nyu.edu on the Internet describing Xwhat you had to do to make the programs compile. (Of course, please also Xlet me know if you have trouble, or if you have comments, questions, or Xsuggestions.) I'd rather be flooded with reports and be able to compile Xa more comprehensive list than have no feedback because everyone assumes Xsomeone else has talked to me first. Use FORMLETTER if you want. Thanks Xfor being a good sport. X X X X3. How to configure authd X XEither authd.c has the right magic to compile and run on your system, or Xit doesn't. In the first case you don't have to configure anything, and Xin the second case automatic configuration would be pretty much Xhopeless. (If authd doesn't compile, you might try sending me the Xcompiler output to see if I can figure out how to make it work on your Xmachine.) The authuser library should compile without trouble in any Xcase. X XYou can change CC or CCOPTS in Makefile if you want. If you want authd Xto record connections through syslog at LOG_DEBUG, define -DUSE_SYSLOG Xin the Makefile. X X X X4. How to compile authd X XJust make. This will create authd, tcpuid, tcpuname, authuser.o, and Xtest. X X X X5. How to install authd X XIf you don't have privileges, skip this part. X XBy default, authd, tcpuid, and tcpuname are installed in /etc, Xauthuser.o is installed as /usr/lib/libauthuser.a, authuser.3 is Xinstalled in /usr/man/man3, and authd.8, tcpuid.8, and tcpuname.8 are Xinstalled in /usr/man/man8. The binaries are installed setgid to group Xkmem. If you want to change these defaults, edit INSTALL. X XThen run INSTALL in a root shell; the script will check every action Xwith you before doing it. X XTo test tcpuname, make sure it is in your path, and run netstatuid. You Xshould get a report of all active network connections including Xusernames. X XTo test authuser and authd, run ./test. You should get an ``everything Xlooks okay'' message. X X X X6. TODO list X Xfast multiple-connection version of tcpuid/tcpuname, like netstatuid? END_OF_FILE if test 5011 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'FORMLETTER' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'FORMLETTER'\" else echo shar: Extracting \"'FORMLETTER'\" \(418 characters\) sed "s/^X//" >'FORMLETTER' <<'END_OF_FILE' XTo: brnstnd@nyu.edu XFrom: XDate: X XPackage: authd 3.0 XObtained from (e.g., uunet.uu.net): XObtained by (e.g., ftp): X X1. Machine architecture (e.g., Sun 4/280): X2. Operating system (e.g., SunOS 4.1): X3. OS vendor (e.g., Sun): X4. Does authd work on your machine so far (yes/no)? X5. Describe any problems you've had with authd, tcpuid, or tcpuname. X X X6. Any further questions, comments, or suggestions? X X XYour name: END_OF_FILE if test 418 -ne `wc -c <'FORMLETTER'`; then echo shar: \"'FORMLETTER'\" unpacked with wrong size! fi # end of 'FORMLETTER' fi if test -f 'CHANGES' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'CHANGES'\" else echo shar: Extracting \"'CHANGES'\" \(43 characters\) sed "s/^X//" >'CHANGES' <<'END_OF_FILE' XChange file for authd X X X2/5/91: authd 3.0. END_OF_FILE if test 43 -ne `wc -c <'CHANGES'`; then echo shar: \"'CHANGES'\" unpacked with wrong size! fi # end of 'CHANGES' fi if test -f 'INSTALL' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'INSTALL'\" else echo shar: Extracting \"'INSTALL'\" \(3474 characters\) sed "s/^X//" >'INSTALL' <<'END_OF_FILE' X#!/bin/sh X X# Change kmem to staff and mode to 0755 if you don't have a kmem group, X# or if you don't want normal users to be able to use these utilities. XMEM=kmem XMODE=02755 X X# These must all be in the same filesystem. XAUTHD=/etc/authd XTCPUID=/etc/tcpuid XTCPUNAME=/etc/tcpuname X XAUTHUSER=/usr/lib/libauthuser.a X X# Man pages. XMAUTHUSER=/usr/man/man3/authuser.3 XMAUTHD=/usr/man/man8/authd.8 XMTCPUID=/usr/man/man8/tcpuid.8 XMTCPUNAME=/usr/man/man8/tcpuname.8 X X# Name of port 113 in /etc/services. XPORTNAME=auth X Xecho "Each action will be printed before it is run. Press return to proceed." X Xecho "1. Install authd, tcpuid, and tcpuname." Xecho "! install -c -g $MEM -m $MODE authd $AUTHD: " | tr -d '\012' Xread line Xinstall -c -g "$MEM" -m "$MODE" authd "$AUTHD" X Xecho "! rm -f $TCPUID; ln $AUTHD $TCPUID: " | tr -d '\012' Xread line Xrm -f "$TCPUID"; ln "$AUTHD" "$TCPUID" X Xecho "! rm -f $TCPUNAME; ln $AUTHD $TCPUNAME: " | tr -d '\012' Xread line Xrm -f "$TCPUNAME"; ln "$AUTHD" "$TCPUNAME" X Xecho "2. Install the authuser library." Xecho "! ar rv $AUTHUSER authuser.o: " | tr -d '\012' Xread line Xar rv "$AUTHUSER" authuser.o X Xecho "! ranlib $AUTHUSER: " | tr -d '\012' Xread line Xranlib "$AUTHUSER" X Xecho "! chmod 644 $AUTHUSER: " | tr -d '\012' Xread line Xchmod 644 "$AUTHUSER" X Xecho "3. Make the man pages available." Xecho "! install -c -m 0444 authuser.3 $MAUTHUSER: " | tr -d '\012' Xread line Xinstall -c -m 0444 authuser.3 "$MAUTHUSER" X Xecho "! install -c -m 0444 authd.8 $MAUTHD: " | tr -d '\012' Xread line Xinstall -c -m 0444 authd.8 "$MAUTHD" X Xecho "! install -c -m 0444 tcpuid.8 $MTCPUID: " | tr -d '\012' Xread line Xinstall -c -m 0444 tcpuid.8 "$MTCPUID" X Xecho "! install -c -m 0444 tcpuname.8 $MTCPUNAME: " | tr -d '\012' Xread line Xinstall -c -m 0444 tcpuname.8 "$MTCPUNAME" X Xecho "4. Make sure an auth port is in /etc/services." Xecho "Let me glance at /etc/services for you..." Xif grep '^'$PORTNAME'[ ]*113/tcp' /etc/services >/dev/null 2>&1 Xthen echo "Okay, you have it already. Let's continue." Xelse echo "Nope, it's not there." X echo "Let me check that you don't have a different auth port..." X if grep '^'$PORTNAME'[ ][ ]*' /etc/services >/dev/null 2>&1 X then echo "Aaack! $PORTNAME is already used in /etc/services. Exiting." X exit 1 X fi X echo "! echo $PORTNAME' 113/tcp' >> /etc/services: " | tr -d '\012' X read line X echo "$PORTNAME"' 113/tcp' >> /etc/services Xfi X Xecho "5. Enable auth in /etc/inetd.conf." Xecho "Let me glance at /etc/inetd.conf for you..." Xif grep '^'"$PORTNAME"'[ ]' /etc/inetd.conf >/dev/null 2>&1 Xthen echo "Okay, it's already there. That's it!" X exit 0 Xfi Xif grep 'telnet.*root' /etc/inetd.conf >/dev/null 2>&1 Xthen echo "It's not there yet. Hmmm, looks like you have a Sun-style inetd." X echo "! echo $PORTNAME' stream tcp nowait root '$AUTHD' authd' >> /etc/inetd.conf: " | tr -d '\012' X read line X echo "$PORTNAME"' stream tcp nowait root '"$AUTHD"' authd' >> /etc/inetd.conf Xelse echo "It's not there yet." X echo "! echo $PORTNAME' stream tcp nowait '$AUTHD' authd' >> /etc/inetd.conf: " | tr -d '\012' X read line X echo "$PORTNAME"' stream tcp nowait '"$AUTHD"' authd' >> /etc/inetd.conf Xfi X Xecho "6. Let inetd know about the new service." Xecho "On most machines you have to % kill -HUP nn" Xecho "where nn is the number of the inetd process." Xecho "Here's what ps augx shows about inetd:" Xps augx | sed -n -e 1p -e /inetd/p Xecho "I'll leave this step to you. That's it!" X Xexit 0 END_OF_FILE if test 3474 -ne `wc -c <'INSTALL'`; then echo shar: \"'INSTALL'\" unpacked with wrong size! fi chmod +x 'INSTALL' # end of 'INSTALL' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(569 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' XCC=cc XCCOPTS=-g X Xdefault: all X Xshar: authd.shar X Xall: authd tcpuid tcpuname authuser.o test X Xauthd: authd.c Makefile X $(CC) $(CCOPTS) -o authd authd.c X Xtcpuid: authd Makefile X rm -f tcpuid X ln authd tcpuid X Xtcpuname: authd Makefile X rm -f tcpuname X ln authd tcpuname X Xauthuser.o: authuser.c authuser.h Makefile X $(CC) $(CCOPTS) -c authuser.c X Xtest: authuser.o authuser.h test.c Makefile X $(CC) $(CCOPTS) -o test test.c authuser.o X Xauthd.shar: FILES X shar `cat FILES` > authd.shar X chmod 400 authd.shar X Xinstall: X echo 'Run the INSTALL shell script.' X Xclean: X rm -f *.o END_OF_FILE if test 569 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'authd.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'authd.8'\" else echo shar: Extracting \"'authd.8'\" \(1531 characters\) sed "s/^X//" >'authd.8' <<'END_OF_FILE' X.TH authd 8 X.SH NAME Xauthd \- Authentication Server daemon X.SH SYNTAX Xauthd X.SH DESCRIPTION X.I authd Xis a daemon implementing the XRFC 931 Authentication Server protocol. XIt should be invoked by a network server, Xsuch as X.I attachport(1) Xor X.I inetd(8), Xfor connections to TCP port 113 (auth). X.PP XThe client host Xgives X.I authd Xtwo numbers separated by a comma. X.I authd Xinterprets the numbers as TCP port numbers Xfor the local and remote sides respectively Xof a TCP connection between this host and the client host. XIt returns a line of the form X.EX Xlocalport, remoteport: USERID: UNIX: username X.EE Xwhere username Xis the name of the user on this side of Xthe specified connection. XIf X.I authd Xdoes not have an authentication entry for that connection, Xit returns a line of the form X.EX Xlocalport, remoteport: ERROR: UNKNOWN-ERROR. X.EE X.PP X.SH DIAGNOSTICS X.TP XNone. X.SH BUGS XNone known. X.SH VERSION Xauthd version 3.0, February 5, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. XPartially inspired by code written by Vic Abell for ofiles. X.SH REFERENCES XThe authentication server is more secure than passwords Xin some ways, but less secure than passwords in many ways. X(It's certainly better than no password at all---e.g., for Xmail or news.) XIt is not the final solution. XFor an excellent discussion of security problems within Xthe TCP/IP protocol suite, see XSteve Bellovin's article X``Security Problems in the TCP/IP Protocol Suite.'' X.SH "SEE ALSO" Xauthtcp(1), Xattachport(1), Xauthuser(3), Xtcp(4), Xinetd(8) END_OF_FILE if test 1531 -ne `wc -c <'authd.8'`; then echo shar: \"'authd.8'\" unpacked with wrong size! fi # end of 'authd.8' fi if test -f 'authuser.3' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'authuser.3'\" else echo shar: Extracting \"'authuser.3'\" \(3354 characters\) sed "s/^X//" >'authuser.3' <<'END_OF_FILE' X.TH authuser 3 X.SH NAME Xauthuser \- remote authentication library using the Authentication Server X.SH SYNTAX X.B #include <authuser.h> X.PP X.B unsigned short auth_tcpport; X.PP X.B char *auth_xline(user,fd,&in); X.PP X.B int auth_fd(fd,&in,&local,&remote); X.PP X.B char *auth_tcpuser(in,local,remote); X.PP X.B char *user; X.br X.B int fd; X.br X.B unsigned long in; X.br X.B unsigned short local; X.br X.B unsigned short remote; X.SH DESCRIPTION XThe X.I authuser Xlibrary provides a simple interface for Xfinding out the remote identity Xof a connection through the XAuthentication Server Xas specified by RFC 931. XUse the -lauthuser loader option Xto compile a program with this library. X.PP X.B auth_xline(user,fd,&in) Xreturns a line of the form X-Auth-User: user or X-Forgery-By: username, Xdepending upon what the host on the other side of X.B fd Xthinks of the user. XThis is particularly appropriate for Xmail and news headers. X.PP XIf the remote host reports that X.B user Xowns the connection on that side, X.B auth_xline Xwill return X-Auth-User: user. XIf the remote host reports that a different X.B username Xowns the connection, X.B auth_xline Xwill return X-Forgery-By: username. XIf user is NULL, Xit returns X-Auth-User: username Xwith the username reported by the remote host. XIf X.B fd Xis not a TCP connection Xor authentication is impossible, X.B auth_xline Xreturns NULL, setting errno appropriately. X.PP XThe line is not cr-lf terminated. XIt is stored in a static area Xwhich is overwritten on each call to X.B auth_xline. X.B auth_xline Xplaces the Internet address of the other host into in. X.PP X.B auth_fd(fd,&in,&local,&remote) Xretrieves address information from the connection in socket X.B fd. XIt places the XInternet address of the host on other side into X.B in Xand the local and remote XTCP ports into X.B local Xand X.B remote. X.B auth_fd Xreturns -1 upon error, setting errno appropriately. X.PP X.B auth_tcpuser(in,local,remote) Xreturns the name of the user on the other end of the TCP connection Xbetween X.B remote@in Xand X.B local. XIf authentication is impossible, X.B auth_tcpuser Xreturns XNULL, setting errno appropriately. XThe user name is stored in a static area Xwhich is overwritten on each call to X.B auth_tcpuser Xand X.B auth_xline. X.PP XThe authentication routines check with the Xremote Authentication Server on port X.B auth_tcpport, Xwhich defaults to 113 Xas specified by RFC 931. XYou can set X.B auth_tcpport Xto other values Xfor nonstandard implementations. X.PP X.SH RESTRICTIONS X.I authuser Xdoes no backslash interpretation Xupon the remote user name. XHopefully the next revision of RFC 931 Xwill make clear exactly what backslash Xinterpretation should be going on. X.PP X.I authuser Xdoes not use the operating system type Xinformation provided by the Authentication Server. X.SH VERSION Xauthuser version 3.0, February 5, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. X.SH REFERENCES XThe authentication server is more secure than passwords Xin some ways, but less secure than passwords in many ways. X(It's certainly better than no password at all---e.g., for Xmail or news.) XIt is not the final solution. XFor an excellent discussion of security problems within Xthe TCP/IP protocol suite, see XSteve Bellovin's article X``Security Problems in the TCP/IP Protocol Suite.'' X.SH "SEE ALSO" Xauthtcp(1), Xattachport(1), Xgetpeername(3), Xgetsockname(3), Xtcp(4), Xauthd(8) END_OF_FILE if test 3354 -ne `wc -c <'authuser.3'`; then echo shar: \"'authuser.3'\" unpacked with wrong size! fi # end of 'authuser.3' fi if test -f 'tcpuid.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tcpuid.8'\" else echo shar: Extracting \"'tcpuid.8'\" \(617 characters\) sed "s/^X//" >'tcpuid.8' <<'END_OF_FILE' X.TH tcpuid 8 X.SH NAME Xtcpuid \- show the user id that created a network connection X.SH SYNTAX Xtcpuid X.I rem.ote.in.addr X.I remport X.I loc.al.in.addr X.I locport X.SH DESCRIPTION X.I tcpuid Xprints the numeric user id of Xthe user who created Xthe network connection specified by its arguments. X.PP X.SH DIAGNOSTICS X.TP XLots, none of which should happen if the specified Xconnection is valid. X.SH BUGS XNone known. X.SH VERSION Xtcpuid version 3.0, February 5, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. XPartially inspired by code written by Vic Abell for ofiles. X.SH "SEE ALSO" Xauthd(8), Xtcpuname(8) END_OF_FILE if test 617 -ne `wc -c <'tcpuid.8'`; then echo shar: \"'tcpuid.8'\" unpacked with wrong size! fi # end of 'tcpuid.8' fi if test -f 'tcpuname.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tcpuname.8'\" else echo shar: Extracting \"'tcpuname.8'\" \(620 characters\) sed "s/^X//" >'tcpuname.8' <<'END_OF_FILE' X.TH tcpuname 8 X.SH NAME Xtcpuname \- show the user name that created a network connection X.SH SYNTAX Xtcpuname X.I rem.ote.in.addr X.I remport X.I loc.al.in.addr X.I locport X.SH DESCRIPTION X.I tcpuname Xprints the username of Xthe user who created Xthe network connection specified by its arguments. X.PP X.SH DIAGNOSTICS X.TP XLots, none of which should happen if the specified Xconnection is valid. X.SH BUGS XNone known. X.SH VERSION Xtcpuname version 3.0, February 5, 1991. X.SH AUTHOR XPlaced into the public domain by Daniel J. Bernstein. XPartially inspired by code written by Vic Abell for ofiles. X.SH "SEE ALSO" Xauthd(8), Xtcpuid(8) END_OF_FILE if test 620 -ne `wc -c <'tcpuname.8'`; then echo shar: \"'tcpuname.8'\" unpacked with wrong size! fi # end of 'tcpuname.8' fi if test -f 'authd.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'authd.c'\" else echo shar: Extracting \"'authd.c'\" \(7872 characters\) sed "s/^X//" >'authd.c' <<'END_OF_FILE' X#define KMEM "/dev/kmem" X#define VMUNIX "/vmunix" X#define NETSTAT "/usr/ucb/netstat -n -A -f inet" X#define NETSTATBUF 200 /* 80 would suffice */ X#define NETSTATREMOTE 49 X#define NETSTATWIDTH 17 X#define REMOTESIZE 100 /* guaranteed to be enough */ X X#include <stdio.h> X#include <ctype.h> X#ifdef USE_SYSLOG X#include <syslog.h> X#endif X#include <sys/types.h> X#include <sys/param.h> X#include <sys/dir.h> X#include <sys/user.h> X#ifdef convex X#include <sys/ucred.h> /* dorks */ X#define FCRED_ISNOT_POINTER X#endif X#define KERNEL X#include <sys/file.h> X#undef KERNEL X#ifdef BSD X#include <limits.h> X#endif X#include <nlist.h> X#include <sys/socket.h> X#include <sys/socketvar.h> X#ifdef convex X#include <sys/mbuf.h> X#endif X#include <net/route.h> X#include <netinet/in.h> X#include <netinet/in_pcb.h> X#include <netinet/tcp.h> X#include <netinet/tcp_fsm.h> X#include <netinet/tcp_timer.h> X#include <netinet/tcp_var.h> X#include <arpa/inet.h> X#include <pwd.h> Xextern char *calloc(); Xextern long lseek(); X X#define ZAP(x,err) if (x) if (flagauthd) \ X{printf("%s, %s: ERROR: UNKNOWN-ERROR\r\n",localport,remoteport);exit(37);} \ Xelse { fprintf(stderr,"%s: fatal: %s\n",argv[0],err); exit(37); } X/* Reporting errors honestly to a remote host could damage security. */ X Xstatic struct nlist nl[] = { { "_file" }, { "_nfile" }, { "" } }; X#define SFIL 0 X#define SNFILE 1 X Xstatic char s[NETSTATBUF]; Xstatic char remote[REMOTESIZE]; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X register struct file *xfile; X register struct file *fp; X register char *sockloc; X int nfile; X struct tcpcb tcp; X struct inpcb inp; X struct socket sock; X struct ucred uc; X struct file *ftp; X FILE *fi; X int fd; X unsigned long pcbl; X int pcb; X int r1; int r2; int r3; int r4; int rp; X int l1; int l2; int l3; int l4; int lp; X int uid; X struct passwd *pw; X int flagpwnam = 0; X int flagauthd = 0; X char localport[10]; X char remoteport[10]; X X if ((!strcmp(argv[0],"authd")) X || ((strlen(argv[0]) >= 6) X && (!strcmp(argv[0] + strlen(argv[0]) - 6,"/authd")))) X flagauthd = flagpwnam = 1; X else X if ((!strcmp(argv[0],"tcpuname")) X || ((strlen(argv[0]) >= 9) X && (!strcmp(argv[0] + strlen(argv[0]) - 9,"/tcpuname")))) X flagpwnam = 1; X X if (flagauthd) X { X int ch; X int localportlen; X int remoteportlen; X int loop; X struct sockaddr_in sa; X int salen; X X localportlen = remoteportlen = loop = 0; X X while ((ch = getchar()) != ',') X { X if (isascii(ch) && isdigit(ch)) localport[localportlen++] = ch; X if (localportlen == 6) /* tough luck! */ exit(2); X if ((++loop) > 1000) /* tough luck! */ exit(3); X } X while ((ch = getchar()) != '\n') X { X if (isascii(ch) && isdigit(ch)) remoteport[remoteportlen++] = ch; X if (remoteportlen == 6) /* tough luck! */ exit(4); X if ((++loop) > 1000) /* tough luck! */ exit(5); X } X X localport[localportlen] = remoteport[remoteportlen] = 0; X lp = atoi(localport); X rp = atoi(remoteport); X X salen = sizeof(sa); X if (getpeername(0,&sa,&salen) == -1) X { X printf("%s, %s: ERROR: UNKNOWN-ERROR\r\n",localport,remoteport); X exit(6); X } X r1 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[0]; X r2 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[1]; X r3 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[2]; X r4 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[3]; X X salen = sizeof(sa); X if (getsockname(0,&sa,&salen) == -1) X { X printf("%s, %s: ERROR: UNKNOWN-ERROR\r\n",localport,remoteport); X exit(6); X } X l1 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[0]; X l2 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[1]; X l3 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[2]; X l4 = (int) (unsigned int) ((unsigned char *) &sa.sin_addr)[3]; X } X else X { X ZAP(argc < 4,"need four arguments") X ZAP(sscanf(argv[1],"%d.%d.%d.%d",&r1,&r2,&r3,&r4)<4,"arg 1 must be a.b.c.d") X ZAP(sscanf(argv[2],"%d",&rp) < 1,"arg 2 must be integer") X ZAP(sscanf(argv[3],"%d.%d.%d.%d",&l1,&l2,&l3,&l4)<4,"arg 3 must be a.b.c.d") X ZAP(sscanf(argv[4],"%d",&lp) < 1,"arg 4 must be integer") X } X X (void) sprintf(remote,"%d.%d.%d.%d.%d ",r1,r2,r3,r4,rp); X X#ifdef USE_SYSLOG X /* This isn't worth the time for the procedure call, but if you want... */ X syslog(LOG_DEBUG,"authd: checking up on %d.%d.%d.%d %d %d.%d.%d.%d %d\n", X r1,r2,r3,r4,rp,l1,l2,l3,l4,lp); X#endif X X nlist(VMUNIX,nl); X ZAP(!(nl[SNFILE].n_value),"cannot nlist _nfile") X ZAP(!(nl[SFIL].n_value),"cannot nlist _file") X fd = open(KMEM,O_RDONLY); X ZAP(fd == -1,"cannot open kernel memory") X ZAP(lseek(fd,(long) (nl[SNFILE].n_value),0) == -1,"cannot seek to _nfile") X ZAP(read(fd,(char *) &nfile,sizeof(nfile)) < sizeof(nfile),"cannot read _nfile") X X ZAP(lseek(fd,(long) nl[SFIL].n_value,0) == 1,"cannot seek to _file") X ZAP(read(fd,(char *) &ftp,sizeof(ftp)) < sizeof(ftp),"cannot read _file") X ZAP(lseek(fd,(long) ftp,0),"cannot lseek to file table") X xfile = (struct file *) calloc((unsigned) nfile,sizeof(struct file)); X ZAP(!xfile,"cannot allocate space for copy of file table") X ZAP(read(fd,(char *) xfile,nfile * sizeof(struct file)) < nfile * sizeof(struct file),"cannot read file table") X X fi = popen(NETSTAT,"r"); X ZAP(!fi,"cannot execute netstat") X ZAP(!fgets(s,sizeof(s),fi),"cannot read netstat header line 1") X ZAP(!fgets(s,sizeof(s),fi),"cannot read netstat header line 2") X while (fgets(s,sizeof(s),fi)) X { X ZAP(sscanf(s,"%8x",&pcb) != 1,"cannot scan netstat pcb address") X pcbl = pcb; X if (!strncmp(s + NETSTATREMOTE,remote,NETSTATWIDTH)) X { X ZAP(lseek(fd,(long) pcbl,0) == -1,"cannot seek to pcb address") X ZAP(read(fd,(char *) &tcp,sizeof(tcp)) < sizeof(tcp),"cannot read tcp buffer") X ZAP(!tcp.t_inpcb,"tcp buffer unlinked") X ZAP(lseek(fd,(long) tcp.t_inpcb,0) == -1,"cannot seek to inpcb address") X ZAP(read(fd,(char *) &inp,sizeof(inp)) < sizeof(inp),"cannot read inpcb buffer") X ZAP(inp.inp_ppcb != (char *) pcbl,"inpcb not linked to pcb") X X/* Cursed be Convex and the other manufacturers who make this code */ X/* nearly impossible to write with any pretense of portability. */ X if((((char *) &inp.inp_faddr)[0] == (char) r1) X &&(((char *) &inp.inp_faddr)[1] == (char) r2) X &&(((char *) &inp.inp_faddr)[2] == (char) r3) X &&(((char *) &inp.inp_faddr)[3] == (char) r4) X &&(inp.inp_fport == htons((unsigned short) rp)) X &&(((char *) &inp.inp_laddr)[0] == (char) l1) X &&(((char *) &inp.inp_laddr)[1] == (char) l2) X &&(((char *) &inp.inp_laddr)[2] == (char) l3) X &&(((char *) &inp.inp_laddr)[3] == (char) l4) X &&(inp.inp_lport == htons((unsigned short) lp)) X ) X { X sockloc = (char *) inp.inp_socket; X ZAP(!sockloc,"inp not linked to socket") X ZAP(lseek(fd,(long) sockloc,0) == -1,"cannot seek to socket address") X ZAP(read(fd,(char *) &sock,sizeof(sock)) < sizeof(sock),"cannot read socket buffer") X ZAP(sock.so_pcb != (char *) tcp.t_inpcb,"socket not linked to inpcb") X for (fp = xfile;fp < xfile + nfile;++fp) X if (fp->f_count && (fp->f_type == DTYPE_SOCKET)) X if (fp->f_data == sockloc) X break; X if (fp != xfile + nfile) X { X#ifdef FCRED_ISNOT_POINTER X uid = (int) fp->f_cred.cr_ruid; X#else X ZAP(lseek(fd,(long) (fp->f_cred),0) == -1,"cannot seek to credentials") X ZAP(read(fd,(char *) &uc,sizeof(uc)) < sizeof(uc),"cannot read credentials") X uid = (int) uc.cr_ruid; X#endif X if (flagpwnam) X { X pw = getpwuid(uid); X ZAP(!pw,"cannot get password entry") X if (flagauthd) X /* UNIX is a trademark of AT&T. :-) */ X printf("%s, %s: USERID: UNIX: %s\r\n" X ,localport,remoteport,pw->pw_name); X else X printf("%s\n",pw->pw_name); X } X else X printf("%d\n",uid); X exit(0); X } X } X } X } X ZAP(1,"no such TCP connection") X exit(1); X} END_OF_FILE if test 7872 -ne `wc -c <'authd.c'`; then echo shar: \"'authd.c'\" unpacked with wrong size! fi # end of 'authd.c' fi if test -f 'authuser.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'authuser.h'\" else echo shar: Extracting \"'authuser.h'\" \(161 characters\) sed "s/^X//" >'authuser.h' <<'END_OF_FILE' X#ifndef AUTHUSER_H X#define AUTHUSER_H X Xextern unsigned short auth_tcpport; Xextern char *auth_xline(); Xextern int auth_fd(); Xextern char *auth_tcpuser(); X X#endif END_OF_FILE if test 161 -ne `wc -c <'authuser.h'`; then echo shar: \"'authuser.h'\" unpacked with wrong size! fi # end of 'authuser.h' fi if test -f 'authuser.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'authuser.c'\" else echo shar: Extracting \"'authuser.c'\" \(3519 characters\) sed "s/^X//" >'authuser.c' <<'END_OF_FILE' X#include <stdio.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <arpa/inet.h> X#include <netdb.h> X#include <errno.h> X#include <ctype.h> Xextern int errno; X#include "authuser.h" X Xunsigned short auth_tcpport = 113; X X#define SIZ 500 /* various buffers */ X Xstatic int auth_casecmp(u,v) Xregister char *u; Xregister char *v; X{ X /* is it correct to consider Foo and fOo the same user? yes */ X while (*u && *v) X if (tolower(*u) != tolower(*v)) X return tolower(*u) - tolower(*v); X else X ++u,++v; X return *u || *v; X} X Xstatic char authline[SIZ]; X Xchar *auth_xline(user,fd,in) Xregister char *user; /* the supposed name of the user, NULL if unknown */ Xregister int fd; /* the file descriptor of the connection */ Xregister unsigned long *in; X{ X unsigned short local; X unsigned short remote; X register char *ruser; X X if (auth_fd(fd,in,&local,&remote) == -1) X return 0; X ruser = auth_tcpuser(*in,local,remote); X if (!ruser) X return 0; X if (!user) X user = ruser; /* forces X-Auth-User */ X (void) sprintf(authline, X (auth_casecmp(ruser,user) ? "X-Forgery-By: %s" : "X-Auth-User: %s"), X ruser); X return authline; X} X Xint auth_fd(fd,in,local,remote) Xregister int fd; Xregister unsigned long *in; Xregister unsigned short *local; Xregister unsigned short *remote; X{ X struct sockaddr_in sa; X int dummy; X X dummy = sizeof(sa); X if (getsockname(fd,&sa,&dummy) == -1) X return -1; X if (sa.sin_family != AF_INET) X { X errno = EAFNOSUPPORT; X return -1; X } X *local = ntohs(sa.sin_port); X dummy = sizeof(sa); X if (getpeername(fd,&sa,&dummy) == -1) X return -1; X *remote = ntohs(sa.sin_port); X *in = sa.sin_addr.s_addr; X return 0; X} X Xstatic char ruser[SIZ]; Xstatic char realbuf[SIZ]; Xstatic char *buf; X Xchar *auth_tcpuser(in,local,remote) Xregister unsigned long in; Xregister unsigned short local; Xregister unsigned short remote; X{ X struct sockaddr_in sa; X register int s; X register int buflen; X register int w; X register int saveerrno; X char ch; X unsigned short rlocal; X unsigned short rremote; X X if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) X return 0; X sa.sin_family = AF_INET; X sa.sin_port = htons(auth_tcpport); X sa.sin_addr.s_addr = in; X if (connect(s,&sa,sizeof(sa)) == -1) X { X saveerrno = errno; X (void) close(s); X errno = saveerrno; X return 0; X } X X buf = realbuf; X (void) sprintf(buf,"%u , %u\r\n",(unsigned int) remote,(unsigned int) local); X /* note the reversed order---the example in the RFC is misleading */ X buflen = strlen(buf); X while ((w = write(s,buf,buflen)) < buflen) X if (w == -1) /* should we worry about 0 as well? */ X { X saveerrno = errno; X (void) close(s); X errno = saveerrno; X return 0; X } X else X { X buf += w; X buflen -= w; X } X buf = realbuf; X while ((w = read(s,&ch,1)) == 1) X { X *buf = ch; X if ((ch != ' ') && (ch != '\t') && (ch != '\r')) X ++buf; X if ((buf - realbuf == sizeof(realbuf) - 1) || (ch == '\n')) X break; X } X if (w == -1) X { X saveerrno = errno; X (void) close(s); X errno = saveerrno; X return 0; X } X *buf = '\0'; X X if (sscanf(realbuf,"%hd,%hd: USERID :%*[^:]:%s",&rremote,&rlocal,ruser) < 3) X { X (void) close(s); X errno = EIO; X /* makes sense, right? well, not when USERID failed to match ERROR */ X /* but there's no good error to return in that case */ X return 0; X } X if ((remote != rremote) || (local != rlocal)) X { X (void) close(s); X errno = EIO; X return 0; X } X /* XXX: we're not going to do any backslash processing */ X (void) close(s); X return ruser; X} END_OF_FILE if test 3519 -ne `wc -c <'authuser.c'`; then echo shar: \"'authuser.c'\" unpacked with wrong size! fi # end of 'authuser.c' fi if test -f 'test.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'test.c'\" else echo shar: Extracting \"'test.c'\" \(2640 characters\) sed "s/^X//" >'test.c' <<'END_OF_FILE' X#include <stdio.h> X#include <sys/types.h> X#include <sys/file.h> X#ifdef sun X#include <sys/fcntl.h> X#endif X#include <sys/socket.h> X#include <netinet/in.h> X#include <arpa/inet.h> X#include <pwd.h> X#include <errno.h> Xextern int errno; X#include "authuser.h" X Xmain() X{ X int s; X int t; X int u; X struct sockaddr_in sa; X int salen; X int localport; X unsigned long in; X unsigned short local; X unsigned short remote; X char *user; X struct passwd *pw; X int ok; X X ok = 1; X X#define ZOT(x) { fprintf(stderr,"test: fatal: %s\n",x); exit(37); } X X s = socket(AF_INET,SOCK_STREAM,0); X if (s == -1) X ZOT("cannot create server socket") X X localport = 0; /* meaning pick a port, we don't care which */ X X sa.sin_family = AF_INET; X sa.sin_port = htons(localport); X sa.sin_addr.s_addr = INADDR_ANY; X X if (bind(s,&sa,sizeof(sa)) == -1) X ZOT("cannot bind server socket") X X salen = sizeof(sa); X if (getsockname(s,&sa,&salen) == -1) X ZOT("cannot get name of server socket") X X if (listen(s,5) == -1) X ZOT("cannot listen for connections") /* XXX: impossible */ X X u = socket(AF_INET,SOCK_STREAM,0); X if (u == -1) X ZOT("cannot create client socket") X X /* we could bind now if we wanted to pick a local port, or to know */ X /* our local port before connection */ X X /* if connect() blocked then we'd never get a chance to accept() */ X if (fcntl(u,F_SETFL,O_NDELAY) == -1) /* XXX: FNDELAY? */ X ZOT("cannot set client socket to non-blocking mode") X X /* sa is already initialized above to the address we want to connect to */ X if (connect(u,&sa,sizeof(sa)) != -1) X ; /* XXX: this is slightly screwy, though common, behavior */ X else X if (errno != EINPROGRESS) X ZOT("connect failed") /* XXX: should retry if EINTR */ X X salen = sizeof(sa); X if ((t = accept(s,&sa,&salen)) == -1) X ZOT("cannot accept connection") X X printf("system says host is %s\n",inet_ntoa(sa.sin_addr)); X X /* now let's see what the server can figure out about the client */ X X if (auth_fd(t,&in,&local,&remote) == -1) X ZOT("authuser cannot figure out connection information") X X if (sa.sin_addr.s_addr != in) X { X ok = 0; X sa.sin_addr.s_addr = in; X } X printf("authuser says host is %s\n",inet_ntoa(sa.sin_addr)); X X pw = getpwuid(getuid()); X if (pw) X printf("system says username is %s\n",pw->pw_name); X else X { X ok = 0; X printf("system cannot figure out your username\n"); X } X X user = auth_tcpuser(in,local,remote); X if (user) X printf("authd says username is %s\n",user); X else X { X ok = 0; X printf("authd cannot figure out your username\n"); X } X X if (ok) X if (!strcmp(user,pw->pw_name)) X printf("Everything looks okay to me.\n"); X else X ok = 1; X X exit(!ok); X} END_OF_FILE if test 2640 -ne `wc -c <'test.c'`; then echo shar: \"'test.c'\" unpacked with wrong size! fi # end of 'test.c' fi if test -f 'netstatuid' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'netstatuid'\" else echo shar: Extracting \"'netstatuid'\" \(319 characters\) sed "s/^X//" >'netstatuid' <<'END_OF_FILE' X#!/bin/sh Xnetstat -n -f inet \ X| sed -n 's+^.....................\([^.]*\.[^.]*\.[^.]*\.[^.]*\)\.\([^ ]*\) *\([^.]*\.[^.]*\.[^.]*\.[^.]*\)\.\([^ ]*\).*$+ echo -n \3 \4 \1 \2" "\; tcpuname \3 \4 \1 \2 2>\&1+p' \ X| sh \ X| awk '!/ fatal:/ { printf "remote %-15s.%-5s local %-15s.%-5s user %s\n" , $1, $2, $3, $4, $5 } END_OF_FILE if test 319 -ne `wc -c <'netstatuid'`; then echo shar: \"'netstatuid'\" unpacked with wrong size! fi chmod +x 'netstatuid' # end of 'netstatuid' fi if test -f 'rfc931' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'rfc931'\" else echo shar: Extracting \"'rfc931'\" \(9196 characters\) sed "s/^X//" >'rfc931' <<'END_OF_FILE' X X X X X X--------- X X X< INC-PROJECT, AUTH-RFC-VER-2.NLS.5, >, 7-Jan-85 17:18-PST JBP X;;;; X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X XStJohns [Page 0] X X XNetwork Working Group Mike StJohns XRequest for Comments: 931 TPSC XSupersedes: RFC 912 January 1985 X X Authentication Server X X XSTATUS OF THIS MEMO X X This RFC suggests a proposed protocol for the ARPA-Internet X community, and requests discussion and suggestions for improvements. X This is the second draft of this proposal (superseding RFC 912) and X incorporates a more formal description of the syntax for the request X and response dialog, as well as a change to specify the type of user X identification returned. Distribution of this memo is unlimited. X XINTRODUCTION X X The Authentication Server Protocol provides a means to determine the X identity of a user of a particular TCP connection. Given a TCP port X number pair, it returns a character string which identifies the owner X of that connection on the server's system. Suggested uses include X automatic identification and verification of a user during an FTP X session, additional verification of a TAC dial up user, and access X verification for a generalized network file server. X XOVERVIEW X X This is a connection based application on TCP. A server listens for X TCP connections on TCP port 113 (decimal). Once a connection is X established, the server reads one line of data which specifies the X connection of interest. If it exists, the system dependent user X identifier of the connection of interest is sent out the connection. X The service closes the connection after sending the user identifier. X XRESTRICTIONS X X Queries are permitted only for fully specified connections. The X local/foreign host pair used to fully specify the connection are X taken from the query connection. This means a user on Host A may X only query the server on Host B about connections between A and B. X X X X X X X X X X X X XStJohns [Page 1] X X XRFC 931 January 1985 XAuthentication Server X X XQUERY/RESPONSE FORMAT X X The server accepts simple text query requests of the form X X <local-port>, <foreign-port> X X where <local-port> is the TCP port (decimal) on the target (server) X system, and <foreign-port> is the TCP port (decimal) on the source X (user) system. X X For example: X X 23, 6191 X X The response is of the form X X <local-port>, <foreign-port> : <response-type> : <additional-info> X X where <local-port>,<foreign-port> are the same pair as the query, X <response-type> is a keyword identifying the type of response, and X <additional info> is context dependent. X X For example: X X 23, 6191 : USERID : MULTICS : StJohns.DODCSC.a X 23, 6193 : USERID : TAC : MCSJ-MITMUL X 23, 6195 : ERROR : NO-USER X XRESPONSE TYPES X X A response can be one of two types: X X USERID X X In this case, <additional-info> is a string consisting of an X operating system name, followed by a ":", followed by user X identification string in a format peculiar to the operating system X indicated. Permitted operating system names are specified in X RFC-923, "Assigned Numbers" or its successors. The only other X names permitted are "TAC" to specify a BBN Terminal Access X Controller, and "OTHER" to specify any other operating system not X yet registered with the NIC. X X X X X X X XStJohns [Page 2] X X XRFC 931 January 1985 XAuthentication Server X X X ERROR X X For some reason the owner of <TCP-port> could not be determined, X <additional-info> tells why. The following are suggested values X of <additional-info> and their meanings. X X INVALID-PORT X X Either the local or foreign port was improperly specified. X X NO-USER X X The connection specified by the port pair is not currently in X use. X X UNKNOWN-ERROR X X Can't determine connection owner; reason unknown. Other values X may be specified as necessary. X XCAVEATS X X Unfortunately, the trustworthiness of the various host systems that X might implement an authentication server will vary quite a bit. It X is up to the various applications that will use the server to X determine the amount of trust they will place in the returned X information. It may be appropriate in some cases restrict the use of X the server to within a locally controlled subnet. X XAPPLICATIONS X X 1) Automatic user authentication for FTP X X A user-FTP may send a USER command with no argument to the X server-FTP to request automatic authentication. The server-FTP X will reply with a 230 (user logged in) if it can use the X authentication. It will reply with a 530 (not logged in) if it X cannot authenticate the user. It will reply with a 500 or 501 X (syntax or parameter problem) if it does not implement automatic X authentication. Please note that no change is needed to currently X implemented servers to handle the request for authentication; they X will reject it normally as a parameter problem. This is a X suggested implementation for experimental use only. X X 2) Verification for privileged network operations. For example, X having the server start or stop special purpose servers. X X X XStJohns [Page 3] X X XRFC 931 January 1985 XAuthentication Server X X X 3) Elimination of "double login" for TAC and other TELNET users. X X This will be implemented as a TELNET option. X XFORMAL SYNTAX X X <request> ::= <port-pair> <CR> <LF> X X <port-pair> ::= <integer-number> "," <integer-number> X X <reply> ::= <reply-text> <CR> <LF> X X <reply-text> ::= <error-reply> | <auth-reply> X X <error-reply> ::= <port-pair> ":" ERROR ":" <error-type> X X <auth-reply> ::= <port-pair> ":" USERID ":" <opsys> ":" <user-id> X X <error-type> ::= INVALID-PORT | NO-USER | UNKNOWN-ERROR X X <opsys> ::= TAC | OTHER | MULTICS | UNIX ...etc. X (See "Assigned Numbers") X X Notes on Syntax: X X 1) White space (blanks and tab characters) between tokens is not X important and may be ignored. X X 2) White space, the token separator character (":"), and the port X pair separator character (",") must be quoted if used within a X token. The quote character is a back-slash, ASCII 92 (decimal) X ("\"). For example, a quoted colon is "\:". The back-slash must X also be quoted if its needed to represent itself ("\\"). X XNotes on User Identification Format: X X The user identifier returned by the server should be the standard one X for the system. For example, the standard Multics identifier X consists of a PERSONID followed by a ".", followed by a PROJECTID, X followed by a ".", followed by an INSTANCE TAG of one character. An X instance tag of "a" identifies an interactive user, and instance tag X of "m" identifies an absentee job (batch job) user, and an instance X tag of "z" identifies a daemon (background) user. X X Each set of operating system users must come to a consensus as to X X X X XStJohns [Page 4] X X XRFC 931 January 1985 XAuthentication Server X X X what the OFFICIAL user identification for their systems will be. X Until they register this information, they must use the "OTHER" tag X to specify their user identification. X XNotes on User Identification Translation: X X Once you have a user identifier from a remote system, you must then X have a way of translating it into an identifier that meaningful on X the local system. The following is a sketchy outline of table driven X scheme for doing this. X X The table consists of four columns, the first three are used to match X against, the fourth is the result. X X USERID Opsys Address Result X MCSJ-MITMUL TAC 26.*.*.* StJohns X * MULTICS 192.5.42.* = X * OTHER 10.0.0.42 anonymous X MSJ ITS 10.3.0.44 StJohns X X The above table is a sample one for a Multics system on MILNET at the X Pentagon. When an authentication is returned, the particular X application using the userid simply looks for the first match in the X table. Notice the second line. It says that any authentication X coming from a Multics system on Net 192.5.42 is accepted in the same X format. X X Obviously, various users will have to be registered to use this X facility, but the registration can be done at the same time the use X receives his login identity from the system. X X X X X X X X X X X X X X X X X X X XStJohns [Page 5] END_OF_FILE if test 9196 -ne `wc -c <'rfc931'`; then echo shar: \"'rfc931'\" unpacked with wrong size! fi # end of 'rfc931' fi echo shar: End of shell archive. exit 0