#! /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 Makefile portmap.c daemon.c strerror.c hostname.c
#   hosts_access.c shell_cmd.c strcasecmp.c log_tcp.h paths.h unistd.h
#   hosts_access.5 diffs_wrt_bsd BLURB
# Wrapped by wswietse@wsbs06 on Wed May  6 14:11:43 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\" \(3115 characters\)
sed "s/^X//" >README <<'END_OF_README'
XThis is a portmap replacement with access control in the style of the
Xtcp wrapper (log_tcp) package.  It provides a simple mechanism to
Xrestrict access to the NIS, mount, and to all other rpc services that
Xare normally registered with the portmap daemon.
X
XA quick analysis of how the portmap operates revealed several potential
Xsecurity problems.  This portmap replacement is a first attempt to get
Xrid of the worst holes.
X
XOne of the holes that are closed involves the PMAPPROC_CALLIT feature.
XOn unprotected systems, PMAPPROC_CALLIT can be used by any system to
Xaccess your NIS, mount etc.  daemons even if they refuse to talk to
Xrandom hosts, because the requests appear to come from the local host.
X
XWithout the availability of portmap source, possible alternatives
Xare 1) packet filtering with a smart router; 2) linking the portmap
Xagainst the securelib shared library. Of course, the latter option
Xmakes sense only if your OS supports shared libraries.
X
XThe sources in this distribution are derived from code on the second
XBSD networking tape, plus a few routines from the most recent tcp
Xwrapper (log_tcp) distribution. Besides BSD 4.3, the code compiles fine
Xwith SunOS 4.1.1, Ultrix 4.x and ESIX System V release 4.0.
X
XUntil now, the portmap replacement has been tested with SunOS 4.1.1,
XPC-NFS 3.0.1 and 386BSD alpha.  If you have the courage to try it out,
Xplease report any feedback you have (positive or negative). If the
Xprogram can be made generally usable I may make it part of the next tcp
Xwrapper (log_tcp) release.
X
XInstallation:
X-------------
X
XYour compiler may need additional link libraries and/or options; hints
Xare given in the Makefile. Build the portmap program, save the original
Xportmap executable and install the new one in its place. Then 1) reboot
Xthe machine or 2) kill off the inetd and all rpc daemons (portmap, yp*,
Xrpc.*, mountd, pcnfsd, etc.), and restart them in the same order as the
Xrc files do. Rebooting is by far the simplest way to get things right.
X
XSuggested entries for the access-control files are:
X
X    /etc/hosts.allow:
X	portmap: LOCAL .your.domain
X
X    /etc/hosts.deny
X	portmap: ALL
X
XThe syntax is documented in the hosts_access.5 manual page.  Normally,
Xallowed requests are NOT reported to the syslog daemon. Rejected
Xrequests show up loud and clear with priority LOG_ERR, but this is
Xeasily changed by editing one source line.
X
XTesting:
X--------
X
XNormally, the portmap will be utterly silent. In fact, it turns out
Xthat the portmap is not called that often. Sending a SIGINT signal to
Xthe portmap process enables syslogging of all requests.  With verbose
Xlogging turned on, requests such as "ypcat" or "rpcinfo -p" should show
Xup with logfile entries such as:
X
X May  5 16:02:05 wzv portmap[50]: connect from wzv to pmapproc_getport(ypserv)
X May  5 16:02:26 wzv portmap[50]: connect from localhost to pmapproc_dump()
X
XAnother SIGINT to the portmap process will turn the verbose logging off
Xso that only refused requests are reported.
X
X	Wietse Venema
X	wietse@wzv.win.tue.nl
X	Mathematics and Computing Science
X	Eindhoven University of Technology
X	The Netherlands
END_OF_README
if test 3115 -ne `wc -c <README`; then
    echo shar: \"README\" 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\" \(1688 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X# %Z% %M% %I% %E% %U%
