This one has been patched for the missing alarm(0) call in
my RFC 931 user name lookup code.

	Wietse

#! /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:  README miscd.c tcpd.c fromhost.c hosts_access.c
#   shell_cmd.c log_tcp.h try.c refuse.c Makefile hosts_access.5
#   strcasecmp.c BLURB rfc931.c tcpd.8 hosts_info.c hosts_access.3
#   hosts_ctl.c percent_x.c options.c clean_exit.c rfc931_option
# Wrapped by wietse@wzv on Mon Jun 22 16:34:18 1992
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(13298 characters\)
sed "s/^X//" >README <<'END_OF_README'
X@(#) README 1.7 92/06/11 22:21:17
X
XGeneral description
X-------------------
X
XWith this package you can monitor incoming connections to the SYSTAT,
XFINGER, FTP, TELNET, RLOGIN, RSH, EXEC, TFTP, TALK, and other IP
Xnetwork services.  Connections are reported through the syslog daemon.
XRequirements are that network daemons are started by the inetd program
Xor something similar, and the availability of a syslog(3) library.
X
XThe programs are tiny front ends. By default, they just report the name
Xor address of the remote host and of the requested service, and then
Xinvoke the real network daemon; no information is exchanged with the
Xremote client process.
X
XOptional features are: access control that limits the number of hosts
Xthat can connect to your network daemons, remote user name lookups with
Xthe RFC 931 protocol, and protection against hosts that pretend to have
Xsomeone elses host name.
X
XThe programs can be installed without any changes to existing software
Xor to existing configuration files.  Just move the vendor-provided
Xdaemons to another directory and install the front ends into their
Xoriginal places.  Installation details are given below.
X
XEarly versions of the programs were tested with Ultrix >= 2.2, with
XSunOS >= 3.4 and ISC 2.2. Later versions have been installed on a wide
Xvariety of platforms such as SunOS 4.1.1, Ultrix 4.0 and 4.2, Apollo
XSR10.3.5 and an unknown number of other ones. The software should run
Xwithout modification on top of most BSD-style TCP/IP implementations.
X
XRestrictions
X------------
X
XSome UDP (and RPC) daemons linger around for a while after they have
Xserviced a request, just in case another request comes in.  In the
Xinetd configuration file these daemons are registered with the `wait'
Xoption. Only the request that started such a daemon will be handled by
Xthe front ends.  This restriction does not apply to connection-oriented
X(TCP) services.
X
XSome ConvexOS versions come with a broken recvfrom(2) implementation.
XThis makes it impossible for the daemon front ends to look up the
Xremote host address (and hence, the name) in case of UDP connections.
X
XAccess control
X--------------
X
XWhen compiled with -DHOSTS_ACCESS, the front-end programs support a
Xsimple form of access control that is based on pattern matching.  The
Xaccess-control software provides hooks for the execution of shell
Xcommands when a pattern fires; this feature may be useful to install
X"booby traps" on specific network services.  For details, see the
Xhosts_access(5) manual page, which is in `nroff -man' format.
X
XDetection of hosts that pretend to have someone elses host name
X---------------------------------------------------------------
X
XAuthentication based on host names, such as used by RLOGIN and RSH,
Xused to work quite reliably when all host name lookups were done from
Xa _local_ hosts file.
X
XWith _distributed_ name services, authentication schemes that rely on
Xhost names can be subverted by playing games with the address->name and
Xname->address maps that are maintained by some far-away name servers.
X
XThe front-end programs verify the remote host name that is returned by
Xthe DNS server responsible for the address->name mapping, by looking at
Xthe name and address that are returned by the DNS server responsible
Xfor the name->address mapping. If any discrepancies are found, the
Xfront ends conclude that they are dealing with a host that pretends to
Xhave someone elses host name.
X
XIf the sources are compiled with -DPARANOID, the front ends will drop
Xthe connection in case of a host name/address mismatch. Otherwise, the
Xfront ends pretend that the host name is unknown when logging the
Xconnection and consulting the optional access control tables.
X
XRFC 931 support
X---------------
X
XThe protocol described in RFC 931 provides a means to get the remote
Xuser name from the client host.  The requirement is that the client
Xhost runs an RFC 931-compliant daemon.
X
XUser name lookups are enabled if the source is compiled with -DRFC931.
XThere are some limitations, though: the number of hosts that run an RFC
X931 daemon is still small; user name lookups do not work for datagram
X(UDP) connections. More seriously, remote user name loookups can cause
Xnoticeable delays with connections from PCs.
X
XHooks for extending the access control language
X-----------------------------------------------
X
XA skeleton is available for adding user-defined extensions to the
Xaccess control language.  The options.c file implements examples that
Xselectively (1) make a daemon front end switch to another user or group
Xid, (2) perform remote user name lookups, and (3) run an alternate
Xserver (for example, a bogus ftp daemon that mumbles some faked error
Xmessage before hanging up).
X
XThe the language extension hook is not enabled by default because it
Xintroduces a minor change to the access control language syntax.
X
XRelated software
X----------------
X
XVersions of rshd and rlogind, hacked to report the remote user name in
Xaddition to the remote host name, are available for anonymous ftp
X(ftp.win.tue.nl:/pub/security/logdaemon.tar.Z).  These programs are
Xderived from source code on the first 43BSD network source tape; they
Xhave been tested only with SunOS >= 4.0 (the rshd appears to work with
XUltrix 4.x, too).
X
XThe securelib shared library by William LeFebvre can be used to control
Xaccess to network daemons that are not run under control of the inetd,
Xsuch as the RPC daemons that are registered with the portmap daemon.
XAvailable as eecs.nwu.edu:/pub/securelib.tar.
X
XAn alternative portmap daemon can also help to improve RPC security.
Xftp.win.tue.nl:/pub/security/portmap.shar.Z was tested with SunOS
X4.1.1, Ultrix 3.0 and Ultrix 4.x. The protection is less effective than
Xthat of the securelib library because portmap's primary task is to
Xmaintain the RPC daemon lookup table. SunOS 4.x users should install
Xthe latest revision of the portmap and NIS software.
X
XAnother way to manage access to TCP/IP services is illustrated by the
Xservers provided with the authutil package (comp.sources.unix volume
X22) by Dan Bernstein. This one relies on RFC 931.
X
XSource for a reasonably fast and portable RFC 931 daemon by Peter
XEriksson is available from ftp.lysator.liu.se:/pub/net/pauthd*.tar.Z.
X
XSome TCP/IP implementations come without syslog library. A replacement
Xcan be found in ftp.win.tue.nl:/pub/security/surrogate-syslog.tar.Z.
X
XConfiguration and installation (the easy way)
X---------------------------------------------
X
XAn advanced installation recipe is given later on. The "easy" recipe
Xrequires no changes to existing software or configuration files.
X
XIf you don't run Ultrix, you don't need the miscd front-end program.
XThe miscd daemon implements among others the SYSTAT service, which
Xproduces the same output as the the WHO command.
X
XBy default, the front-end programs assume that the vendor-provided
Xdaemons will be moved to the "/usr/etc/..." directory.  If you want
Xsomething else, adjust the REAL_DAEMON_DIR macro in the file tcpd.c
X(and the REAL_DAEMON macro in miscd.c).
X
XFollow the instructions at the beginning of the Makefile and compile
Xthe programs. The result is two binaries (three in case of Ultrix). The
X`try' program can be used to play with host access control tables and
Xis described in a later section. 
X
XThe tcpd program can be used for monitoring requests for the telnet,
Xfinger, ftp, exec, rsh, rlogin, tftp, talk, spray, rusers, comsat and
Xother services that have a one-to-one mapping onto executable files.
X
XDecide which services you want to be monitored. Move the corresponding
Xvendor-provided daemon programs to the location specified by the
XREAL_DAEMON_DIR macro in the file tcpd.c, and copy the tcpd front end
Xto the locations where the vendor-provided daemons used to be. That is,
Xone copy of (or link to) the tcpd program for each service that you
Xwant to monitor.
X
XUltrix only:  If you want to monitor and/or restrict access to the
XSYSTAT service, move the vendor-provided miscd daemon to the location
Xspecified by the REAL_DAEMON macro in the miscd.c file, and install the
Xmiscd front end into the original miscd location.
X
XConfiguration and installation (the advanced way)
X-------------------------------------------------
X
XInstead of moving the vendor-provided daemons to another directory,
Xdefine the REAL_DAEMON_DIR macro in the file tcpd.c (and, if you run
XUltrix, REAL_DAEMON in miscd.c) to reflect the present location of
Xthose daemons. Then follow the instructions in the Makefile and do
Xa "make".
X
XThe tcpd program can be used for monitoring requests for the telnet,
Xfinger, ftp, exec, rsh, rlogin, tftp, talk, spray, rusers, comsat and
Xother services that have a one-to-one mapping onto executable files.
X
XInstall the tcpd command in a suitable place. Apollo UNIX users will
Xwant to install it under a different name because tcpd is the name of
Xan already existing command. A suitable name for the front-end program
Xwould be "frontd".  Then perform the following edits on the inetd
Xconfiguration file (usually /etc/inetd.conf):
X
X    finger  stream  tcp     nowait  nobody  /usr/etc/in.fingerd     in.fingerd
X
Xbecomes:
X
X    finger  stream  tcp     nowait  nobody  /usr/etc/tcpd           in.fingerd
X
XThe example applies to SunOS 4.x; other UNIX implementations should not
Xdiffer much. Similar changes will be needed for other services that are
Xto be covered by the tcpd (or frontd) front-end program. Send a SIGHUP
Xto the inetd process to make the changes effective.
X
XThe miscd daemon that comes with Ultrix implements several network
Xservices. It decides what to do by looking at its process name. One of
Xthe services is systat, which is a kind of limited finger service.  If
Xyou want to monitor the systat service, install the miscd front end in
Xa suitable place and update the inetd configuration file:
X
X    systat  stream  tcp     nowait  /front/ends/miscd           systatd
X
XThat's right, Ultrix still runs its daemons with root privileges.
X
XDaemons with arbitrary path names
X---------------------------------
X
XThe above tcpd examples work fine with network daemons that live in a
Xcommon directory, but sometimes that is not possible. You can cope with
Xthese cases by specifying, in the inetd configuration file, an absolute
Xpath name for the daemon process name.  For example,
X
X    ntalk   dgram   udp     wait    root    /usr/etc/tcpd /usr/local/lib/ntalkd
X
XTcpd ignores the REAL_DAEMON_DIR macro when the daemon process name is
Xan absolute pathname;  logging and access control will be based on the
Xlast component of the daemon process name.
X
XTesting the access control files
X--------------------------------
X
XThe "try" command, provided with this package, can be used to test out
Xthe access control files.  The command syntax is:
X
X    ./try process_name hostname	(e.g. ./try in.tftpd localhost)
X
X    ./try process_name address	(e.g. ./try in.tftpd 127.0.0.1)
X
XIn the first case, the program will use both the host name and
Xaddress.  In the second case, the program will pretend that the host
Xname is unknown, so that you can simulate what happens when hostname
Xlookup fails.  If there are any serious errors they will be reported
Xvia the syslog daemon.  Run a "tail -f" on the logfile while playing
Xwith the "try" command.
X
XOther applications
X------------------
X
XThe access control routines can easily be integrated with other
Xprograms.  The hosts_access.3 manual page (`nroff -man' format)
Xdescribes the external interface of the libwrap.a library.
X
XThe tcpd front end can even be used to control access to the smtp port.
XIn that case, sendmail should not be run as a stand-alone daemon, but
Xit should be registered in the inetd.conf file. For example:
X
X    smtp    stream  tcp     nowait  root    /usr/etc/tcpd /usr/lib/sendmail -bs
X
XYou will periodically want to run sendmail to process queued-up
Xmessages. A crontab entry like:
X
X    0,15,30,45 * * * * /usr/lib/sendmail -q
X
Xshould take care of that.
X
XAcknowledgements
X----------------
X
XThanks to Brendan Kehoe (brendan@cs.widener.edu), Heimir Sverrisson
X(heimir@hafro.is) and Dan Bernstein (brnstnd@kramden.acf.nyu.edu) for
Xfeedback on an early release of this product.  The host name/address
Xcheck was suggested by John Kimball (jkimball@src.honeywell.com).
XApollo's UNIX environment has some peculiar quirks: Willem-Jan Withagen
X(wjw@eb.ele.tue.nl), Pieter Schoenmakers (tiggr@es.ele.tue.nl) and
XCharles S. Fuller (fuller@wccs.psc.edu) provided assistance.  Hal R.
XBrand (BRAND@addvax.llnl.gov) told me how to get the remote IP address
Xin case of datagram-oriented services, and suggested the optional shell
Xcommand feature.  Shabbir Safdar (shabby@mentor.cc.purdue.edu) provided
Xa first version of a much-needed manual page.  Granville Boman Goza, IV
X(gbg@sei.cmu.edu) suggested to use the remote IP address even when the
Xhost name is available.  Casper H.S. Dik (casper@fwi.uva.nl) provided
Xadditional insight into DNS spoofing techniques.  The bogus daemon
Xfeature was inspired by code from Andrew Macpherson (BNR Europe Ltd).
XI appreciate the code fragments that I received from Howard Chu
X(hyc@hanauma.jpl.nasa.gov), John P. Rouillard (rouilj@cs.umb.edu) and
Xothers. These saved me a lot of work.
X
X	Wietse Venema (wietse@wzv.win.tue.nl),
X	Department of Mathematics and Computing Science,
X	Eindhoven University of Technology,
X	The Netherlands.
END_OF_README
if test 13298 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f miscd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"miscd.c\"
else
echo shar: Extracting \"miscd.c\" \(2761 characters\)
sed "s/^X//" >miscd.c <<'END_OF_miscd.c'
X /*
X  * Front end to the ULTRIX miscd service. The front end logs the remote host
X  * name and then invokes the real miscd daemon. Install as "/usr/etc/miscd",
X  * after moving the real miscd daemon to the "/usr/etc/..." directory.
X  * Connections and diagnostics are logged through syslog(3).
X  * 
X  * The Ultrix miscd program implements (among others) the systat service, which
X  * pipes the output from who(1) to stdout. This information is potentially
X  * useful to systems crackers.
X  * 
X  * Compile with -DHOSTS_ACCESS in order to enable access control. See the
X  * hosts_access(5) manual page for details.
X  * 
X  * Compile with -DPARANOID if service should be refused to hosts that pretend
X  * to have someone elses host name. This gives some protection against rsh
X  * and rlogin attacks that involve compromised domain name servers.
X  * 
X  * Compile with -DDAEMON_UMASK=nnn if daemons should run with a non-default
X  * umask value (the system default is 000, resulting in world-writable
X  * files).
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) miscd.c 1.3 92/06/11 22:21:20";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <syslog.h>
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* The following specifies where the vendor-provided daemon should go. */
X
X#define REAL_DAEMON	"/usr/etc/.../miscd"
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    struct from_host from;
X    int     from_stat;
X
X    /* Attempt to prevent the creation of world-writable files. */
X
X#ifdef DAEMON_UMASK
X    umask(DAEMON_UMASK);
X#endif
X
X    /*
X     * Open a channel to the syslog daemon. Older versions of openlog()
X     * require only two arguments.
X     */
X
X#ifdef LOG_MAIL
X    (void) openlog(argv[0], LOG_PID, FACILITY);
X#else
X    (void) openlog(argv[0], LOG_PID);
X#endif
X
X    /*
X     * Find out and verify the remote host name. Sites concerned with
X     * security may choose to refuse connections from hosts that pretend to
X     * have someone elses host name.
X     */
X
X    from_stat = fromhost(&from);
X#ifdef PARANOID
X    if (from_stat == -1)
X	refuse(&from);
X#endif
X
X    /*
X     * Check whether this host can access the service in argv[0]. The
X     * access-control code invokes optional shell commands as specified in
X     * the access-control tables.
X     */
X
X#ifdef HOSTS_ACCESS
X    if (!hosts_access(argv[0], &from))
X	refuse(&from);
X#endif
X
X    /* Report remote client and invoke the real daemon program. */
X
X    syslog(LOG_INFO, "connect from %s", hosts_info(&from));
X    (void) execv(REAL_DAEMON, argv);
X    syslog(LOG_ERR, "%s: %m", REAL_DAEMON);
X    clean_exit(&from);
X    /* NOTREACHED */
X}
END_OF_miscd.c
if test 2761 -ne `wc -c <miscd.c`; then
    echo shar: \"miscd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tcpd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tcpd.c\"
