Project import
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..163a3ea
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,102 @@
+#
+# Copyright (c) 2010-2011 Nest, Inc.
+# All rights reserved.
+#
+# This document is the property of Nest. It is considered
+# confidential and proprietary information.
+#
+# This document may not be reproduced or transmitted in any form,
+# in whole or in part, without the express written permission of
+# Nest.
+#
+# Description:
+# This file is the makefile for the TCP/IP port number to RPC
+# number mapper daemon and utilities.
+#
+
+BuildConfigSpecialized := No
+BuildProductSpecialized := No
+
+include pre.mak
+
+PackageName := portmap
+
+PackageExtension := tar.gz
+PackageSeparator := _
+
+PackagePatchArgs := -p1
+
+PackageArchive := $(PackageName).$(PackageExtension)
+PackageSourceDir := $(PackageName)$(PackageSeparator)$(PackageVersion)
+
+PackageBuildMakefile = $(call GenerateBuildPaths,Makefile)
+
+CleanPaths += $(PackageLicenseFile)
+
+all: $(PackageDefaultGoal)
+
+# Generate the package license contents.
+
+$(PackageSourceDir)/portmap.c: source
+
+$(PackageLicenseFile): $(PackageSourceDir)/portmap.c
+ $(Verbose)$(SED) -n -e '/^\/\*-$$/,/\*\/$$/{;p;/\*\/$$/q;}' < $< > $@
+
+# Extract the source from the archive and apply patches, if any.
+
+$(PackageSourceDir): $(PackageArchive) $(PackagePatchPaths)
+ $(expand-and-patch-package)
+
+# Prepare the sources.
+
+.PHONY: source
+source: | $(PackageSourceDir)
+
+# Patch the sources, if necessary.
+
+.PHONY: patch
+patch: source
+
+# Generate the package build makefile.
+
+$(PackageBuildMakefile): | $(PackageSourceDir) $(BuildDirectory)
+ $(call create-links,$(CURDIR)/$(PackageSourceDir),$(BuildDirectory))
+
+# Configure the source for building.
+
+.PHONY: configure
+configure: source $(PackageBuildMakefile)
+
+# Build the source.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: build
+build: configure
+ $(Verbose)unset MAKEFLAGS && \
+ $(MAKE) $(JOBSFLAG) -C $(BuildDirectory) \
+ WRAP_INC="-I$(call GenerateResultPaths,sw/tps/tcp_wrappers,usr/include)" \
+ WRAP_LIB="-L$(call GenerateResultPaths,sw/tps/tcp_wrappers,usr/lib) -lwrap" \
+ INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+ CC="$(CC)" \
+ all
+
+# Stage the build to a temporary installation area.
+#
+# We have to unset MAKEFLAGS since they confuse the package build otherwise.
+
+.PHONY: stage
+stage: build | $(ResultDirectory)
+ $(Verbose)unset MAKEFLAGS && \
+ $(MAKE) $(JOBSFLAG) \
+ -C $(BuildDirectory) \
+ BASEDIR=$(ResultDirectory) \
+ INSTALL="$(INSTALL) $(INSTALLFLAGS)" \
+ install
+
+clean:
+ $(Verbose)$(RM) $(RMFLAGS) -r $(PackageSourceDir)
+ $(Verbose)$(RM) $(RMFLAGS) -r $(BuildDirectory)
+ $(Verbose)$(RM) $(RMFLAGS) -r $(ResultDirectory)
+
+include post.mak
diff --git a/portmap.patches/portmap-50.description b/portmap.patches/portmap-50.description
new file mode 100644
index 0000000..4049b94
--- /dev/null
+++ b/portmap.patches/portmap-50.description
@@ -0,0 +1,3 @@
+This patch adds support for specifying a non-standard location for TCP
+Wrappers headers, disables stripping binaries and setting user/group
+attributes (which fails for non-privileged users).
diff --git a/portmap.patches/portmap-50.patch b/portmap.patches/portmap-50.patch
new file mode 100644
index 0000000..7aa8bd5
--- /dev/null
+++ b/portmap.patches/portmap-50.patch
@@ -0,0 +1,32 @@
+diff -r -N -u portmap_6.0/Makefile portmap_6.0.N/Makefile
+--- portmap_6.0/Makefile 2007-05-10 20:02:10.000000000 -0700
++++ portmap_6.0.N/Makefile 2008-01-22 16:09:21.000000000 -0800
+@@ -128,6 +128,7 @@
+ portmap: CFLAGS += -fpie
+ portmap: LDLIBS += $(WRAP_LIB)
+ portmap: LDFLAGS += -pie
++portmap: CPPFLAGS += $(WRAP_INC)
+ portmap: portmap.o pmap_check.o from_local.o
+
+ from_local: CPPFLAGS += -DTEST
+@@ -136,12 +137,14 @@
+ sed $(MAN_SED) < portmap.8 > portmap.man
+
+ install: all
+- install -o root -g root -m 0755 -s portmap ${BASEDIR}/sbin
+- install -o root -g root -m 0755 -s pmap_dump ${BASEDIR}/sbin
+- install -o root -g root -m 0755 -s pmap_set ${BASEDIR}/sbin
+- install -o root -g root -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8
+- install -o root -g root -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8
+- install -o root -g root -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8
++ mkdir -p ${BASEDIR}/sbin
++ install -m 0755 portmap ${BASEDIR}/sbin
++ install -m 0755 pmap_dump ${BASEDIR}/sbin
++ install -m 0755 pmap_set ${BASEDIR}/sbin
++ mkdir -p ${BASEDIR}/usr/share/man/man8
++ install -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8
++ install -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8
++ install -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8
+
+ clean:
+ rm -f *.o portmap pmap_dump pmap_set from_local \
diff --git a/portmap.tar.gz b/portmap.tar.gz
new file mode 100644
index 0000000..e517542
--- /dev/null
+++ b/portmap.tar.gz
Binary files differ
diff --git a/portmap.url b/portmap.url
new file mode 100644
index 0000000..6b2aff3
--- /dev/null
+++ b/portmap.url
@@ -0,0 +1 @@
+http://neil.brown.name/portmap/portmap-6.0.tgz
diff --git a/portmap.version b/portmap.version
new file mode 100644
index 0000000..e0ea36f
--- /dev/null
+++ b/portmap.version
@@ -0,0 +1 @@
+6.0
diff --git a/portmap_6.0/BLURBv5 b/portmap_6.0/BLURBv5
new file mode 100644
index 0000000..ce28af8
--- /dev/null
+++ b/portmap_6.0/BLURBv5
@@ -0,0 +1,42 @@
+@(#) BLURB 1.5 96/07/06 23:09:45
+
+This is the fifth replacement portmapper release.
+
+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. Possible attacks on RPC daemons involve:
+
+ - theft of 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 (optional) is in the style of my tcp wrapper (log_tcp) package.
+
+Supported platforms: this program is known to work with all SunOS 4.x
+releases. With some Makefile editing it should also work on Ultrix 4.x,
+HP-UX 9.x, AIX 3.x and AIX 4.x, and Digital UNIX (OSF/1).
+
+Solaris 2.x and other System V.4 UNIXes should use use my rpcbind
+replacement (ftp.win.tue.nl:/pub/security/rpcbind_*.tar.Z).
+
+This portmap version attempts to close all portmap security problems
+that are known to me. 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 (which we do anyway); 2)
+linking the portmap executable against the securelib shared library.
+Linking 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_*.tar.gz.
+
+ Wietse Venema (wietse@wzv.win.tue.nl)
+ Mathematics and Computing Science
+ Eindhoven University of Technology
+ The Netherlands
diff --git a/portmap_6.0/CHANGES b/portmap_6.0/CHANGES
new file mode 100644
index 0000000..0e88d45
--- /dev/null
+++ b/portmap_6.0/CHANGES
@@ -0,0 +1,36 @@
+Changes with release 6.0 (May 2007)
+
+- compile and runtime selection of uid to 'setuid' to
+- mapping table is stored in a file and can be restored on restart
+- If a privilege program registers a non-privileged port, and
+ non-privileged program can no-longer unregister it.
+- add man pages
+- allow portmap to bind to a local address only
+- support 'chroot'
+- various cleanups and minor bug fixes
+
+
+Changes with release 5 (July 1996)
+
+Unprivileged clients can no longer unset or set the nfsd port.
+
+The really desperate can force all set/unset requests to arrive via the
+loopback interface and block set/unset requests from outside. Besides
+changes to the portmapper, this requires changes to system libraries,
+to statically linked rpc servers, to the kernel configuration (no IP
+source routing), and perhaps even to system startup procedures. Not for
+the faint of hart.
+
+Changes with release 4 (May 1996)
+
+The old code could not handle more than 16 interface addresses per
+host. With virtual hosting, a system can have more than 16 addresses.
+We now allocate memory dynamically.
+
+Support for AIX 4.1. Just like 4.4 BSD, it has variable-length sockaddr
+structures. Build with -DHAS_SA_LEN.
+
+Support for NextStep 3.2. This is a pre-posix system without setsid().
+
+Support for Digital UNIX on the Alpha. On these machines, long and int
+are not interchangeable.
diff --git a/portmap_6.0/Makefile b/portmap_6.0/Makefile
new file mode 100644
index 0000000..aa5e0b0
--- /dev/null
+++ b/portmap_6.0/Makefile
@@ -0,0 +1,157 @@
+
+####################################
+### Beginning of configurable stuff.
+
+# By default, logfile entries are written to the same file as used for
+# sendmail transaction logs. Change the definition of the following macro
+# if you disagree. See `man 3 syslog' for examples. Some syslog versions
+# do not provide this flexibility.
+
+FACILITY=LOG_DAEMON
+
+# To disable tcp-wrapper style access control, comment out the following
+# macro definitions. Access control can also be turned off by providing
+# no access control tables. The local system, since it runs the portmap
+# daemon, is always treated as an authorized host.
+# By default, access control does not do hostname lookup as there is a risk
+# that will require portmap access, hence deadlock. If you are sure the
+# target system will never user NIS for hostname lookup, you can define
+# USE_DNS to add hostname tests in hosts.allow/deny.
+
+ifeq ($(NO_TCP_WRAPPER),)
+CPPFLAGS += -DHOSTS_ACCESS
+WRAP_LIB = -lwrap
+ifdef USE_DNS
+CPPFLAGS += -DENABLE_DNS
+MAN_SED += -e 's/USE_DNS/yes/'
+endif
+endif
+
+# Comment out if your RPC library does not allocate privileged ports for
+# requests from processes with root privilege, or the new portmap will
+# always reject requests to register/unregister services on privileged
+# ports. You can find out by running "rpcinfo -p"; if all mountd and NIS
+# daemons use a port >= 1024 you should probably disable the next line.
+
+CPPFLAGS += -DCHECK_PORT
+
+# The portmap daemon runs a uid=1/gid=1 by default. You can change that
+# be defining DAEMON_UID and DAMEON_GID to numbers, or RPCUSER to a
+# name, though you must be sure that name lookup will not require use
+# of portmap.
+ifdef RPCUSER
+CPPFLAGS += -DRPCUSER=\"$(RPCUSER)\"
+MAN_SED += -e 's/RPCUSER/$(RPCUSER)/'
+else
+MAN_SED += -e 's/RPCUSER//'
+endif
+ifdef DAEMON_UID
+CPPFLAGS += -DDAEMON_UID=$(DAEMON_UID) -DDAEMON_GID=$(DAEMON_GID)
+MAN_SED += -e 's/DAEMON_UID/$(DAEMON_UID)/' -e 's/DAEMON_GID/$(DAEMON_GID)/'
+else
+MAN_SED += -e 's/DAEMON_UID/1/' -e 's/DAEMON_GID/1/'
+endif
+
+# Warning: troublesome feature ahead!! Enable only when you are really
+# desperate!!
+#
+# It is possible to prevent an attacker from manipulating your portmapper
+# tables from outside with requests that contain spoofed source addresses.
+# The countermeasure is to force all rpc servers to register and
+# unregister with the portmapper via the loopback network interface,
+# instead of via the primary network interface that every host can talk
+# to. For this countermeasure to work it is necessary to uncomment the
+# LOOPBACK definition below, and to take the following additional steps:
+#
+# (1) Modify the libc library (or librpc if you have one) and replace
+# get_myaddress() by a version that selects the loopback address instead
+# of the primary network interface address. A suitable version is
+# provided in the file get_myaddress.c. This forces rpc servers to send
+# all set/unset requests to the loopback address.
+#
+# (2) Rebuild all statically-linked rpc servers with the modified
+# library.
+#
+# (3) Disable IP source routing in the kernel (otherwise an outside
+# attacker can still send requests that appear to come from the local
+# machine).
+#
+# Instead of (1) it may be sufficient to run the rpc servers with a
+# preload shared object that implements the alternate get_myaddress()
+# behavior (see Makefile.shlib). You still need to disable IP source
+# routing, though.
+#
+# I warned you, you need to be really desperate to do this. It is
+# probably much easier to just block port UDP and TCP ports 111 on
+# your routers.
+#
+# CPPFLAGS += -DLOOPBACK_SETUNSET
+
+# When the portmapper cannot find any local interfaces (it will complain
+# to the syslog daemon) your system probably has variable-length socket
+# address structures (struct sockaddr has a sa_len component; examples:
+# AIX 4.1 and 4.4BSD). Uncomment next macro definition in that case.
+#
+# CPPFLAGS += -DHAS_SA_LEN # AIX 4.x, BSD 4.4, FreeBSD, NetBSD
+
+# With verbose logging on, HP-UX 9.x and AIX 4.1 leave zombies behind when
+# SIGCHLD is not ignored. Enable next macro for a fix.
+#
+CPPFLAGS += -DIGNORE_SIGCHLD # AIX 4.x, HP-UX 9.x
+
+# Uncomment the following macro if your system does not have u_long.
+#
+# CPPFLAGS +=-Du_long="unsigned long"
+
+#
+# LDLIBS += -m
+# CFLAGS += -arch m68k -arch i386 -arch hppa
+
+# Auxiliary libraries that you may have to specify
+#
+# LDLIBS += -lrpc
+
+# Comment out if your compiler talks ANSI and understands const
+#
+# CPPFLAGS += -Dconst=
+
+### End of configurable stuff.
+##############################
+
+CPPFLAGS += -DFACILITY=$(FACILITY)
+CFLAGS ?= -O2
+CFLAGS += -Wall -Wstrict-prototypes
+
+all: portmap pmap_dump pmap_set portmap.man
+
+CPPFLAGS += $(HOSTS_ACCESS)
+portmap: CFLAGS += -fpie
+portmap: LDLIBS += $(WRAP_LIB)
+portmap: LDFLAGS += -pie
+portmap: CPPFLAGS += $(WRAP_INC)
+portmap: portmap.o pmap_check.o from_local.o
+
+from_local: CPPFLAGS += -DTEST
+
+portmap.man : portmap.8
+ sed $(MAN_SED) < portmap.8 > portmap.man
+
+install: all
+ mkdir -p ${BASEDIR}/sbin
+ install -m 0755 portmap ${BASEDIR}/sbin
+ install -m 0755 pmap_dump ${BASEDIR}/sbin
+ install -m 0755 pmap_set ${BASEDIR}/sbin
+ mkdir -p ${BASEDIR}/usr/share/man/man8
+ install -m 0644 portmap.man ${BASEDIR}/usr/share/man/man8/portmap.8
+ install -m 0644 pmap_dump.8 ${BASEDIR}/usr/share/man/man8
+ install -m 0644 pmap_set.8 ${BASEDIR}/usr/share/man/man8
+
+clean:
+ rm -f *.o portmap pmap_dump pmap_set from_local \
+ core portmap.man
+
+-include .depend
+.depend: *.c
+ $(CC) -MM $(CFLAGS) *.c > .depend
+
+.PHONY: all clean install
diff --git a/portmap_6.0/README b/portmap_6.0/README
new file mode 100644
index 0000000..0da54cc
--- /dev/null
+++ b/portmap_6.0/README
@@ -0,0 +1,32 @@
+
+portmap-6.0 is the first release in 10 year of portmap based on the code
+from Wietse Venema.
+
+It consolidates patches that various Linux distributions were shipping
+with their versions of portmap, and add some more functionality.
+
+This version is currently maintained by
+ Neil Brown <neilb@suse.de>
+and can be found at
+ git://neil.brown.name/portmap
+ http://neil.brown.name/git/portmap
+ http://neil.brown.name/portmap/
+
+NeilBrown - 11may2007
+
+There is no "./configure", just use "make".
+
+Some make variable can be used to control compilation.
+
+ NO_TCP_WRAPPER= if non-empty, doen't use tcp_wrappers
+ USE_DNS= if set, tcp_wrappers can check peers based on hostname
+ as well as IP address. This should only be used if you
+ are certain that gethostbyname will never trigger a
+ called to portmap (as it might if 'nis' is used for hostnames).
+ RPCUSER= is set, portmap will use getpwnam to find the user for
+ that user, and will setuid to that user before listening
+ for incoming messages
+ DAEMON_UID= Can be set to a number to override the default UID
+ to setuid to. Default is '1'.
+ DAEMON_GID= As above, but for setgid.
+
diff --git a/portmap_6.0/README.5 b/portmap_6.0/README.5
new file mode 100644
index 0000000..c2b0c0b
--- /dev/null
+++ b/portmap_6.0/README.5
@@ -0,0 +1,214 @@
+@(#) README 1.7 96/07/06 23:06:19
+
+This is the README file for the 5th enhanced portmapper release.
+
+Description
+-----------
+
+This README describes a replacement portmapper that prevents theft of
+NIS (YP), NFS, and other sensitive information via the portmapper. As
+an option, the program supports access control in the style of the tcp
+wrapper (log_tcp) package.
+
+Like all portmappers, this one is intended to be started at boot time.
+Daemons that offer RPC services tell the portmapper on what port they
+listen. Unlike the well-known services registered with the inetd, RPC
+network port numbers may change each time the system is booted.
+Whenever a client wants to use an RPC service it is supposed to first
+ask the portmapper on what port the corresponding daemon is listening.
+The rpcinfo command can tell you what RPC services your system offers.
+
+As described in the features section below, the replacement portmapper
+can prevent undesirable client-server interactions. In some cases,
+better or equivalent alternatives are available:
+
+ The SunOS portmap that is provided with patch id 100482-02 should
+ close the same security holes. In addition, it provides an YPSERV
+ daemon with its own access control list. This is better than just
+ portmapper access control.
+
+ The "securelib" shared library (eecs.nwu.edu:/pub/securelib.tar)
+ implements access control for all kinds of (RPC) services, not
+ just the portmapper.
+
+However, vendors still ship portmap implementations that allow anyone
+to read or modify its tables and that will happily forward any request
+so that it appears to come from the local system.
+
+Features
+--------
+
+- optional: host access control. The local host is always considered
+authorized. Access control requires the libwrap.a library that comes
+with recent tcp wrapper (log_tcp) implementations.
+
+- requests to change the portmap tables are accepted only when they
+come from the local system.
+
+- optional: requests to (un)register services that listen on privileged
+ports (port < 1024) are accepted only when the requests themselves come
+from a privileged port. This feature is optional because of older RPC
+implementations.
+
+- requests that are forwarded by the portmapper will be forwarded
+through an unprivileged port.
+
+- the portmapper refuses to forward requests to rpc daemons that do (or
+should) verify the origin of each request: when the portmapper forwards
+a request it appears to come from the local machine. At present, the
+portmapper refuses to forward all RPC calls to itself, and most RPC
+calls to the NFS mountd/nfsd daemons, and to the NIS daemons.
+
+- the really desperate can harden the portmapper even more by requiring
+that requests to modify its tables arrive via the loopback network
+interface, instead of via the primary network interface that every host
+can talk to. The cost is high: besides changes to the portmapper, this
+requires changes to system libraries, to statically-linked rpc servers,
+to the kernel to disable IP source routing, and perhaps even to system
+startup procedures. Don't do this unless you're desperate. Details
+are given in the Makefile.
+
+Restrictions
+------------
+
+Limiting access to the portmapper does not protect you from direct
+attacks on the rpc daemons; the main task of portmap is to maintain a
+table of available RPC services and of the network ports that they are
+listening on. The securelib can be used to protect individual RPC
+daemons, and the latest SunOS portmap+NIS fix already protects the NIS
+daemons and implements limited forwarding.
+
+On the other hand, even though a portmapper with access control only
+makes an attack more difficult, it still provides an excellent early
+warning system.
+
+Origin and portability
+----------------------
+
+The sources in this distribution are derived from code on the second
+BSD networking tape, which was derived from Sun's RPCSRC 4.0 code, and
+from Sun's TIRPC (transport-independent rpc) distribution.
+
+The code compiles fine with SunOS 4.1.x, Ultrix 4.x, HP-UX 9.x, AIX 3.x
+and AIX 4.x, and Digital UNIX (OSF/1). See the notes in the Makefile.
+
+Solaris 2.x (and other true System V.4 clones) use a different program
+called rpcbind. I have written a replacement for that program, too.
+The primary achive is ftp.win.tue.nl:/pub/security/rpcbind_xx.tar.Z.
+
+Installation
+------------
+
+(1) Follow the instructions in the Makefile, then build the portmap and
+auxiliary executables.
+
+(2) Before killing the present portmap process, save the present
+portmapper tables using the command:
+
+ ./pmap_dump >table
+
+If you kill the portmap process without saving its tables you will have
+to reboot the machine.
+
+Note: the information in the portmap tables is dynamic: For example, it
+will be different after each reboot. On a Sun, it even changes each
+time a windowing system is started that uses the selection service.
+
+(3) Kill the running portmap process and start the new portmap
+program. Then (still as root) initialize the portmap tables with:
+
+ ./pmap_set <table
+
+(4) If you get error messages of the form: "not registered: xxxx",
+disable the CHECK_PORT feature in the Makefile, remove pmap_check.o and
+rebuild the portmap program. Then proceed with step 3.
+
+If the portmapper complains that it cannot find all machine interfaces
+you will have to rebuild it with -DHAS_SA_LEN set (see Makefile). You
+can test this with the "from_local" command (to build: make from_local).
+
+In order to revert to the original portmap daemon, kill off the running
+one, restart the original portmapper and reload its tables using the
+"pmap_set" command as shown above.
+
+Access control:
+---------------
+
+By default, host access control is enabled. However, the host that runs
+the portmapper is always considered authorized. The host access control
+tables are never consulted with requests from the local system itself;
+they are always consulted with requests from other hosts.
+
+In order to avoid deadlocks, the portmap program does not attempt to
+look up the remote host name or user name, nor will it try to match NIS
+netgroups. The upshot of all this is that only network number patterns
+will work for portmap access control.
+
+Sample entries for the host access-control files are:
+
+ /etc/hosts.allow:
+ portmap: your.sub.net.number/your.sub.net.mask
+ portmap: 255.255.255.255 0.0.0.0
+
+ /etc/hosts.deny
+ portmap: ALL: (/some/where/safe_finger -l @%h | mail root) &
+
+The syntax of the access-control files is described in the
+hosts_access.5 manual page that comes with the tcp wrapper (log_tcp)
+sources. The safe_finger command comes with later wrapper releases.
+
+The first line in the hosts.allow file permits access from all systems
+within your own subnet. Some rpc services rely on broadcasts and will
+contact your portmapper anyway; and once an intruder has access to your
+local network segment you're already in deep trouble.
+
+The second line in the hosts.allow file may be needed if there are
+any PC-NFS systems on your network segment.
+
+For security reasons, the portmap process drops root privilegs after
+initialization. The access control files should therefore be readable
+for group or world.
+
+Testing:
+--------
+
+Normally, only rejected requests will be reported via the syslog
+daemon. Logging is done in a child process, in order to avoid
+possible deadlock in case the logging code needs assistance from
+the portmapper.
+
+By default, the portmapper will be utterly silent. In fact, the portmap
+daemon is not consulted that often. Sending a SIGINT signal to the
+portmap process will enable the logging of all requests.
+
+Another way to enable verbose logging is to start the daemon with the
+"-v" option. See above, steps (2) and later, on how to stop and restart
+the portmapper without having to reboot.
+
+Warning: with some HP-UX and AIX versions, when verbose logging is on,
+the system fills up with zombie processes. This can be fixed by
+compiling with -DIGNORE_SIGCHLD (see instructions in the Makefile).
+
+With verbose logging turned on, requests such as "ypcat" or "rpcinfo
+-p" should show up with log file entries such as:
+
+ MMM dd hh:mm:ss hostname portmap[pid]: connect from x.x.x.x to getport(ypserv)
+ MMM dd hh:mm:ss hostname portmap[pid]: connect from y.y.y.y to dump()
+
+Send SIGINT to the portmapper to turn the verbose logging off.
+
+Acknowledgements
+----------------
+
+Casper H.S. Dik (casper@fwi.uva.nl) provided valuable information on
+RPC security and tested an intermediate version of the portmapper with
+SunOS 4.1.2. Lyford D. Rich (rich@ece.nps.navy.mil) was helpful with
+porting the daemon to Ultrix 3.x. Lionel Cons (cons@dxcern.cern.ch)
+solved the HP-UX problem. Fabrice Gonton (Fabrice.Gonton@sagem.fr)
+figured out how to make the program work on AIX 4.1, and Michael
+Matthews took care of the DEC Alpha platform.
+
+ Wietse Venema (wietse@wzv.win.tue.nl)
+ Mathematics and Computing Science
+ Eindhoven University of Technology
+ The Netherlands
diff --git a/portmap_6.0/from_local.c b/portmap_6.0/from_local.c
new file mode 100644
index 0000000..da851c6
--- /dev/null
+++ b/portmap_6.0/from_local.c
@@ -0,0 +1,180 @@
+ /*
+ * Check if an address belongs to the local system. Adapted from:
+ *
+ * pmap_svc.c 1.32 91/03/11 Copyright 1984,1990 Sun Microsystems, Inc.
+ * get_myaddress.c 2.1 88/07/29 4.0 RPCSRC.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <syslog.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+ /*
+ * With virtual hosting, each hardware network interface can have multiple
+ * network addresses. On such machines the number of machine addresses can
+ * be surprisingly large.
+ */
+static int num_local;
+static int num_addrs;
+static struct in_addr *addrs;
+
+/* grow_addrs - extend list of local interface addresses */
+
+static int grow_addrs(void)
+{
+ struct in_addr *new_addrs;
+ int new_num;
+
+ /*
+ * Keep the previous result if we run out of memory. The system would
+ * really get hosed if we simply give up.
+ */
+ new_num = (addrs == 0) ? 1 : num_addrs + num_addrs;
+ new_addrs = (struct in_addr *) malloc(sizeof(*addrs) * new_num);
+ if (new_addrs == 0) {
+ perror("portmap: out of memory");
+ return (0);
+ } else {
+ if (addrs != 0) {
+ memcpy((char *) new_addrs, (char *) addrs,
+ sizeof(*addrs) * num_addrs);
+ free((char *) addrs);
+ }
+ num_addrs = new_num;
+ addrs = new_addrs;
+ return (1);
+ }
+}
+
+/* find_local - find all IP addresses for this host */
+
+static int
+find_local(void)
+{
+ struct ifconf ifc;
+ struct ifreq ifreq;
+ struct ifreq *ifr;
+ struct ifreq *the_end;
+ int sock;
+ char buf[BUFSIZ];
+
+ /*
+ * Get list of network interfaces. We use a huge buffer to allow for the
+ * presence of non-IP interfaces.
+ */
+
+ if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ return (0);
+ }
+ ifc.ifc_len = sizeof(buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) < 0) {
+ perror("SIOCGIFCONF");
+ (void) close(sock);
+ return (0);
+ }
+ /* Get IP address of each active IP network interface. */
+
+ the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
+ num_local = 0;
+ for (ifr = ifc.ifc_req; ifr < the_end; ifr++) {
+ if (ifr->ifr_addr.sa_family == AF_INET) { /* IP net interface */
+ ifreq = *ifr;
+ if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
+ perror("SIOCGIFFLAGS");
+ } else if (ifreq.ifr_flags & IFF_UP) { /* active interface */
+ if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) {
+ perror("SIOCGIFADDR");
+ } else {
+ if (num_local >= num_addrs)
+ if (grow_addrs() == 0)
+ break;
+ addrs[num_local++] = ((struct sockaddr_in *)
+ & ifreq.ifr_addr)->sin_addr;
+ }
+ }
+ }
+ /* Support for variable-length addresses. */
+#ifdef HAS_SA_LEN
+ ifr = (struct ifreq *) ((caddr_t) ifr
+ + ifr->ifr_addr.sa_len - sizeof(struct sockaddr));
+#endif
+ }
+ (void) close(sock);
+ return (num_local);
+}
+
+/* from_local - determine whether request comes from the local system */
+
+int from_local(struct sockaddr_in *addr)
+{
+ int i;
+
+ if (addrs == 0 && find_local() == 0)
+ syslog(LOG_ERR, "cannot find any active local network interfaces");
+
+ for (i = 0; i < num_local; i++) {
+ if (memcmp((char *) &(addr->sin_addr), (char *) &(addrs[i]),
+ sizeof(struct in_addr)) == 0)
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+#ifdef TEST
+
+main()
+{
+ char *inet_ntoa();
+ int i;
+
+ find_local();
+ for (i = 0; i < num_local; i++)
+ printf("%s\n", inet_ntoa(addrs[i]));
+}
+
+#endif
diff --git a/portmap_6.0/pmap_check.c b/portmap_6.0/pmap_check.c
new file mode 100644
index 0000000..84f2c12
--- /dev/null
+++ b/portmap_6.0/pmap_check.c
@@ -0,0 +1,328 @@
+ /*
+ * pmap_check - additional portmap security.
+ *
+ * Always reject non-local requests to update the portmapper tables.
+ *
+ * Refuse to forward mount requests to the nfs mount daemon. Otherwise, the
+ * requests would appear to come from the local system, and nfs export
+ * restrictions could be bypassed.
+ *
+ * Refuse to forward requests to the nfsd process.
+ *
+ * Refuse to forward requests to NIS (YP) daemons; The only exception is the
+ * YPPROC_DOMAIN_NONACK broadcast rpc call that is used to establish initial
+ * contact with the NIS server.
+ *
+ * Always allocate an unprivileged port when forwarding a request.
+ *
+ * If compiled with -DCHECK_PORT, require that requests to register or
+ * unregister a privileged port come from a privileged port. This makes it
+ * more difficult to replace a critical service by a trojan. Also, require
+ * that requests to set/unset the NFSD port come form a privileged port.
+ *
+ * If compiled with -DHOSTS_ACCESS, reject requests from hosts that are not
+ * authorized by the /etc/hosts.{allow,deny} files. The local system is
+ * always treated as an authorized host. The access control tables are never
+ * consulted for requests from the local system, and are always consulted
+ * for requests from other hosts. Access control is based on IP addresses
+ * only; attempts to map an address to a host name might cause the
+ * portmapper to hang.
+ *
+ * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+ * Computing Science, Eindhoven University of Technology, The Netherlands.
+ */
+
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#include <rpc/rpcent.h>
+#endif
+#include <tcpd.h>
+#include <arpa/inet.h>
+#include <grp.h>
+
+#include "pmap_check.h"
+
+/* Explicit #defines in case the include files are not available. */
+
+#define NFSPROG ((u_long) 100003)
+#define MOUNTPROG ((u_long) 100005)
+#define YPXPROG ((u_long) 100069)
+#define YPPROG ((u_long) 100004)
+#define YPPROC_DOMAIN_NONACK ((u_long) 2)
+#define MOUNTPROC_MNT ((u_long) 1)
+#define NFS_PORT 2049
+
+static void logit(int severity, struct sockaddr_in *addr,
+ u_long procnum, u_long prognum, char *text);
+static void toggle_verboselog(int sig);
+int verboselog __attribute ((visibility ("hidden"))) = 0;
+int allow_severity __attribute ((visibility ("hidden"))) = LOG_INFO;
+int deny_severity __attribute ((visibility ("hidden"))) = LOG_WARNING;
+
+/* A handful of macros for "readability". */
+
+#define reserved_port(p) (IPPORT_RESERVED/2 < (p) && (p) < IPPORT_RESERVED)
+
+#define unreserved_port(p) (IPPORT_RESERVED <= (p) && (p) != NFS_PORT)
+
+#define legal_port(a,p) \
+ (reserved_port(ntohs((a)->sin_port)) || unreserved_port(p))
+
+#define log_bad_port(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
+
+#define log_bad_host(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
+
+#define log_bad_owner(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request from non-local host")
+
+#define log_no_forward(addr, proc, prog) \
+ logit(deny_severity, addr, proc, prog, ": request not forwarded")
+
+#define log_client(addr, proc, prog) \
+ logit(allow_severity, addr, proc, prog, "")
+
+/* check_startup - additional startup code */
+
+void check_startup(void)
+{
+
+ /*
+ * Give up root privileges so that we can never allocate a privileged
+ * port when forwarding an rpc request.
+ */
+ setgid(daemon_gid);
+ setgroups(0, NULL);
+ if (setuid(daemon_uid) == -1) {
+ syslog(LOG_ERR, "setuid(1) failed: %m");
+ exit(1);
+ }
+ (void) signal(SIGINT, toggle_verboselog);
+}
+
+
+#ifdef HOSTS_ACCESS
+static int
+good_client(struct sockaddr_in *addr)
+{
+ if (hosts_ctl("portmap", "", inet_ntoa(addr->sin_addr), ""))
+ return 1;
+#ifdef ENABLE_DNS
+{
+ struct hostent *hp;
+ char **sp;
+ char *tmpname;
+
+ /* Check the hostname. */
+ hp = gethostbyaddr ((const char *) &(addr->sin_addr),
+ sizeof (addr->sin_addr), AF_INET);
+
+ if (!hp)
+ return 0;
+
+ /* must make sure the hostent is authoritative. */
+ tmpname = alloca (strlen (hp->h_name) + 1);
+ strcpy (tmpname, hp->h_name);
+ hp = gethostbyname(tmpname);
+ if (hp) {
+ /* now make sure the "addr->sin_addr" is on the list */
+ for (sp = hp->h_addr_list ; *sp ; sp++) {
+ if (memcmp(*sp, &(addr->sin_addr), hp->h_length)==0)
+ break;
+ }
+ if (!*sp)
+ /* it was a FAKE. */
+ return 0;
+ } else
+ /* never heard of it. misconfigured DNS? */
+ return 0;
+
+ /* Check the official name first. */
+ if (hosts_ctl("portmap", "", hp->h_name, ""))
+ return 1;
+
+ /* Check aliases. */
+ for (sp = hp->h_aliases; *sp ; sp++) {
+ if (hosts_ctl("portmap", "", *sp, ""))
+ return 1;
+ }
+}
+#endif /* ENABLE_DNS */
+ return 0;
+}
+#endif /* HOSTS_ACCESS */
+
+/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
+
+int
+check_default(struct sockaddr_in *addr, u_long proc,
+ u_long prog)
+{
+#ifdef HOSTS_ACCESS
+ if (!(from_local(addr) || good_client(addr))) {
+ log_bad_host(addr, proc, prog);
+ return (FALSE);
+ }
+#endif
+ if (verboselog)
+ log_client(addr, proc, prog);
+ return (TRUE);
+}
+
+/* check_privileged_port - additional checks for privileged-port updates */
+
+int
+check_privileged_port(struct sockaddr_in *addr, u_long proc,
+ u_long prog, u_long port)
+{
+#ifdef CHECK_PORT
+ if (!legal_port(addr, port)) {
+ log_bad_port(addr, proc, prog);
+ return (FALSE);
+ }
+#endif
+ return (TRUE);
+}
+
+/* check_setunset - additional checks for update requests */
+
+#ifdef LOOPBACK_SETUNSET
+
+int
+check_setunset(SVCXPRT *xprt, SVCXPRT *ludp_xprt, SVCXPRT *ltcp_xprt,
+ u_long proc, u_long prog, u_long port)
+{
+ struct sockaddr_in *addr = svc_getcaller(xprt);
+
+ if (xprt != ludp_xprt && xprt != ltcp_xprt) {
+#ifdef HOSTS_ACCESS
+ (void) good_client(addr); /* because of side effects */
+#endif
+ log_bad_owner(addr, proc, prog);
+ return (FALSE);
+ }
+ if (port && !check_privileged_port(addr, proc, prog, port))
+ return (FALSE);
+ if (verboselog)
+ log_client(addr, proc, prog);
+ return (TRUE);
+}
+
+#else
+
+int
+check_setunset(struct sockaddr_in *addr, u_long proc,
+ u_long prog, u_long port)
+{
+ if (!from_local(addr)) {
+#ifdef HOSTS_ACCESS
+ (void) good_client(addr); /* because of side effects */
+#endif
+ log_bad_owner(addr, proc, prog);
+ return (FALSE);
+ }
+ if (port && !check_privileged_port(addr, proc, prog, port))
+ return (FALSE);
+ if (verboselog)
+ log_client(addr, proc, prog);
+ return (TRUE);
+}
+
+#endif
+
+/* check_callit - additional checks for forwarded requests */
+
+int
+check_callit(struct sockaddr_in *addr, u_long proc,
+ u_long prog, u_long aproc)
+{
+#ifdef HOSTS_ACCESS
+ if (!(from_local(addr) || good_client(addr))) {
+ log_bad_host(addr, proc, prog);
+ return (FALSE);
+ }
+#endif
+ if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG ||
+ (prog == MOUNTPROG && aproc == MOUNTPROC_MNT) ||
+ (prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) {
+ log_no_forward(addr, proc, prog);
+ return (FALSE);
+ }
+ if (verboselog)
+ log_client(addr, proc, prog);
+ return (TRUE);
+}
+
+/* toggle_verboselog - toggle verbose logging flag */
+
+static void toggle_verboselog(int sig)
+{
+ (void) signal(sig, toggle_verboselog);
+ verboselog = !verboselog;
+}
+
+/* logit - report events of interest via the syslog daemon */
+
+static void logit(int severity, struct sockaddr_in *addr,
+ u_long procnum, u_long prognum, char *text)
+{
+ char *procname;
+ char procbuf[4 * sizeof(u_long)];
+ char *progname;
+ char progbuf[4 * sizeof(u_long)];
+ struct rpcent *rpc;
+ struct proc_map {
+ u_long code;
+ char *proc;
+ };
+ struct proc_map *procp;
+ static struct proc_map procmap[] = {
+ { PMAPPROC_CALLIT, "callit" },
+ { PMAPPROC_DUMP, "dump"} ,
+ { PMAPPROC_GETPORT, "getport"} ,
+ { PMAPPROC_NULL, "null"} ,
+ { PMAPPROC_SET, "set"} ,
+ { PMAPPROC_UNSET, "unset"} ,
+ { 0, 0} ,
+ };
+
+ /*
+ * Fork off a process or the portmap daemon might hang while
+ * getrpcbynumber() or syslog() does its thing.
+ */
+
+ if (fork() == 0) {
+
+ /* Try to map program number to name. */
+
+ if (prognum == 0) {
+ progname = "";
+ } else if ((rpc = getrpcbynumber((int) prognum))) {
+ progname = rpc->r_name;
+ } else {
+ sprintf(progname = progbuf, "%lu", prognum);
+ }
+
+ /* Try to map procedure number to name. */
+
+ for (procp = procmap; procp->proc && procp->code != procnum; procp++)
+ /* void */ ;
+ if ((procname = procp->proc) == 0)
+ sprintf(procname = procbuf, "%lu", (u_long) procnum);
+
+ /* Write syslog record. */
+
+ syslog(severity, "connect from %s to %s(%s)%s",
+ inet_ntoa(addr->sin_addr), procname, progname, text);
+ exit(0);
+ }
+}
diff --git a/portmap_6.0/pmap_check.h b/portmap_6.0/pmap_check.h
new file mode 100644
index 0000000..bc21dfd
--- /dev/null
+++ b/portmap_6.0/pmap_check.h
@@ -0,0 +1,33 @@
+/* pmap_check.h */
+
+extern int from_local(struct sockaddr_in *addr);
+extern void check_startup(void);
+extern int check_default(struct sockaddr_in *addr,
+ u_long proc, u_long prog);
+#ifdef LOOPBACK_SETUNSET
+extern int
+check_setunset(SVCXPRT *xprt, SVCXPRT *ludp_xprt, SVCXPRT *ltcp_xprt,
+ u_long proc, u_long prog, u_long port);
+#else
+extern int
+check_setunset(struct sockaddr_in *addr, u_long proc,
+ u_long prog, u_long port);
+#endif
+extern int check_privileged_port(struct sockaddr_in *addr,
+ u_long proc,
+ u_long prog, u_long port);
+extern int check_callit(struct sockaddr_in *addr, u_long proc,
+ u_long prog, u_long aproc);
+extern int verboselog __attribute__ ((visibility ("hidden")));
+extern int allow_severity __attribute__ ((visibility ("hidden")));
+extern int deny_severity __attribute__ ((visibility ("hidden")));
+
+#ifdef LOOPBACK_SETUNSET
+#define CHECK_SETUNSET check_setunset
+#else
+#define CHECK_SETUNSET(xprt,ludp,ltcp,proc,prog,port) \
+ check_setunset(svc_getcaller(xprt),proc,prog,port)
+#endif
+
+extern int daemon_uid;
+extern int daemon_gid;
diff --git a/portmap_6.0/pmap_dump.8 b/portmap_6.0/pmap_dump.8
new file mode 100644
index 0000000..0da5162
--- /dev/null
+++ b/portmap_6.0/pmap_dump.8
@@ -0,0 +1,24 @@
+.TH PMAP_DUMP 8 "21th June 1997" Linux "Linux Programmer's Manual"
+.SH NAME
+pmap_dump \- print a list of all registered RPC programs
+.SH SYNOPSIS
+.B pmap_dump
+.SH DESCRIPTION
+The
+.B pmap_dump
+command can be used to restart a running portmapper or to print
+a list of all registered RPC programs on the local host. If you
+want to use the program to restart the portmapper you have to
+redirect the output of
+.B pmap_dump
+to a file. After this you can restart the portmapper and restore
+the list of the registered RPC programs by feeding the output
+of
+.B pmap_dump
+to the
+.B pmap_set
+command.
+.SH SEE ALSO
+.BR pmap_set (8),
+.BR portmap (8)
+
diff --git a/portmap_6.0/pmap_dump.c b/portmap_6.0/pmap_dump.c
new file mode 100644
index 0000000..333f41d
--- /dev/null
+++ b/portmap_6.0/pmap_dump.c
@@ -0,0 +1,59 @@
+ /*
+ * pmap_dump - dump portmapper table in format readable by pmap_set
+ *
+ * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+ * Computing Science, Eindhoven University of Technology, The Netherlands.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#include <rpc/rpcent.h>
+#else
+#include <netdb.h>
+#endif
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+
+static char *protoname(u_long proto);
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr_in addr;
+ struct pmaplist *list;
+ struct rpcent *rpc;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = htons(PMAPPORT);
+
+ for (list = pmap_getmaps(&addr); list; list = list->pml_next) {
+ rpc = getrpcbynumber((int) list->pml_map.pm_prog);
+ printf("%10lu %4lu %5s %6lu %s\n",
+ list->pml_map.pm_prog,
+ list->pml_map.pm_vers,
+ protoname(list->pml_map.pm_prot),
+ list->pml_map.pm_port,
+ rpc ? rpc->r_name : "");
+ }
+ return (fclose(stdout) ? (perror(argv[0]), 1) : 0);
+}
+
+static char *protoname(u_long proto)
+{
+ static char buf[BUFSIZ];
+
+ switch (proto) {
+ case IPPROTO_UDP:
+ return ("udp");
+ case IPPROTO_TCP:
+ return ("tcp");
+ default:
+ sprintf(buf, "%lu", proto);
+ return (buf);
+ }
+}
diff --git a/portmap_6.0/pmap_set.8 b/portmap_6.0/pmap_set.8
new file mode 100644
index 0000000..c4da65d
--- /dev/null
+++ b/portmap_6.0/pmap_set.8
@@ -0,0 +1,24 @@
+.TH PMAP_SET 8 "21th June 1997" Linux "Linux Programmer's Manual"
+.SH NAME
+pmap_set \- set the list of registered RPC programs
+.SH SYNOPSIS
+.B pmap_set
+.SH DESCRIPTION
+The
+.B pmap_set
+command can be used to restart a running portmapper or to set
+the list of registered RPC programs on the local host. If you
+want to use the program to restart the portmapper you have to
+redirect the output of
+.B pmap_dump
+to a file. After this you can restart the portmapper and restore
+the list of the registered RPC programs by feeding the output
+of
+.B pmap_dump
+to the
+.B pmap_set
+command.
+.SH SEE ALSO
+.BR pmap_dump (8),
+.BR portmap (8)
+
diff --git a/portmap_6.0/pmap_set.c b/portmap_6.0/pmap_set.c
new file mode 100644
index 0000000..017a359
--- /dev/null
+++ b/portmap_6.0/pmap_set.c
@@ -0,0 +1,63 @@
+ /*
+ * pmap_set - set portmapper table from data produced by pmap_dump
+ *
+ * Author: Wietse Venema (wietse@wzv.win.tue.nl), dept. of Mathematics and
+ * Computing Science, Eindhoven University of Technology, The Netherlands.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#endif
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+
+static int
+parse_line(char *buf, u_long *prog, u_long *vers,
+ int *prot, unsigned *port);
+
+int
+main(int argc, char **argv)
+{
+ char buf[BUFSIZ];
+ u_long prog;
+ u_long vers;
+ int prot;
+ unsigned port;
+
+ while (fgets(buf, sizeof(buf), stdin)) {
+ if (parse_line(buf, &prog, &vers, &prot, &port) == 0) {
+ fprintf(stderr, "%s: malformed line: %s", argv[0], buf);
+ return (1);
+ }
+ if (pmap_set(prog, vers, prot, (unsigned short) port) == 0)
+ fprintf(stderr, "not registered: %s", buf);
+ }
+ return (0);
+}
+
+/* parse_line - convert line to numbers */
+
+static int
+parse_line(char *buf, u_long *prog, u_long *vers,
+ int *prot, unsigned *port)
+{
+ char proto_name[256];
+
+ if (sscanf(buf, "%lu %lu %255s %u", prog, vers, proto_name, port) != 4) {
+ return (0);
+ }
+ if (strcmp(proto_name, "tcp") == 0) {
+ *prot = IPPROTO_TCP;
+ return (1);
+ }
+ if (strcmp(proto_name, "udp") == 0) {
+ *prot = IPPROTO_UDP;
+ return (1);
+ }
+ if (sscanf(proto_name, "%d", prot) == 1) {
+ return (1);
+ }
+ return (0);
+}
diff --git a/portmap_6.0/portmap.8 b/portmap_6.0/portmap.8
new file mode 100644
index 0000000..4c92cac
--- /dev/null
+++ b/portmap_6.0/portmap.8
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1987 Sun Microsystems
+.\" Copyright (c) 1990, 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)portmap.8 5.3 (Berkeley) 3/16/91
+.\" $Id: portmap.8,v 1.2 2004/04/03 09:30:21 herbert Exp $
+.\"
+.Dd Apr 20, 2007
+.Dt PORTMAP 8
+.Os BSD 4.3
+.Sh NAME
+.Nm portmap
+.Nd
+.Tn DARPA
+port to
+.Tn RPC
+program number mapper
+.Sh SYNOPSIS
+.Nm portmap
+.Op Fl d
+.Op Fl f
+.Op Fl t Ar dir
+.Op Fl v
+.Op Fl V
+.Op Fl i Ar address
+.Op Fl l
+.Op Fl u Ar uid
+.Op Fl g Ar gid
+.Sh DESCRIPTION
+.Nm Portmap
+is a server that converts
+.Tn RPC
+program numbers into
+.Tn DARPA
+protocol port numbers.
+It must be running in order to make
+.Tn RPC
+calls.
+.Pp
+When an
+.Tn RPC
+server is started, it will tell
+.Nm portmap
+what port number it is listening to, and what
+.Tn RPC
+program numbers it is prepared to serve.
+When a client wishes to make an
+.Tn RPC
+call to a given program number,
+it will first contact
+.Nm portmap
+on the server machine to determine
+the port number where
+.Tn RPC
+packets should be sent.
+.Pp
+.Nm Portmap
+must be started before any
+.Tn RPC
+servers are invoked.
+.Pp
+Normally
+.Nm portmap
+forks and dissociates itself from the terminal
+like any other daemon.
+.Nm Portmap
+then logs errors using
+.Xr syslog 3 .
+.Pp
+.Nm Portmap
+records all current mapping in the file
+.Nm /var/run/portmap_mapping
+so that if it gets killed and restarted, it can reload the mapping for
+currently active services.
+.Pp
+Options available:
+.Bl -tag -width Ds
+.It Fl V
+Display version number and exit.
+.It Fl d
+(debug) prevents
+.Nm portmap
+from running as a daemon,
+and causes errors and debugging information
+to be printed to the standard error output.
+.It Fl f
+(foreground) prevents
+.Nm portmap
+from running as a daemon,
+and causes log messages
+to be printed to the standard error output.
+.It Fl t Ar dir
+(chroot) tell
+.Nm portmap
+to
+.Xr chroot 2
+into
+.Ar dir .
+.Ar dir
+should be empty, not writeable by the daemon user, and preferably on a
+filesystem mounted read-only, noexec, nodev, and nosuid.
+.It Fl u Ar uid
+.It Fl g Ar gid
+Set the user-id and group-id of the running process to those given,
+rather than the compiled-in defaults of DAEMON_UID/DAEMON_GID.
+.if 'RPCUSER'' .ig
+If neither are set, then
+.Nm portmap
+will look up the user
+.Nm RPCUSER
+and use the uid and gid of that user.
+..
+.It Fl v
+(verbose) run
+.Nm portmap
+in verbose mode.
+.It Fl i Ar address
+bind
+.Nm portmap
+to address. If you specify 127.0.0.1 it will bind to the loopback
+interface only.
+.It Fl l
+bind
+.Nm portmap
+to the loop-back address 127.0.0.1. This is a shorthand for
+specifying 127.0.0.1 with -i.
+.El
+
+This
+.Nm portmap
+version is protected by the
+.Nm tcp_wrapper
+library. You have to give the clients access to
+.Nm portmap
+if they should be allowed to use it.
+.if 'USE_DNS'yes' .ig
+To allow connects from clients of the network 192.168. you could use
+the following line in /etc/hosts.allow:
+
+portmap: 192.168.
+
+In order to avoid deadlocks, the
+.Nm portmap
+program does not attempt to look up the remote host name or user name, nor will
+it try to match NIS netgroups. As a consequence only network number patterns
+(or IP addresses) will work for portmap access control, do not use hostnames.
+Notice that localhost will always be allowed access to the portmapper.
+
+You have to use the daemon name
+.Nm portmap
+for the daemon name (even if the binary has a different name). For the
+client names you can only use the keyword ALL or IP addresses (NOT
+host or domain names).
+..
+.if !'USE_DNS'yes' .ig
+To allow connects from clients of
+the .bar.com domain you could use the following line in /etc/hosts.allow:
+.Pp
+portmap: .bar.com
+.Pp
+You have to use the daemon name
+.Nm portmap
+for the daemon name (even if the binary has a different name). For the
+client names you can use the keyword ALL, IP addresses, hostnames or domain
+names. Using netgroup names will likely cause
+.Nm portmap
+to deadlock.
+Note that localhost will always be allowed access to the portmapper.
+..
+
+For further information please have a look at the
+.Xr tcpd 8 ,
+.Xr hosts_allow 5
+and
+.Xr hosts_access 5
+manual pages.
+
+.Sh SEE ALSO
+.Xr inetd.conf 5 ,
+.Xr rpcinfo 8 ,
+.Xr pmap_set 8 ,
+.Xr pmap_dump 8 ,
+.Xr inetd 8 ,
+.Xr tcpd 8 ,
+.Xr hosts_access 5 ,
+.Xr hosts_options 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3
+.Sh AUTHORS
+This
+manual page was changed by
+.An Anibal Monsalve Salazar
+for the Debian Project.
diff --git a/portmap_6.0/portmap.c b/portmap_6.0/portmap.c
new file mode 100644
index 0000000..2a98881
--- /dev/null
+++ b/portmap_6.0/portmap.c
@@ -0,0 +1,864 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1990 The Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
+/*
+@(#)portmap.c 2.3 88/08/11 4.0 RPCSRC
+static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
+*/
+
+/*
+ * portmap.c, Implements the program,version to port number mapping for
+ * rpc.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#ifdef SYSV40
+#include <netinet/in.h>
+#endif
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <pwd.h>
+
+#ifndef LOG_PERROR
+#define LOG_PERROR 0
+#endif
+
+#ifndef LOG_DAEMON
+#define LOG_DAEMON 0
+#endif
+
+/* Older SYSV. */
+#if !defined(SIGCHLD) && defined(SIGCLD)
+#define SIGCHLD SIGCLD
+#endif
+
+#ifndef svc_getcaller /* SYSV4 */
+# define svc_getcaller svc_getrpccaller
+#endif
+
+static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt);
+#ifndef IGNORE_SIGCHLD /* Lionel Cons <cons@dxcern.cern.ch> */
+static void reap(int);
+#endif
+static void callit(struct svc_req *rqstp, SVCXPRT *xprt);
+struct pmaplist *pmaplist;
+int debugging = 0;
+int store_fd = -1;
+static void dump_table(void);
+static void load_table(void);
+
+#include "pmap_check.h"
+
+ /*
+ * How desperate can one be. It is possible to prevent an attacker from
+ * manipulating your portmapper tables from outside with requests that
+ * contain spoofed source address information. The countermeasure is to
+ * force all rpc servers to register and unregister with the portmapper via
+ * the loopback network interface, instead of via the primary network
+ * interface that every host can talk to. For this countermeasure to work it
+ * is necessary to #define LOOPBACK_SETUNSET, to disable source routing in
+ * the kernel, and to modify libc so that get_myaddress() chooses the
+ * loopback interface address.
+ */
+
+#ifdef LOOPBACK_SETUNSET
+static SVCXPRT *ludpxprt, *ltcpxprt;
+static int on = 1;
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK ntohl(inet_addr("127.0.0.1"))
+#endif
+#endif
+
+#ifdef DAEMON_UID
+int daemon_uid = DAEMON_UID;
+int daemon_gid = DAEMON_GID;
+#else
+int daemon_uid = 1;
+int daemon_gid = 1;
+#endif
+
+/*
+ * We record with each registration a flag telling whether it was
+ * registered with a privilege port or not.
+ * If it was, it can only be unregistered with a privileged port.
+ * So that we can still use standard pmap xdr routines, we store
+ * this flag in a structure wrapped around a pmaplist.
+ */
+struct flagged_pml {
+ struct pmaplist pml;
+ int priv;
+};
+
+int
+main(int argc, char **argv)
+{
+ SVCXPRT *xprt;
+ int sock, c;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+ struct pmaplist *pml;
+ struct flagged_pml *fpml;
+ char *chroot_path = NULL;
+ struct in_addr bindaddr;
+ int have_bindaddr = 0;
+ int foreground = 0;
+ int have_uid = 0;
+
+ while ((c = getopt(argc, argv, "Vdflt:vi:u:g:")) != EOF) {
+ switch (c) {
+
+ case 'V':
+ printf("portmap version 6.0 - 2007-May-11\n");
+ exit(1);
+
+ case 'u':
+ daemon_uid = atoi(optarg);
+ if (daemon_uid <= 0) {
+ fprintf(stderr,
+ "portmap: illegal uid: %s\n", optarg);
+ exit(1);
+ }
+ have_uid = 1;
+ break;
+ case 'g':
+ daemon_gid = atoi(optarg);
+ if (daemon_gid <= 0) {
+ fprintf(stderr,
+ "portmap: illegal gid: %s\n", optarg);
+ exit(1);
+ }
+ have_uid = 1;
+ break;
+ case 'd':
+ debugging = 1;
+ case 'f':
+ foreground = 1;
+ break;
+
+ case 't':
+ chroot_path = optarg;
+ break;
+
+ case 'v':
+ verboselog = 1;
+ break;
+
+ case 'l':
+ optarg = "127.0.0.1";
+ /* FALL THROUGH */
+ case 'i':
+ have_bindaddr = inet_aton(optarg, &bindaddr);
+ break;
+ default:
+ fprintf(stderr,
+ "usage: %s [-dflv] [-t dir] [-i address] "
+ "[-u uid] [-g gid]\n",
+ argv[0]);
+ fprintf(stderr, "-d: debugging mode\n");
+ fprintf(stderr,
+ "-f: don't daemonize, log to standard error\n");
+ fprintf(stderr, "-t dir: chroot into dir\n");
+ fprintf(stderr, "-v: verbose logging\n");
+ fprintf(stderr, "-i address: bind to address\n");
+ fprintf(stderr, "-l: same as -i 127.0.0.1\n");
+ fprintf(stderr, "-u uid : setuid to this uid\n");
+ fprintf(stderr, "-g uid : setgid to this gid\n");
+ exit(1);
+ }
+ }
+
+ if (!foreground && daemon(0, 0)) {
+ (void) fprintf(stderr, "portmap: fork: %s", strerror(errno));
+ exit(1);
+ }
+
+#ifdef LOG_DAEMON
+ openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0),
+ FACILITY);
+#else
+ openlog("portmap", LOG_PID|LOG_NDELAY | ( foreground ? LOG_PERROR : 0));
+#endif
+
+#ifdef RPCUSER
+ if (!have_uid) {
+ struct passwd *pwent;
+ pwent = getpwnam(RPCUSER);
+ if (pwent) {
+ daemon_uid = pwent->pw_uid;
+ daemon_gid = pwent->pw_gid;
+ } else
+ syslog(LOG_WARNING, "user '" RPCUSER
+ "' not found, reverting to default uid");
+ }
+#endif
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ syslog(LOG_ERR, "cannot create udp socket: %m");
+ exit(1);
+ }
+#ifdef LOOPBACK_SETUNSET
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+#endif
+
+ memset((char *) &addr, 0, sizeof(addr));
+ addr.sin_addr.s_addr = 0;
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(PMAPPORT);
+ if (have_bindaddr)
+ memcpy(&addr.sin_addr, &bindaddr, sizeof(bindaddr));
+
+ if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+ syslog(LOG_ERR, "cannot bind udp: %m");
+ exit(1);
+ }
+
+ if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "couldn't do udp_create");
+ exit(1);
+ }
+ /* make an entry for ourself */
+ fpml = malloc(sizeof(struct flagged_pml));
+ pml = &fpml->pml;
+ fpml->priv = 1;
+ pml->pml_next = NULL;
+ pml->pml_map.pm_prog = PMAPPROG;
+ pml->pml_map.pm_vers = PMAPVERS;
+ pml->pml_map.pm_prot = IPPROTO_UDP;
+ pml->pml_map.pm_port = PMAPPORT;
+ pmaplist = pml;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ syslog(LOG_ERR, "cannot create tcp socket: %m");
+ exit(1);
+ }
+#ifdef LOOPBACK_SETUNSET
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+#endif
+ if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+ syslog(LOG_ERR, "cannot bind tcp: %m");
+ exit(1);
+ }
+ if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
+ == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "couldn't do tcp_create");
+ exit(1);
+ }
+ /* make an entry for ourself */
+ fpml = malloc(sizeof(struct flagged_pml));
+ pml = &fpml->pml;
+ fpml->priv = 1;
+ pml->pml_map.pm_prog = PMAPPROG;
+ pml->pml_map.pm_vers = PMAPVERS;
+ pml->pml_map.pm_prot = IPPROTO_TCP;
+ pml->pml_map.pm_port = PMAPPORT;
+ pml->pml_next = pmaplist;
+ pmaplist = pml;
+
+#ifdef LOOPBACK_SETUNSET
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ syslog(LOG_ERR, "cannot create udp socket: %m");
+ exit(1);
+ }
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+ syslog(LOG_ERR, "cannot bind udp: %m");
+ exit(1);
+ }
+
+ if ((ludpxprt = svcudp_create(sock)) == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "couldn't do udp_create");
+ exit(1);
+ }
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ syslog(LOG_ERR, "cannot create tcp socket: %m");
+ exit(1);
+ }
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
+ if (bind(sock, (struct sockaddr *)&addr, len) != 0) {
+ syslog(LOG_ERR, "cannot bind tcp: %m");
+ exit(1);
+ }
+ if ((ltcpxprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE))
+ == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "couldn't do tcp_create");
+ exit(1);
+ }
+#endif
+
+ (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE);
+
+ store_fd = open("/var/run/portmap_mapping", O_RDWR|O_CREAT, 0600);
+ load_table();
+
+ /* additional initializations */
+ if (chroot_path) {
+ if (chroot(chroot_path) < 0) {
+ syslog(LOG_ERR, "couldn't do chroot");
+ exit(1);
+ }
+ }
+ check_startup();
+#ifdef IGNORE_SIGCHLD /* Lionel Cons <cons@dxcern.cern.ch> */
+ (void)signal(SIGCHLD, SIG_IGN);
+#else
+ (void)signal(SIGCHLD, reap);
+#endif
+ (void)signal(SIGPIPE, SIG_IGN);
+ svc_run();
+ syslog(LOG_ERR, "run_svc returned unexpectedly");
+ abort();
+}
+
+/* need to override perror calls in rpc library */
+void perror(const char *what)
+{
+
+ syslog(LOG_ERR, "%s: %m", what);
+}
+
+static struct pmaplist *
+find_service(u_long prog, u_long vers, u_long prot)
+{
+ struct pmaplist *hit = NULL;
+ struct pmaplist *pml;
+
+ for (pml = pmaplist; pml != NULL; pml = pml->pml_next) {
+ if ((pml->pml_map.pm_prog != prog) ||
+ (pml->pml_map.pm_prot != prot))
+ continue;
+ hit = pml;
+ if (pml->pml_map.pm_vers == vers)
+ break;
+ }
+ return (hit);
+}
+
+/*
+ * 1 OK, 0 not
+ */
+static void reg_service(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+ struct pmap reg;
+ struct pmaplist *pml, *prevpml, *fnd;
+ struct flagged_pml *fpml;
+ int ans, port;
+ caddr_t t;
+
+ /*
+ * Later wrappers change the logging severity on the fly. Reset to
+ * defaults before handling the next request.
+ */
+ allow_severity = LOG_INFO;
+ deny_severity = LOG_WARNING;
+
+ if (debugging)
+ (void) fprintf(stderr, "server: about do a switch\n");
+ switch (rqstp->rq_proc) {
+
+ case PMAPPROC_NULL:
+ /*
+ * Null proc call
+ */
+ /* remote host authorization check */
+ check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0);
+ if (!svc_sendreply(xprt, (xdrproc_t) xdr_void, (caddr_t)0)
+ && debugging) {
+ abort();
+ }
+ break;
+
+ case PMAPPROC_SET:
+ /*
+ * Set a program,version to port mapping
+ */
+ if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (caddr_t)®))
+ svcerr_decode(xprt);
+ else {
+ /* reject non-local requests, protect priv. ports */
+ if (!CHECK_SETUNSET(xprt, ludpxprt, ltcpxprt,
+ rqstp->rq_proc, reg.pm_prog, reg.pm_port)) {
+ ans = 0;
+ goto done;
+ }
+ /*
+ * check to see if already used
+ * find_service returns a hit even if
+ * the versions don't match, so check for it
+ */
+ fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+ if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) {
+ if (fnd->pml_map.pm_port == reg.pm_port) {
+ ans = 1;
+ goto done;
+ }
+ else {
+ ans = 0;
+ goto done;
+ }
+ } else {
+ /*
+ * add to END of list
+ */
+ fpml = (struct flagged_pml *)
+ malloc((u_int)sizeof(struct flagged_pml));
+ pml = &fpml->pml;
+ fpml->priv =
+ (ntohs(svc_getcaller(xprt)->sin_port)
+ < IPPORT_RESERVED);
+ pml->pml_map = reg;
+ pml->pml_next = 0;
+
+ if (pmaplist == 0) {
+ pmaplist = pml;
+ } else {
+ for (fnd= pmaplist; fnd->pml_next != 0;
+ fnd = fnd->pml_next);
+ fnd->pml_next = pml;
+ }
+ ans = 1;
+ dump_table();
+ }
+ done:
+ if ((!svc_sendreply(xprt, (xdrproc_t)xdr_int,
+ (caddr_t)&ans)) &&
+ debugging) {
+ (void) fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_UNSET:
+ /*
+ * Remove a program,version to port mapping.
+ */
+ if (!svc_getargs(xprt, (xdrproc_t)xdr_pmap, (caddr_t)®))
+ svcerr_decode(xprt);
+ else {
+ ans = 0;
+ /* reject non-local requests */
+ if (!CHECK_SETUNSET(xprt, ludpxprt, ltcpxprt,
+ rqstp->rq_proc, reg.pm_prog, (u_long) 0))
+ goto done;
+ for (prevpml = NULL, pml = pmaplist; pml != NULL; ) {
+ if ((pml->pml_map.pm_prog != reg.pm_prog) ||
+ (pml->pml_map.pm_vers != reg.pm_vers)) {
+ /* both pml & prevpml move forwards */
+ prevpml = pml;
+ pml = pml->pml_next;
+ continue;
+ }
+ /* found it; pml moves forward, prevpml stays */
+ /* privileged port check */
+ if (!check_privileged_port(svc_getcaller(xprt),
+ rqstp->rq_proc,
+ reg.pm_prog,
+ pml->pml_map.pm_port)) {
+ ans = 0;
+ break;
+ }
+ fpml = (struct flagged_pml*)pml;
+ if (fpml->priv &&
+ (ntohs(svc_getcaller(xprt)->sin_port)
+ >= IPPORT_RESERVED)) {
+ ans = 0;
+ break;
+ }
+
+ ans = 1;
+ t = (caddr_t)pml;
+ pml = pml->pml_next;
+ if (prevpml == NULL)
+ pmaplist = pml;
+ else
+ prevpml->pml_next = pml;
+ free(t);
+ dump_table();
+ }
+ if ((!svc_sendreply(xprt, (xdrproc_t)xdr_int,
+ (caddr_t)&ans)) &&
+ debugging) {
+ (void) fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_GETPORT:
+ /*
+ * Lookup the mapping for a program,version and return its port
+ */
+ if (!svc_getargs(xprt, (xdrproc_t)xdr_pmap, (caddr_t)®))
+ svcerr_decode(xprt);
+ else {
+ /* remote host authorization check */
+ if (!check_default(svc_getcaller(xprt),
+ rqstp->rq_proc,
+ reg.pm_prog)) {
+ ans = 0;
+ goto done;
+ }
+ fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+ if (fnd)
+ port = fnd->pml_map.pm_port;
+ else
+ port = 0;
+ if ((!svc_sendreply(xprt, (xdrproc_t)xdr_int,
+ (caddr_t)&port)) &&
+ debugging) {
+ (void) fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_DUMP:
+ /*
+ * Return the current set of mapped program,version
+ */
+ if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL))
+ svcerr_decode(xprt);
+ else {
+ /* remote host authorization check */
+ struct pmaplist *p;
+ if (!check_default(svc_getcaller(xprt),
+ rqstp->rq_proc, (u_long) 0)) {
+ p = 0; /* send empty list */
+ } else {
+ p = pmaplist;
+ }
+ if ((!svc_sendreply(xprt, (xdrproc_t)xdr_pmaplist,
+ (caddr_t)&p)) && debugging) {
+ (void) fprintf(stderr, "svc_sendreply\n");
+ abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_CALLIT:
+ /*
+ * Calls a procedure on the local machine. If the requested
+ * procedure is not registered this procedure does not return
+ * error information!!
+ * This procedure is only supported on rpc/udp and calls via
+ * rpc/udp. It passes null authentication parameters.
+ */
+ callit(rqstp, xprt);
+ break;
+
+ default:
+ /* remote host authorization check */
+ check_default(svc_getcaller(xprt), rqstp->rq_proc, (u_long) 0);
+ svcerr_noproc(xprt);
+ break;
+ }
+}
+
+
+/*
+ * Stuff for the rmtcall service
+ */
+#define ARGSIZE 9000
+
+struct encap_parms {
+ u_int arglen;
+ char *args;
+};
+
+static bool_t
+xdr_encap_parms(XDR *xdrs, struct encap_parms *epp)
+{
+
+ return (xdr_bytes(xdrs, &(epp->args), &(epp->arglen), ARGSIZE));
+}
+
+struct rmtcallargs {
+ u_long rmt_prog;
+ u_long rmt_vers;
+ u_long rmt_port;
+ u_long rmt_proc;
+ struct encap_parms rmt_args;
+};
+
+static bool_t
+xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap)
+{
+
+ /* does not get a port number */
+ if (xdr_u_long(xdrs, &(cap->rmt_prog)) &&
+ xdr_u_long(xdrs, &(cap->rmt_vers)) &&
+ xdr_u_long(xdrs, &(cap->rmt_proc))) {
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ }
+ return (FALSE);
+}
+
+static bool_t
+xdr_rmtcall_result(XDR *xdrs, struct rmtcallargs *cap)
+{
+ if (xdr_u_long(xdrs, &(cap->rmt_port)))
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ return (FALSE);
+}
+
+/*
+ * only worries about the struct encap_parms part of struct rmtcallargs.
+ * The arglen must already be set!!
+ */
+static bool_t
+xdr_opaque_parms(XDR *xdrs, struct rmtcallargs *cap)
+{
+
+ return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
+}
+
+/*
+ * This routine finds and sets the length of incoming opaque paraters
+ * and then calls xdr_opaque_parms.
+ */
+static bool_t
+xdr_len_opaque_parms(XDR *xdrs, struct rmtcallargs *cap)
+{
+ u_int beginpos, lowpos, highpos, currpos, pos;
+
+ beginpos = lowpos = pos = xdr_getpos(xdrs);
+ highpos = lowpos + ARGSIZE;
+ while ((int)(highpos - lowpos) >= 0) {
+ currpos = (lowpos + highpos) / 2;
+ if (xdr_setpos(xdrs, currpos)) {
+ pos = currpos;
+ lowpos = currpos + 1;
+ } else {
+ highpos = currpos - 1;
+ }
+ }
+ xdr_setpos(xdrs, beginpos);
+ cap->rmt_args.arglen = pos - beginpos;
+ return (xdr_opaque_parms(xdrs, cap));
+}
+
+/*
+ * Call a remote procedure service
+ * This procedure is very quiet when things go wrong.
+ * The proc is written to support broadcast rpc. In the broadcast case,
+ * a machine should shut-up instead of complain, less the requestor be
+ * overrun with complaints at the expense of not hearing a valid reply ...
+ *
+ * This now forks so that the program & process that it calls can call
+ * back to the portmapper.
+ */
+static void callit(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+ struct rmtcallargs a;
+ struct pmaplist *pml;
+ u_short port;
+ struct sockaddr_in me;
+ int pid, so = -1;
+ CLIENT *client;
+ struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred;
+ struct timeval timeout;
+ char buf[ARGSIZE];
+
+ timeout.tv_sec = 5;
+ timeout.tv_usec = 0;
+ a.rmt_args.args = buf;
+ if (!svc_getargs(xprt, (xdrproc_t)xdr_rmtcall_args, (caddr_t)&a))
+ return;
+ /* host and service access control */
+ if (!check_callit(svc_getcaller(xprt),
+ rqstp->rq_proc, a.rmt_prog, a.rmt_proc))
+ return;
+ if ((pml = find_service(a.rmt_prog, a.rmt_vers,
+ (u_long)IPPROTO_UDP)) == NULL)
+ return;
+ /*
+ * fork a child to do the work. Parent immediately returns.
+ * Child exits upon completion.
+ */
+ if ((pid = fork()) != 0) {
+ if (pid < 0)
+ syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m",
+ a.rmt_prog);
+ return;
+ }
+ port = pml->pml_map.pm_port;
+ get_myaddress(&me);
+ me.sin_port = htons(port);
+ client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so);
+ if (client != (CLIENT *)NULL) {
+ if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
+ client->cl_auth = authunix_create(au->aup_machname,
+ au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids);
+ }
+ a.rmt_port = (u_long)port;
+ if (clnt_call(client, a.rmt_proc, (xdrproc_t)xdr_opaque_parms,
+ (caddr_t)&a, (xdrproc_t)xdr_len_opaque_parms,
+ (caddr_t)&a, timeout) == RPC_SUCCESS) {
+ svc_sendreply(xprt, (xdrproc_t)xdr_rmtcall_result,
+ (caddr_t)&a);
+ }
+ AUTH_DESTROY(client->cl_auth);
+ clnt_destroy(client);
+ }
+ (void)close(so);
+ exit(0);
+}
+
+#ifndef IGNORE_SIGCHLD /* Lionel Cons <cons@dxcern.cern.ch> */
+static void reap(int ignore)
+{
+ int save_errno = errno;
+ while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0);
+ errno = save_errno;
+}
+#endif
+
+/* Dump and restore mapping table so that we can survive kill/restart.
+ * To cope with chroot, an fd is opened early and we just write to that.
+ * If we are killed while writing the file, we lose, but that isn't
+ * very likely...
+ */
+
+static void dump_table(void)
+{
+ FILE *f;
+ struct pmaplist *pml;
+
+ if (store_fd < 0)
+ return;
+ ftruncate(store_fd, 0);
+ lseek(store_fd, 0, 0);
+ f = fdopen(dup(store_fd), "w");
+ if (!f)
+ return;
+
+ for (pml = pmaplist ; pml ; pml = pml->pml_next) {
+ struct flagged_pml *fpml = (struct flagged_pml*)pml;
+
+ fprintf(f, "%lu %lu %lu %lu %d\n",
+ pml->pml_map.pm_prog,
+ pml->pml_map.pm_vers,
+ pml->pml_map.pm_prot,
+ pml->pml_map.pm_port,
+ fpml->priv);
+ }
+ fclose(f);
+}
+
+static void load_table(void)
+{
+ FILE *f;
+ struct pmaplist **ep;
+ struct flagged_pml fpml, *fpmlp;
+
+ ep = &pmaplist;
+ while ((*ep)->pml_next)
+ ep = & (*ep)->pml_next;
+
+ if (store_fd < 0)
+ return;
+ lseek(store_fd, 0, 0);
+ f = fdopen(dup(store_fd), "r");
+ if (f == NULL)
+ return;
+
+ while (fscanf(f, "%lu %lu %lu %lu %d\n",
+ &fpml.pml.pml_map.pm_prog,
+ &fpml.pml.pml_map.pm_vers,
+ &fpml.pml.pml_map.pm_prot,
+ &fpml.pml.pml_map.pm_port,
+ &fpml.priv) == 5) {
+ if (fpml.pml.pml_map.pm_port == PMAPPORT)
+ continue;
+ fpmlp = malloc(sizeof(struct flagged_pml));
+ if (!fpmlp)
+ break;
+ *fpmlp = fpml;
+ *ep = &fpmlp->pml;
+ ep = &fpmlp->pml.pml_next;
+ *ep = NULL;
+ }
+ fclose(f);
+}