X
X### Beginning of configurable stuff.
X
X# Uncomment the following two macro definitions if you are running SYSV.4.
X#
X# CC	= /usr/ucb/cc
X# LIBS	= -lrpcsoc
X
X# Uncomment the following macro if your system does not have u_long.
X#
X# U_LONG=-Du_long="unsigned long"
X
X# The FACILITY macro is used only if the optional shell command (third field 
X# in the access-control files) fails, so it is of minor importance.
X#
XFACILITY=-DFACILITY=LOG_DAEMON
X
X# Uncomment the following macro if you have netgroup support. In the access
X# control files, netgroups provide a convenient shorthand for describing
X# groups of related hosts. Details are given in the hosts_access.5 manual page.
X#
X# NETGROUP= -DNETGROUP
X
X# Auxiliary object files that may be missing from your C library.
X#
XAUX	= daemon.o strerror.o # strcasecmp.o
X
X### End of configurable stuff.
X
XSHELL	= /bin/sh
X
XCFLAGS	= -Dconst= -I. -Dperror=xperror -DHOSTS_ACCESS $(FACILITY) \
X	$(NETGROUP) $(U_LONG)
XOBJECTS	= portmap.o hostname.o hosts_access.o shell_cmd.o $(AUX)
X
Xportmap: $(OBJECTS)
X	$(CC) $(CFLAGS) -o $@ $(OBJECTS) $(LIBS)
X
Xclean:
X	rm -f *.o portmap core
X
Xshar:
X	@shar README Makefile portmap.c daemon.c strerror.c hostname.c \
X	hosts_access.c shell_cmd.c strcasecmp.c log_tcp.h paths.h unistd.h \
X	hosts_access.5 diffs_wrt_bsd BLURB
X
Xdiffs_wrt_bsd: portmap.c.bsd portmap.c daemon.c.bsd daemon.c
X	-(diff -c portmap.c.bsd portmap.c; diff -c daemon.c.bsd daemon.c) >$@
X
Xdaemon.o: daemon.c
Xdaemon.o: unistd.h
Xdaemon.o: paths.h
Xhostname.o: hostname.c
Xhostname.o: log_tcp.h
Xhosts_access.o: hosts_access.c
Xportmap.o: portmap.c
Xportmap.o: unistd.h
Xshell_cmd.o: shell_cmd.c
Xstrcasecmp.o: strcasecmp.c
Xstrerror.o: strerror.c
END_OF_Makefile
if test 1688 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f portmap.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"portmap.c\"
else
echo shar: Extracting \"portmap.c\" \(17418 characters\)
sed "s/^X//" >portmap.c <<'END_OF_portmap.c'
X/*-
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)portmap.c	5.4 (Berkeley) 4/19/91";
X#endif /* not lint */
X
X/*
X@(#)portmap.c	2.3 88/08/11 4.0 RPCSRC
Xstatic char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
X*/
X
X/*
X * portmap.c, Implements the program,version to port number mapping for
X * rpc.
X */
X
X/*
X * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
X * unrestricted use provided that this legend is included on all tape
X * media and as a part of the software program in whole or part.  Users
X * may copy or modify Sun RPC without charge, but are not authorized
X * to license or distribute it to anyone else except as part of a product or
X * program developed by the user.
X * 
X * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
X * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
X * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
X * 
X * Sun RPC is provided with no support and without any obligation on the
X * part of Sun Microsystems, Inc. to assist in its use, correction,
X * modification or enhancement.
X * 
X * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
X * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
X * OR ANY PART THEREOF.
X * 
X * In no event will Sun Microsystems, Inc. be liable for any lost revenue
X * or profits or other special, indirect and consequential damages, even if
X * Sun has been advised of the possibility of such damages.
X * 
X * Sun Microsystems, Inc.
X * 2550 Garcia Avenue
X * Mountain View, California  94043
X */
X
X#include <rpc/rpc.h>
X#include <rpc/pmap_prot.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <syslog.h>
X#include <unistd.h>
X#include <netdb.h>
X#include <sys/socket.h>
X#include <sys/ioctl.h>
X#include <sys/wait.h>
X#include <sys/signal.h>
X#include <sys/time.h>
X#include <sys/resource.h>
X#include <netinet/in.h>
X
X#ifndef LOG_PERROR
X#define LOG_PERROR 0
X#endif
X
X#ifndef LOG_DAEMON
X#define LOG_DAEMON 0
X#endif
X
X#ifdef HOSTS_ACCESS
X#include "log_tcp.h"
Xint checkhost = 0;		/* host checking flag */
Xint verboselog = 0;		/* log allowed requests too */
Xvoid toggle_checkhost();	/* toggle host checking flag */
Xvoid toggle_verboselog();	/* toggle verbose logging flag */
X
X#ifndef svc_getcaller		/* SYSV.4 */
X#  define svc_getcaller svc_getrpccaller
X#  include <rpc/rpcent.h>
X#endif
X#endif
X
Xvoid reg_service();
Xvoid reap();
Xstatic void callit();
Xstruct pmaplist *pmaplist;
Xint debugging = 0;
Xextern int errno;
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	SVCXPRT *xprt;
X	int sock, c;
X	struct sockaddr_in addr;
X	int len = sizeof(struct sockaddr_in);
X	register struct pmaplist *pml;
X
X	while ((c = getopt(argc, argv, "d")) != EOF) {
X		switch (c) {
X
X		case 'd':
X			debugging = 1;
X			break;
X
X		default:
X			(void) fprintf(stderr, "usage: %s [-d]\n", argv[0]);
X			exit(1);
X		}
X	}
X
X	if (!debugging && daemon(0, 0)) {
X		(void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
X		exit(1);
X	}
X
X	openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID,
X	    LOG_DAEMON);
X
X	if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
X		syslog(LOG_ERR, "cannot create udp socket: %m");
X		exit(1);
X	}
X
X	addr.sin_addr.s_addr = 0;
X	addr.sin_family = AF_INET;
X	addr.sin_port = htons(PMAPPORT);
X	if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
X		syslog(LOG_ERR, "cannot bind udp: %m");
X		exit(1);
X	}
X
X	if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
X		syslog(LOG_ERR, "couldn't do udp_create");
X		exit(1);
X	}
X	/* make an entry for ourself */
X	pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
X	pml->pml_next = 0;
X	pml->pml_map.pm_prog = PMAPPROG;
X	pml->pml_map.pm_vers = PMAPVERS;
X	pml->pml_map.pm_prot = IPPROTO_UDP;
X	pml->pml_map.pm_port = PMAPPORT;
X	pmaplist = pml;
X
X	if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
X		syslog(LOG_ERR, "cannot create tcp socket: %m");
X		exit(1);
X	}
X	if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
X		syslog(LOG_ERR, "cannot bind udp: %m");
X		exit(1);
X	}
X	if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
X	    == (SVCXPRT *)NULL) {
X		syslog(LOG_ERR, "couldn't do tcp_create");
X		exit(1);
X	}
X	/* make an entry for ourself */
X	pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist));
X	pml->pml_map.pm_prog = PMAPPROG;
X	pml->pml_map.pm_vers = PMAPVERS;
X	pml->pml_map.pm_prot = IPPROTO_TCP;
X	pml->pml_map.pm_port = PMAPPORT;
X	pml->pml_next = pmaplist;
X	pmaplist = pml;
X
X	(void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
X
X#ifdef HOSTS_ACCESS
X	(void)signal(SIGALRM, toggle_checkhost);
X	(void)signal(SIGINT, toggle_verboselog);
X	/* Give NIS etc. a chance to come up before turning on host checking. */
X	alarm(60);
X#endif
X	(void)signal(SIGCHLD, reap);
X	svc_run();
X	syslog(LOG_ERR, "run_svc returned unexpectedly");
X	abort();
X}
X
X#ifndef lint
X/* need to override perror calls in rpc library */
Xvoid
Xperror(what)
X	const char *what;
X{
X
X	syslog(LOG_ERR, "%s: %m", what);
X}
X#endif
X
Xstatic struct pmaplist *
Xfind_service(prog, vers, prot)
X	u_long prog, vers, prot;
X{
X	register struct pmaplist *hit = NULL;
X	register struct pmaplist *pml;
X
X	for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
X		if ((pml->pml_map.pm_prog != prog) ||
X			(pml->pml_map.pm_prot != prot))
X			continue;
X		hit = pml;
X		if (pml->pml_map.pm_vers == vers)
X		    break;
X	}
X	return (hit);
X}
X
X/* 
X * 1 OK, 0 not
X */
Xvoid
Xreg_service(rqstp, xprt)
X	struct svc_req *rqstp;
X	SVCXPRT *xprt;
X{
X	struct pmap reg;
X	struct pmaplist *pml, *prevpml, *fnd;
X	int ans, port;
X	caddr_t t;
X	
X	if (debugging)
X		(void) fprintf(stderr, "server: about do a switch\n");
X	switch (rqstp->rq_proc) {
X
X	case PMAPPROC_NULL:
X		/*
X		 * Null proc call
X		 */
X#ifdef HOSTS_ACCESS
X		if (checkhost && !islegal(rqstp, xprt, (u_long) 0))
X			break;
X#endif
X		if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
X			abort();
X		}
X		break;
X
X	case PMAPPROC_SET:
X		/*
X		 * Set a program,version to port mapping
X		 */
X		if (!svc_getargs(xprt, xdr_pmap, &reg))
X			svcerr_decode(xprt);
X		else {
X#ifdef HOSTS_ACCESS
X			if (checkhost && !islegal(rqstp, xprt, reg.pm_prog))
X				break;
X#endif
X			/*
X			 * check to see if already used
X			 * find_service returns a hit even if
X			 * the versions don't match, so check for it
X			 */
X			fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
X			if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
X				if (fnd->pml_map.pm_port == reg.pm_port) {
X					ans = 1;
X					goto done;
X				}
X				else {
X					ans = 0;
X					goto done;
X				}
X			} else {
X				/* 
X				 * add to END of list
X				 */
X				pml = (struct pmaplist *)
X				    malloc((u_int)sizeof(struct pmaplist));
X				pml->pml_map = reg;
X				pml->pml_next = 0;
X				if (pmaplist == 0) {
X					pmaplist = pml;
X				} else {
X					for (fnd= pmaplist; fnd->pml_next != 0;
X					    fnd = fnd->pml_next);
X					fnd->pml_next = pml;
X				}
X				ans = 1;
X			}
X		done:
X			if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
X			    debugging) {
X				(void) fprintf(stderr, "svc_sendreply\n");
X				abort();
X			}
X		}
X		break;
X
X	case PMAPPROC_UNSET:
X		/*
X		 * Remove a program,version to port mapping.
X		 */
X		if (!svc_getargs(xprt, xdr_pmap, &reg))
X			svcerr_decode(xprt);
X		else {
X#ifdef HOSTS_ACCESS
X			if (checkhost && !islegal(rqstp, xprt, reg.pm_prog))
X				break;
X#endif
X			ans = 0;
X			for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
X				if ((pml->pml_map.pm_prog != reg.pm_prog) ||
X					(pml->pml_map.pm_vers != reg.pm_vers)) {
X					/* both pml & prevpml move forwards */
X					prevpml = pml;
X					pml = pml->pml_next;
X					continue;
X				}
X				/* found it; pml moves forward, prevpml stays */
X				ans = 1;
X				t = (caddr_t)pml;
X				pml = pml->pml_next;
X				if (prevpml == NULL)
X					pmaplist = pml;
X				else
X					prevpml->pml_next = pml;
X				free(t);
X			}
X			if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) &&
X			    debugging) {
X				(void) fprintf(stderr, "svc_sendreply\n");
X				abort();
X			}
X		}
X		break;
X
X	case PMAPPROC_GETPORT:
X		/*
X		 * Lookup the mapping for a program,version and return its port
X		 */
X		if (!svc_getargs(xprt, xdr_pmap, &reg))
X			svcerr_decode(xprt);
X		else {
X#ifdef HOSTS_ACCESS
X			if (checkhost && !islegal(rqstp, xprt, reg.pm_prog))
X				break;
X#endif
X			fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
X			if (fnd)
X				port = fnd->pml_map.pm_port;
X			else
X				port = 0;
X			if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) &&
X			    debugging) {
X				(void) fprintf(stderr, "svc_sendreply\n");
X				abort();
X			}
X		}
X		break;
X
X	case PMAPPROC_DUMP:
X		/*
X		 * Return the current set of mapped program,version
X		 */
X		if (!svc_getargs(xprt, xdr_void, NULL))
X			svcerr_decode(xprt);
X		else {
X#ifdef HOSTS_ACCESS
X			if (checkhost && !islegal(rqstp, xprt, (u_long) 0))
X				break;
X#endif
X			if ((!svc_sendreply(xprt, xdr_pmaplist,
X			    (caddr_t)&pmaplist)) && debugging) {
X				(void) fprintf(stderr, "svc_sendreply\n");
X				abort();
X			}
X		}
X		break;
X
X	case PMAPPROC_CALLIT:
X		/*
X		 * Calls a procedure on the local machine.  If the requested
X		 * procedure is not registered this procedure does not return
X		 * error information!!
X		 * This procedure is only supported on rpc/udp and calls via 
X		 * rpc/udp.  It passes null authentication parameters.
X		 */
X		callit(rqstp, xprt);
X		break;
X
X	default:
X#ifdef HOSTS_ACCESS
X		if (checkhost && !islegal(rqstp, xprt, (u_long) 0))
X			break;
X#endif
X		svcerr_noproc(xprt);
X		break;
X	}
X}
X
X
X/*
X * Stuff for the rmtcall service
X */
X#define ARGSIZE 9000
X
Xstruct encap_parms {
X	u_long arglen;
X	char *args;
X};
X
Xstatic bool_t
Xxdr_encap_parms(xdrs, epp)
X	XDR *xdrs;
X	struct encap_parms *epp;
X{
X
X	return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
X}
X
Xstruct rmtcallargs {
X	u_long	rmt_prog;
X	u_long	rmt_vers;
X	u_long	rmt_port;
X	u_long	rmt_proc;
X	struct encap_parms rmt_args;
X};
X
Xstatic bool_t
Xxdr_rmtcall_args(xdrs, cap)
X	register XDR *xdrs;
X	register struct rmtcallargs *cap;
X{
X
X	/* does not get a port number */
X	if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
X	    xdr_u_long(xdrs, &(cap->rmt_vers)) &&
X	    xdr_u_long(xdrs, &(cap->rmt_proc))) {
X		return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
X	}
X	return (FALSE);
X}
X
Xstatic bool_t
Xxdr_rmtcall_result(xdrs, cap)
X	register XDR *xdrs;
X	register struct rmtcallargs *cap;
X{
X	if (xdr_u_long(xdrs, &(cap->rmt_port)))
X		return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
X	return (FALSE);
X}
X
X/*
X * only worries about the struct encap_parms part of struct rmtcallargs.
X * The arglen must already be set!!
X */
Xstatic bool_t
Xxdr_opaque_parms(xdrs, cap)
X	XDR *xdrs;
X	struct rmtcallargs *cap;
X{
X
X	return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
X}
X
X/*
X * This routine finds and sets the length of incoming opaque paraters
X * and then calls xdr_opaque_parms.
X */
Xstatic bool_t
Xxdr_len_opaque_parms(xdrs, cap)
X	register XDR *xdrs;
X	struct rmtcallargs *cap;
X{
X	register u_int beginpos, lowpos, highpos, currpos, pos;
X
X	beginpos = lowpos = pos = xdr_getpos(xdrs);
X	highpos = lowpos + ARGSIZE;
X	while ((int)(highpos - lowpos) >= 0) {
X		currpos = (lowpos + highpos) / 2;
X		if (xdr_setpos(xdrs, currpos)) {
X			pos = currpos;
X			lowpos = currpos + 1;
X		} else {
X			highpos = currpos - 1;
X		}
X	}
X	xdr_setpos(xdrs, beginpos);
X	cap->rmt_args.arglen = pos - beginpos;
X	return (xdr_opaque_parms(xdrs, cap));
X}
X
X/*
X * Call a remote procedure service
X * This procedure is very quiet when things go wrong.
X * The proc is written to support broadcast rpc.  In the broadcast case,
X * a machine should shut-up instead of complain, less the requestor be
X * overrun with complaints at the expense of not hearing a valid reply ...
X *
X * This now forks so that the program & process that it calls can call 
X * back to the portmapper.
X */
Xstatic void
Xcallit(rqstp, xprt)
X	struct svc_req *rqstp;
X	SVCXPRT *xprt;
X{
X	struct rmtcallargs a;
X	struct pmaplist *pml;
X	u_short port;
X	struct sockaddr_in me;
X	int pid, so = -1;
X	CLIENT *client;
X	struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
X	struct timeval timeout;
X	char buf[ARGSIZE];
X
X	timeout.tv_sec = 5;
X	timeout.tv_usec = 0;
X	a.rmt_args.args = buf;
X	if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
X		return;
X#ifdef HOSTS_ACCESS
X	if (checkhost && !islegal(rqstp, xprt, a.rmt_prog))
X		return;
X#endif
X	if ((pml = find_service(a.rmt_prog, a.rmt_vers,
X	    (u_long)IPPROTO_UDP)) == NULL)
X		return;
X	/*
X	 * fork a child to do the work.  Parent immediately returns.
X	 * Child exits upon completion.
X	 */
X	if ((pid = fork()) != 0) {
X		if (pid < 0)
X			syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
X			    a.rmt_prog);
X		return;
X	}
X	port = pml->pml_map.pm_port;
X	get_myaddress(&me);
X	me.sin_port = htons(port);
X	client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
X	if (client != (CLIENT *)NULL) {
X		if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
X			client->cl_auth = authunix_create(au->aup_machname,
X			   au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
X		}
X		a.rmt_port = (u_long)port;
X		if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a,
X		    xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) {
X			svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a);
X		}
X		AUTH_DESTROY(client->cl_auth);
X		clnt_destroy(client);
X	}
X	(void)close(so);
X	exit(0);
X}
X
Xvoid
Xreap()
X{
X	while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
X}
X
X#ifdef HOSTS_ACCESS
X
X/* toggle_checkhost - toggle the host checking flag */
X
Xvoid toggle_checkhost(sig)
X	int sig;
X{
X	(void)signal(sig, toggle_checkhost);
X	checkhost = !checkhost;
X}
X
X/* toggle_verboselog - toggle verbose logging flag. */
X
Xvoid toggle_verboselog(sig)
X	int sig;
X{
X	(void)signal(sig, toggle_verboselog);
X	verboselog = !verboselog;
X}
X
X/* islegal - validate host and optionally log request */
X
Xislegal(rqstp, xprt, prognum)
X	struct svc_req *rqstp;
X	SVCXPRT *xprt;
X	u_long prognum;
X{
X	struct from_host from;
X
X	/* 
X	 * Refuse access from hosts that pretend to have someone elses name
X	 * or that are not allowed to contact us. Log allowed connections
X	 * only if verbose mode is turned on.
X	 */
X
X	if (hostname(svc_getcaller(xprt), &from) == -1
X	|| hosts_access("portmap", from.source) == 0) {
X		logit(LOG_ERR,"refused connect from %s to %s(%s)", 
X		       from.source, (u_long) rqstp->rq_proc, prognum);
X		return FALSE;
X	} else {
X		if (verboselog)
X			logit(LOG_INFO,"connect from %s to %s(%s)", 
X			       from.source, (u_long) rqstp->rq_proc, prognum);
X		return TRUE;
X	}
X}
X
X/* logit - report request to the syslog daemon */
X
Xlogit(severity, format, hostname, procnum, prognum)
X	int severity;
X	char *format;
X	char *hostname;
X	u_long procnum;
X	u_long prognum;
X{
X	char *procname = 0;
X	char procbuf[30];
X	char *progname;
X	char progbuf[30];
X	struct rpcent *rpc;
X	static struct {
X		u_long code;
X		char *proc;
X	} *procp, procmap[] = {
X		PMAPPROC_CALLIT, "pmapproc_callit",
X		PMAPPROC_DUMP, "pmapproc_dump",
X		PMAPPROC_GETPORT, "pmapproc_getport",
X		PMAPPROC_NULL, "pmapproc_null",
X		PMAPPROC_SET, "pmapproc_set",
X		PMAPPROC_UNSET, "pmapproc_unset",
X		0, 0,
X	};
X
X	/* Map procedure number to name. */
X
X	for (procp = procmap; procp->proc; procp++)
X		if (procp->code == procnum) 
X		 	procname = procp->proc;
X	if (procname == 0)
X		sprintf(procname = procbuf, "%lu", (u_long) procnum);
X
X	/* Map program number to name. */
X
X	if (prognum == 0) {
X		progname = "";
X	} else if (rpc = getrpcbynumber(prognum)) {
X		progname = rpc->r_name;
X	} else {
X		sprintf(progname = progbuf, "%lu", prognum);
X	}
X
X	/* Write syslog record. */
X
X	syslog(severity, format, hostname, procname, progname);
X}
X
X#endif
END_OF_portmap.c
if test 17418 -ne `wc -c <portmap.c`; then
    echo shar: \"portmap.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f daemon.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"daemon.c\"