else
echo shar: Extracting \"tcpd.c\" \(3146 characters\)
sed "s/^X//" >tcpd.c <<'END_OF_tcpd.c'
X /*
X  * General front end for stream and datagram IP services. This program logs
X  * the remote host name and then invokes the real daemon. For example,
X  * install as /usr/etc/{tftpd,fingerd,telnetd,ftpd,rlogind,rshd,rexecd},
X  * after saving the real daemons in the directory "/usr/etc/...". This
X  * arrangement requires that the network daemons are started by inetd or
X  * something similar. Connections and diagnostics are logged through
X  * syslog(3).
X  * 
X  * Compile with -DHOSTS_ACCESS in order to enable access control. See the
X  * hosts_access(5) manual page for details.
X  * 
X  * Compile with -DPARANOID if service should be refused to hosts that pretend
X  * to have someone elses host name. This gives some protection against rsh
X  * and rlogin attacks that involve compromised domain name servers.
X  * 
X  * Compile with -DDAEMON_UMASK=nnn if daemons should run with a non-default
X  * umask value (the system default is 000, resulting in world-writable
X  * files).
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) tcpd.c 1.3 92/06/11 22:21:22";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/stat.h>
X#include <stdio.h>
X#include <syslog.h>
X
Xextern char *strrchr();
Xextern char *strcpy();
X
X#ifndef MAXPATHNAMELEN
X#define MAXPATHNAMELEN	BUFSIZ
X#endif
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* The following specifies where the vendor-provided daemons should go. */
X
X#define REAL_DAEMON_DIR	"/usr/etc/..."
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    struct from_host from;
X    int     from_stat;
X    char    path[MAXPATHNAMELEN];
X
X    /* Attempt to prevent the creation of world-writable files. */
X
X#ifdef DAEMON_UMASK
X    umask(DAEMON_UMASK);
X#endif
X
X    /*
X     * If argv[0] is an absolute path name, ignore REAL_DAEMON_DIR, and strip
X     * argv[0] to its basename.
X     */
X
X    if (argv[0][0] == '/') {
X	strcpy(path, argv[0]);
X	argv[0] = strrchr(argv[0], '/') + 1;
X    } else {
X	sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]);
X    }
X
X    /*
X     * Open a channel to the syslog daemon. Older versions of openlog()
X     * require only two arguments.
X     */
X
X#ifdef LOG_MAIL
X    (void) openlog(argv[0], LOG_PID, FACILITY);
X#else
X    (void) openlog(argv[0], LOG_PID);
X#endif
X
X    /*
X     * Find out and verify the remote host name. Sites concerned with
X     * security may choose to refuse connections from hosts that pretend to
X     * have someone elses host name.
X     */
X
X    from_stat = fromhost(&from);
X#ifdef PARANOID
X    if (from_stat == -1)
X	refuse(&from);
X#endif
X
X    /*
X     * Check whether this host can access the service in argv[0]. The
X     * access-control code invokes optional shell commands as specified in
X     * the access-control tables.
X     */
X
X#ifdef HOSTS_ACCESS
X    if (!hosts_access(argv[0], &from))
X	refuse(&from);
X#endif
X
X    /* Report remote client and invoke the real daemon program. */
X
X    syslog(LOG_INFO, "connect from %s", hosts_info(&from));
X    (void) execv(path, argv);
X    syslog(LOG_ERR, "%s: %m", path);
X    clean_exit(&from);
X    /* NOTREACHED */
X}
END_OF_tcpd.c
if test 3146 -ne `wc -c <tcpd.c`; then
    echo shar: \"tcpd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fromhost.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fromhost.c\"
