|
There is an increasing interest in access control for the NIS, mount and other RPC-based services that are normally registered with the portmap process. These days, popular attacks on RPC daemons involve: - theft or NIS (YP) password files - ypset to force hosts to bind to a rogue NIS (YP) server - theft of NFS file handles My contribution is a replacement portmap program, derived from source code in the RPCSRC 4.0 and the TIRPC source distributions. Access control is in the style of my tcp wrapper (log_tcp) package. It should work with all SunOS 4.x and Ultrix >= 3.0 releases. However, the source is reasonably portable and the code should work on most UNIX systems that provide SUNRPC on top of BSD-style TCP/IP. System V.4 support is problematic, though. The present portmap version attempts to close all portmap security problems that are known to me. It should be as secure as the portmap daemon that comes with the SunOS 4.x portmap+NIS patch (patch id 100482-02). The README file gives a complete list of security features. Without the availability of portmap source, possible alternatives are 1) packet filtering with a smart router; 2) linking the portmap executable against the securelib shared library. Linking other RPC daemons against the securelib library is a good idea, anyway. The source is available for anonymous FTP from ftp.win.tue.nl directory /pub/security/portmap.shar.Z. It requires the access control library that it built with /pub/security/log_tcp.shar.Z. Wietse Venema (wietse@wzv.win.tue.nl) Mathematics and Computing Science Eindhoven University of Technology The Netherlands #! /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 # diffs_wrt_bsd pmap_dump.c pmap_set.c from_local.c pmap_check.c # pmap_check.h BLURB # Wrapped by wietse@wzv on Mon Jul 6 19:57:40 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\" \(6515 characters\) sed "s/^X//" >README <<'END_OF_README' X@(#) README 1.2 92/07/06 19:53:25 X XDescription X----------- X XThis is a portmapper replacement with access control in the style of Xthe tcp wrapper (log_tcp) package. It provides a simple mechanism to Xdiscourage access to the NIS (YP), NFS, and other services registered Xwith the portmapper. X XIn some cases, better or equivalent alternatives are available: X X The SunOS portmap that is provided with patch id 100482-02 should X close the same security holes. In addition, it provides NIS X daemons with their own access control lists. This is better than X just portmapper access control. X X The "securelib" shared library (eecs.nwu.edu:/pub/securelib.tar) X implements access control for all kinds of (RPC) services, not X just the portmapper. X X Reportedly, Irix 4.0.x already has a secured portmapper. X XHowever, many vendors still ship portmap implementations that allow Xanyone to read or modify its tables and that will happily forward any Xrequest so that it appears to come from the local system. X XFeatures X-------- X X- optional: host access control. The local host is always considered Xauthorized. This feature requires the libwrap.a library that comes with Xrecent tcp wrapper (log_tcp) implementations. X X- requests to change the portmap tables are accepted only when they Xcome from the local system. X X- optional: requests to (un)register services on privileged ports (port X< 1024) are accepted only when they come from a privileged port. This Xfeature is optional because some RPC implementations still run all RPC Xdaemons of an unprivileged port. Bug your vendor if your RPC is like Xthat. X X- requests that are forwarded by the portmapper will be forwarded Xthrough an unprivileged port. X X- the portmapper refuses to forward requests to rpc daemons that do (or Xshould) verify the origin of the request: at present, the list includes Xmost of the calls to the NFS mountd/nfsd daemons and the NIS daemons. X XRestrictions X------------ X XLimiting access to the portmapper does not protect you from direct Xattacks on the rpc daemons; the main task of portmap is to maintain a Xtable of available RPC services and the network ports that they are Xlistening on. The securelib can be used to protect individual RPC Xdaemons, and the latest SunOS portmap+NIS fix already protects the NIS Xdaemons and implements limited forwarding. X XOn the other hand, even though a portmapper with access control only Xmakes an attack more difficult, it still provides an excellent early Xwarning system. X XOrigin and portability X---------------------- X XThe sources in this distribution are derived from code on the second XBSD networking tape, which was derived from Sun's RPCSRC 4.0 code, and Xfrom Sun's TIRPC (transport-independent rpc) distribution. X XThe code compiles fine with SunOS 4.1.1, Ultrix 4.x and ESIX System V Xrelease 4.0, but I expect it will work with many other UNIX flavours. XTested with SunOS 4.1.1; an earlier version was also tested with Ultrix X3.0. If anyone can get this thing working with SYSV4 let me know; it Xdidn't with ESIX. X XInstallation X------------ X X(1) Follow the instructions in the Makefile, then build the portmap and Xauxiliary executables. X X(2) Before killing the present portmap process, save the present Xportmapper tables using the command: X X ./pmap_dump >table X XIf you kill the portmap process without saving its tables you will have Xto reboot the machine. X XNote: the information in the portmap tables is dynamic: For example, it Xwill be different after each reboot. On a Sun, it even changes each Xtime a windowing system is started that uses the selection service. X X(3) Kill the running portmap process and start the new portmap Xprogram. Then (still as root) initialize the portmap tables with: X X ./pmap_set <table X X(4) If you get error messages of the form: "not registered: xxxx", Xdisable the CHECK_PORT feature in the Makefile, remove pmap_check.o and Xrebuild the portmap program. Then proceed with step 3. X XIn order to revert to the original portmap daemon, kill off the running Xone, restart the original one and reload its tables using the X"pmap_set" command as shown above. X XSuggested entries for the host access-control files are: X X /etc/hosts.allow: X portmap: your.sub.net.number/your.sub.net.mask X portmap: 255.255.255.255 0.0.0.0 X X /etc/hosts.deny X portmap: ALL: (finger -l @%h | mail root) & X XThe syntax of the access-control files is described in the Xhosts_access.5 manual page that comes with the tcp wrapper (log_tcp) Xsources. The second line in the hosts.allow file may be needed if Xthere are PC-NFS systems on your network segment. X XFor security reasons, the portmap process does not run as root. The Xaccess control files should therefore be group readable. X XIn order to avoid deadlocks, the portmap program does not attempt to Xlook up the remote host name, nor will it try to match NIS netgroups. XIf you do not want to accept requests from everyone on your subnet you Xwill have to enumerate the addresses of authorised hosts. There is no Xneed to specify the local system: since it runs the portmap daemon, it Xis authorized by definition. X XTesting: X-------- X XNormally, only rejected requests will be reported via the syslog Xdaemon. Logging is done in a child process, in order to avoid Xpossible deadlock in case the logging code needs assistance from Xthe portmapper. X XBy default, the portmapper will be utterly silent. In fact, the portmap Xdaemon is not consulted that often. Sending a SIGINT signal to the Xportmap process will enable the logging of all requests. X XWarning: with some systems, such as HP-UX, the logging code needs Xassistance from the portmapper. If verbose logging is on, these calls Xfor assistance will also be logged, so that you end up with a system Xfull of portmap processes. X XWith verbose logging turned on, requests such as "ypcat" or "rpcinfo X-p" should show up with log file entries such as: X X MMM dd hh:mm:ss hostname portmap[pid]: connect from x.x.x.x to getport(ypserv) X MMM dd hh:mm:ss hostname portmap[pid]: connect from y.y.y.y to dump() X XSend another SIGINT to the portmapper to turn the verbose logging off. X XAcknowledgements X---------------- X XCasper H.S. Dik (casper@fwi.uva.nl) provided lots of valuable Xinformation on RPC security and tested an intermediate version of the Xportmapper with SunOS 4.1.2. Lyford D. Rich (rich@ece.nps.navy.mil) Xwas helpful with porting the daemon to Ultrix 3.0. X X Wietse Venema (wietse@wzv.win.tue.nl) X Mathematics and Computing Science X Eindhoven University of Technology X The Netherlands END_OF_README if test 6515 -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\" \(2955 characters\) sed "s/^X//" >Makefile <<'END_OF_Makefile' X# @(#) Makefile 1.2 92/07/06 19:53:28 X X#################################### X### Beginning of configurable stuff. 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. The local system, since it runs the portmap daemon, is always X# treated as an authorized host. X XHOSTS_ACCESS= -DHOSTS_ACCESS X X# Comment out if your RPC library does not allocate privileged ports for X# requests from processes with root privilege, or the new portmap will X# always reject requests to register/unregister services on privileged X# ports. You can find out by running "rpcinfo -p"; if the mountd and NIS X# daemons use a port >= 1024 you should probably disable the next line. X XCHECK_PORT = -DCHECK_PORT X X# Uncomment the following macro if your system does not have u_long. X# X# ULONG =-Du_long="unsigned long" X X# Later versions of the tcp wrapper (log_tcp package) come with a X# libwrap.a object library. WRAP_DIR should specify the directory with X# that library. X XWRAP_DIR= ../log_tcp X X# Auxiliary object files that may be missing from your C library. X# XAUX = daemon.o strerror.o X X# Uncomment the following macro definitions if you are running SYSV.4. X# X# CC = /usr/ucb/cc X# LIBS = -lrpcsoc X# SYS = -DSYSV40 X X# Auxiliary libraries that you may have to specify X# X# LIBS = -lrpc X X### End of configurable stuff. X############################## X XSHELL = /bin/sh X XCOPT = -Dconst= -Dperror=xperror $(HOSTS_ACCESS) $(CHECK_PORT) \ X $(SYS) -DFACILITY=$(FACILITY) $(ULONG) XCFLAGS = $(COPT) -O XOBJECTS = portmap.o pmap_check.o from_local.o $(AUX) X Xall: portmap pmap_dump pmap_set X Xportmap: $(OBJECTS) $(WRAP_DIR)/libwrap.a X $(CC) $(CFLAGS) -o $@ $(OBJECTS) $(WRAP_DIR)/libwrap.a $(LIBS) X Xpmap_dump: pmap_dump.c X $(CC) $(CFLAGS) -o $@ $? $(LIBS) X Xpmap_set: pmap_set.c X $(CC) $(CFLAGS) -o $@ $? $(LIBS) X Xfrom_local: from_local.c X cc $(CFLAGS) -DTEST -o $@ from_local.c X Xlint: X lint $(COPT) $(OBJECTS:%.o=%.c) X Xclean: X rm -f *.o portmap pmap_dump pmap_set from_local core X Xshar: X @shar README Makefile portmap.c daemon.c strerror.c diffs_wrt_bsd \ X pmap_dump.c pmap_set.c from_local.c pmap_check.c pmap_check.h 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 Xdeps: X @$(CC) -M $(CFLAGS) *.c | grep -v /usr/include |sed 's/\.\///' X Xdaemon.o: daemon.c Xfrom_local.o: from_local.c Xpmap_check.o: pmap_check.c pmap_check.h Makefile Xpmap_dump.o: pmap_dump.c Xpmap_set.o: pmap_set.c Xportmap.o: portmap.c Xportmap.o: pmap_check.h Xstrerror.o: strerror.c END_OF_Makefile if test 2955 -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\" \(15524 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 <syslog.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#ifdef SYSV40 X#include <netinet/in.h> X#endif X Xextern char *strerror(); Xextern char *malloc(); 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#ifndef svc_getcaller /* SYSV4 */ X# define svc_getcaller svc_getrpccaller X#endif X Xvoid reg_service(); Xvoid reap(); Xstatic void callit(); Xstruct pmaplist *pmaplist; Xint debugging = 0; Xextern int errno; X X#include "pmap_check.h" 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#ifdef LOG_MAIL X openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID, X FACILITY); X#else X openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID); X#endif 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 /* additional initializations */ X check_startup(); 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 /* remote host authorization check */ X check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0); 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, ®)) X svcerr_decode(xprt); X else { X /* reject non-local requests, protect priv. ports */ X if (!check_setunset(svc_getcaller(xprt), X rqstp->rq_proc, reg.pm_prog, reg.pm_port)) { X ans = 0; X goto done; X } 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, ®)) X svcerr_decode(xprt); X else { X ans = 0; X /* reject non-local requests */ X if (!check_setunset(svc_getcaller(xprt), X rqstp->rq_proc, reg.pm_prog, (u_long) 0)) X goto done; 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 /* privileged port check */ X if (!check_privileged_port(svc_getcaller(xprt), X rqstp->rq_proc, X reg.pm_prog, X pml->pml_map.pm_port)) { X ans = 0; X break; X } 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, ®)) X svcerr_decode(xprt); X else { X /* remote host authorization check */ X if (!check_default(svc_getcaller(xprt), X rqstp->rq_proc, X reg.pm_prog)) { X ans = 0; X goto done; X } 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 /* remote host authorization check */ X struct pmaplist *p; X if (!check_default(svc_getcaller(xprt), X rqstp->rq_proc, (u_long) 0)) { X p = 0; /* send empty list */ X } else { X p = pmaplist; X } X if ((!svc_sendreply(xprt, xdr_pmaplist, X (caddr_t)&p)) && 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 /* remote host authorization check */ X check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0); 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 /* host and service access control */ X if (!check_callit(svc_getcaller(xprt), X rqstp->rq_proc, a.rmt_prog, a.rmt_proc)) X return; 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} END_OF_portmap.c if test 15524 -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\" \(2590 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 X/* From unistd.h */ X#define STDIN_FILENO 0 X#define STDOUT_FILENO 1 X#define STDERR_FILENO 2 X X/* From paths.h */ X#define _PATH_DEVNULL "/dev/null" 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 return(0); X} END_OF_daemon.c if test 2590 -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 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\" \(6210 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 Thu Jun 4 23:16:36 1992 X*************** X*** 83,99 **** 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/resource.h> X X void reg_service(); X void reap(); X static void callit(); X--- 83,115 ---- X #include <rpc/rpc.h> X #include <rpc/pmap_prot.h> X #include <stdio.h> X #include <syslog.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+ #ifdef SYSV40 X+ #include <netinet/in.h> X+ #endif X X+ extern char *strerror(); X+ extern char *malloc(); 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+ #ifndef svc_getcaller /* SYSV4 */ X+ # define svc_getcaller svc_getrpccaller X+ #endif X+ X void reg_service(); X void reap(); X static void callit(); X*************** X*** 101,106 **** X--- 117,124 ---- X int debugging = 0; X extern int errno; X X+ #include "pmap_check.h" X+ X main(argc, argv) X int argc; X char **argv; X*************** X*** 130,136 **** 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--- 148,154 ---- X } X X openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID, X! FACILITY); X X if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { X syslog(LOG_ERR, "cannot create udp socket: %m"); X*************** X*** 182,187 **** X--- 200,207 ---- X X (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE); X X+ /* additional initializations */ X+ check_startup(); X (void)signal(SIGCHLD, reap); X svc_run(); X syslog(LOG_ERR, "run_svc returned unexpectedly"); X*************** X*** 238,243 **** X--- 258,265 ---- X /* X * Null proc call X */ X+ /* remote host authorization check */ X+ check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0); X if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) { X abort(); X } X*************** X*** 250,255 **** X--- 272,283 ---- X if (!svc_getargs(xprt, xdr_pmap, ®)) X svcerr_decode(xprt); X else { X+ /* reject non-local requests, protect priv. ports */ X+ if (!check_setunset(svc_getcaller(xprt), X+ rqstp->rq_proc, reg.pm_prog, reg.pm_port)) { X+ ans = 0; X+ goto done; X+ } X /* X * check to see if already used X * find_service returns a hit even if X*************** X*** 299,304 **** X--- 327,336 ---- X svcerr_decode(xprt); X else { X ans = 0; X+ /* reject non-local requests */ X+ if (!check_setunset(svc_getcaller(xprt), X+ rqstp->rq_proc, reg.pm_prog, (u_long) 0)) X+ goto done; 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*************** X*** 308,313 **** X--- 340,353 ---- X continue; X } X /* found it; pml moves forward, prevpml stays */ X+ /* privileged port check */ X+ if (!check_privileged_port(svc_getcaller(xprt), X+ rqstp->rq_proc, X+ reg.pm_prog, X+ pml->pml_map.pm_port)) { X+ ans = 0; X+ break; X+ } X ans = 1; X t = (caddr_t)pml; X pml = pml->pml_next; X*************** X*** 332,337 **** X--- 372,384 ---- X if (!svc_getargs(xprt, xdr_pmap, ®)) X svcerr_decode(xprt); X else { X+ /* remote host authorization check */ X+ if (!check_default(svc_getcaller(xprt), X+ rqstp->rq_proc, X+ reg.pm_prog)) { X+ ans = 0; X+ goto done; X+ } 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,359 **** X if (!svc_getargs(xprt, xdr_void, NULL)) X svcerr_decode(xprt); X else { X if ((!svc_sendreply(xprt, xdr_pmaplist, X! (caddr_t)&pmaplist)) && debugging) { X (void) fprintf(stderr, "svc_sendreply\n"); X abort(); X } X--- 399,414 ---- X if (!svc_getargs(xprt, xdr_void, NULL)) X svcerr_decode(xprt); X else { X+ /* remote host authorization check */ X+ struct pmaplist *p; X+ if (!check_default(svc_getcaller(xprt), X+ rqstp->rq_proc, (u_long) 0)) { X+ p = 0; /* send empty list */ X+ } else { X+ p = pmaplist; X+ } X if ((!svc_sendreply(xprt, xdr_pmaplist, X! (caddr_t)&p)) && debugging) { X (void) fprintf(stderr, "svc_sendreply\n"); X abort(); X } X*************** X*** 372,377 **** X--- 427,434 ---- X break; X X default: X+ /* remote host authorization check */ X+ check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0); X svcerr_noproc(xprt); X break; X } X*************** X*** 499,504 **** X--- 556,565 ---- X timeout.tv_usec = 0; X a.rmt_args.args = buf; X if (!svc_getargs(xprt, xdr_rmtcall_args, &a)) X+ return; X+ /* host and service access control */ X+ if (!check_callit(svc_getcaller(xprt), X+ rqstp->rq_proc, a.rmt_prog, a.rmt_proc)) X return; X if ((pml = find_service(a.rmt_prog, a.rmt_vers, X (u_long)IPPROTO_UDP)) == NULL) X*** daemon.c.bsd Sun May 3 22:45:10 1992 X--- daemon.c Sat May 23 16:38:02 1992 X*************** X*** 35,44 **** 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 daemon(nochdir, noclose) X int nochdir, noclose; X { X--- 35,50 ---- 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 X+ /* From unistd.h */ X+ #define STDIN_FILENO 0 X+ #define STDOUT_FILENO 1 X+ #define STDERR_FILENO 2 X+ X+ /* From paths.h */ X+ #define _PATH_DEVNULL "/dev/null" X+ X daemon(nochdir, noclose) X int nochdir, noclose; X { X*************** X*** 62,65 **** X--- 68,72 ---- X (void) close(devnull); X } X } X+ return(0); X } END_OF_diffs_wrt_bsd if test 6210 -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 pmap_dump.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"pmap_dump.c\" else echo shar: Extracting \"pmap_dump.c\" \(1379 characters\) sed "s/^X//" >pmap_dump.c <<'END_OF_pmap_dump.c' X /* X * pmap_dump - dump portmapper table in format readable by pmap_set X * X * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and X * Computing Science, Eindhoven University of Technology, The Netherlands. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#) pmap_dump.c 1.1 92/06/11 22:53:15"; X#endif X X#include <stdio.h> X#include <sys/types.h> X#ifdef SYSV40 X#include <netinet/in.h> X#include <rpc/rpcent.h> X#else X#include <netdb.h> X#endif X#include <rpc/rpc.h> X#include <rpc/pmap_clnt.h> X#include <rpc/pmap_prot.h> X Xstatic char *protoname(); X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X struct sockaddr_in addr; X register struct pmaplist *list; X register struct rpcent *rpc; X X get_myaddress(&addr); X X for (list = pmap_getmaps(&addr); list; list = list->pml_next) { X rpc = getrpcbynumber((int) list->pml_map.pm_prog); X printf("%10lu %4lu %5s %6lu %s\n", X list->pml_map.pm_prog, X list->pml_map.pm_vers, X protoname(list->pml_map.pm_prot), X list->pml_map.pm_port, X rpc ? rpc->r_name : ""); X } X#undef perror X return (fclose(stdout) ? (perror(argv[0]), 1) : 0); X} X Xstatic char *protoname(proto) Xu_long proto; X{ X static char buf[BUFSIZ]; X X switch (proto) { X case IPPROTO_UDP: X return ("udp"); X case IPPROTO_TCP: X return ("tcp"); X default: X sprintf(buf, "%lu", proto); X return (buf); X } X} END_OF_pmap_dump.c if test 1379 -ne `wc -c <pmap_dump.c`; then echo shar: \"pmap_dump.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f pmap_set.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"pmap_set.c\" else echo shar: Extracting \"pmap_set.c\" \(1511 characters\) sed "s/^X//" >pmap_set.c <<'END_OF_pmap_set.c' X /* X * pmap_set - set portmapper table from data produced by pmap_dump X * X * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and X * Computing Science, Eindhoven University of Technology, The Netherlands. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#) pmap_set.c 1.1 92/06/11 22:53:16"; X#endif X X#include <stdio.h> X#include <sys/types.h> X#ifdef SYSV40 X#include <netinet/in.h> X#endif X#include <rpc/rpc.h> X#include <rpc/pmap_clnt.h> X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X struct sockaddr_in addr; X char buf[BUFSIZ]; X u_long prog; X u_long vers; X int prot; X unsigned port; X X get_myaddress(&addr); X X while (fgets(buf, sizeof(buf), stdin)) { X if (parse_line(buf, &prog, &vers, &prot, &port) == 0) { X fprintf(stderr, "%s: malformed line: %s", argv[0], buf); X return (1); X } X if (pmap_set(prog, vers, prot, (unsigned short) port) == 0) X fprintf(stderr, "not registered: %s", buf); X } X return (0); X} X X/* parse_line - convert line to numbers */ X Xparse_line(buf, prog, vers, prot, port) Xchar *buf; Xu_long *prog; Xu_long *vers; Xint *prot; Xunsigned *port; X{ X char proto_name[BUFSIZ]; X X if (sscanf(buf, "%lu %lu %s %u", prog, vers, proto_name, port) != 4) { X return (0); X } X if (strcmp(proto_name, "tcp") == 0) { X *prot = IPPROTO_TCP; X return (1); X } X if (strcmp(proto_name, "udp") == 0) { X *prot = IPPROTO_UDP; X return (1); X } X if (sscanf(proto_name, "%d", prot) == 1) { X return (1); X } X return (0); X} END_OF_pmap_set.c if test 1511 -ne `wc -c <pmap_set.c`; then echo shar: \"pmap_set.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f from_local.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"from_local.c\" else echo shar: Extracting \"from_local.c\" \(4052 characters\) sed "s/^X//" >from_local.c <<'END_OF_from_local.c' X /* X * Check if an address belongs to the local system. Adapted from: X * X * @(#)pmap_svc.c 1.32 91/03/11 Copyright 1984,1990 Sun Microsystems, Inc. X * @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC. 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 or with the express written consent of X * Sun Microsystems, Inc. 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#ifndef lint Xstatic char sccsid[] = "@(#) from_local.c 1.1 92/06/11 22:53:17"; X#endif X X#ifdef TEST X#undef perror X#endif X X#include <sys/types.h> X#include <sys/socket.h> X#include <netdb.h> X#include <netinet/in.h> X#include <net/if.h> X#include <sys/ioctl.h> X#include <syslog.h> X X#ifndef TRUE X#define TRUE 1 X#define FALSE 0 X#endif X X/* How many interfaces could there be on a computer? */ X X#define MAX_LOCAL 16 Xstatic int num_local = -1; Xstatic struct in_addr addrs[MAX_LOCAL]; X X/* find_local - find all IP addresses for this host */ X Xfind_local() X{ X struct ifconf ifc; X struct ifreq ifreq; X struct ifreq *ifr; X struct ifreq *the_end; X int sock; X char buf[MAX_LOCAL * sizeof(struct ifreq)]; X X /* Get list of network interfaces. */ X X if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { X perror("socket"); X return (0); X } X ifc.ifc_len = sizeof(buf); X ifc.ifc_buf = buf; X if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) { X perror("SIOCGIFCONF"); X (void) close(sock); X return (0); X } X /* Get IP address of each active IP network interface. */ X X the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); X num_local = 0; X for (ifr = ifc.ifc_req; ifr < the_end; ifr++) { X if (ifr->ifr_addr.sa_family == AF_INET) { /* IP net interface */ X ifreq = *ifr; X if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) { X perror("SIOCGIFFLAGS"); X } else if (ifreq.ifr_flags & IFF_UP) { /* active interface */ X if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) { X perror("SIOCGIFADDR"); X } else { X addrs[num_local++] = ((struct sockaddr_in *) X & ifreq.ifr_addr)->sin_addr; X } X } X#ifdef TIRPC X /* Support for variable-length addresses. */ X if (num_local >= MAX_LOCAL) X break; X ifr = (struct ifreq *) ((caddr_t) ifr X + ifr->ifr_addr.sa_len - sizeof(struct sockaddr)); X#endif X } X } X (void) close(sock); X return (num_local); X} X X/* from_local - determine whether request comes from the local system */ X Xfrom_local(addr) Xstruct sockaddr_in *addr; X{ X int i; X X if (num_local == -1 && find_local() == 0) X syslog(LOG_ERR, "cannot find any active local network interfaces"); X X for (i = 0; i < num_local; i++) { X if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]), X sizeof(struct in_addr)) == 0) X return (TRUE); X } X return (FALSE); X} X X#ifdef TEST X Xmain() X{ X char *inet_ntoa(); X int i; X X find_local(); X for (i = 0; i < num_local; i++) X printf("%s\n", inet_ntoa(addrs[i])); X} X X#endif END_OF_from_local.c if test 4052 -ne `wc -c <from_local.c`; then echo shar: \"from_local.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f pmap_check.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"pmap_check.c\" else echo shar: Extracting \"pmap_check.c\" \(6443 characters\) sed "s/^X//" >pmap_check.c <<'END_OF_pmap_check.c' X /* X * pmap_check - additional portmap security. X * X * Always reject non-local requests to update the portmapper tables. X * X * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the X * requests would appear to come from the local system, and nfs export X * restrictions could be bypassed. X * X * Refuse to forward requests to the nfsd process. X * X * Refuse to forward requests to NIS (YP) daemons; The only exception is the X * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial X * contact with the NIS server. X * X * Always allocate an unprivileged port when forwarding a request. X * X * If compiled with -DCHECK_PORT, require that requests to register or X * unregister a privileged port come from a privileged port. This makes it X * more difficult to replace a critical service by a trojan. X * X * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not X * authorized by the /etc/hosts.{allow,deny} files. The local system is X * always treated as an authorized host. Access control is based on IP X * addresses only; attempts to map an address to a host name might cause the X * portmapper to hang. X * X * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and X * Computing Science, Eindhoven University of Technology, The Netherlands. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#) pmap_check.c 1.2 92/07/06 19:53:32"; X#endif X X#include <rpc/rpc.h> X#include <rpc/pmap_prot.h> X#include <syslog.h> X#include <netdb.h> X#include <sys/signal.h> X#ifdef SYSV40 X#include <netinet/in.h> X#include <rpc/rpcent.h> X#endif X Xextern char *inet_ntoa(); X X#include "pmap_check.h" X X/* Explicit #defines in case the include files are not available. */ X X#define NFSPROG ((u_long) 100003) X#define MOUNTPROG ((u_long) 100005) X#define YPXPROG ((u_long) 100069) X#define YPPROG ((u_long) 100004) X#define YPPROC_DOMAIN_NONACK ((u_long) 2) X#define MOUNTPROC_MNT ((u_long) 1) X Xstatic void logit(); Xstatic void toggle_verboselog(); Xstatic int verboselog = 0; X X/* A handful of macros for "readability". */ X X#define legal_host(a) \ X (from_local(a) || hosts_ctl("portmap", "", inet_ntoa(a->sin_addr), "")) X X#define legal_port(a,p) \ X (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED) X X#define log_bad_port(addr, proc, prog) \ X logit(LOG_ERR, addr, proc, prog, ": request from unprivileged port") X X#define log_bad_host(addr, proc, prog) \ X logit(LOG_ERR, addr, proc, prog, ": request from unauthorized host") X X#define log_bad_owner(addr, proc, prog) \ X logit(LOG_ERR, addr, proc, prog, ": request from non-local host") X X#define log_no_forward(addr, proc, prog) \ X logit(LOG_ERR, addr, proc, prog, ": request not forwarded") X X#define log_client(addr, proc, prog) \ X logit(LOG_INFO, addr, proc, prog, "") X X/* check_startup - additional startup code */ X Xvoid check_startup() X{ X X /* X * Give up root privileges so that we can never allocate a privileged X * port when forwarding an rpc request. X */ X if (setuid(1) == -1) { X syslog(LOG_ERR, "setuid(1) failed: %m"); X exit(1); X } X (void) signal(SIGINT, toggle_verboselog); X} X X/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */ X Xcheck_default(addr, proc, prog) Xstruct sockaddr_in *addr; Xu_long proc; Xu_long prog; X{ X#ifdef HOSTS_ACCESS X if (!legal_host(addr)) { X log_bad_host(addr, proc, prog); X return (FALSE); X } X#endif X if (verboselog) X log_client(addr, proc, prog); X return (TRUE); X} X X/* check_privileged_port - additional checks for privileged-port updates */ X Xcheck_privileged_port(addr, proc, prog, port) Xstruct sockaddr_in *addr; Xu_long proc; Xu_long prog; Xu_long port; X{ X#ifdef CHECK_PORT X if (!legal_port(addr, port)) { X log_bad_port(addr, proc, prog); X return (FALSE); X } X#endif X return (TRUE); X} X X/* check_setunset - additional checks for update requests */ X Xcheck_setunset(addr, proc, prog, port) Xstruct sockaddr_in *addr; Xu_long proc; Xu_long prog; Xu_long port; X{ X if (!from_local(addr)) { X log_bad_owner(addr, proc, prog); X return (FALSE); X } X if (port && !check_privileged_port(addr, proc, prog, port)) X return (FALSE); X if (verboselog) X log_client(addr, proc, prog); X return (TRUE); X} X X/* check_callit - additional checks for forwarded requests */ X Xcheck_callit(addr, proc, prog, aproc) Xstruct sockaddr_in *addr; Xu_long proc; Xu_long prog; Xu_long aproc; X{ X#ifdef HOSTS_ACCESS X if (!legal_host(addr)) { X log_bad_host(addr, proc, prog); X return (FALSE); X } X#endif X if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG || X (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) || X (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) { X log_no_forward(addr, proc, prog); X return (FALSE); X } X if (verboselog) X log_client(addr, proc, prog); X return (TRUE); X} X X/* toggle_verboselog - toggle verbose logging flag */ X Xstatic void toggle_verboselog(sig) Xint sig; X{ X (void) signal(sig, toggle_verboselog); X verboselog = !verboselog; X} X X/* logit - report events of interest via the syslog daemon */ X Xstatic void logit(severity, addr, procnum, prognum, text) Xint severity; Xstruct sockaddr_in *addr; Xu_long procnum; Xu_long prognum; Xchar *text; X{ X char *procname; X char procbuf[4 * sizeof(u_long)]; X char *progname; X char progbuf[4 * sizeof(u_long)]; X struct rpcent *rpc; X struct proc_map { X u_long code; X char *proc; X }; X struct proc_map *procp; X static struct proc_map procmap[] = { X PMAPPROC_CALLIT, "callit", X PMAPPROC_DUMP, "dump", X PMAPPROC_GETPORT, "getport", X PMAPPROC_NULL, "null", X PMAPPROC_SET, "set", X PMAPPROC_UNSET, "unset", X 0, 0, X }; X X /* X * Fork off a process or the portmap daemon might hang while X * getrpcbynumber() or syslog() does its thing. X */ X X if (fork() == 0) { X X /* Try to map program number to name. */ X X if (prognum == 0) { X progname = ""; X } else if (rpc = getrpcbynumber((int) prognum)) { X progname = rpc->r_name; X } else { X sprintf(progname = progbuf, "%lu", prognum); X } X X /* Try to map procedure number to name. */ X X for (procp = procmap; procp->proc && procp->code != procnum; procp++) X /* void */ ; X if ((procname = procp->proc) == 0) X sprintf(procname = procbuf, "%lu", (u_long) procnum); X X /* Write syslog record. */ X X syslog(severity, "connect from %s to %s(%s)%s", X inet_ntoa(addr->sin_addr), procname, progname, text); X exit(0); X } X} END_OF_pmap_check.c if test 6443 -ne `wc -c <pmap_check.c`; then echo shar: \"pmap_check.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f pmap_check.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"pmap_check.h\" else echo shar: Extracting \"pmap_check.h\" \(221 characters\) sed "s/^X//" >pmap_check.h <<'END_OF_pmap_check.h' X/* @(#) pmap_check.h 1.1 92/06/11 22:53:20 */ X Xextern int from_local(); Xextern void check_startup(); Xextern int check_default(); Xextern int check_setunset(); Xextern int check_privileged_port(); Xextern int check_callit(); END_OF_pmap_check.h if test 221 -ne `wc -c <pmap_check.h`; then echo shar: \"pmap_check.h\" 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\" \(1585 characters\) sed "s/^X//" >BLURB <<'END_OF_BLURB' X@(#) BLURB 1.2 92/07/06 19:57:28 X 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. These days, popular attacks on RPC daemons involve: X X - theft or NIS (YP) password files X X - ypset to force hosts to bind to a rogue NIS (YP) server X X - theft of NFS file handles X XMy contribution is a replacement portmap program, derived from source Xcode in the RPCSRC 4.0 and the TIRPC source distributions. Access Xcontrol is in the style of my tcp wrapper (log_tcp) package. It should Xwork with all SunOS 4.x and Ultrix >= 3.0 releases. However, the source Xis reasonably portable and the code should work on most UNIX systems Xthat provide SUNRPC on top of BSD-style TCP/IP. System V.4 support is Xproblematic, though. X XThe present portmap version attempts to close all portmap security Xproblems that are known to me. It should be as secure as the portmap Xdaemon that comes with the SunOS 4.x portmap+NIS patch (patch id X100482-02). The README file gives a complete list of security Xfeatures. X XWithout the availability of portmap source, possible alternatives are X1) packet filtering with a smart router; 2) linking the portmap Xexecutable against the securelib shared library. Linking other RPC Xdaemons against the securelib library is a good idea, anyway. X XThe source is available for anonymous FTP from ftp.win.tue.nl directory X/pub/security/portmap.shar.Z. X X Wietse Venema (wietse@wzv.win.tue.nl) X Mathematics and Computing Science X Eindhoven University of Technology X The Netherlands END_OF_BLURB if test 1585 -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