else
echo shar: Extracting \"daemon.c\" \(2471 characters\)
sed "s/^X//" >daemon.c <<'END_OF_daemon.c'
X/*-
X * Copyright (c) 1990 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)daemon.c	5.3 (Berkeley) 12/28/90";
X#endif /* LIBC_SCCS and not lint */
X
X#include <fcntl.h>
X#include <unistd.h>
X#include <paths.h>
X
Xdaemon(nochdir, noclose)
X	int nochdir, noclose;
X{
X	int cpid;
X
X	if ((cpid = fork()) == -1)
X		return (-1);
X	if (cpid)
X		exit(0);
X	(void) setsid();
X	if (!nochdir)
X		(void) chdir("/");
X	if (!noclose) {
X		int devnull = open(_PATH_DEVNULL, O_RDWR, 0);
X
X		if (devnull != -1) {
X			(void) dup2(devnull, STDIN_FILENO);
X			(void) dup2(devnull, STDOUT_FILENO);
X			(void) dup2(devnull, STDERR_FILENO);
X			if (devnull > 2)
X				(void) close(devnull);
X		}
X	}
X}
END_OF_daemon.c
if test 2471 -ne `wc -c <daemon.c`; then
    echo shar: \"daemon.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f strerror.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"strerror.c\"
else
echo shar: Extracting \"strerror.c\" \(2566 characters\)
sed "s/^X//" >strerror.c <<'END_OF_strerror.c'
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)strerror.c	5.6 (Berkeley) 5/4/91";
X#endif /* LIBC_SCCS and not lint */
X
X#include <string.h>
X
Xchar *
Xstrerror(num)
X	int num;
X{
X	extern int sys_nerr;
X	extern char *sys_errlist[];
X#define	UPREFIX	"Unknown error: "
X	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */
X	register unsigned int errnum;
X	register char *p, *t;
X	char tmp[40];
X
X	errnum = num;				/* convert to unsigned */
X	if (errnum < sys_nerr)
X		return(sys_errlist[errnum]);
X
X	/* Do this by hand, so we don't include stdio(3). */
X	t = tmp;
X	do {
X		*t++ = "0123456789"[errnum % 10];
X	} while (errnum /= 10);
X	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
X		*p++ = *--t;
X		if (t <= tmp)
X			break;
X	}
X	return(ebuf);
X}
END_OF_strerror.c
if test 2566 -ne `wc -c <strerror.c`; then
    echo shar: \"strerror.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hostname.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hostname.c\"