else
echo shar: Extracting \"fromhost.c\" \(6349 characters\)
sed "s/^X//" >fromhost.c <<'END_OF_fromhost.c'
X /*
X  * fromhost() determines the type of connection (datagram, stream), the name
X  * and address of the host at the other end of standard input, and the
X  * remote user name (if RFC 931 lookups are enabled). A host name of "stdin"
X  * is returned if the program is run from a tty. The value "unknown" is
X  * returned as a placeholder for information that could not be looked up.
X  * All results are in static memory.
X  * 
X  * The return status is (-1) if the remote host pretends to have someone elses
X  * host name, otherwise a zero status is returned.
X  * 
X  * Diagnostics are reported through syslog(3).
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) fromhost.c 1.5 92/06/11 22:21:24";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <errno.h>
X
Xextern char *inet_ntoa();
Xextern char *strncpy();
Xextern char *strcpy();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Forward declarations. */
X
Xstatic int matchname();
X
X/* The following are to be used in assignment context, not in comparisons. */
X
X#define	GOOD	1
X#define	BAD	0
X
X/* Initially, we know nothing about the origin of the connection. */
X
Xstatic struct from_host from_unknown = {
X    0,					/* connected/unconnected */
X    FROM_UNKNOWN,			/* remote host name */
X    FROM_UNKNOWN,			/* remote host address */
X    FROM_UNKNOWN,			/* remote user name */
X};
X
X /*
X  * The Apollo SR10.3 and some SYSV4 getpeername(2) versions do not return an
X  * error in case of a datagram-oriented socket. Instead, they claim that all
X  * UDP requests come from address 0.0.0.0. The following code works around
X  * the problem. It does no harm on "normal" systems.
X  */
X
X#ifdef GETPEERNAME_BUG
X
Xstatic int fix_getpeername(sock, sa, len)
Xint     sock;
Xstruct sockaddr *sa;
Xint    *len;
X{
X    int     ret;
X    struct sockaddr_in *sin = (struct sockaddr_in *) sa;
X
X    if ((ret = getpeername(sock, sa, len)) >= 0
X	&& sa->sa_family == AF_INET
X	&& sin->sin_addr.s_addr == 0) {
X	errno = ENOTCONN;
X	return (-1);
X    } else {
X	return (ret);
X    }
X}
X
X#define	getpeername	fix_getpeername
X#endif
X
X/* fromhost - find out what is at the other end of standard input */
X
Xint     fromhost(f)
Xstruct from_host *f;
X{
X    struct sockaddr sa;
X    struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
X    struct hostent *hp;
X    int     length = sizeof(sa);
X    char    buf[BUFSIZ];
X    static char addr_buf[FROM_ADDRLEN];
X    static char name_buf[MAXHOSTNAMELEN];
X
X    /*
X     * There are so many results and so many early returns that it seems
X     * safest to first initialize all results to UNKNOWN.
X     */
X
X    *f = from_unknown;
X
X    /*
X     * Look up the remote host address. Hal R. Brand <BRAND@addvax.llnl.gov>
X     * suggested how to get the remote host info in case of UDP connections:
X     * peek at the first message without actually looking at its contents.
X     */
X
X    if (getpeername(0, &sa, &length) >= 0) {	/* assume TCP request */
X	f->sock_type = FROM_CONNECTED;
X    } else {
X	switch (errno) {
X	case ENOTSOCK:				/* stdin is not a socket */
X	    if (isatty(0))
X		f->name = "stdin";
X	    return (0);
X	case ENOTCONN:				/* assume UDP request */
X	    length = sizeof(sa);
X	    if (recvfrom(0, buf, sizeof(buf), MSG_PEEK, &sa, &length) < 0) {
X		syslog(LOG_ERR, "recvfrom: %m");
X		return (0);
X	    }
X#ifdef really_paranoid
X	    memset(buf, 0 sizeof(buf));
X#endif
X	    f->sock_type = FROM_UNCONNECTED;
X	    break;
X	default:				/* other, punt */
X	    syslog(LOG_ERR, "getpeername: %m");
X	    return (0);
X	}
X    }
X    /* At present, we can only deal with the AF_INET address family. */
X
X    if (sa.sa_family != AF_INET) {
X	syslog(LOG_ERR, "unexpected address family %ld", (long) sa.sa_family);
X	return (0);
X    }
X    /* Save the host address. A later inet_ntoa() call may clobber it. */
X
X    f->addr = strcpy(addr_buf, inet_ntoa(sin->sin_addr));
X
X    /* Look up the remote user name. Does not work for UDP services. */
X
X#ifdef RFC931
X    if (f->sock_type == FROM_CONNECTED)
X	f->user = rfc931_name(sin);
X#endif
X
X    /* Look up the remote host name. */
X
X    if ((hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
X			    sizeof(sin->sin_addr.s_addr),
X			    AF_INET)) == 0) {
X	return (0);
X    }
X    /* Save the host name. A later gethostbyxxx() call may clobber it. */
X
X    f->name = strncpy(name_buf, hp->h_name, sizeof(name_buf) - 1);
X    name_buf[sizeof(name_buf) - 1] = 0;
X
X    /*
X     * Verify that the host name does not belong to someone else. If host
X     * name verification fails, pretend that the host name lookup failed.
X     */
X
X    if (matchname(f->name, sin->sin_addr)) {
X	return (0);
X    } else {
X	f->name = FROM_UNKNOWN;
X	return (-1);				/* verification failed */
X    }
X}
X
X/* matchname - determine if host name matches IP address */
X
Xstatic int matchname(remotehost, addr)
Xchar   *remotehost;
Xstruct in_addr addr;
X{
X    struct hostent *hp;
X    int     i;
X
X    if ((hp = gethostbyname(remotehost)) == 0) {
X
X	/*
X	 * Unable to verify that the host name matches the address. This may
X	 * be a transient problem or a botched name server setup. We decide
X	 * to play safe.
X	 */
X
X	syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
X	return (BAD);
X
X    } else {
X
X	if (strcasecmp(remotehost, hp->h_name)) {
X	    syslog(LOG_ERR, "host name/name mismatch: %s != %s",
X		   remotehost, hp->h_name);
X	    return (BAD);
X	}
X	/* Look up the host address in the address list we just got. */
X
X	for (i = 0; hp->h_addr_list[i]; i++) {
X	    if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
X		return (GOOD);
X	}
X
X	/*
X	 * The host name does not map to the original host address. Perhaps
X	 * someone has compromised a name server. More likely someone botched
X	 * it, but that could be dangerous, too.
X	 */
X
X	syslog(LOG_ERR, "host name/address mismatch: %s != %s",
X	       inet_ntoa(addr), hp->h_name);
X	return (BAD);
X    }
X}
X
X#ifdef TEST
X
X/* Code for stand-alone testing. */
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    struct from_host from;
X
X#ifdef LOG_MAIL
X    (void) openlog(argv[0], LOG_PID, FACILITY);
X#else
X    (void) openlog(argv[0], LOG_PID);
X#endif
X    (void) fromhost(&from);
X    printf("%s\n", hosts_info(&from));
X    return (0);
X}
X
X#endif
END_OF_fromhost.c
if test 6349 -ne `wc -c <fromhost.c`; then
    echo shar: \"fromhost.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_access.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hosts_access.c\"
else
echo shar: Extracting \"hosts_access.c\" \(7329 characters\)
sed "s/^X//" >hosts_access.c <<'END_OF_hosts_access.c'
X /*
X  * This module implements a simple access control language that is based on
X  * host (or domain) names, netgroup, internet addresses (or network numbers)
X  * and daemon process names. When a match is found an optional shell command
X  * is executed and the search is terminated.
X  * 
X  * Diagnostics are reported through syslog(3).
X  * 
X  * Compile with -DNETGROUP if your library provides support for netgroups.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) hosts_access.c 1.8 92/06/12 15:55:52";
X#endif
X
X /* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <ctype.h>
X
Xextern char *fgets();
Xextern char *strchr();
Xextern char *strtok();
X
X#ifndef	INADDR_NONE
X#define	INADDR_NONE	(-1)		/* XXX should be 0xffffffff */
X#endif
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Delimiters for lists of daemons or clients. */
X
Xstatic char sep[] = ", \t";
X
X/* Constants to be used in assignments only, not in comparisons... */
X
X#define	YES		1
X#define	NO		0
X#define	FAIL		(-1)
X
X/* Forward declarations. */
X
Xstatic int table_match();
Xstatic int list_match();
Xstatic int masked_match();
Xstatic void list_split();
X
X/* hosts_access - host access control facility */
X
Xint     hosts_access(daemon, client)
Xchar   *daemon;
Xstruct from_host *client;		/* host or user name may be empty */
X{
X
X    /*
X     * If the (daemon, client) pair is matched by an entry in the file
X     * /etc/hosts.allow, access is granted. Otherwise, if the (daemon,
X     * client) pair is matched by an entry in the file /etc/hosts.deny,
X     * access is denied. Otherwise, access is granted. A non-existent
X     * access-control file is treated as an empty file.
X     */
X
X    if (table_match(HOSTS_ALLOW, daemon, client))
X	return (YES);
X    if (table_match(HOSTS_DENY, daemon, client))
X	return (NO);
X    return (YES);
X}
X
X/* table_match - match table entries with (daemon, client) pair */
X
Xstatic int table_match(table, daemon, client)
Xchar   *table;
Xchar   *daemon;
Xstruct from_host *client;		/* host or user name may be empty */
X{
X    FILE   *fp;
X    char    sv_list[BUFSIZ];		/* becomes list of daemons */
X    char   *cl_list;			/* becomes list of clients */
X    char   *argv[sizeof(sv_list) / 2 + 1];
X    char   *sh_cmd;			/* becomes optional shell command */
X    int     match;
X    int     end;
X
X    /* The following variables should always be tested together. */
X
X    int     sv_match = NO;		/* daemon matched */
X    int     cl_match = NO;		/* client matced */
X
X    /*
X     * Process the table one line at a time. Lines that begin with a '#'
X     * character are ignored. Non-comment lines are broken at the ':'
X     * character (we complain if there is none). The first field is matched
X     * against the daemon process name (argv[0]), the second field against
X     * the host name or address. A non-existing table is treated as if it
X     * were an empty table. When a match is found an optional shell command
X     * is executed.
X     * 
X     * Daemon and client lists are converted to arrays of character pointers
X     * because the client list may have to be processed twice: once to match
X     * the host name, and once for matching the address.
X     */
X
X    if (fp = fopen(table, "r")) {
X	while (!(sv_match && cl_match) && fgets(sv_list, sizeof(sv_list), fp)) {
X	    if (sv_list[end = strlen(sv_list) - 1] != '\n') {
X		syslog(LOG_ERR, "%s: missing newline or line too long", table);
X		continue;
X	    } else {
X		sv_list[end] = '\0';		/* strip trailing newline */
X	    }
X	    if (sv_list[0] == '#')		/* skip comments */
X		continue;
X	    if ((cl_list = strchr(sv_list, ':')) == 0) {
X		syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
X		continue;
X	    }
X	    *cl_list++ = '\0';			/* split 1st and 2nd fields */
X	    if ((sh_cmd = strchr(cl_list, ':')) != 0)
X		*sh_cmd++ = '\0';		/* split 2nd and 3rd fields */
X	    list_split(sv_list, argv);
X	    if ((sv_match = list_match(argv, daemon)) != 0) {
X		list_split(cl_list, argv);
X		if (client->name[0] == 0
X		    || (cl_match = list_match(argv, client->name)) == 0)
X		    cl_match = list_match(argv, client->addr);
X	    }
X	}
X	(void) fclose(fp);
X    }
X    match = (sv_match == YES && cl_match == YES);
X    if (match && sh_cmd)
X	shell_cmd(sh_cmd, daemon, client);
X    return (match);
X}
X
X/* list_split - destructively convert string to array of character pointers */
X
Xstatic void list_split(string, argv)
Xregister char *string;
Xregister char **argv;
X{
X    for (*argv = strtok(string, sep); *argv; *++argv = strtok((char *) 0, sep))
X	 /* void */ ;
X}
X
X/* list_match - match a string against a list of tokens */
X
Xstatic int list_match(list, string)
Xchar  **list;
Xchar   *string;
X{
X    char   *tok;
X    int     tok_len;
X    int     str_len;
X    char   *cut;
X
X    /*
X     * Process tokens one at a time. Return YES if a token has the magic
X     * value "ALL". Return FAIL if the token is "FAIL". If the token starts
X     * with a "." (domain name), return YES if it matches the last fields of
X     * the string. If the token has the magic value "LOCAL", return YES if
X     * the string does not contain a "." character. If the token ends on a
X     * "." (network number), return YES if it matches the first fields of the
X     * string. If the token begins with a "@" (netgroup name), return YES if
X     * the string is a (host) member of the netgroup. Return YES if the token
X     * fully matches the string. If the token is a netnumber/netmask pair,
X     * return YES if the address is a member of the specified subnet.
X     */
X
X    for (tok = *list; tok; tok = *++list) {
X	if (tok[0] == '.') {			/* domain: match last fields */
X	    if ((str_len = strlen(string)) > (tok_len = strlen(tok))
X		&& strcasecmp(tok, string + str_len - tok_len) == 0)
X		return (YES);
X#ifdef	NETGROUP
X	} else if (tok[0] == '@') {		/* netgroup: look it up */
X	    if (!isdigit(string[0])
X		&& innetgr(tok + 1, string, (char *) 0, (char *) 0))
X		return (YES);
X#endif
X	} else if (strcasecmp(tok, "ALL") == 0) {	/* all: match any */
X	    return (YES);
X	} else if (strcasecmp(tok, "FAIL") == 0) {	/* fail: match any */
X	    return (FAIL);
X	} else if (strcasecmp(tok, "LOCAL") == 0) {	/* local: no dots */
X	    if (strchr(string, '.') == 0 && strcasecmp(string, "unknown") != 0)
X		return (YES);
X	} else if (!strcasecmp(tok, string)) {	/* match host name or address */
X	    return (YES);
X	} else if (tok[(tok_len = strlen(tok)) - 1] == '.') {	/* network */
X	    if (strncmp(tok, string, tok_len) == 0)
X		return (YES);
X	} else if ((cut = strchr(tok, '/')) != 0) {	/* netnumber/netmask */
X	    if (isdigit(string[0]) && masked_match(tok, cut, string))
X		return (YES);
X	}
X    }
X    return (NO);
X}
X
X/* masked_match - match address against netnumber/netmask */
X
Xstatic int masked_match(tok, slash, string)
Xchar   *tok;
Xchar   *slash;
Xchar   *string;
X{
X    unsigned long net;
X    unsigned long mask;
X    unsigned long addr;
X
X    if ((addr = inet_addr(string)) == INADDR_NONE)
X	return (NO);
X    *slash = 0;
X    net = inet_addr(tok);
X    *slash = '/';
X    if (net == INADDR_NONE || (mask = inet_addr(slash + 1)) == INADDR_NONE) {
X	syslog(LOG_ERR, "bad net/mask access control: %s", tok);
X	return (NO);
X    }
X    return ((addr & mask) == net);
X}
END_OF_hosts_access.c
if test 7329 -ne `wc -c <hosts_access.c`; then
    echo shar: \"hosts_access.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f shell_cmd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"shell_cmd.c\"