else
echo shar: Extracting \"hostname.c\" \(2960 characters\)
sed "s/^X//" >hostname.c <<'END_OF_hostname.c'
X /*
X  * hostname() returns name (or IP address) of the host at the other end of a
X  * connection. The return status is (-1) if the remote host pretends to have
X  * someone elses 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[] = "%Z% %M% %I% %E% %U%";
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/* hostname - find out remote host name */
X
Xint     hostname(sin, f)
Xstruct sockaddr_in *sin;
Xstruct from_host *f;
X{
X    struct hostent *hp;
X    int     length = sizeof(*sin);
X    char    buf[BUFSIZ];
X
X    if ((hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
X			    sizeof(sin->sin_addr.s_addr),
X			    AF_INET)) == 0) {
X	strcpy(f->source, inet_ntoa(sin->sin_addr));	/* use address */
X	return (0);
X    }
X
X    /*
X     * Save the host name, even if we may decide to not use it, because the
X     * next gethostbyxxx() call will clobber it.
X     */
X
X    strncpy(f->source, hp->h_name, sizeof(f->source) - 1);
X    f->source[sizeof(f->source) - 1] = 0;
X
X    /*
X     * Verify that the host name does not belong to someone else. If host
X     * name verification fails, ignore the host name and use the address
X     * instead.
X     */
X
X    if (matchname(f->source, sin)) {
X	return (0);
X    } else {
X	strcpy(f->source, inet_ntoa(sin->sin_addr));
X	return (-1);				/* verification failed */
X    }
X}
X
X/* matchname - determine if host name matches IP address */
X
Xstatic int matchname(remotehost, sin)
Xchar   *remotehost;
Xstruct sockaddr_in *sin;
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	/* 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],
X		       (caddr_t) & sin->sin_addr,
X		       sizeof(sin->sin_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(sin->sin_addr), hp->h_name);
X	return (BAD);
X    }
X}
END_OF_hostname.c
if test 2960 -ne `wc -c <hostname.c`; then
    echo shar: \"hostname.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\" \(5582 characters\)
sed "s/^X//" >hosts_access.c <<'END_OF_hosts_access.c'
X#ifdef HOSTS_ACCESS
X
X /*
X  * This module implements a simple but effective form of access control
X  * based on host (or domain) names, netgroup, internet addresses (or network
X  * numbers) and daemon process names, with wild card support. Upon the first
X  * match with an entry in the access-control tables, an optional shell
X  * command is executed.
X  * 
X  * Diagnostics are reported through 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 -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.6 91/10/02 23:01:49";
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#include <ctype.h>
X
Xextern char *fgets();
Xextern char *strchr();
Xextern char *strtok();
Xextern void exit();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Path names of the access control files. */
X
X#define HOSTS_ALLOW	"/etc/hosts.allow"
X#define HOSTS_DENY	"/etc/hosts.deny"
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
X/* Forward declarations. */
X
Xstatic int table_match();
Xstatic int list_match();
X
X/* hosts_access - host access control facility */
X
Xint hosts_access(daemon, client)
Xchar   *daemon;
Xchar   *client;
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;
Xchar   *client;
X{
X    FILE   *fp;
X    char    sv_list[BUFSIZ];		/* becomes list of daemons */
X    char   *cl_list;			/* becomes list of clients */
X    char   *sh_cmd;			/* becomes optional shell command */
X    int     match = NO;
X    int     end;
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. A non-existing table is treated as if it were an empty
X     * table. The optional shell command (third field) is executed when the
X     * first match is found.
X     */
X
X    if (fp = fopen(table, "r")) {
X	while (match == 0 && fgets(sv_list, sizeof(sv_list), fp)) {
X	    if (sv_list[end = strlen(sv_list) - 1] != '\n') {
X		syslog(LOG_ERR, "%s: line exceeds STDIO buffer size", table);
X		continue;
X	    } else {
X		sv_list[end] = '\0';		/* strip trailing newline */
X	    }
X	    if (sv_list[0] == '#') {		/* skip comments */
X		continue;
X	    } else if ((cl_list = strchr(sv_list, ':')) == 0) {
X		syslog(LOG_ERR, "%s: malformed entry: \"%s\"", table, sv_list);
X		continue;
X	    } else {
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		match = (list_match(sv_list, daemon)
X			 && list_match(cl_list, client));
X	    }
X	}
X	(void) fclose(fp);
X    }
X    if (match && sh_cmd)
X	shell_cmd(sh_cmd, daemon, client);
X    return (match);
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
X    /*
X     * Process tokens one at a time. If a token has the magic value "ALL" the
X     * match always succeeds. If the token is a domain name, return YES if it
X     * matches the last fields of the string. If the token has the magic
X     * value "LOCAL", return YES if the string does not contain a "."
X     * character. If the token is a network number, return YES if it matches
X     * the head of the string. If the token looks like a netgroup name,
X     * return YES if the string is a (host) member of the netgroup.
X     * Otherwise, return YES if the token fully matches the string. Note: we
X     * assume that a daemon process name never begins or ends with a "." or
X     * "@" character.
X     */
X
X    for (tok = strtok(list, sep); tok; tok = strtok((char *) 0, sep)) {
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 (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, "LOCAL") == 0) {	/* local: no dots */
X	    if (strchr(string, '.') == 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] == '.'	/* net number */
X		   && strncmp(tok, string, tok_len) == 0) {
X	    return (YES);
X	}
X    }
X    return (NO);
X}
X
X#endif
END_OF_hosts_access.c
if test 5582 -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\" \(3723 characters\)
sed "s/^X//" >shell_cmd.c <<'END_OF_shell_cmd.c'
X#ifdef HOSTS_ACCESS
X
X /*
X  * shell_cmd() takes a shell command, performs %h (host name or address), %d
X  * (daemon name) and %p (daemon process id) substitutions and passes the
X  * result to /bin/sh, with standard input, standard output and standard
X  * error connected to /dev/null. This code is never called when host access
X  * control is disabled.
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.1 91/10/02 23:01:51";
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 *strcpy();
Xextern void closelog();
Xextern void exit();
X
X/* Local stuff. */
X
X#include "log_tcp.h"
X
X/* Forward declarations. */
X
Xstatic void do_percent();
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;
Xchar   *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	do_percent(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_percent - do %<char> expansion, abort if result buffer is too small */
X
Xstatic void do_percent(result, result_len, str, daemon, client, pid)
Xchar   *result;
Xint     result_len;
Xchar   *str;
Xchar   *daemon;
Xchar   *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     * %h becomes the remote host name or address; %d the daemon process
X     * name; %p the daemon process id; %% becomes a %, and %other is ignored.
X     * We terminate with a diagnostic if we would overflow the result buffer.
X     */
X
X    while (*str) {
X	if (*str == '%') {
X	    str++;
X	    expansion =
X		*str == 'd' ? (str++, daemon) :
X		*str == 'h' ? (str++, client) :
X		*str == 'p' ? (str++, sprintf(pid_buf, "%d", pid), pid_buf) :
X		*str == '%' ? (str++, "%") :
X		*str == 0 ? "" : (str++, "");
X	    expansion_len = strlen(expansion);
X	    if (result + expansion_len >= end) {
X		syslog(LOG_ERR, "shell command too long: %30s...", result);
X		exit(0);
X	    }
X	    (void) strcpy(result, expansion);
X	    result += expansion_len;
X	} else {
X	    *result++ = *str++;
X	}
X    }
X    *result = 0;
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    /* Close a bunch of file descriptors. Ignore errors. */
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}
X
X#endif
END_OF_shell_cmd.c
if test 3723 -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 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 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\" \(742 characters\)
sed "s/^X//" >log_tcp.h <<'END_OF_log_tcp.h'
X/* @(#) log_tcp.h 1.1 91/10/02 23:01:55 */
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
X#endif
X
Xstruct from_host {
X    int     sock_type;			/* socket type, see below */
X    char    source[MAXHOSTNAMELEN + 1];	/* host name or address */
X};
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 */
END_OF_log_tcp.h
if test 742 -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 paths.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"paths.h\"
else
echo shar: Extracting \"paths.h\" \(2688 characters\)
sed "s/^X//" >paths.h <<'END_OF_paths.h'
X/*
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X *    notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X *    notice, this list of conditions and the following disclaimer in the
X *    documentation and/or other materials provided with the distribution.
X * 3. All advertising materials mentioning features or use of this software
X *    must display the following acknowledgement:
X *	This product includes software developed by the University of
X *	California, Berkeley and its contributors.
X * 4. Neither the name of the University nor the names of its contributors
X *    may be used to endorse or promote products derived from this software
X *    without specific prior written permission.
X *
X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X *	@(#)paths.h	5.15 (Berkeley) 5/29/91
X */
X
X#ifndef _PATHS_H_
X#define	_PATHS_H_
X
X/* Default search path. */
X#define	_PATH_DEFPATH	"/usr/bin:/bin"
X
X#define	_PATH_BSHELL	"/bin/sh"
X#define	_PATH_CONSOLE	"/dev/console"
X#define	_PATH_CSHELL	"/bin/csh"
X#define	_PATH_DEVDB	"/var/run/dev.db"
X#define	_PATH_DEVNULL	"/dev/null"
X#define	_PATH_DRUM	"/dev/drum"
X#define	_PATH_KMEM	"/dev/kmem"
X#define	_PATH_MAILDIR	"/var/mail"
X#define	_PATH_MAN	"/usr/share/man"
X#define	_PATH_MEM	"/dev/mem"
X#define	_PATH_NOLOGIN	"/etc/nologin"
X#define	_PATH_SENDMAIL	"/usr/sbin/sendmail"
X#define	_PATH_TTY	"/dev/tty"
X#define	_PATH_UNIX	"/386bsd"
X#define	_PATH_VI	"/usr/bin/vi"
X
X/* Provide trailing slash, since mostly used for building pathnames. */
X#define	_PATH_DEV	"/dev/"
X#define	_PATH_TMP	"/tmp/"
X#define	_PATH_VARRUN	"/var/run/"
X#define	_PATH_VARTMP	"/var/tmp/"
X
X#endif /* !_PATHS_H_ */
END_OF_paths.h
if test 2688 -ne `wc -c <paths.h`; then
    echo shar: \"paths.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f unistd.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"unistd.h\"