else
echo shar: Extracting \"shell_cmd.c\" \(2608 characters\)
sed "s/^X//" >shell_cmd.c <<'END_OF_shell_cmd.c'
X /*
X  * shell_cmd() takes a shell command template and performs %a (host
X  * address), %c (client info), %h (host name or address), %d (daemon name),
X  * %p (process id) and %u (user name) substitutions. The result is executed
X  * by a /bin/sh child process, with standard input, standard output and
X  * standard error connected to /dev/null.
X  * 
X  * Diagnostics are reported through syslog(3).
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) shell_cmd.c 1.2 92/06/11 22:21:28";
X#endif
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <stdio.h>
X#include <syslog.h>
X
Xextern char *strncpy();
Xextern void closelog();
Xextern void exit();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Forward declarations. */
X
Xstatic void do_child();
X
X/* shell_cmd - expand %<char> sequences and execute shell command */
X
Xvoid    shell_cmd(string, daemon, client)
Xchar   *string;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    char    cmd[BUFSIZ];
X    int     child_pid;
X    int     wait_pid;
X    int     daemon_pid = getpid();
X
X    /*
X     * Most of the work is done within the child process, to minimize the
X     * risk of damage to the parent.
X     */
X
X    switch (child_pid = fork()) {
X    case -1:					/* error */
X	syslog(LOG_ERR, "fork: %m");
X	break;
X    case 00:					/* child */
X	percent_x(cmd, sizeof(cmd), string, daemon, client, daemon_pid);
X	do_child(daemon, cmd);
X	/* NOTREACHED */
X    default:					/* parent */
X	while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
X	     /* void */ ;
X    }
X}
X
X/* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
X
Xstatic void do_child(myname, command)
Xchar   *myname;
Xchar   *command;
X{
X    char   *error = 0;
X    int     tmp_fd;
X
X    /*
X     * Close a bunch of file descriptors. The Ultrix inetd only passes stdin,
X     * but other inetd implementations set up stdout as well. Ignore errors.
X     */
X
X    closelog();
X    for (tmp_fd = 0; tmp_fd < 10; tmp_fd++)
X	(void) close(tmp_fd);
X
X    /* Set up new stdin, stdout, stderr, and exec the shell command. */
X
X    if (open("/dev/null", 2) != 0) {
X	error = "open /dev/null: %m";
X    } else if (dup(0) != 1 || dup(0) != 2) {
X	error = "dup: %m";
X    } else {
X	(void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
X	error = "execl /bin/sh: %m";
X    }
X
X    /* We can reach the following code only if there was an error. */
X
X#ifdef LOG_MAIL
X    (void) openlog(myname, LOG_PID, FACILITY);
X#else
X    (void) openlog(myname, LOG_PID);
X#endif
X    syslog(LOG_ERR, error);
X    exit(0);
X}
END_OF_shell_cmd.c
if test 2608 -ne `wc -c <shell_cmd.c`; then
    echo shar: \"shell_cmd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f log_tcp.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"log_tcp.h\"
else
echo shar: Extracting \"log_tcp.h\" \(1400 characters\)
sed "s/^X//" >log_tcp.h <<'END_OF_log_tcp.h'
X/* @(#) log_tcp.h 1.2 92/06/11 22:21:30 */
X
X/* Location of the access control files. */
X
X#define HOSTS_ALLOW	"/etc/hosts.allow"
X#define HOSTS_DENY	"/etc/hosts.deny"
X
X /*
X  * Structure filled in by the fromhost() routine. Prerequisites:
X  * <sys/types.h> and <sys/param.h>.
X  */
X
X#ifndef MAXHOSTNAMELEN
X#define MAXHOSTNAMELEN	1024		/* string with host name */
X#endif
X
X#define FROM_ADDRLEN	(4*3+3+1)	/* string with IP address */
X
Xstruct from_host {
X    int     sock_type;			/* socket type, see below */
X    char   *name;			/* host name */
X    char   *addr;			/* host address */
X    char   *user;			/* user name */
X};
X
X#define FROM_UNKNOWN	"unknown"	/* name or address lookup failed */
X#define FROM_HOST(f) \
X    (((f)->name[0] && strcmp((f)->name, FROM_UNKNOWN)) ? (f)->name : (f)->addr)
X
X/* Socket types: 0 means unknown. */
X
X#define FROM_CONNECTED		1	/* connection-oriented */
X#define FROM_UNCONNECTED	2	/* non connection-oriented */
X
X/* Global functions. */
X
Xextern int fromhost();			/* get/validate remote host info */
Xextern int hosts_access();		/* access control */
Xextern void refuse();			/* refuse request */
Xextern void shell_cmd();		/* execute shell command */
Xextern void percent_x();		/* do %<char> expansion */
Xextern char *rfc931_name();		/* remote name from RFC 931 daemon */
Xextern char *hosts_info();		/* show origin of connection */
Xextern void clean_exit();		/* clean up and exit */
END_OF_log_tcp.h
if test 1400 -ne `wc -c <log_tcp.h`; then
    echo shar: \"log_tcp.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f try.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"try.c\"
else
echo shar: Extracting \"try.c\" \(2553 characters\)
sed "s/^X//" >try.c <<'END_OF_try.c'
X /*
X  * try - program to try out host access-control tables, including the
X  * optional shell commands.
X  * 
X  * usage: try process_name host_name_or_address
X  * 
X  * where process_name is a daemon process name (argv[0] value). If a host name
X  * is specified, both the name and address will be used to check the address
X  * control tables. If a host address is specified, the program pretends that
X  * host name lookup failed.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) try.c 1.2 92/06/11 22:21:32";
X#endif
X
X#include <sys/types.h>
X#include <netinet/in.h>
X#include <arpa/inet.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X
X#ifdef HOSTS_ACCESS
X
X#ifndef	INADDR_NONE
X#define	INADDR_NONE	(-1)		/* XXX should be 0xffffffff */
X#endif
X
X#include "log_tcp.h"
X
X/* Try out a (daemon,client) pair */
X
Xtry(daemon, name, addr)
Xchar   *daemon;
Xchar   *name;
Xchar   *addr;
X{
X    printf("daemon %s: host name %s (address %s): ",
X	   daemon, name, addr);
X    printf("access %s\n",
X	   hosts_ctl(daemon, name, addr, "you") ? "granted" : "denied");
X}
X
X/* function to intercept the real shell_cmd() */
X
Xvoid    shell_cmd(cmd, daemon, client)
Xchar   *cmd;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    char    buf[BUFSIZ];
X    int     pid = getpid();
X
X    percent_x(buf, sizeof(buf), cmd, daemon, client, pid);
X    printf("shell command: %s: ", buf);
X}
X
X/* function to intercept the real process_options() */
X
Xprocess_options(options, daemon, client)
Xchar   *options;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    char    buf[BUFSIZ];
X    int     pid = getpid();
X
X    percent_x(buf, sizeof(buf), options, daemon, client, pid);
X    printf("options: %s: ", buf);
X}
X
Xmain(argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    struct hostent *hp;
X
X#ifdef LOG_MAIL
X    openlog(argv[0], LOG_PID, FACILITY);
X#else
X    openlog(argv[0], LOG_PID);
X#endif
X
X    if (argc != 3) {
X	fprintf(stderr, "usage: %s process_name host_name_or_address\n",
X		argv[0]);
X	return (1);
X    } else {
X	if (inet_addr(argv[2]) != INADDR_NONE) {/* pretend host name unknown */
X	    try(argv[1], FROM_UNKNOWN, argv[2]);
X	} else {
X	    if ((hp = gethostbyname(argv[2])) == 0) {	/* bad host name */
X		fprintf(stderr, "warning: host unknown: %s\n", argv[2]);
X		try(argv[1], argv[2], "?.?.?.?");
X	    } else {				/* use both name and address */
X		while (hp->h_addr_list[0])
X		    try(argv[1], hp->h_name,
X			inet_ntoa(*(struct in_addr *) * hp->h_addr_list++));
X	    }
X	}
X	return (0);
X    }
X}
X
X#else
X
Xmain()
X{
X    fprintf(stderr, "host access control is not enabled.\n");
X    return (1);
X}
X
X#endif
END_OF_try.c
if test 2553 -ne `wc -c <try.c`; then
    echo shar: \"try.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f refuse.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"refuse.c\"
else
echo shar: Extracting \"refuse.c\" \(737 characters\)
sed "s/^X//" >refuse.c <<'END_OF_refuse.c'
X /*
X  * refuse() reports a refused connection, and takes the consequences: in
X  * case of a datagram-oriented service, the unread datagram is taken from
X  * the input queue (or inetd would see the same datagram again and again);
X  * the program is terminated.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) refuse.c 1.2 92/06/11 22:21:34";
X#endif
X
X/* System libraries. */
X
X#include <syslog.h>
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* refuse - refuse request from bad host */
X
Xvoid    refuse(client)
Xstruct from_host *client;
X{
X    syslog(LOG_WARNING, "refused connect from %s", hosts_info(client));
X    clean_exit(client);
X    /* NOTREACHED */
X}
END_OF_refuse.c
if test 737 -ne `wc -c <refuse.c`; then
    echo shar: \"refuse.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(5800 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# @(#) Makefile 1.5 92/06/11 22:21:35
X
X##############################
X## Begin configuration options
X
X# By default, logfile entries are written to the same file as used for
X# sendmail transaction logs. Change the definition of the following macro
X# if you disagree. See `man 3 syslog' for examples. Some syslog versions
X# do not provide this flexibility.
X
XFACILITY= LOG_MAIL
X
X# To disable host access control, comment out the following macro definition.
X# Note: host access control requires the strtok() and strchr() routines.
X# Host access control can also be turned off by providing no access control
X# tables.
X
XACCESS	= -DHOSTS_ACCESS
X
X# Disable the following macro definition if you wish to talk to hosts that
X# pretend to have someone elses host name. Doing so is a bad idea if you run
X# services whose authentication relies on host names, such as rlogin or rsh.
X
XPARANOID= -DPARANOID
X
X# If your system supports NIS or YP-style netgroups, enable the following
X# macro definition.
X
XNETGROUP= -DNETGROUP
X
X# Enable the following definition if the front ends should attempt to get
X# the remote user name. This works only if the remote host runs a daemon
X# that supports the RFC 931 protocol. Remote user name lookups will not
X# work for UDP-based connections, and will cause noticeable delays with
X# connections from PCs.
X
X#AUTH	= -DRFC931
X
X# On many systems, network daemons and other system processes are started
X# with a zero umask value, so that world-writable files may be produced.
X# It is a good idea to edit your /etc/rc* files so that they begin with
X# an explicit umask setting.  On our site we use 022 because it does not
X# break anything yet gives adequate protection against tampering.
X# 
X# The following macro specifies the default umask for daemons run under
X# control of the daemon front ends. Comment it out only if you are sure
X# that inetd and its children are started with a sane umask value.
X
XUMASK	= -DDAEMON_UMASK=022
X
X# Some versions of Apollo or SYSV.4 UNIX have a bug in the getpeername(2)
X# routine.  You have this bug if the front end reports that all UDP
X# connections come from address 0.0.0.0. Compile with -DGETPEERNAME_BUG
X# for a workaround. The workaround does no harm on other systems. If in
X# doubt, leave it in.
X
XBUGS	= -DGETPEERNAME_BUG
X
X# Apollo Domain/OS offers both bsd and sys5 environments, sometimes
X# on the same machine.  If your Apollo is primarily sys5.3 and also
X# has bsd4.3, enable the following to build under bsd and run under
X# either environment.
X
X#SYSTYPE=  -A run,any -A sys,any
X
X# Some C compilers (Ultrix 4.x) insist that ranlib(1) be run on an object
X# library; some don't care as long as the modules are in the right order;
X# some systems don't even have a ranlib(1) command. Make your choice.
X
XRANLIB	= ranlib	# use ranlib
X#RANLIB	= echo		# no ranlib
X
X# If your C library does not have memcmp(3), compile with -Dmemcmp=bcmp.
X
XCFLAGS	= -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
X	$(BUGS) $(SYSTYPE) $(AUTH) $(UMASK)
X
X# Include the file strcasecmp.o if strcasecmp() is not provided by your C
X# library.  The strcasecmp.c file provided with this package comes from
X# 43BSD UNIX.  You may have to add -Du_char="unsigned char" to the CFLAGS
X# macro above.
X
XAUX_OBJ	= # strcasecmp.o
X
X# Some System-V versions require that you explicitly specify the networking
X# libraries (for example, -lnet or -linet).
X
XLIBS	= # -lnet -lsyslog -ldbm
X
X# Ultrix users may want to use the miscd front end, too. The Ultrix miscd
X# implements among others the SYSTAT service which runs the WHO command,
X# and thus provides a subset of the finger service. The very first front
X# end application was to monitor the use of SYSTAT.
X
Xall:	tcpd try # miscd
X
X## End configuration options
X############################
X
XLIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o hosts_info.o \
X	hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ)
X
XKIT	= README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \
X	log_tcp.h try.c refuse.c Makefile hosts_access.5 strcasecmp.c BLURB \
X	rfc931.c tcpd.8 hosts_info.c hosts_access.3 hosts_ctl.c percent_x.c \
X	options.c clean_exit.c rfc931_option
X
XLIB	= libwrap.a
X
X$(LIB):	$(LIB_OBJ)
X	rm -f $(LIB)
X	ar rv $(LIB) $(LIB_OBJ)
X	$(RANLIB) $(LIB)
X
Xtcpd:	tcpd.o fromhost.o $(LIB)
X	$(CC) $(CFLAGS) -o $@ tcpd.o fromhost.o $(LIB)
X
Xmiscd:	miscd.o fromhost.o $(LIB)
X	$(CC) $(CFLAGS) -o $@ miscd.o fromhost.o $(LIB)
X
Xtry:	try.o $(LIB)
X	$(CC) $(CFLAGS) -o $@ try.o $(LIB)
X
Xfromhost: fromhost.c log_tcp.h Makefile $(LIB)
X	$(CC) $(CFLAGS) -DTEST -o fromhost fromhost.c $(LIB)
X	rm -f fromhost.o
X
Xshar:	
X	@shar $(KIT)
X
Xkit:
X	@makekit $(KIT)
X
Xarchive:
X	$(ARCHIVE) $(KIT)
X
Xclean:
X	rm -f tcpd miscd try fromhost *.[oa] core
X
X# Enable all bells and whistles for linting.
X
Xlint: tcpd_lint miscd_lint try_lint
X
Xtcpd_lint:
X	lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
X	-DGETPEERNAME_BUG -DRFC931 -DDAEMON_UMASK=022 tcpd.c fromhost.c \
X	hosts_access.c shell_cmd.c refuse.c rfc931.c hosts_info.c percent_x.c \
X	clean_exit.c
X
Xmiscd_lint:
X	lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DPARANOID -DNETGROUP \
X	-DGETPEERNAME_BUG -DRFC931 -DDAEMON_UMASK=022 miscd.c fromhost.c \
X	hosts_access.c shell_cmd.c refuse.c rfc931.c hosts_info.c percent_x.c \
X	clean_exit.c
X
Xtry_lint:
X	lint -DFACILITY=LOG_MAIL -DHOSTS_ACCESS -DNETGROUP try.c \
X	hosts_ctl.c hosts_access.c hosts_info.c percent_x.c
X
X# Compilation dependencies.
X
Xclean_exit.o: log_tcp.h Makefile
Xfromhost.o: log_tcp.h Makefile
Xhosts_access.o: log_tcp.h Makefile
Xhosts_ctl.o: log_tcp.h Makefile
Xhosts_info.o: log_tcp.h Makefile
Xmiscd.o: log_tcp.h Makefile
Xoptions.o: log_tcp.h Makefile
Xpercent_x.o: log_tcp.h Makefile
Xrefuse.o: log_tcp.h Makefile
Xrfc931.o: log_tcp.h Makefile
Xshell_cmd.o: log_tcp.h Makefile
Xtcpd.o: log_tcp.h Makefile
Xtry.o: log_tcp.h Makefile
END_OF_Makefile
if test 5800 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_access.5 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hosts_access.5\"
else
echo shar: Extracting \"hosts_access.5\" \(7619 characters\)
sed "s/^X//" >hosts_access.5 <<'END_OF_hosts_access.5'
X.TH HOSTS_ACCESS 5
X.SH NAME
Xhosts_access \- format of host access control files
X.SH DESCRIPTION
XThis manual page describes a simple access control language that is
Xbased on host (or domain) names, netgroups, internet addresses (or
Xnetwork numbers) and on network daemon process names. Examples are
Xgiven at the end.
X.PP
XIn the following text, \fIdaemon\fR is the the process name (argv[0]
Xvalue) of a network daemon process, and \fIclient\fR is the name and/or
Xaddress of a remote host.
X.SH ACCESS CONTROL FILES
XThe access control software consults two files:
X.IP o
XAccess will be granted when a (daemon,client) pair matches an entry in
Xthe \fI/etc/hosts.allow\fR file.
X.IP o
XOtherwise, access will be denied when a (daemon,client) pair matches an
Xentry in the \fI/etc/hosts.deny\fR file.
X.IP o
XOtherwise, access will be granted.
X.PP
XA non-existing access control file is treated as if it were an empty
Xfile. Thus, access control can be turned off by providing no access
Xcontrol files.
X.SH ACCESS CONTROL RULES
XEach access control file consists of zero or more lines of text.  These
Xlines are processed in order of apperance. The search terminates when a
Xmatch is found.
X.IP o
XLines that begin with a `#\' character are ignored.
X.IP o
XAll other lines should satisfy the following format, things between []
Xbeing optional:
X.sp
X.ti +3
Xdaemon_list : client_list [ : shell_command ]
X.PP
X\fIdaemon_list\fR is a list of one or more daemon process names
X(argv[0] values) or wildcards (see below).  
X.PP
X\fIclient_list\fR is a list
Xof one or more host names, host addresses, patterns or wildcards (see
Xbelow) that will be matched against the remote host name or address.
X.PP
XList elements should be separated by blanks and/or commas.  
X.PP
XWith the exception of netgroup lookups, all access control checks are
Xcase insensitive.
X.br
X.ne 4
X.SH PATTERNS
XThe access control language implements the following patterns:
X.IP o
XA string that begins with a `.\' character.  A client name or address
Xis matched if its last components match the specified pattern.  For
Xexample, the pattern `.tue.nl\' matches the host name
X`wzv.win.tue.nl\'.
X.IP o
XA string that ends with a `.\' character.  A client name or address is
Xmatched if its first fields match the given string.  For example, the
Xpattern `131.155.\' matches the address of (almost) every host on the
XEind\%hoven University network (131.155.x.x).
X.IP o
XA string that begins with a `@\' character is treated as a netgroup
Xname.  Netgroups are usually supported on systems with NIS (formerly
XYP) data bases. A client host name is matched if it is a (host) member
Xof the specified netgroup.
X.IP o
XAn expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
X`net/mask\' pair. A client address is matched if `net\' is equal to the
Xbitwise AND of the address and the `mask\'. For example, the net/mask
Xpattern `131.155.72.0/255.255.254.0\' matches every address in the
Xrange `131.155.72.0\' through `131.155.73.255\'.
X.SH WILDCARDS
XThe access control language supports explicit wildcards:
X.IP ALL
XIf this token appears in a daemon_list, it matches all network daemon
Xprocess names.  If the ALL token appears in a client_list, it matches
Xall client names and addresses.
X.IP LOCAL
XMatches any string that does not contain a dot character.
XTypical use is in client_lists.
X.IP UNKNOWN
XMatches any host whose name and/or address lookup failed.  Should be
Xused with care, because host names may also be unavailable due to
Xtemporary name server problems.
X.IP FAIL
XLike the ALL wildcard, but causes the software to pretend that the scan
Xof the current access control table fails. This is useful to avoid
Xunwanted matches with later entries in the same access control table.
X.br
X.ne 6
X.SH SHELL COMMANDS
XIf the first-matched access control rule contains a shell command, that
Xcommand is subjected to the following subsitutions:
X.IP %a
Xexpands to the remote host address.
X.IP %c
Xexpands to client information: user@host, user@address, a host name, or
Xjust an address, depending on how much information is available.
X.IP %h
Xexpands to the remote host name (or address, if the host name is
Xunavailable).
X.IP %d
Xexpands to the daemon process name (argv[0] value).
X.IP %p
Xexpands to the daemon process id.
X.IP %u
Xexpands to the remote user name.
X.IP %%
Xexpands to a single `%\' character.
X.PP
XThe result is executed by a \fI/bin/sh\fR child process with standard
Xinput, output and error connected to \fI/dev/null\fR.  Specify an `&\'
Xat the end of the command if you do not want to wait until it has
Xcompleted.
X.PP
XShell commands should not rely on the PATH setting of the inetd.
XInstead, they should use absolute path names, or they should begin with
Xan explicit PATH=whatever statement.
X.SH EXAMPLES
XThe following example restricts services to hosts within the local
Xdomain (no `.\' character in the host name), 
Xall hosts below the \fI.some.domain\fR, and all hosts in the
X\fIsome_netgroup\fR netgroup:
X.PP
X.ne 2
X/etc/hosts.allow: 
X.in +3
XALL: LOCAL, .some.domain, @some_netgroup
X.PP
X.ne 2
X/etc/hosts.deny: 
X.in +3
XALL: ALL
X.PP
X.ne 4
XThe following fragment matches any host below .some.domain, with the
Xexception of hosts below .sub.some.domain:
X.PP
X.ne 2
X.in +3
XFAIL: .sub.some.domain 
X.br
XALL: .some.domain
X.PP
X.ne 8
XIn order to deny some hosts all services, except ftp:
X.PP
X/etc/hosts.allow: 
X.in +3
Xin.ftpd: ALL
X.PP
X/etc/hosts.deny: 
X.in +3
XALL: some.host.name, .some.domain
X.PP
XThe example can be improved a little by including address and/or
Xnetwork/netmask information, so that there is no way to "sneak in" when
Xhost names are temporarily unavailable.
X.PP
XThe last example performs a reverse finger whenever someone invokes
Xthe tftp service from outside the local domain. The result is mailed
Xto root:
X.PP
X.ne 2
X/etc/hosts.allow:
X.in +3
X.nf
Xin.tftpd: LOCAL, .my.domain
X.PP
X.ne 2
X/etc/hosts.deny:
X.in +3
X.nf
Xin.tftpd: ALL: /usr/ucb/finger -l @%h | /usr/ucb/mail -s %d-%h root &
X.fi
X.PP
XOn network firewall systems this trick can be carried even further.
XThe typical network firewall only provides a limited set of services to
Xthe outer world. All other services can be "bugged" just like the above
Xtftp example. The result is an excellent early-warning system.
X.SH DIAGNOSTICS
XAn error is reported when a syntax error is found in a host access
Xcontrol rule; when the length of access control rule exceeds the STDIO
Xbuffer size; when an access control rule is not terminated by a newline
Xcharacter; when the result of %<character> expansion would overflow an
Xinternal buffer; when a system call fails that shouldn\'t.  All
Xproblems are reported via the syslog daemon.
X.SH FILES
X.na
X.nf
X/etc/hosts.allow, (daemon,client) pairs that are granted access.
X/etc/hosts.deny, (daemon,client) pairs that are denied access.
X.ad
X.fi
X.SH BUGS
XIf a name server lookup times out, the host name will not be available
Xto the access control software, even though the host is registered.
X.PP
XDomain name server lookups are case insensitive; NIS (formerly YP)
Xnetgroup lookups are case sensitive.
X.PP
XSome UDP (and RPC) daemons linger around for a while after they have
Xserviced a request, in case another request comes in. In the inetd
Xconfiguration file, these daemons are registered with the `wait\'
Xoption.  Access control will apply only to the request that started
Xsuch a daemon. This restriction does not apply to connection-oriented
X(TCP) services.
X.SH AUTHOR
X.na
X.nf
XWietse Venema (wietse@wzv.win.tue.nl)
XDepartment of Mathematics and Computing Science
XEindhoven University of Technology
XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X\" @(#) hosts_access.5 1.9 92/06/11 22:21:37
END_OF_hosts_access.5
if test 7619 -ne `wc -c <hosts_access.5`; then
    echo shar: \"hosts_access.5\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f strcasecmp.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"strcasecmp.c\"
else
echo shar: Extracting \"strcasecmp.c\" \(3767 characters\)
sed "s/^X//" >strcasecmp.c <<'END_OF_strcasecmp.c'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strcasecmp.c	5.6 (Berkeley) 6/27/88";
X#endif /* LIBC_SCCS and not lint */
X
X#include <sys/types.h>
X
X/*
X * This array is designed for mapping upper and lower case letter
X * together for a case independent comparison.  The mappings are
X * based upon ascii character sequences.
X */
Xstatic u_char charmap[] = {
X	'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
X	'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
X	'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
X	'\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
X	'\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
X	'\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
X	'\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
X	'\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
X	'\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
X	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
X	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
X	'\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
X	'\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
X	'\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
X	'\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
X	'\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
X	'\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
X	'\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
X	'\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
X	'\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
X	'\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
X	'\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
X	'\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
X	'\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
X	'\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
X	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
X	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
X	'\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
X	'\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
X	'\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
X	'\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
X	'\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
X};
X
Xstrcasecmp(s1, s2)
X	char *s1, *s2;
X{
X	register u_char	*cm = charmap,
X			*us1 = (u_char *)s1,
X			*us2 = (u_char *)s2;
X
X	while (cm[*us1] == cm[*us2++])
X		if (*us1++ == '\0')
X			return(0);
X	return(cm[*us1] - cm[*--us2]);
X}
X
Xstrncasecmp(s1, s2, n)
X	char *s1, *s2;
X	register int n;
X{
X	register u_char	*cm = charmap,
X			*us1 = (u_char *)s1,
X			*us2 = (u_char *)s2;
X
X	while (--n >= 0 && cm[*us1] == cm[*us2++])
X		if (*us1++ == '\0')
X			return(0);
X	return(n < 0 ? 0 : cm[*us1] - cm[*--us2]);
X}
END_OF_strcasecmp.c
if test 3767 -ne `wc -c <strcasecmp.c`; then
    echo shar: \"strcasecmp.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f BLURB -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"BLURB\"
else
echo shar: Extracting \"BLURB\" \(1635 characters\)
sed "s/^X//" >BLURB <<'END_OF_BLURB'
X@(#) BLURB 1.5 92/06/11 22:21:40
X
XThis package provides a couple of tiny programs that monitor incoming
Xrequests for IP services such as TFTP, EXEC, FTP, RSH, TELNET, RLOGIN,
XFINGER, SYSTAT, and many others.
X
XOptional features are: access control based on pattern matching; remote
Xusername lookup using the RFC 931 protocol; protection against rsh and
Xrlogin attacks from hosts that pretend to have someone elses name.
X
XThe programs can be installed without requiring any changes to existing
Xsoftware or configuration files. By default, they just log the remote
Xhost name and then invoke the real network daemon. No information is
Xexchanged with the remote client process.
X
XEnhancements over the previous release are: 
X
X    1 - network daemons no longer have to live within a common directory
X    2 - the access control code now uses both the host address and name
X    3 - an access control pattern that supports netmasks
X    4 - additional protection against forged host names
X    5 - a pattern that matches hosts whose name or address lookup fails
X    6 - an operator that prevents hosts or services from being matched
X    7 - optional remote username lookup with the RFC 931 protocol
X    8 - an optional umask to prevent the creation of world-writable files
X    9 - hooks for access control language extensions
X   10 - last but not least, thoroughly revised documentation.
X
XExcept for the change described under (2) the present version should be
Xbackwards compatible with earlier ones.
X
X	Wietse Venema (wietse@wzv.win.tue.nl),
X	Department of Mathematics and Computing Science,
X	Eindhoven University of Technology,
X	The Netherlands.
END_OF_BLURB
if test 1635 -ne `wc -c <BLURB`; then
    echo shar: \"BLURB\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rfc931.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rfc931.c\"
else
echo shar: Extracting \"rfc931.c\" \(2664 characters\)
sed "s/^X//" >rfc931.c <<'END_OF_rfc931.c'
X /*
X  * rfc931_user() consults the RFC 931 daemon on the client host to look up
X  * the remote user name.
X  * 
X  * Diagnostics are reported through syslog(3).
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  * 
X  * Inspired by the authutil package (comp.sources.unix volume 22) by Dan
X  * Bernstein (brnstnd@kramden.acf.nyu.edu).
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) rfc931.c 1.2 92/06/22 16:32:14";
X#endif
X
X#include <stdio.h>
X#include <syslog.h>
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <setjmp.h>
X#include <signal.h>
X
X#include "log_tcp.h"
X
X#define	RFC931_PORT	113		/* Semi-well-known port */
X#define	TIMEOUT		10		/* wait for at most 10 seconds */
X
Xextern char *strchr();
X
Xstatic jmp_buf timebuf;
X
X/* timeout - handle timeouts */
X
Xstatic void timeout(sig)
Xint     sig;
X{
X    longjmp(timebuf, sig);
X}
X
X/* rfc931_name - return remote user name */
X
Xchar   *rfc931_name(there)
Xstruct sockaddr_in *there;		/* remote link information */
X{
X    struct sockaddr_in here;		/* local link information */
X    struct sockaddr_in sin;		/* for talking to RFC931 daemon */
X    int     length;
X    int     s;
X    unsigned remote;
X    unsigned local;
X    static char user[256];		/* XXX */
X    FILE   *fp;
X    char   *cp;
X    char   *result = FROM_UNKNOWN;
X
X    /* Find out local port number of our stdin. */
X
X    length = sizeof(here);
X    if (getsockname(0, (struct sockaddr *) & here, &length) == -1) {
X	syslog(LOG_ERR, "getsockname: %m");
X	return (result);
X    }
X    /* Set up timer so we won't get stuck. */
X
X    if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1)
X	return (result);
X    signal(SIGALRM, timeout);
X    if (setjmp(timebuf)) {
X	close(s);				/* not: fclose(fp) */
X	return (result);
X    }
X    alarm(TIMEOUT);
X
X    /* Connect to the RFC931 daemon. */
X
X    sin = *there;
X    sin.sin_port = htons(RFC931_PORT);
X    if (connect(s, (struct sockaddr *) & sin, sizeof(sin)) == -1
X	|| (fp = fdopen(s, "w+")) == 0) {
X	close(s);
X	alarm(0);
X	return (result);
X    }
X    /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */
X
X    fprintf(fp, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port));
X    fflush(fp);
X
X    /* Read response. Kill stdio buffer or we may read back our own query. */
X
X    setbuf(fp, (char *) 0);
X    if (fscanf(fp, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, user) == 3
X	&& ferror(fp) == 0 && feof(fp) == 0
X	&& ntohs(there->sin_port) == remote
X	&& ntohs(here.sin_port) == local) {
X	/* Strip trailing carriage return. */
X
X	if (cp = strchr(user, '\r'))
X	    *cp = 0;
X	result = user;
X    }
X    alarm(0);
X    fclose(fp);
X    return (result);
X}
END_OF_rfc931.c
if test 2664 -ne `wc -c <rfc931.c`; then
    echo shar: \"rfc931.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tcpd.8 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tcpd.8\"