else
echo shar: Extracting \"unistd.h\" \(184 characters\)
sed "s/^X//" >unistd.h <<'END_OF_unistd.h'
X#define	 STDIN_FILENO	0	/* standard input file descriptor */
X#define	STDOUT_FILENO	1	/* standard output file descriptor */
X#define	STDERR_FILENO	2	/* standard error file descriptor */
END_OF_unistd.h
if test 184 -ne `wc -c <unistd.h`; then
    echo shar: \"unistd.h\" 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\" \(5785 characters\)
sed "s/^X//" >hosts_access.5 <<'END_OF_hosts_access.5'
X.TH HOSTS_ACCESS 5
X.ad
X.fi
X.SH NAME
Xhosts_access \- host access control files
X.SH DESCRIPTION
X.ad
X.fi
XThis manual page describes a simple, but effective, access control
Xfacility that is based on host (or domain) names, netgroups, internet
Xaddresses (or network numbers) and on network daemon process names.
X.PP
XIn the following text, \fIdaemon\fP is the the process name (argv[0]
Xvalue) of a network daemon process, and \fIclient\fP is the name of
Xa remote host (or its internet address if the name is not available).
X.IP o
XAccess will be granted when a (daemon,client) pair is matched by an
Xentry in the \fI/etc/hosts.allow\fP file.
X.IP o
XIf the previous test fails (perhaps because the \fIhosts.allow\fP file
Xdoes not exist), access will be denied when a (daemon,client) pair is
Xmatched by an entry in the \fI/etc/hosts.deny\fP file.
X.IP o
XIf the previous test fails (perhaps because the \fIhosts.deny\fP file
Xdoes not exist), 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.PP
XThe format of the access control files is as follows.
X.IP o
XLines that begin with a `#\' character are ignored.
X.IP o
XOther lines should have the format (things between [] are optional):
X.sp
X.ti +3
Xdaemon_list : client_list [ : shell_command ]
X.PP
X\fIdaemon_list\fP is a list of one or more daemon process names
X(argv[0] values).  \fIclient_list\fP is a list of one or more host
Xnames, domain names, netgroups, internet addresses or internet network
Xnumbers.  List elements should be separated by blanks and/or commas.
XWith the exception of netgroup lookups, all access control lookups are
Xcase insensitive.
X.PP
XClient_list fields that specify a domain name should begin with a
X`.\' character (see example below). Internet \fInetwork\fP numbers (as
Xopposed to internet \fIhost\fP numbers) should be terminated with a `.\'
Xcharacter. A netgroup name should begin with the `@\' character.
XNetgroups are usually supported on systems with NIS (formerly YP)
Xdata bases.
X.PP
XSpecial meaning is given to the magic token \fIALL\fP.  If it appears
Xin a daemon_list, this token matches all network daemon process
Xnames.  If the magic token appears in a client_list, it matches
Xall clients.  Another token that receives special treatment is
X\fILOCAL\fP. If it appears in a daemon_list or client_list,
Xit matches any string that does not contain a dot character.
X.PP
XThe optional \fIshell_command\fP is executed if the table entry is the
Xfirst one that matches the (daemon,client) pair. The format is: one or
Xmore statements separated by a `;\' character. Prior to execution,
Xthe following substitutions are done on the shell_command:
X.TP
X%h
Xis replaced by the remote host name
X(or address, if the host name is not available).
X.TP
X%d
Xis replaced by the daemon process name (argv[0] value).
X.TP
X%p
Xis replaced by the daemon process id.
X.TP
X%%
Xis replaced by a single `%\' character.
X.PP
XThe resulting command is given to \fI/bin/sh\fP, with standard input,
Xoutput and error connected to \fI/dev/null\fP.  Specify an `&\' at the
Xend of the command if you do not want to wait until it has completed.
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 all services to hosts within the local
Xdomain (no `.\' character in the host name), all hosts below 
Xthe \fI.some.domain\fP, and all hosts in the \fIthatgroup\fP netgroup:
X.PP
X/etc/hosts.allow: 
X.in +3
XALL: LOCAL, .some.domain, @thatgroup
X.PP
X/etc/hosts.deny: 
X.in +3
XALL: ALL
X.PP
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 following example implements a backfinger facility that is
Xtriggered when someone invokes your tftp service from a host outside the
Xlocal domain:
X.PP
X/etc/hosts.allow:
X.in +3
X.nf
Xin.tftpd: LOCAL, .my.domain
X.PP
X/etc/hosts.deny:
X.in +3
X.nf
Xin.tftpd: ALL: (/bin/date; /usr/ucb/finger -l @%h) >>/var/adm/%d.log &
X.fi
X.PP
XIf your tftp daemon is run under a uid other than root (strongly
Xrecommended), the /var/adm/whatever.log file should be writable for
Xthat uid. Watch out for infinite backfinger loops!
X.SH DIAGNOSTICS
X.ad
X.fi
XAn error is reported when a syntax error is found in a host access
Xcontrol file; when the length of an entry in a host access control file
Xexceeds the STDIO buffer size; when the result of %<character>
Xexpansion would overflow an internal buffer; when a system call fails
Xthat shouldn\'t.
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.SH BUGS
X.ad
X.fi
XIf there are problems with a name server, the access control software
Xwill use a host\'s address instead of its name.  A workaround is to
Xalso list internet addresses and network numbers in the access-control
Xfiles.
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
Xfinished their work, just in case another request comes in (in the
Xinetd configuration file, these daemons are registered with the `wait\'
Xoption).  In such cases, access control will apply only to the request
Xthat started such a daemon. This restriction usually does not apply to
Xconnection-oriented (TCP) services.
X.SH AUTHOR
X.na
X.nf
XWietse Venema
XEindhoven University of Technology
XDepartment of Mathematics and Computer Science
XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X\" @(#) hosts_access.5 1.8 91/10/02 23:02:00
END_OF_hosts_access.5
if test 5785 -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 diffs_wrt_bsd -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"diffs_wrt_bsd\"
else
echo shar: Extracting \"diffs_wrt_bsd\" \(6500 characters\)
sed "s/^X//" >diffs_wrt_bsd <<'END_OF_diffs_wrt_bsd'
X*** portmap.c.bsd	Sun May  3 22:39:52 1992
X--- portmap.c	Tue May  5 18:18:20 1992
X***************
X*** 92,99 ****
X--- 92,122 ----
X  #include <sys/ioctl.h>
X  #include <sys/wait.h>
X  #include <sys/signal.h>
X+ #include <sys/time.h>
X  #include <sys/resource.h>
X+ #include <netinet/in.h>
X  
X+ #ifndef LOG_PERROR
X+ #define LOG_PERROR 0
X+ #endif
X+ 
X+ #ifndef LOG_DAEMON
X+ #define LOG_DAEMON 0
X+ #endif
X+ 
X+ #ifdef HOSTS_ACCESS
X+ #include "log_tcp.h"
X+ int checkhost = 0;		/* host checking flag */
X+ int verboselog = 0;		/* log allowed requests too */
X+ void toggle_checkhost();	/* toggle host checking flag */
X+ void toggle_verboselog();	/* toggle verbose logging flag */
X+ 
X+ #ifndef svc_getcaller		/* SYSV.4 */
X+ #  define svc_getcaller svc_getrpccaller
X+ #  include <rpc/rpcent.h>
X+ #endif
X+ #endif
X+ 
X  void reg_service();
X  void reap();
X  static void callit();
X***************
X*** 182,187 ****
X--- 205,216 ----
X  
X  	(void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
X  
X+ #ifdef HOSTS_ACCESS
X+ 	(void)signal(SIGALRM, toggle_checkhost);
X+ 	(void)signal(SIGINT, toggle_verboselog);
X+ 	/* Give NIS etc. a chance to come up before turning on host checking. */
X+ 	alarm(60);
X+ #endif
X  	(void)signal(SIGCHLD, reap);
X  	svc_run();
X  	syslog(LOG_ERR, "run_svc returned unexpectedly");
X***************
X*** 238,243 ****
X--- 267,276 ----
X  		/*
X  		 * Null proc call
X  		 */
X+ #ifdef HOSTS_ACCESS
X+ 		if (checkhost && !islegal(rqstp, xprt, (u_long) 0))
X+ 			break;
X+ #endif
X  		if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) {
X  			abort();
X  		}
X***************
X*** 250,255 ****
X--- 283,292 ----
X  		if (!svc_getargs(xprt, xdr_pmap, &reg))
X  			svcerr_decode(xprt);
X  		else {
X+ #ifdef HOSTS_ACCESS
X+ 			if (checkhost && !islegal(rqstp, xprt, reg.pm_prog))
X+ 				break;
X+ #endif
X  			/*
X  			 * check to see if already used
X  			 * find_service returns a hit even if
X***************
X*** 298,303 ****
X--- 335,344 ----
X  		if (!svc_getargs(xprt, xdr_pmap, &reg))
X  			svcerr_decode(xprt);
X  		else {
X+ #ifdef HOSTS_ACCESS
X+ 			if (checkhost && !islegal(rqstp, xprt, reg.pm_prog))
X+ 				break;
X+ #endif
X  			ans = 0;
X  			for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
X  				if ((pml->pml_map.pm_prog != reg.pm_prog) ||
X***************
X*** 332,337 ****
X--- 373,382 ----
X  		if (!svc_getargs(xprt, xdr_pmap, &reg))
X  			svcerr_decode(xprt);
X  		else {
X+ #ifdef HOSTS_ACCESS
X+ 			if (checkhost && !islegal(rqstp, xprt, reg.pm_prog))
X+ 				break;
X+ #endif
X  			fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
X  			if (fnd)
X  				port = fnd->pml_map.pm_port;
X***************
X*** 352,357 ****
X--- 397,406 ----
X  		if (!svc_getargs(xprt, xdr_void, NULL))
X  			svcerr_decode(xprt);
X  		else {
X+ #ifdef HOSTS_ACCESS
X+ 			if (checkhost && !islegal(rqstp, xprt, (u_long) 0))
X+ 				break;
X+ #endif
X  			if ((!svc_sendreply(xprt, xdr_pmaplist,
X  			    (caddr_t)&pmaplist)) && debugging) {
X  				(void) fprintf(stderr, "svc_sendreply\n");
X***************
X*** 372,377 ****
X--- 421,430 ----
X  		break;
X  
X  	default:
X+ #ifdef HOSTS_ACCESS
X+ 		if (checkhost && !islegal(rqstp, xprt, (u_long) 0))
X+ 			break;
X+ #endif
X  		svcerr_noproc(xprt);
X  		break;
X  	}
X***************
X*** 500,505 ****
X--- 553,562 ----
X  	a.rmt_args.args = buf;
X  	if (!svc_getargs(xprt, xdr_rmtcall_args, &a))
X  		return;
X+ #ifdef HOSTS_ACCESS
X+ 	if (checkhost && !islegal(rqstp, xprt, a.rmt_prog))
X+ 		return;
X+ #endif
X  	if ((pml = find_service(a.rmt_prog, a.rmt_vers,
X  	    (u_long)IPPROTO_UDP)) == NULL)
X  		return;
X***************
X*** 539,541 ****
X--- 596,698 ----
X  {
X  	while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
X  }
X+ 
X+ #ifdef HOSTS_ACCESS
X+ 
X+ /* toggle_checkhost - toggle the host checking flag */
X+ 
X+ void toggle_checkhost(sig)
X+ 	int sig;
X+ {
X+ 	(void)signal(sig, toggle_checkhost);
X+ 	checkhost = !checkhost;
X+ }
X+ 
X+ /* toggle_verboselog - toggle verbose logging flag. */
X+ 
X+ void toggle_verboselog(sig)
X+ 	int sig;
X+ {
X+ 	(void)signal(sig, toggle_verboselog);
X+ 	verboselog = !verboselog;
X+ }
X+ 
X+ /* islegal - validate host and optionally log request */
X+ 
X+ islegal(rqstp, xprt, prognum)
X+ 	struct svc_req *rqstp;
X+ 	SVCXPRT *xprt;
X+ 	u_long prognum;
X+ {
X+ 	struct from_host from;
X+ 
X+ 	/* 
X+ 	 * Refuse access from hosts that pretend to have someone elses name
X+ 	 * or that are not allowed to contact us. Log allowed connections
X+ 	 * only if verbose mode is turned on.
X+ 	 */
X+ 
X+ 	if (hostname(svc_getcaller(xprt), &from) == -1
X+ 	|| hosts_access("portmap", from.source) == 0) {
X+ 		logit(LOG_ERR,"refused connect from %s to %s(%s)", 
X+ 		       from.source, (u_long) rqstp->rq_proc, prognum);
X+ 		return FALSE;
X+ 	} else {
X+ 		if (verboselog)
X+ 			logit(LOG_INFO,"connect from %s to %s(%s)", 
X+ 			       from.source, (u_long) rqstp->rq_proc, prognum);
X+ 		return TRUE;
X+ 	}
X+ }
X+ 
X+ /* logit - report request to the syslog daemon */
X+ 
X+ logit(severity, format, hostname, procnum, prognum)
X+ 	int severity;
X+ 	char *format;
X+ 	char *hostname;
X+ 	u_long procnum;
X+ 	u_long prognum;
X+ {
X+ 	char *procname = 0;
X+ 	char procbuf[30];
X+ 	char *progname;
X+ 	char progbuf[30];
X+ 	struct rpcent *rpc;
X+ 	static struct {
X+ 		u_long code;
X+ 		char *proc;
X+ 	} *procp, procmap[] = {
X+ 		PMAPPROC_CALLIT, "pmapproc_callit",
X+ 		PMAPPROC_DUMP, "pmapproc_dump",
X+ 		PMAPPROC_GETPORT, "pmapproc_getport",
X+ 		PMAPPROC_NULL, "pmapproc_null",
X+ 		PMAPPROC_SET, "pmapproc_set",
X+ 		PMAPPROC_UNSET, "pmapproc_unset",
X+ 		0, 0,
X+ 	};
X+ 
X+ 	/* Map procedure number to name. */
X+ 
X+ 	for (procp = procmap; procp->proc; procp++)
X+ 		if (procp->code == procnum) 
X+ 		 	procname = procp->proc;
X+ 	if (procname == 0)
X+ 		sprintf(procname = procbuf, "%lu", (u_long) procnum);
X+ 
X+ 	/* Map program number to name. */
X+ 
X+ 	if (prognum == 0) {
X+ 		progname = "";
X+ 	} else if (rpc = getrpcbynumber(prognum)) {
X+ 		progname = rpc->r_name;
X+ 	} else {
X+ 		sprintf(progname = progbuf, "%lu", prognum);
X+ 	}
X+ 
X+ 	/* Write syslog record. */
X+ 
X+ 	syslog(severity, format, hostname, procname, progname);
X+ }
X+ 
X+ #endif
X*** daemon.c.bsd	Sun May  3 22:45:10 1992
X--- daemon.c	Tue May  5 17:43:00 1992
X***************
X*** 35,41 ****
X  static char sccsid[] = "@(#)daemon.c	5.3 (Berkeley) 12/28/90";
X  #endif /* LIBC_SCCS and not lint */
X  
X! #include <sys/fcntl.h>
X  #include <unistd.h>
X  #include <paths.h>
X  
X--- 35,41 ----
X  static char sccsid[] = "@(#)daemon.c	5.3 (Berkeley) 12/28/90";
X  #endif /* LIBC_SCCS and not lint */
X  
X! #include <fcntl.h>
X  #include <unistd.h>
X  #include <paths.h>
X  
END_OF_diffs_wrt_bsd
if test 6500 -ne `wc -c <diffs_wrt_bsd`; then
    echo shar: \"diffs_wrt_bsd\" 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\" \(1505 characters\)
sed "s/^X//" >BLURB <<'END_OF_BLURB'
XThere is an increasing interest in access control for the NIS, mount
Xand other rpc-based services that are normally registered with the
Xportmap process.
X
XMy contribution is a replacement portmap program, derived from BSD 4.3
Xportmap source, which in turn originates from Sun (whatever they are
Xcalled these days).  Access control is in the style of my tcp wrapper
X(log_tcp) package. I am looking for people who are willing to try it
Xout and help to get rid of possible portability problems.
X
XThe present version only begins to address the worst problems.  For
Xexample, using the portmap daemon to forward requests to the NIS or
Xmount daemons and so that they appear to come from the local host.
X
XWithout the availability of portmap source, possible alternatives
Xare 1) packet filtering with a smart router; 2) linking the portmap
Xexecutable against the securelib shared library. Of course, the latter
Xoption makes sense only with an OS that supports shared libraries.
X
XBesides BSD 4.3, The code compiles fine with SunOS 4.1.1, Ultrix 4.x
Xand ESIX System V release 4.0.  The portmap replacement has been tested
Xwith SunOS 4.1.1, PC-NFS 3.0.1 and 386BSD alpha.
X
XIf you have the courage to try it out, please report any feedback you
Xhave (positive or negative). If the program can be made generally
Xusable I may make it part of the next tcp wrapper (log_tcp) release.
X
XThe source has been posted to alt.{sources,security} and is available
Xfor anonymous ftp from ftp.win.tue.nl:/pub/security/portmap_0.shar.Z
END_OF_BLURB
if test 1505 -ne `wc -c <BLURB`; then
    echo shar: \"BLURB\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