else
echo shar: Extracting \"tcpd.8\" \(4928 characters\)
sed "s/^X//" >tcpd.8 <<'END_OF_tcpd.8'
X.TH TCPD 8
X.SH NAME
Xtcpd \- access control facility for internet services
X.SH SYNOPSIS
X.B /some/where/tcpd [arguments]
X.SH DESCRIPTION
X.PP
XThe \fItcpd\fR program can be set up to monitor incoming requests for
X\fItelnet\fR, \fIfinger\fR, \fIftp\fR, \fIexec\fR, \fIrsh\fR,
X\fIrlogin\fR, \fItftp\fR, \fItalk\fR, \fIspray\fR, \fIrusers\fR,
X\fIcomsat\fR and other services that have a one-to-one mapping onto
Xexecutable files.
X.PP
XOptional features are:  access control based on pattern matching,
Xremote username lookups with the RFC 931 protocol, and protection
Xagainst hosts that pretend to have someone elses host name.
X.PP
XRequirements are: network daemons should be launched on-demand, e.g. by
Xa central process such as the \fIinetd\fR; a syslog(3)-like interface.
X.SH LOGGING
XConnections that are monitored by
X.I tcpd
Xare reported through the \fIsyslog\fR(3) facility. Each record contains
Xa time stamp, the remote host name and the name of the service
Xrequested. The information can be useful to detect unwanted activities,
Xespecially when logfile information from several hosts is merged.
X.SH ACCESS CONTROL
XOptionally,
X.I tcpd
Xsupports a simple form of access control that is based on pattern
Xmatching.  The access-control software provides hooks for the execution
Xof shell commands when a pattern fires.  For details, see the
X\fIhosts_access\fR(5) manual page.
X.SH HOST NAME VERIFICATION
XThe authentication scheme of some protocols (\fIrlogin, rsh\fR) relies
Xon host names. Some implementations believe the host name that they get
Xfrom any random name server; other implementations are more careful but
Xuse a flawed algorithm.
X.PP
X.I tcpd
Xverifies the remote host name that is returned by the DNS server
Xresponsible for the address->name mapping, by looking at the host name
Xand address that are returned by the DNS server responsible for the
Xname->address mapping. If any discrepancy is detected,
X.I tcpd
Xconcludes that it is dealing with a host that pretends to have someone
Xelses host name.
X.PP
XIf the sources are compiled with the \*QPARANOID\*U option,
X.I tcpd
Xwill drop the connection in case of a host name/address mismatch.
XOtherwise,
X.I tcpd
Xjust pretends that host name lookup failed when logging the connection
Xand consulting the optional access control tables.
X.SH RFC 931
XWhen RFC 931 lookups are enabled (compile-time option) \fItcpd\fR will
Xattempt to establish the name of the remote user. This will succeed
Xonly if the client host runs an RFC 931-compliant daemon.  Remote user
Xname lookups will not work for datagram-oriented connections, and may
Xcause noticeable delays in the case of connections from PCs.
X.SH EXAMPLES
XThe details of using \fItcpd\fR depend on pathname information that was
Xcompiled into the program.
X.SH EXAMPLE 1
XThis example applies when \fItcpd\fR expects that the original network
Xdaemons will be moved to a "secret" place.
X.PP
XIn order to monitor access to the \fIfinger\fR service, move the
Xoriginal finger daemon to the "secret" place and install tcpd in the
Xplace of the original finger daemon. No changes are required to
Xconfiguration files.
X.SH EXAMPLE 2
XThis example applies when \fItcpd\fR expects that the network daemons
Xare left in their original place.
X.PP
XIn order to monitor access to the \fIfinger\fR service, perform the
Xfollowing edits on the \fIinetd\fR configuration file (usually 
X\fI/etc/inetd.conf\fR):
X.nf
X.sp
X.ti +5
Xfinger  stream  tcp  nowait  nobody  /usr/etc/in.fingerd  in.fingerd
X.sp
Xbecomes:
X.sp
X.ti +5
Xfinger  stream  tcp  nowait  nobody  /some/where/tcpd     in.fingerd
X.sp
X.fi
X.PP
XThe example assumes that the network daemons live in /usr/etc.
X.PP
XSimilar changes will be needed for the other services that are to be
Xcovered by \fItcpd\fR.  Send a SIGHUP to the \fIinetd\fR(8) process to
Xmake the changes effective.
X.SH EXAMPLE 3
XIn the case of daemons that do not live in a common directory ("secret"
Xor otherwise), edit the \fIinetd\fR configuration file so that it
Xspecifies an absolute path name for the process name field. For example:
X.nf
X.sp
X    ntalk  dgram  udp  wait  root  /some/where/tcpd  /usr/local/lib/ntalkd
X.sp
X.fi
X.PP
XOnly the last component (ntalkd) of the process name will be used for
Xaccess control and logging.
X.SH BUGS
XSome UDP (and RPC) daemons linger around for a while after they have
Xfinished their work, in case another request comes in.  In the
X\fIinetd\fR configuration file these services are registered with the
X`wait\' option. Only the request that started such a daemon will be
Xlogged. This restriction does not apply to connection-oriented (TCP)
Xservices.
X.SH FILES
X.PP
XThe host access control tables are:
X.PP
X/etc/hosts.allow
X.br
X/etc/hosts.deny
X.SH SEE ALSO
Xhosts_access(5), format of the access control tables.
X.SH AUTHORS
X.na
X.nf
XWietse Venema (wietse@wzv.win.tue.nl),
XDepartment of Mathematics and Computing Science,
XEindhoven University of Technology,
XThe Netherlands.
X\" @(#) tcpd.8 1.1 92/06/11 22:21:43
END_OF_tcpd.8
if test 4928 -ne `wc -c <tcpd.8`; then
    echo shar: \"tcpd.8\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_info.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hosts_info.c\"
else
echo shar: Extracting \"hosts_info.c\" \(788 characters\)
sed "s/^X//" >hosts_info.c <<'END_OF_hosts_info.c'
X /*
X  * hosts_info() returns a string with as much information about the origin
X  * of a connection as we have: the user name, if known, and the host name,
X  * or the host address if the name is not available.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) hosts_info.c 1.1 92/06/11 22:21:44";
X#endif
X
X#include <stdio.h>
X
X#include "log_tcp.h"
X
X/* hosts_info - return string with as much about the client as we know */
X
Xchar   *hosts_info(client)
Xstruct from_host *client;
X{
X    static char buf[BUFSIZ];		/* XXX */
X
X    if (client->user[0] && strcmp(client->user, FROM_UNKNOWN)) {
X	sprintf(buf, "%s@%s", client->user, FROM_HOST(client));
X	return (buf);
X    } else {
X	return (FROM_HOST(client));
X    }
X}
END_OF_hosts_info.c
if test 788 -ne `wc -c <hosts_info.c`; then
    echo shar: \"hosts_info.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_access.3 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hosts_access.3\"
else
echo shar: Extracting \"hosts_access.3\" \(2018 characters\)
sed "s/^X//" >hosts_access.3 <<'END_OF_hosts_access.3'
X.TH HOSTS_ACCESS 3
X.SH
Xhosts_access, hosts_ctl \- access control library
X.SH SYNOPSIS
X.nf
X#include "log_tcp.h"
X
Xint hosts_access(daemon, client)
Xchar *daemon;
Xstruct from_host *client;
X
Xint hosts_ctl(daemon, client_name, client_addr, client_user)
Xchar *daemon;
Xchar *client_host;
Xchar *client_addr;
Xchar *client_user;
X.fi
X.SH DESCRIPTION
XThe routines described in this document are part of the \fIlibwrap.a\fR
Xlibrary. They implement a pattern-based access control language with
Xoptional shell commands that are executed when a pattern fires.
X.PP
XIn all cases, the daemon argument should specify a daemon process name
X(argv[0] value).  The client host address should be a valid address, or
XFROM_UNKNOWN if address lookup failed. The client host name and user
Xname should be empty strings if no information is available,
XFROM_UNKNOWN if lookup failed, or an actual host or user name.
X.PP
Xhosts_access() consults the access control tables described in the
X\fIhosts_access(5)\fR manual page.  If a match is found, an optional
Xshell command is executed and the search terminates. hosts_access()
Xreturns zero if access should be denied.
X.PP
Xhosts_ctl() is a wrapper around the hosts_access() routine with a
Xperhaps more convenient interface.  hosts_ctl() returns zero if access
Xshould be denied.
X.SH DIAGNOSTICS
XProblems are reported via the syslog daemon.
X.SH SEE ALSO
Xhosts_access(5), format of the access control tables.
X.SH FILES
X/etc/hosts.access, /etc/hosts.deny, access control tables.
X.SH BUGS
XThe functions described here do not make copies of their string-valued
Xarguments.  Beware of data from functions that overwrite their results
Xupon each call.
X.sp
Xhosts_access() uses the strtok() library function. This may interfere
Xwith other code that relies on strtok().
X.SH AUTHOR
X.na
X.nf
XWietse Venema (wietse@wzv.win.tue.nl)
XDepartment of Mathematics and Computing Science
XEindhoven University of Technology
XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X\" @(#) hosts_access.3 1.1 92/06/11 22:21:45
END_OF_hosts_access.3
if test 2018 -ne `wc -c <hosts_access.3`; then
    echo shar: \"hosts_access.3\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hosts_ctl.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hosts_ctl.c\"
else
echo shar: Extracting \"hosts_ctl.c\" \(969 characters\)
sed "s/^X//" >hosts_ctl.c <<'END_OF_hosts_ctl.c'
X /*
X  * hosts_ctl() combines the most common applications of the host access
X  * control library. routine. It bundles its arguments into a from_host
X  * structure, then calls the hosts_access() access control checker. The host
X  * name and user name arguments should be empty strings, "unknown" or real
X  * data. if a match is found, the optional shell command is executed.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) hosts_ctl.c 1.1 92/06/11 22:21:48";
X#endif
X
X#include <stdio.h>
X
X#include "log_tcp.h"
X
X/* hosts_ctl - general interface for the hosts_access() routine */
X
Xint     hosts_ctl(daemon, name, addr, user)
Xchar   *daemon;
Xchar   *name;
Xchar   *addr;
Xchar   *user;
X{
X    struct from_host client;
X    static struct from_host zeros;
X
X    client = zeros;
X    client.name = name;
X    client.addr = addr;
X    client.user = user;
X
X    return (hosts_access(daemon, &client));
X}
END_OF_hosts_ctl.c
if test 969 -ne `wc -c <hosts_ctl.c`; then
    echo shar: \"hosts_ctl.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f percent_x.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"percent_x.c\"
else
echo shar: Extracting \"percent_x.c\" \(2134 characters\)
sed "s/^X//" >percent_x.c <<'END_OF_percent_x.c'
X /*
X  * percent_x() takes a string and performs %a (host address), %c (client
X  * info), %h (host name or address), %d (daemon name), %p (process id) and
X  * %u (user name) substitutions. It aborts the program when the result of
X  * expansion would overflow the output buffer.
X  * 
X  * Diagnostics are reported through syslog(3).
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) percent_x.c 1.1 92/06/11 22:21:49";
X#endif
X
X/* System libraries. */
X
X#include <stdio.h>
X#include <syslog.h>
X
Xextern char *strncpy();
Xextern void exit();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* percent_x - do %<char> expansion, abort if result buffer is too small */
X
Xvoid    percent_x(result, result_len, str, daemon, client, pid)
Xchar   *result;
Xint     result_len;
Xchar   *str;
Xchar   *daemon;
Xstruct from_host *client;
Xint     pid;
X{
X    char   *end = result + result_len - 1;	/* end of result buffer */
X    char   *expansion;
X    int     expansion_len;
X    char    pid_buf[10];
X
X    /*
X     * %a becomes the client address; %c all user and host information we
X     * have about the client; %d the daemon process name; %h the client host
X     * name or address; %p the daemon process id; %u the remote user name; %%
X     * becomes a %, and %other is ignored. We terminate with a diagnostic if
X     * we would overflow the result buffer.
X     */
X
X    while (*str) {
X	if (*str == '%') {
X	    str++;
X	    expansion =
X		*str == 'a' ? (str++, client->addr) :
X		*str == 'c' ? (str++, hosts_info(client)) :
X		*str == 'd' ? (str++, daemon) :
X		*str == 'h' ? (str++, FROM_HOST(client)) :
X		*str == 'p' ? (str++, sprintf(pid_buf, "%d", pid), pid_buf) :
X		*str == 'u' ? (str++, client->user) :
X		*str == '%' ? (str++, "%") :
X		*str == 0 ? "" : (str++, "");
X	    expansion_len = strlen(expansion);
X	} else {
X	    expansion = str++;
X	    expansion_len = 1;
X	}
X	if (result + expansion_len >= end) {
X	    syslog(LOG_ERR, "shell command too long: %30s...", result);
X	    exit(0);
X	}
X	strncpy(result, expansion, expansion_len);
X	result += expansion_len;
X    }
X    *result = 0;
X}
END_OF_percent_x.c
if test 2134 -ne `wc -c <percent_x.c`; then
    echo shar: \"percent_x.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f options.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"options.c\"
else
echo shar: Extracting \"options.c\" \(7510 characters\)
sed "s/^X//" >options.c <<'END_OF_options.c'
X /*
X  * General skeleton for adding options to the access control language. This
X  * code can be enabled by replacing in hosts_access.c the shell_command()
X  * call by a call to process_options(), with the same argument list. Shell
X  * commands will still be available, be it with a slightly different syntax.
X  * 
X  * The code uses a slightly different format of access control rules. It
X  * assumes that an access control rule looks like this:
X  * 
X  * daemon_list : client_list : option : option ...
X  * 
X  * An option is of the form "keyword" or "keyword = value". Option fields are
X  * processed from left to right. Blanks around keywords, "="  and values are
X  * optional.
X  * 
X  * Diagnostics are reported through syslog(3).
X  * 
X  * Examples of options that are already implemented by the current skeleton:
X  * 
X  * user = nobody
X  * 
X  * Causes the process to switch its user id to that of "nobody". This normally
X  * requires root privilege.
X  * 
X  * group = tty
X  * 
X  * Causes the process to change its group id to that of the "tty" group. In
X  * order to switch both user and group ids you should normally switch the
X  * group id before switching the user id.
X  * 
X  * spawn = /usr/ucb/finger -l @%h | /usr/ucb/mail root
X  * 
X  * Executes (in a child process) the shell command "finger -l @%h | mail root"
X  * after doing the %<character> expansions described in the hosts_access(5)
X  * manual page. The command is executed with stdin, stdout and stderr
X  * connected to the null device. Because options are processed in order,
X  * multiple spawn comands can be specified within the same access control
X  * rule, though "spawn = command1; command2" would be more efficient.
X  * 
X  * in.ftpd : client_list : twist = /bin/echo 421 Some bogus error message
X  * 
X  * Sends some bogus error message to the remote client instead of running the
X  * real ftp daemon. The command is subjected to %<character> expansion and
X  * executed by /bin/sh. Stdin, stdout and stderr are not redirected. Some
X  * inetd's only pass stdin to their servers; in that case the command should
X  * write its output to stdin, as with: "command >&0". The twist'ed command
X  * overlays the current process; it makes no sense to specify other options
X  * on the same line after a "twist". The "twist" option was inspired by Dan
X  * Bernstein's shuctl daemon wrapper control language.
X  * 
X  * The decision to do RFC 931 lookups can be moved to this code, too. This can
X  * be accomplished by feeding the rfc931_option file to the "patch" command.
X  * In that case you get a fifth option:
X  * 
X  * rfc931
X  * 
X  * Causes the daemon front ends to look up the remote user name with the RFC
X  * 931 protocol.
X  * 
X  * Warnings:
X  * 
X  * This module uses the non-reentrant strtok() library routine. The options
X  * argument to process_options() is destroyed.
X  * 
X  * There cannot be a ":" character in keywords or values. Backslash sequences
X  * are not yet recognized.
X  * 
X  * In case of UDP connections, do not "twist" commands that use the standard
X  * I/O or read(2)/write(2) routines to communicate with the client process.
X  * 
X  * In case of errors, use clean_exit() instead of directly calling exit(), or
X  * your inetd may go into a loop.
X  */
X
X/* System libraries. */
X
X#include <sys/types.h>
X#include <sys/param.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#include <stdio.h>
X#include <syslog.h>
X#include <pwd.h>
X#include <ctype.h>
X
Xextern char *strtok();
Xextern char *strchr();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* List of functions that implement the options. Add yours here. */
X
Xstatic void user_option();		/* execute "user=name" option */
Xstatic void group_option();		/* execute "group=name" option */
Xstatic void twist_option();		/* execute "twist=command" option */
X#ifdef RFC931_OPTION
Xstatic void rfc931_option();		/* execute "rfc931" option */
X#endif
X
Xstatic char *chop_string();		/* strip leading and trailing blanks */
X
X/* Structure of the options table. */
X
Xstruct option {
X    char   *name;			/* keyword name, case does not matter */
X    int     need_value;			/* value required or not */
X    void    (*func) ();			/* function that does the real work */
X};
X
X/* List of known keywords. Add yours here. */
X
Xstatic struct option option_table[] = {
X    "user", 1, user_option,		/* switch user id */
X    "group", 1, group_option,		/* switch group id */
X    "spawn", 1, shell_cmd,		/* spawn shell command */
X    "twist", 1, twist_option,		/* replace current process */
X#ifdef RFC931_OPTION
X    "rfc931", 0, rfc931_option,		/* do RFC 931 lookup */
X#endif
X    0,
X};
X
X/* process_options - process optional access control information */
X
Xprocess_options(options, daemon, client)
Xchar   *options;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    char   *key;
X    char   *value;
X    struct option *op;
X
X    /* Light-weight parser. We're not going to duplicate PERL. */
X
X    for (key = strtok(options, ":"); key; key = strtok((char *) 0, ":")) {
X	if (value = strchr(key, '=')) {		/* keyword=value */
X	    *value++ = 0;
X	    value = chop_string(value);		/* strip blanks around value */
X	    if (*value == 0)
X		value = 0;
X	}
X	key = chop_string(key);			/* strip blanks around key */
X	for (op = option_table; op->name; op++)	/* find keyword */
X	    if (strcasecmp(op->name, key) == 0)
X		break;
X	if (op->name == 0) {
X	    syslog(LOG_ERR, "bad option or syntax: \"%s\"", key);
X	} else if (value == 0 && op->need_value) {
X	    syslog(LOG_ERR, "option \"%s\" requires value", key);
X	} else if (value && op->need_value == 0) {
X	    syslog(LOG_ERR, "option \"%s\" requires no value", key);
X	} else {
X	    (*(op->func)) (value, daemon, client);
X	}
X    }
X}
X
X/* user_option - switch user id */
X
X/* ARGSUSED */
X
Xstatic void user_option(value, daemon, client)
Xchar   *value;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    struct passwd *pwd;
X
X    if ((pwd = getpwnam(value)) == 0) {
X	syslog(LOG_ERR, "unknown user: \"%s\"", value);
X	clean_exit(client);
X    } else if (setuid(pwd->pw_uid)) {
X	syslog(LOG_ERR, "setuid(%s): %m", value);
X	clean_exit(client);
X    }
X}
X
X/* group_option - switch group id */
X
X/* ARGSUSED */
X
Xstatic void group_option(value, daemon, client)
Xchar   *value;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    struct passwd *pwd;
X
X    if ((pwd = getpwnam(value)) == 0) {
X	syslog(LOG_ERR, "unknown group: \"%s\"", value);
X	clean_exit(client);
X    } else if (setgid(pwd->pw_gid)) {
X	syslog(LOG_ERR, "setgid(%s): %m", value);
X	clean_exit(client);
X    }
X}
X
X/* twist_option - replace process by shell command */
X
Xstatic void twist_option(value, daemon, client)
Xchar   *value;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    char    buf[BUFSIZ];
X    int     pid = getpid();
X
X    percent_x(buf, sizeof(buf), value, daemon, client, pid);
X    (void) execl("/bin/sh", "sh", "-c", buf, (char *) 0);
X    syslog(LOG_ERR, "twist \"%s\": %m", buf);
X    clean_exit(client);
X}
X
X#ifdef RFC931_OPTION
X
X/* rfc931_option - look up remote user name */
X
X/* ARGSUSED */
X
Xstatic void rfc931_option(value, daemon, client)
Xchar   *value;
Xchar   *daemon;
Xstruct from_host *client;
X{
X    if (client->sin != 0 && client->sock_type == FROM_CONNECTED)
X	client->user = rfc931_name(client->sin);
X}
X
X#endif
X
X/* chop_string - strip leading and trailing blanks from string */
X
Xstatic char *chop_string(start)
Xregister char *start;
X{
X    register char *end;
X
X    while (*start && isspace(*start))
X	start++;
X
X    end = start + strlen(start) - 1;
X    while (end > start && isspace(*end))
X	*end-- = 0;
X
X    return (start);
X}
END_OF_options.c
if test 7510 -ne `wc -c <options.c`; then
    echo shar: \"options.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f clean_exit.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"clean_exit.c\"
else
echo shar: Extracting \"clean_exit.c\" \(1268 characters\)
sed "s/^X//" >clean_exit.c <<'END_OF_clean_exit.c'
X /*
X  * clean_exit() cleans up and terminates the program. It should be called
X  * instead of exit when for some reason the real network daemon will not or
X  * cannot be run. Reason: in the case of a datagram-oriented service we must
X  * discard the not-yet received data from the client. Otherwise, inetd will
X  * see the same datagram again and again, and go into a loop.
X  * 
X  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
X  */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#) clean_exit.c 1.1 92/06/11 22:21:52";
X#endif
X
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <stdio.h>
X
Xextern void exit();
X
X#include "log_tcp.h"
X
X/* clean_exit - clean up and exit */
X
Xvoid    clean_exit(client)
Xstruct from_host *client;
X{
X    char    buf[BUFSIZ];
X    struct sockaddr sa;
X    int     size = sizeof(sa);
X
X    /*
X     * Eat up the not-yet received packet. Some systems insist on a non-zero
X     * source address argument in the recvfrom() call below.
X     */
X
X    if (client->sock_type == FROM_UNCONNECTED)
X	(void) recvfrom(0, buf, sizeof(buf), 0, &sa, &size);
X
X    /*
X     * Be kind to the inetd. We already reported the problem via the syslogd,
X     * and there is no need for additional garbage in the logfile.
X     */
X
X    exit(0);
X}
END_OF_clean_exit.c
if test 1268 -ne `wc -c <clean_exit.c`; then
    echo shar: \"clean_exit.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rfc931_option -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rfc931_option\"
else
echo shar: Extracting \"rfc931_option\" \(2015 characters\)
sed "s/^X//" >rfc931_option <<'END_OF_rfc931_option'
X*** fromhost.c.orig	Tue Jun  9 19:38:26 1992
X--- fromhost.c	Thu Jun 11 20:39:31 1992
X***************
X*** 90,96 ****
X  int     fromhost(f)
X  struct from_host *f;
X  {
X!     struct sockaddr sa;
X      struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
X      struct hostent *hp;
X      int     length = sizeof(sa);
X--- 90,96 ----
X  int     fromhost(f)
X  struct from_host *f;
X  {
X!     static struct sockaddr sa;
X      struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
X      struct hostent *hp;
X      int     length = sizeof(sa);
X***************
X*** 143,156 ****
X      }
X      /* Save the host address. A later inet_ntoa() call may clobber it. */
X  
X      f->addr = strcpy(addr_buf, inet_ntoa(sin->sin_addr));
X- 
X-     /* Look up the remote user name. Does not work for UDP services. */
X- 
X- #ifdef RFC931
X-     if (f->sock_type == FROM_CONNECTED)
X- 	f->user = rfc931_name(sin);
X- #endif
X  
X      /* Look up the remote host name. */
X  
X--- 143,150 ----
X      }
X      /* Save the host address. A later inet_ntoa() call may clobber it. */
X  
X+     f->sin = sin;
X      f->addr = strcpy(addr_buf, inet_ntoa(sin->sin_addr));
X  
X      /* Look up the remote host name. */
X  
X*** log_tcp.h.orig	Thu Jun 11 19:16:27 1992
X--- log_tcp.h	Thu Jun 11 20:39:30 1992
X***************
X*** 21,26 ****
X--- 21,27 ----
X      char   *name;			/* host name */
X      char   *addr;			/* host address */
X      char   *user;			/* user name */
X+     struct sockaddr_in *sin;		/* remote link info */
X  };
X  
X  #define FROM_UNKNOWN	"unknown"	/* name or address lookup failed */
X*** options.c.orig	Thu Jun 11 19:15:58 1992
X--- options.c	Thu Jun 11 20:39:31 1992
X***************
X*** 86,91 ****
X--- 86,93 ----
X  
X  /* List of functions that implement the options. Add yours here. */
X  
X+ #define RFC931_OPTION			/* rfc 931 is a run-time option */
X+ 
X  static void user_option();		/* execute "user=name" option */
X  static void group_option();		/* execute "group=name" option */
X  static void twist_option();		/* execute "twist=command" option */
END_OF_rfc931_option
if test 2015 -ne `wc -c <rfc931_option`; then
    echo shar: \"rfc931_option\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
