diff options
author | wpaul <wpaul@FreeBSD.org> | 1995-12-16 20:54:17 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1995-12-16 20:54:17 +0000 |
commit | 6c6bb5ba6adeb2ff4ad3daae731ae6fd78bdaa36 (patch) | |
tree | b482c0df4aeed97dbf67034a03c60d54726b3959 /usr.sbin | |
parent | 5cb69655f98eb01c22037b87a84bb2bd50a7b0fb (diff) | |
parent | f177e119995c5aae346675c30599d00d3286440c (diff) | |
download | FreeBSD-src-6c6bb5ba6adeb2ff4ad3daae731ae6fd78bdaa36.zip FreeBSD-src-6c6bb5ba6adeb2ff4ad3daae731ae6fd78bdaa36.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r12891,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ypserv/Makefile | 35 | ||||
-rw-r--r-- | usr.sbin/ypserv/Makefile.yp | 394 | ||||
-rwxr-xr-x | usr.sbin/ypserv/mknetid | 36 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_access.c | 146 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_dblookup.c | 217 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_dnslookup.c | 111 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_error.c | 86 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_extern.h | 73 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_main.c | 315 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_server.c | 626 | ||||
-rw-r--r-- | usr.sbin/ypserv/ypserv.8 | 306 |
11 files changed, 2345 insertions, 0 deletions
diff --git a/usr.sbin/ypserv/Makefile b/usr.sbin/ypserv/Makefile new file mode 100644 index 0000000..e3fe74a --- /dev/null +++ b/usr.sbin/ypserv/Makefile @@ -0,0 +1,35 @@ +# $Id: Makefile,v 1.6 1995/12/16 04:03:02 wpaul Exp $ + +PROG= ypserv +SRCS= yp_svc.c yp_server.c yp_dblookup.c yp_dnslookup.c \ + yp_main.c yp_error.c yp_access.c + +MAN8= ypserv.8 + +CLEANFILES= yp_svc.c yp.h + +RPCSRC= ${.DESTDIR}/usr/include/rpcsvc/yp.x +RPCGEN= rpcgen -I -C -DYPSERV_ONLY + +# We need to remove the 'static' keyword from _rpcsvcstate so that +# yp_main.c can see it. +yp_svc.c: ${RPCSRC} yp.h + rm -f ${.TARGET} + ${RPCGEN} -m ${RPCSRC} | \ + sed s/"static int _rpcsvcstate"/"int _rpcsvcstate"/g > ${.TARGET} + +yp_xdr.c: ${RPCSRC} yp.h + ${RPCGEN} -c -o ${.TARGET} ${RPCSRC} + +yp.h: ${RPCSRC} + ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} + +afterinstall: + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${.CURDIR}/Makefile.yp \ + ${DESTDIR}/var/yp/Makefile + ${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \ + ${.CURDIR}/mknetid \ + ${DESTDIR}/usr/libexec/mknetid + +.include <bsd.prog.mk> diff --git a/usr.sbin/ypserv/Makefile.yp b/usr.sbin/ypserv/Makefile.yp new file mode 100644 index 0000000..67da59ad --- /dev/null +++ b/usr.sbin/ypserv/Makefile.yp @@ -0,0 +1,394 @@ +# +# Makefile for the NIS databases +# +# $Id: Makefile.yp,v 1.1 1995/12/09 04:33:14 wpaul Exp $ +# +# This Makefile should only be run on the NIS master server of a domain. +# All updated maps will be pushed to all NIS slave servers listed in the +# /var/yp/ypservers file. Please make sure that the hostnames of all +# NIS servers in your domain are listed in /var/yp/ypservers. +# +# This Makefile can be modified to support more NIS maps if desired. +# + +# If this machine is an NIS master, comment out this next line so +# that changes to the NIS maps can be propagated to the slave servers. +# (By default we assume that we are only serving a small domain with +# only one server.) +# +NOPUSH = "True" + +# If you want to use a FreeBSD NIS server to serve non-FreeBSD clients +# (i.e. clients who expect the password field in the passwd maps to be +# valid) then uncomment this line. This will cause $YPDIR/passwd to +# be generated with valid password fields. This is insecure: FreeBSD +# normally only serves the master.passwd maps (which have real encrypted +# passwords in them) to the superuser on other FreeBSD machines, but +# non-FreeBSD clients (e.g. SunOS, Solaris (without NIS+), IRIX, HP-UX, +# etc...) will only work properly in 'unsecure' mode. +# +#UNSECURE = "True" + +# These are commands which this Makefile needs to properly rebuild the +# NIS databases. Don't change these unless you have a good reason. Also +# be sure not to place an @ in front of /usr/bin/awk: it isn't necessary +# and it'll break everything in sight. +# +AWK = /usr/bin/awk +RM = @/bin/rm -f +RCAT = /bin/cat +CAT = @$(RCAT) + +DBLOAD = /usr/sbin/yp_mkdb -m `hostname` +MKNETID = /usr/libexec/mknetid +YPPUSH = /usr/bin/yppush +DOMAIN = `/bin/domainname` +REVNETGROUP = /usr/libexec/revnetgroup + +YPSRCDIR = /etc +YPDIR = /var/yp +YPMAPDIR = $(YPDIR)/$(DOMAIN) + +# These are the files from which the NIS databases are built. You may edit +# these to taste in the event that you wish to keep your NIS source files +# seperate from your NIS server's actual configuration files. Note that the +# NIS passwd and master.passwd files are stored in /var/yp: the server's +# real password database is not used by default. However, you may use +# the real /etc/passwd and /etc/master.passwd files by: +# +# +# - invoking yppasswdd without the -m option (yppasswdd will use +# /etc/master.passwd if no alternate master.passwd file is specified +# and do a 'pwd_mkdb' as needed). +# - Specifying the location of the master.passwd file using the +# MASTER_PASSWD variable, i.e.: +# +# # make MASTER_PASSWD=/path/to/some/other/master.passwd +# +# - (optionally): editing this Makefile to change the default location. +# +# To add a user, edit $(YPDIR)/master.passwd and type 'make'. The raw +# passwd file will be generated from the master.passwd file automagically. +# +ETHERS = $(YPSRCDIR)/ethers # ethernet addresses (for rarpd) +BOOTPARAMS= $(YPSRCDIR)/bootparams # for booting Sun boxes (bootparamd) +HOSTS = $(YPSRCDIR)/hosts +NETWORKS = $(YPSRCDIR)/networks +PROTOCOLS = $(YPSRCDIR)/protocols +RPC = $(YPSRCDIR)/rpc +SERVICES = $(YPSRCDIR)/services +GROUP = $(YPSRCDIR)/group +NETGROUP = $(YPSRCDIR)/netgroup +PASSWD = $(YPDIR)/passwd +.if !defined(MASTER_PASSWD) +MASTER = $(YPDIR)/master.passwd +.else +MASTER = $(MASTER_PASSWD) +.endif +YPSERVERS = $(YPDIR)/ypservers # List of all NIS servers for a domain +PUBLICKEY = $(YPSRCDIR)/publickey + +target: + @if [ ! -d $(DOMAIN) ]; then mkdir $(DOMAIN); fi; \ + cd $(DOMAIN) ; echo "NIS Map update started on `date`" ; \ + make -f ../Makefile all; echo "NIS Map update completed." + +# If you don't want some of these maps built, feel free to comment +# them out from this list. +# Note that we don't build the ethers or boorparams maps by default +# since /etc/ethers and /etc/bootparams are not likely to be present +# on all systems. +# + +all: master.passwd passwd hosts group networks protocols \ + rpc services servers netid # publickey netgroup ethers bootparam + +ethers: ethers.byname ethers.byaddr +bootparam: bootparams +hosts: hosts.byname hosts.byaddr +networks: networks.byaddr networks.byname +protocols: protocols.bynumber protocols.byname +rpc: rpc.byname rpc.bynumber +services: services.byname +passwd: passwd.byname passwd.byuid +group: group.byname group.bygid +netgrp: netgroup +netid: netid.byname +servers: ypservers +publickey: publickey.byname + +master.passwd: master.passwd.byname master.passwd.byuid + + +ypservers: $(YPSERVERS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(YPSERVERS) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#") print $$0"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(YPSERVERS) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + +ethers.byname: $(ETHERS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(ETHERS) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#" && $$1 != "+") \ + print $$2"\t"$$0 }' $^ | $(DBLOAD) -i $(ETHERS) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) -i $(ETHERS) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +ethers.byaddr: $(ETHERS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(ETHERS) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#" && $$1 != "+") \ + print $$1"\t"$$0 }' $^ | $(DBLOAD) -i $(ETHERS) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +bootparams: $(BOOTPARAMS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(BOOTPARAMS) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#" && $$1 != "+") \ + print $$0 }' $^ | $(DBLOAD) -i $(BOOTPARAMS) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +netgroup: $(NETGROUP) netgroup.byhost netgroup.byuser + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(NETGROUP) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#" && $$1 != "+") \ + print $$0 }' $^ | $(DBLOAD) -i $(NETGROUP) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + @$(MAKE) -f ../Makefile netid + + +netgroup.byhost: $(NETGROUP) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(NETGROUP) | $(REVNETGROUP) -h -f $(NETGROUP) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#" && $$1 != "+") \ + print $$0 }' $^ | $(DBLOAD) -i $(NETGROUP) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +netgroup.byuser: $(NETGROUP) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(NETGROUP) | $(REVNETGROUP) -u -f $(NETGROUP) | \ + $(AWK) '{ if ($$1 != "" && $$1 != "#" && $$1 != "+") \ + print $$0 }' $^ | $(DBLOAD) -i $(NETGROUP) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +hosts.byname: $(HOSTS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(HOSTS) | \ + $(AWK) '/^[0-9]/ { for (n=2; n<=NF && $$n !~ "#"; n++) \ + print $$n"\t"$$0 }' $^ | $(DBLOAD) -i $(HOSTS) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + @$(MAKE) -f ../Makefile netid + +hosts.byaddr: $(HOSTS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(HOSTS) | \ + $(AWK) '$$1 !~ "#" { print $$1"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(HOSTS) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + @$(MAKE) -f ../Makefile netid + + +networks.byname: $(NETWORKS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(NETWORKS) | \ + $(AWK) \ + '$$1 !~ "#" { print $$1"\t"$$0; \ + for (n=3; n<=NF && $$n !~ "#"; n++) \ + print $$n"\t"$$0 \ + }' $^ | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +networks.byaddr: $(NETWORKS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(NETWORKS) | \ + $(AWK) '$$1 !~ "#" { print $$2"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(NETWORKS) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +protocols.byname: $(PROTOCOLS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(PROTOCOLS) | \ + $(AWK) \ + '$$1 !~ "#" { print $$1"\t"$$0; \ + for (n=3; n<=NF && $$n !~ "#"; n++) \ + print $$n"\t"$$0 \ + }' $^ | $(DBLOAD) -i $(PROTOCOLS) \ + -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +protocols.bynumber: $(PROTOCOLS) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(PROTOCOLS) | \ + $(AWK) '$$1 !~ "#" { print $$2"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(PROTOCOLS) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +rpc.byname: $(RPC) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(RPC) | \ + $(AWK) \ + '$$1 !~ "#" { print $$1"\t"$$0; \ + for (n=3; n<=NF && $$n !~ "#"; n++) \ + print $$n"\t"$$0 \ + }' $^ | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +rpc.bynumber: $(RPC) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(RPC) | \ + $(AWK) '$$1 !~ "#" { print $$2"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(RPC) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +services.byname: $(SERVICES) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(SERVICES) | \ + $(AWK) \ + '$$1 !~ "#" { if (index($$2,"udp")) { printf("%s/udp",$$1) } \ + else { printf("%s/tcp",$$1) }; print "\t"$$0 \ + }' $^ | $(DBLOAD) -i $(SERVICES) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +publickey.byname: $(PUBLICKEY) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(PUBLICKEY) | \ + $(AWK) '$$1 !~ "#" { print $$1"\t"$$2 }' $^ \ + | $(DBLOAD) -i $(PUBLICKEY) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +$(PASSWD): $(MASTER) + @echo "Creating new $@ file from $(MASTER)..." + $(RM) $@ + @if [ ! $(UNSECURE) ]; then \ + $(RCAT) $(MASTER) | \ + $(AWK) -F: '{if ($$1 != "+") \ + print $$1":*:"$$3":"$$4":"$$8":"$$9":"$$10}' $^ \ + > $(PASSWD) ; \ + else $(RCAT) $(MASTER) | \ + $(AWK) -F: '{if ($$1 != "+") \ + print $$1":"$$2":"$$3":"$$4":"$$8":"$$9":"$$10}' $^ \ + > $(PASSWD) ; fi + + +passwd.byname: $(PASSWD) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(PASSWD) | \ + $(AWK) -F: '{ if ($$1 != "+") print $$1"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(PASSWD) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + +passwd.byuid: $(PASSWD) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(PASSWD) | \ + $(AWK) -F: '{ if ($$1 != "+") print $$3"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(PASSWD) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + @$(MAKE) -f ../Makefile netid + + +group.byname: $(GROUP) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(GROUP) | \ + $(AWK) -F: '{ if ($$1 != "+") print $$1"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(GROUP) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +group.bygid: $(GROUP) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(GROUP) | \ + $(AWK) -F: '{ if ($$1 != "+") print $$3"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(GROUP) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + @$(MAKE) -f ../Makefile netid + + +netid.byname: $(GROUP) $(PASSWD) + @echo "Updating $@..." + $(RM) $@ + @$(MKNETID) $(PASSWD) $(GROUP) `basename \`pwd\`` \ + | $(DBLOAD) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +master.passwd.byname: $(MASTER) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(MASTER) | \ + $(AWK) -F: '{ if ($$1 != "+") print $$1"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(MASTER) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi + + +master.passwd.byuid: $(MASTER) + @echo "Updating $@..." + $(RM) $@ + $(CAT) $(MASTER) | \ + $(AWK) -F: '{ if ($$1 != "+") print $$3"\t"$$0 }' $^ \ + | $(DBLOAD) -i $(MASTER) -o $(YPMAPDIR)/$@ - $@ + @if [ ! $(NOPUSH) ]; then $(YPPUSH) -d $(DOMAIN) $@; fi + @if [ ! $(NOPUSH) ]; then echo "Pushed $@ map." ; fi diff --git a/usr.sbin/ypserv/mknetid b/usr.sbin/ypserv/mknetid new file mode 100755 index 0000000..6619b5d --- /dev/null +++ b/usr.sbin/ypserv/mknetid @@ -0,0 +1,36 @@ +#!/bin/sh +# +# Produce netid.byname map file +# +# Written by O.Kirch, 1994. +# +PASSWD=$1 +GROUP=$2 +DOMAIN=$3 + +tempsed=/tmp/pass.$$ + + # First, get all login/uid info from passwd file + grep -v '^+:' $PASSWD | + awk -F: '{ printf "s/^%s:/%s/\n", $1, $3; }' >$tempsed + # next one is a giant pipe: + grep -v '^+:' $GROUP | + grep -v ':[ ]*$' | + sed 's/^[^:]*:[^:]*:\([0-9]*\):\(.*\)/\1,\2/' | + awk -F, '{ for (n=2; n<=NF; n++) + if ($n != "") print $n":\t"$1; + }' | + sed -f $tempsed | sort | grep -v ':' | + awk 'BEGIN { uid=-1; } + { if (uid == $1) { + groups=groups","$2; + } else { + if (uid != -1) + print uid":"groups; + uid=$1; groups=$2; + } + } + END { if (uid != -1) printf("%s:%s\n", uid, groups); }' | + sed "s/\(.*\):/unix.\1@$DOMAIN &/" + rm -f $tempsed + exit 0 diff --git a/usr.sbin/ypserv/yp_access.c b/usr.sbin/ypserv/yp_access.c new file mode 100644 index 0000000..d022d8e --- /dev/null +++ b/usr.sbin/ypserv/yp_access.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. + * + */ + +#include <rpc/rpc.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <sys/stat.h> +#include <paths.h> +#include <sys/param.h> +#include "yp_extern.h" +#ifdef TCP_WRAPPER +#include "tcpd.h" +#endif + +extern int debug; + +char *yp_procs[] = { "ypproc_null" , + "ypproc_domain", + "ypproc_domain_nonack", + "ypproc_match", + "ypproc_first", + "ypproc_next", + "ypproc_xfr", + "ypproc_clear", + "ypproc_all", + "ypproc_master", + "ypproc_order", + "ypproc_maplist" + }; + +/* + * Access control functions. + * + * yp_access() checks the mapname and client host address and watches for + * the following things: + * + * - If the client is referencing one of the master.passwd.* maps, it must + * be using a privileged port to make its RPC to us. If it is, then we can + * assume that the caller is root and allow the RPC to succeed. If it + * isn't access is denied. + * + * - If we are compiled with the tcpwrapper package, we also check to see + * if the host makes it past the libwrap checks and deny access if it + * doesn't. Host address checks are disabled if not compiled with the + * tcp_wrapper package. + * + * The yp_validdomain() functions checks the domain specified by the caller + * to make sure it's actually served by this server. This is more a sanity + * check than an a security check, but this seems to be the best place for + * it. + */ + +int yp_access(map, rqstp) + const char *map; + const struct svc_req *rqstp; +{ + struct sockaddr_in *rqhost; +#ifdef TCP_WRAPPER + int status = 0; + unsigned long oldaddr; +#endif + + rqhost = svc_getcaller(rqstp->rq_xprt); + + if (debug) { + yp_error("Procedure %s called from %s:%d", + yp_procs[rqstp->rq_proc], inet_ntoa(rqhost->sin_addr), + ntohs(rqhost->sin_port)); + if (map != NULL) + yp_error("Client is referencing map \"%s\".", map); + } + + /* Check the map name if one was supplied. */ + if (map != NULL) { + if (strstr(map, "master.passwd.") && ntohs(rqhost->sin_port) > 1023) { + yp_error("Access to %s denied -- client not privileged", map); + return(1); + } + } + +#ifdef TCP_WRAPPER + /* Check client address if TCP_WRAPPER is enalbled. */ + status = hosts_ctl(progname, STRING_UNKNOWN, + inet_ntoa(rqhost->sin_addr, ""); + + if (!status && rqhost->sin_addr.s_addr != oldaddr) { + yp_error("connect from %s:%d refused", + inet_ntoa(rqhost->sin_addr, ntohs(rqhost->sin_port)); + oldaddr = rqhost->sin_addr.s_addr; + return(1); + } +#endif + return(0); + +} + +int yp_validdomain(domain) + const char *domain; +{ + struct stat statbuf; + char dompath[MAXPATHLEN + 2]; + + if (domain == NULL || strstr(domain, "binding") || + !strcmp(domain, ".") || !strcmp(domain, "..") || + strchr(domain, '/')) + return(1); + + snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain); + + if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode)) + return(1); + + return(0); +} diff --git a/usr.sbin/ypserv/yp_dblookup.c b/usr.sbin/ypserv/yp_dblookup.c new file mode 100644 index 0000000..79df52e --- /dev/null +++ b/usr.sbin/ypserv/yp_dblookup.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. + * + * $Id: yp_dblookup.c,v 1.13 1995/12/16 04:46:10 wpaul Exp $ + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <string.h> +#include <limits.h> +#include <unistd.h> +#include <db.h> +#include <sys/stat.h> +#include <errno.h> +#include <paths.h> +#include "yp.h" +#include "yp_extern.h" + +extern int debug_flag; +int yp_errno = YP_TRUE; + +#define PERM_SECURE (S_IRUSR|S_IWUSR) +HASHINFO openinfo = { + 4096, /* bsize */ + 32, /* ffactor */ + 256, /* nelem */ + 2048 * 1024, /* cachesize */ + NULL, /* hash */ + 0, /* lorder */ +}; + +/* + * Open a DB database + */ +DB *yp_open_db(domain, map) + const char *domain; + const char *map; +{ + DB *dbp; + char buf[1025]; + + + yp_errno = YP_TRUE; + + if (map[0] == '.' || strchr(map, '/')) { + yp_errno = YP_BADARGS; + return (NULL); + } + + snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, domain, map); + + dbp = dbopen(buf,O_RDONLY|O_EXCL, PERM_SECURE, DB_HASH, &openinfo); + + if (dbp == NULL) { + switch(errno) { + case ENOENT: + yp_errno = YP_NOMAP; + break; + case EFTYPE: + yp_errno = YP_BADDB; + break; + default: + yp_errno = YP_YPERR; + break; + } + } + + return (dbp); +} + +/* + * Database access routines. + * + * - yp_get_record(): retrieve an arbitrary key/data pair given one key + * to match against. + * + * - yp_first_record(): retrieve first key/data base in a database. + * + * - yp_next_record(): retrieve key/data pair that sequentially follows + * the supplied key value in the database. + */ + +int yp_get_record(domain,map,key,data,allow) + const char *domain; + const char *map; + const DBT *key; + DBT *data; + int allow; +{ + DB *dbp; + + if (debug) + yp_error("Looking up key [%.*s] in map [%s]", + key->size, key->data, map); + + /* + * Avoid passing back magic "YP_*" entries unless + * the caller specifically requested them by setting + * the 'allow' flag. + */ + if (!allow && !strncmp(key->data, "YP_", 3)) + return(YP_NOKEY); + + if ((dbp = yp_open_db(domain, map)) == NULL) { + return(yp_errno); + } + + if ((dbp->get)(dbp,key,data,0)) { + (void)(dbp->close)(dbp); + return(YP_NOKEY); + } + + (void)(dbp->close)(dbp); + + if (debug) + yp_error("Result of lookup: key: [%.*s] data: [%.*s]", + key->size, key->data, data->size, data->data); + + return(YP_TRUE); +} + +int yp_first_record(dbp,key,data) + const DB *dbp; + DBT *key; + DBT *data; +{ + + if (debug) + yp_error("Retrieving first key in map."); + + if ((dbp->seq)(dbp,key,data,R_FIRST)) + return(YP_BADDB); + + /* Avoid passing back magic "YP_*" records. */ + while (!strncmp(key->data, "YP_", 3)) { + if ((dbp->seq)(dbp,key,data,R_NEXT)) + return(YP_BADDB); + } + + if (debug) + yp_error("Result of lookup: key: [%.*s] data: [%.*s]", + key->size, key->data, data->size, data->data); + + return(YP_TRUE); +} + +int yp_next_record(dbp,key,data,all) + const DB *dbp; + DBT *key; + DBT *data; + int all; +{ + DBT lkey, ldata; + + if (key == NULL || key->data == NULL) + return(yp_first_record(dbp,key,data)); + + if (debug) + yp_error("Retreiving next key, previous was: [%.*s]", + key->size, key->data); + + if (!all) { + (dbp->seq)(dbp,&lkey,&ldata,R_FIRST); + while(strncmp((char *)key->data,lkey.data,(int)key->size) || + key->size != lkey.size) + (dbp->seq)(dbp,&lkey,&ldata,R_NEXT); + } + + if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) + return(YP_NOMORE); + + /* Avoid passing back magic "YP_*" records. */ + while (!strncmp(lkey.data, "YP_", 3)) + if ((dbp->seq)(dbp,&lkey,&ldata,R_NEXT)) + return(YP_NOMORE); + + if ((dbp->get)(dbp,&lkey,&ldata,0)) + return(YP_FALSE); + + *key = lkey; + *data = ldata; + + if (debug) + yp_error("Result of lookup: key: [%.*s] data: [%.*s]", + key->size, key->data, data->size, data->data); + + return(YP_TRUE); +} diff --git a/usr.sbin/ypserv/yp_dnslookup.c b/usr.sbin/ypserv/yp_dnslookup.c new file mode 100644 index 0000000..a3d4b7a --- /dev/null +++ b/usr.sbin/ypserv/yp_dnslookup.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 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 Bill Paul 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 Bill Paul 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. + * + * $Id: yp_dnslookup.c,v 1.4 1995/12/07 05:01:34 wpaul Exp $ + */ + +/* + * Do standard and reverse DNS lookups using the resolver library. + * Take care of all the dirty work here so the main program only has to + * pass us a pointer to an array of characters. + * + * We have to use direct resolver calls here otherwise the YP server + * could end up looping by calling itself over and over again until + * it disappeared up its own belly button. + */ + +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/param.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include "yp_extern.h" + +extern struct hostent *_gethostbydnsname __P(( char * )); +extern struct hostent *_gethostbydnsaddr __P(( const char *, int, int )); + +static char *parse(hp) + struct hostent *hp; +{ + static char result[MAXHOSTNAMELEN * 2]; + int len,i; + struct in_addr addr; + + len = 16 + strlen(hp->h_name); + for (i = 0; hp->h_aliases[i]; i++) + len += strlen(hp->h_aliases[i]) + 1; + + bzero(result, sizeof(result)); + + bcopy(hp->h_addr, &addr, sizeof(struct in_addr)); + snprintf(result, sizeof(result), "%s %s", inet_ntoa(addr), hp->h_name); + + for (i = 0; hp->h_aliases[i]; i++) { + strcat(result, " "); + strcat(result, hp->h_aliases[i]); + } + + return ((char *)&result); +} + +char *yp_dnsname(address) + char *address; +{ + struct hostent *hp; + + if (strchr(address, '@')) + return (NULL); + if ((hp = (struct hostent *)_gethostbydnsname(address)) == NULL) + return (NULL); + + return(parse(hp)); +} + +char *yp_dnsaddr(address) + const char *address; +{ + struct hostent *hp; + struct in_addr addr; + + if (strchr(address, '@')) + return (NULL); + if (!inet_aton(address, &addr)) + return (NULL); + if ((hp = (struct hostent *)_gethostbydnsaddr((const char *)&addr, + sizeof(unsigned long), AF_INET)) == NULL) + return (NULL); + + return(parse(hp)); +} diff --git a/usr.sbin/ypserv/yp_error.c b/usr.sbin/ypserv/yp_error.c new file mode 100644 index 0000000..bb5e632 --- /dev/null +++ b/usr.sbin/ypserv/yp_error.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. + * + */ +/* + * error logging/reporting facilities + * stolen from /usr/libexec/mail.local via ypserv + * + * $Id: yp_error.c,v 1.2 1995/12/06 16:02:56 wpaul Exp $ + */ + +#include <stdio.h> +#include <sys/types.h> +#include <syslog.h> + +int debug; +extern int _rpcpmstart; + +extern char *progname; + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +void verr(fmt, ap) + const char *fmt; + _BSD_VA_LIST_ ap; + +{ + if (debug && !_rpcpmstart) { + fprintf(stderr,"%s: ",progname); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } else { + vsyslog(LOG_NOTICE, fmt, ap); + } +} + +void +#ifdef __STDC__ +yp_error(const char *fmt, ...) +#else +yp_error(fmt, va_list) + const char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + verr(fmt,ap); + va_end(ap); +} diff --git a/usr.sbin/ypserv/yp_extern.h b/usr.sbin/ypserv/yp_extern.h new file mode 100644 index 0000000..f16ba20 --- /dev/null +++ b/usr.sbin/ypserv/yp_extern.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. + * + * $Id: yp_extern.h,v 1.9 1995/12/16 04:01:55 wpaul Exp $ + */ +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/cdefs.h> +#include <sys/types.h> +#include <limits.h> +#include <db.h> +#include <rpc/rpc.h> + +#ifndef _PATH_YP +#define _PATH_YP "/var/yp/" +#endif + +#ifndef _PATH_LIBEXEC +#define _PATH_LIBEXEC "/usr/libexec/" +#endif + +#ifndef MAX_CHILDREN +#define MAX_CHILDREN 20 +#endif + +/* + * External functions and variables. + */ + +extern int debug; +extern int do_dns; +extern int children; +extern char *progname; +extern char *yp_dir; +extern int yp_errno; +extern void yp_error __P((const char *, ...)); +extern int yp_get_record __P(( const char *, const char *, const DBT *, DBT *, int)); +extern int yp_first_record __P((const DB *, DBT *, DBT *)); +extern int yp_next_record __P((const DB *, DBT *, DBT *, int)); +extern char *yp_dnsname __P(( char * )); +extern char *yp_dnsaddr __P(( const char * )); +extern int yp_access __P((const char *, const struct svc_req * )); +extern int yp_validdomain __P((const char * )); +extern DB *yp_open_db __P(( const char *, const char *)); diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c new file mode 100644 index 0000000..21748cf --- /dev/null +++ b/usr.sbin/ypserv/yp_main.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. + * + * $Id: yp_main.c,v 1.12 1995/12/11 22:38:19 wpaul Exp $ + */ + +/* + * ypserv startup function. + * We need out own main() since we have to do some additional work + * that rpcgen won't do for us. Most of this file was generated using + * rpcgen.new, and later modified. + */ + +#include "yp.h" +#include <stdio.h> +#include <stdlib.h> /* getenv, exit */ +#include <rpc/pmap_clnt.h> /* for pmap_unset */ +#include <string.h> /* strcmp */ +#include <signal.h> +#include <sys/ttycom.h> /* TIOCNOTTY */ +#ifdef __cplusplus +#include <sysent.h> /* getdtablesize, open */ +#endif /* __cplusplus */ +#include <memory.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <syslog.h> +#include <sys/wait.h> +#include "yp_extern.h" +#include <unistd.h> +#include <rpc/rpc.h> +#include <errno.h> + +#ifndef SIG_PF +#define SIG_PF void(*)(int) +#endif + +#define _RPCSVC_CLOSEDOWN 120 +#ifndef lint +static char rcsid[] = "$Id: yp_main.c,v 1.12 1995/12/11 22:38:19 wpaul Exp $"; +#endif /* not lint */ +int _rpcpmstart; /* Started by a port monitor ? */ +static int _rpcfdtype; + /* Whether Stream or Datagram ? */ + /* States a server can be in wrt request */ + +#define _IDLE 0 +#define _SERVED 1 +#define _SERVING 2 + +extern void ypprog_2 __P((struct svc_req, register SVCXPRT)); +extern int _rpc_dtablesize __P((void)); +extern int _rpcsvcstate; /* Set when a request is serviced */ +char *progname = "ypserv"; +char *yp_dir = _PATH_YP; +int debug = 0; +int do_dns = 0; +int sunos_4_kludge = 0; + +static +void _msgout(char* msg) +{ + if (debug) { + if (_rpcpmstart) + syslog(LOG_ERR, msg); + else + (void) fprintf(stderr, "%s\n", msg); + } else + syslog(LOG_ERR, msg); +} + +static void +yp_svc_run() +{ +#ifdef FD_SETSIZE + fd_set readfds; +#else + int readfds; +#endif /* def FD_SETSIZE */ + extern int forked; + int pid; + + /* Establish the identity of the parent ypserv process. */ + pid = getpid(); + + for (;;) { +#ifdef FD_SETSIZE + readfds = svc_fdset; +#else + readfds = svc_fds; +#endif /* def FD_SETSIZE */ + switch (select(_rpc_dtablesize(), &readfds, NULL, NULL, + (struct timeval *)0)) { + case -1: + if (errno == EINTR) { + continue; + } + perror("svc_run: - select failed"); + return; + case 0: + continue; + default: + svc_getreqset(&readfds); + if (forked && pid != getpid()) + exit(0); + } + } +} + +static void unregister() +{ + (void) pmap_unset(YPPROG, YPVERS); + if (sunos_4_kludge) + (void) pmap_unset(YPPROG, 1); +} + +static void reaper(sig) + int sig; +{ + int status; + + if (sig == SIGCHLD) { + while (wait3(&status, WNOHANG, NULL) > 0) + children--; + } else { + unregister(); + exit(0); + } +} + +static void usage() +{ + fprintf(stderr, "Usage: %s [-h] [-d] [-n] [-k] [-p path]\n", progname); + exit(1); +} + +static void +closedown(int sig) +{ + if (_rpcsvcstate == _IDLE) { + extern fd_set svc_fdset; + static int size; + int i, openfd; + + if (_rpcfdtype == SOCK_DGRAM) { + unregister(); + exit(0); + } + if (size == 0) { + size = getdtablesize(); + } + for (i = 0, openfd = 0; i < size && openfd < 2; i++) + if (FD_ISSET(i, &svc_fdset)) + openfd++; + if (openfd <= 1) { + unregister(); + exit(0); + } + } + if (_rpcsvcstate == _SERVED) + _rpcsvcstate = _IDLE; + + (void) signal(SIGALRM, (SIG_PF) closedown); + (void) alarm(_RPCSVC_CLOSEDOWN/2); +} + +main(argc, argv) + int argc; + char *argv[]; +{ + register SVCXPRT *transp; + int sock; + int proto; + struct sockaddr_in saddr; + int asize = sizeof (saddr); + int ch; + + while ((ch = getopt(argc, argv, "hdnkp:")) != EOF) { + switch(ch) { + case 'd': + debug = 1; + break; + case 'n': + do_dns = 1; + break; + case 'k': + sunos_4_kludge = 1; + break; + case 'p': + yp_dir = optarg; + break; + case 'h': + default: + usage(); + } + } + + if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { + int ssize = sizeof (int); + + if (saddr.sin_family != AF_INET) + exit(1); + if (getsockopt(0, SOL_SOCKET, SO_TYPE, + (char *)&_rpcfdtype, &ssize) == -1) + exit(1); + sock = 0; + _rpcpmstart = 1; + proto = 0; + openlog(progname, LOG_PID, LOG_DAEMON); + } else { + if (!debug) { + if (daemon(0,0)) { + perror("cannot fork"); + exit(1); + } + openlog(progname, LOG_PID, LOG_DAEMON); + } + sock = RPC_ANYSOCK; + (void) pmap_unset(YPPROG, YPVERS); + if (sunos_4_kludge) + (void) pmap_unset(YPPROG, 1); + } + + if (sunos_4_kludge && ((_rpcfdtype == 0)||(_rpcfdtype == SOCK_DGRAM))) { + transp = svcudp_create(sock); + if (transp == NULL) { + _msgout("cannot create udp service."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_UDP; + if (!svc_register(transp, YPPROG, 1, ypprog_2, proto)) { + _msgout("unable to register (YPPROG, OLDYPVERS, udp)."); + exit(1); + } + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { + transp = svcudp_create(sock); + if (transp == NULL) { + _msgout("cannot create udp service."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_UDP; + if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { + _msgout("unable to register (YPPROG, YPVERS, udp)."); + exit(1); + } + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { + transp = svctcp_create(sock, 0, 0); + if (transp == NULL) { + _msgout("cannot create tcp service."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_TCP; + if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { + _msgout("unable to register (YPPROG, YPVERS, tcp)."); + exit(1); + } + } + + if (transp == (SVCXPRT *)NULL) { + _msgout("could not create a handle"); + exit(1); + } + if (_rpcpmstart) { + (void) signal(SIGALRM, (SIG_PF) closedown); + (void) alarm(_RPCSVC_CLOSEDOWN/2); + } +/* + * Make sure SIGPIPE doesn't blow us away while servicing TCP + * connections. + */ + (void) signal(SIGPIPE, SIG_IGN); + (void) signal(SIGCHLD, (SIG_PF) reaper); + (void) signal(SIGTERM, (SIG_PF) reaper); + (void) signal(SIGINT, (SIG_PF) reaper); + (void) signal(SIGHUP, (SIG_PF) reaper); + yp_svc_run(); + _msgout("svc_run returned"); + exit(1); + /* NOTREACHED */ +} diff --git a/usr.sbin/ypserv/yp_server.c b/usr.sbin/ypserv/yp_server.c new file mode 100644 index 0000000..fcc8bbd --- /dev/null +++ b/usr.sbin/ypserv/yp_server.c @@ -0,0 +1,626 @@ +/* + * Copyright (c) 1995 + * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. + * + */ + +#include "yp_extern.h" +#include "yp.h" +#include <stdlib.h> +#include <dirent.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#ifndef lint +static char rcsid[] = "$Id: yp_server.c,v 1.18 1995/12/16 04:01:55 wpaul Exp $"; +#endif /* not lint */ + +int forked = 0; +int children = 0; +DB *spec_dbp = NULL; /* Special global DB handle for ypproc_all. */ + +void * +ypproc_null_2_svc(void *argp, struct svc_req *rqstp) +{ + static char * result; + static char rval = 0; + + if (yp_access(NULL, (struct svc_req *)rqstp)) + return(NULL); + + result = &rval; + + return((void *) &result); +} + +bool_t * +ypproc_domain_2_svc(domainname *argp, struct svc_req *rqstp) +{ + static bool_t result; + + if (yp_access(NULL, (struct svc_req *)rqstp)) { + result = FALSE; + return (&result); + } + + if (argp == NULL || yp_validdomain(*argp)) + result = FALSE; + else + result = TRUE; + + return (&result); +} + +bool_t * +ypproc_domain_nonack_2_svc(domainname *argp, struct svc_req *rqstp) +{ + static bool_t result; + + if (yp_access(NULL, (struct svc_req *)rqstp)) + return (NULL); + + if (argp == NULL || yp_validdomain(*argp)) + return (NULL); + else + result = TRUE; + + return (&result); +} + +ypresp_val * +ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rqstp) +{ + static ypresp_val result; + DBT key, data; + + if (yp_access(argp->map, (struct svc_req *)rqstp)) { + result.stat = YP_YPERR; + return (&result); + } + + if (argp->domain == NULL || argp->map == NULL) { + result.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->domain)) { + result.stat = YP_NODOM; + return(&result); + } + + key.size = argp->key.keydat_len; + key.data = argp->key.keydat_val; + + result.stat = yp_get_record(argp->domain, argp->map, &key, &data, 0); + + if (result.stat == YP_TRUE) { + result.val.valdat_len = data.size; + result.val.valdat_val = data.data; + } + + /* + * Do DNS lookups for hosts maps if database lookup failed. + */ + + if (do_dns && result.stat != YP_TRUE && strstr(argp->map, "hosts")) { + char *rval; + + /* DNS lookups can take time -- do them in a subprocess */ + + if (!debug && children < MAX_CHILDREN && fork()) { + children++; + forked = 0; + /* + * Returning NULL here prevents svc_sendreply() + * from being called by the parent. This is vital + * since having both the parent and the child process + * call it would confuse the client. + */ + return (NULL); + } else { + forked++; + } + + if (debug) + yp_error("Doing DNS lookup of %.*s", + argp->key.keydat_len, + argp->key.keydat_val); + + /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ + argp->key.keydat_val[argp->key.keydat_len] = '\0'; + + if (!strcmp(argp->map, "hosts.byname")) + rval = yp_dnsname((char *)argp->key.keydat_val); + else if (!strcmp(argp->map, "hosts.byaddr")) + rval = yp_dnsaddr((const char *)argp->key.keydat_val); + + + if (rval) { + if (debug) + yp_error("DNS lookup successful. Result: %s", rval); + result.val.valdat_len = strlen(rval); + result.val.valdat_val = rval; + result.stat = YP_TRUE; + } else { + if (debug) + yp_error("DNS lookup failed."); + result.stat = YP_NOKEY; + } + } + + return (&result); +} + +ypresp_key_val * +ypproc_first_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) +{ + static ypresp_key_val result; + DBT key, data; + DB *dbp; + + if (yp_access(argp->map, (struct svc_req *)rqstp)) { + result.stat = YP_YPERR; + return (&result); + } + + if (argp->domain == NULL) { + result.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->domain)) { + result.stat = YP_NODOM; + return(&result); + } + + if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { + result.stat = yp_errno; + return(&result); + } + + key.data = NULL; + key.size = 0; + result.stat = yp_first_record(dbp, &key, &data); + (void)(dbp->close)(dbp); + + if (result.stat == YP_TRUE) { + result.key.keydat_len = key.size; + result.key.keydat_val = key.data; + result.val.valdat_len = data.size; + result.val.valdat_val = data.data; + } + + return (&result); +} + +ypresp_key_val * +ypproc_next_2_svc(ypreq_key *argp, struct svc_req *rqstp) +{ + static ypresp_key_val result; + DBT key, data; + DB *dbp; + + if (yp_access(argp->map, (struct svc_req *)rqstp)) { + result.stat = YP_YPERR; + return (&result); + } + + if (argp->domain == NULL || argp->map == NULL) { + result.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->domain)) { + result.stat = YP_NODOM; + return(&result); + } + + if ((dbp = yp_open_db(argp->domain, argp->map)) == NULL) { + result.stat = yp_errno; + return(&result); + } + + key.size = argp->key.keydat_len; + key.data = argp->key.keydat_val; + + result.stat = yp_next_record(dbp, &key, &data, 0); + (void)(dbp->close)(dbp); + + if (result.stat == YP_TRUE) { + result.key.keydat_len = key.size; + result.key.keydat_val = key.data; + result.val.valdat_len = data.size; + result.val.valdat_val = data.data; + } + + return (&result); +} + +ypresp_xfr * +ypproc_xfr_2_svc(ypreq_xfr *argp, struct svc_req *rqstp) +{ + static ypresp_xfr result; + + if (yp_access(argp->map_parms.map, (struct svc_req *)rqstp)) { + result.xfrstat = YPXFR_REFUSED; + return(&result); + } + + if (argp->map_parms.domain == NULL) { + result.xfrstat = YPXFR_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->map_parms.domain)) { + result.xfrstat = YPXFR_NODOM; + return(&result); + } + + switch(fork()) { + case 0: + { + char g[11], t[11], p[11]; + struct sockaddr_in *rqhost; + char ypxfr_command[MAXPATHLEN + 2]; + + rqhost = svc_getcaller(rqstp->rq_xprt); + sprintf (ypxfr_command, "%sypxfr", _PATH_LIBEXEC); + sprintf (t, "%u", argp->transid); + sprintf (g, "%u", argp->prog); + sprintf (p, "%u", argp->port); + children++; + forked = 0; + execl(ypxfr_command, "ypxfr", "-d", argp->map_parms.domain, + "-h", argp->map_parms.peer, "-f", "-C", t, g, + inet_ntoa(rqhost->sin_addr), p, argp->map_parms.map, + NULL); + yp_error("ypxfr execl(): %s", strerror(errno)); + return(NULL); + } + case -1: + yp_error("ypxfr fork(): %s", strerror(errno)); + result.xfrstat = YPXFR_XFRERR; + break; + default: + result.xfrstat = YPXFR_SUCC; + forked++; + break; + } + + result.transid = argp->transid; + return (&result); +} + +void * +ypproc_clear_2_svc(void *argp, struct svc_req *rqstp) +{ + static char * result; + static char rval = 0; + + /* + * We don't have to do anything for ypproc_clear. Unlike + * the SunOS ypserv, we don't hold out database descriptors + * open forever. + */ + if (yp_access(NULL, (struct svc_req *)rqstp)) + return (NULL); + + result = &rval; + return((void *) &result); +} + +/* + * For ypproc_all, we have to send a stream of ypresp_all structures + * via TCP, but the XDR filter generated from the yp.x protocol + * definition file only serializes one such structure. This means that + * to send the whole stream, you need a wrapper which feeds all the + * records into the underlying XDR routine until it hits an 'EOF.' + * But to use the wrapper, you have to violate the boundaries between + * RPC layers by calling svc_sendreply() directly from the ypproc_all + * service routine instead of letting the RPC dispatcher do it. + * + * Bleah. + */ + +/* + * Custom XDR routine for serialzing results of ypproc_all: keep + * reading from the database and spew until we run out of records + * or encounter an error. + */ +static bool_t +xdr_my_ypresp_all(register XDR *xdrs, ypresp_all *objp) +{ + DBT key, data; + + while (1) { + /* Get a record. */ + key.size = objp->ypresp_all_u.val.key.keydat_len; + key.data = objp->ypresp_all_u.val.key.keydat_val; + + if ((objp->ypresp_all_u.val.stat = + yp_next_record(spec_dbp,&key,&data,1)) == YP_TRUE) { + objp->ypresp_all_u.val.val.valdat_len = data.size; + objp->ypresp_all_u.val.val.valdat_val = data.data; + objp->ypresp_all_u.val.key.keydat_len = key.size; + objp->ypresp_all_u.val.key.keydat_val = key.data; + objp->more = TRUE; + } else { + objp->more = FALSE; + } + + /* Serialize. */ + if (!xdr_ypresp_all(xdrs, objp)) + return(FALSE); + if (objp->more == FALSE) + return(TRUE); + } +} + +ypresp_all * +ypproc_all_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) +{ + static ypresp_all result; + + /* + * Set this here so that the client will be forced to make + * at least one attempt to read from us even if all we're + * doing is returning an error. + */ + result.more = TRUE; + + if (yp_access(argp->map, (struct svc_req *)rqstp)) { + result.ypresp_all_u.val.stat = YP_YPERR; + return (&result); + } + + if (argp->domain == NULL || argp->map == NULL) { + result.ypresp_all_u.val.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->domain)) { + result.ypresp_all_u.val.stat = YP_NODOM; + return(&result); + } + + /* + * The ypproc_all procedure can take a while to complete. + * Best to handle it in a subprocess so the parent doesn't + * block. We fork() here so we don't end up sharing a + * DB file handle with the parent. + */ + + if (!debug && children < MAX_CHILDREN && fork()) { + children++; + forked = 0; + return (NULL); + } else { + forked++; + } + + if ((spec_dbp = yp_open_db(argp->domain, argp->map)) == NULL) { + result.ypresp_all_u.val.stat = yp_errno; + return(&result); + } + + /* Kick off the actual data transfer. */ + svc_sendreply(rqstp->rq_xprt, xdr_my_ypresp_all, (char *)&result); + + /* Close database when done. */ + (void)(spec_dbp->close)(spec_dbp); + + /* + * Returning NULL prevents the dispatcher from calling + * svc_sendreply() since we already did it. + */ + return (NULL); +} + +ypresp_master * +ypproc_master_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) +{ + static ypresp_master result; + DBT key,data; + + if (yp_access(NULL, (struct svc_req *)rqstp)) { + result.stat = YP_YPERR; + return(&result); + } + + if (argp->domain == NULL) { + result.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->domain)) { + result.stat = YP_NODOM; + return (&result); + } + + key.data = "YP_MASTER_NAME"; + key.size = sizeof("YP_MASTER_NAME") - 1; + + result.stat = yp_get_record(argp->domain, argp->map, &key, &data, 1); + + if (result.stat == YP_TRUE) { + result.peer = (char *)data.data; + result.peer[data.size] = '\0'; + } else + result.peer = ""; + + return (&result); +} + +ypresp_order * +ypproc_order_2_svc(ypreq_nokey *argp, struct svc_req *rqstp) +{ + static ypresp_order result; + DBT key,data; + + if (yp_access(NULL, (struct svc_req *)rqstp)) { + result.stat = YP_YPERR; + return(&result); + } + + if (argp->domain == NULL) { + result.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(argp->domain)) { + result.stat = YP_NODOM; + return (&result); + } + + /* + * We could just check the timestamp on the map file, + * but that's a hack: we'll only know the last time the file + * was touched, not the last time the database contents were + * updated. + */ + key.data = "YP_LAST_MODIFIED"; + key.size = sizeof("YP_LAST_MODIFIED") - 1; + + result.stat = yp_get_record(argp->domain, argp->map, &key, &data, 1); + + if (result.stat == YP_TRUE) + result.ordernum = atoi((char *)data.data); + else + result.ordernum = 0; + + return (&result); +} + +static void yp_maplist_free(yp_maplist) + struct ypmaplist *yp_maplist; +{ + register struct ypmaplist *next; + + while(yp_maplist) { + next = yp_maplist->next; + free(yp_maplist->map); + free(yp_maplist); + yp_maplist = next; + } + return; +} + +static struct ypmaplist *yp_maplist_create(domain) + const char *domain; +{ + char yp_mapdir[MAXPATHLEN + 2]; + char yp_mapname[MAXPATHLEN + 2]; + struct ypmaplist *cur = NULL; + struct ypmaplist *yp_maplist = NULL; + DIR *dird; + struct dirent *dirp; + struct stat statbuf; + + snprintf(yp_mapdir, sizeof(yp_mapdir), "%s/%s", yp_dir, domain); + + if ((dird = opendir(yp_mapdir)) == NULL) { + yp_error("opendir(%s) failed: %s", strerror(errno)); + return(NULL); + } + + while ((dirp = readdir(dird)) != NULL) { + if (strcmp(dirp->d_name, ".") && strcmp(dirp->d_name, "..")) { + snprintf(yp_mapname, sizeof(yp_mapname), "%s/%s",yp_mapdir,dirp->d_name); + if (stat(yp_mapname, &statbuf) < 0 || !S_ISREG(statbuf.st_mode)) + continue; + if ((cur = (struct ypmaplist *)malloc(sizeof(struct ypmaplist))) < 0) { + yp_error("malloc() failed: %s", strerror(errno)); + closedir(dird); + yp_maplist_free(yp_maplist); + return(NULL); + } + if ((cur->map = (char *)strdup(dirp->d_name)) == NULL) { + yp_error("strdup() failed: %s", strerror(errno)); + closedir(dird); + yp_maplist_free(yp_maplist); + return(NULL); + } + cur->next = yp_maplist; + yp_maplist = cur; + if (debug) + yp_error("map: %s", yp_maplist->map); + } + + } + closedir(dird); + return(yp_maplist); +} + +ypresp_maplist * +ypproc_maplist_2_svc(domainname *argp, struct svc_req *rqstp) +{ + static ypresp_maplist result; + + if (yp_access(NULL, (struct svc_req *)rqstp)) { + result.stat = YP_YPERR; + return(&result); + } + + if (argp == NULL) { + result.stat = YP_BADARGS; + return (&result); + } + + if (yp_validdomain(*argp)) { + result.stat = YP_NODOM; + return (&result); + } + + /* + * We have to construct a linked list for the ypproc_maplist + * procedure using dynamically allocated memory. Since the XDR + * layer won't free this list for us, we have to deal with it + * ourselves. We call yp_maplist_free() first to free any + * previously allocated data we may have accumulated to insure + * that we have only one linked list in memory at any given + * time. + */ + + yp_maplist_free(result.maps); + + if ((result.maps = yp_maplist_create(*argp)) == NULL) { + yp_error("yp_maplist_create failed"); + result.stat = YP_YPERR; + return(&result); + } else + result.stat = YP_TRUE; + + return (&result); +} diff --git a/usr.sbin/ypserv/ypserv.8 b/usr.sbin/ypserv/ypserv.8 new file mode 100644 index 0000000..7a584b7 --- /dev/null +++ b/usr.sbin/ypserv/ypserv.8 @@ -0,0 +1,306 @@ +.\" Copyright (c) 1995 +.\" Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul. +.\" 4. Neither the name of the author nor the names of any co-contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul 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. +.\" +.\" $Id: ypserv.8,v 1.4 1995/12/10 04:46:38 wpaul Exp $ +.\" +.Dd February 4, 1995 +.Dt YPSERV 8 +.Os +.Sh NAME +.Nm ypserv +.Nd "NIS database server" +.Sh SYNOPSIS +.Nm ypserv +.Op Fl n +.Op Fl d +.Op Fl k +.Op Fl p Ar path +.Sh DESCRIPTION +.Nm NIS +is an RPC-based service designed to allow a number of UNIX-based +machines to share a common set of configuration files. Rather than +requiring a system administrator to update several copies of files +such as +.Pa /etc/hosts , +.Pa /etc/passwd +and +.Pa /etc/group , +which tend to require frequent changes in most environments, NIS +allows groups of computers to share one set of data which can be +updated from a single location. +.Pp +.Nm ypserv +is the server that distributes NIS databases +to client systems within an NIS +.Nm domain. +Each client in an NIS domain must have its domainname set to +one of the domains served by +.Nm ypserv +using the +.Xr domainname 1 +command. The clients must also run +.Xr ypbind 8 +in order to attach to a particular server, since it is possible to +have serveral servers within a single NIS domain. +.Pp +The databases distributed by +.Nm ypserv +are stored in +.Pa /var/yp/[domainname] +where +.Pa domainname +is the name of the domain being served. There can be several +such directories with different domainnames, and you need only one +.Nm ypserv +daemon to handle them all. +.Pp +The databases, or +.Pa maps +as they are often called, +are created by +.Nm /var/yp/Makefile +using several system files as source. The database files are in +.Xr db 3 +format to help speed retrieval when there are many records involved. +In FreeBSD, the +maps are always readable and writable only by root for security +reasons. Technically this is only necessary for the password +maps, but since the data in the other maps can be found in +other world-readable files anyway, it doesn't hurt and it's considered +good general practice. +.Pp +.Nm ypserv +is started by +.Nm /etc/rc +if it has been enabled in +.Nm /etc/sysconfig. +.Sh SPECIAL FEATURES +There are some problems associated with distributing FreeBSD's password +database via NIS: FreeBSD normally only stores encrypted passwords +in +.Pa /etc/master.passwd , +which is readable and writable only by root. By turning this file +into an NIS map, this security feature would be completely defeated. +.Pp +To make up for this, the FreeBSD version of +.Nm ypserv +handles the +.Pa master.passwd.byname +and +.Pa master.basswd.byuid +maps in a special way. When the server receives a request to access +either of these two maps, it will check the TCP port from which the +request originated and return an error if the port number is greater +than 1023. Since only the superuser is allowed to bind to TCP ports +with values less than 1024, the server can use this test to determine +whether or not the access request came from a privileged user. +Any requests made by non-privileged users are therefore rejected. +.Pp +Furthermore, the +.Xr getpwent 3 +routines in FreeBSD's standard C libarary will only attempt to retrieve +data from the +.Pa master.passwd.byname +and +.Pa master.passwd.byuid +maps for the superuser: if a normal user calls any of these functions, +the standard +.Pa passwd.byname +and +.Pa passwd.byuid +maps will be accessed instead. The latter two maps are constructed by +.Nm /var/yp/Makefile +by parsing the +.Pa master.passwd +file and stripping out the password fields, and are therefore +safe to pass on to unprivileged users. In this way, the shadow password +aspect of the protected +.Pa master.passwd +database is maintained through NIS. +.Pp +.Sh NOTES +.Ss Limitations +There are two problems inherent with password shadowing in NIS +that users should +be aware of: +.Bl -enum -offset indent +.It +The 'TCP port less than 1024' test is trivial to defeat for users with +unrestricted access to machines on your network (even those machines +which do not run UNIX-based operating systems). +.It +If you plan to use a FreeBSD system to serve non-FreeBSD clients that +have no support for password shadowing (which is most of them), you +will have to disable the password shadowing entirely by uncommenting the +.Nm UNSECURE=True +entry in +.Nm /var/yp/Makefile . +This will cause the standard +.Pa passwd.byname +and +.Pa passwd.byuid +maps to be generated with valid encrypted password fields, which is +neccesary in order for non-FreeBSD clients to perform user +authentication through NIS. +.El +.Pp +.Ss Security +.Nm ypserv +has support for Wietse Venema's +.Pa tcpwrapper +package built in, though it is not compiled in by default since +the +.Pa tcpwrapper +package is not distributed with FreeBSD. However, if you have +.Nm libwrap.a +and +.Nm tcpd.h , +you can easily recompile +.Nm ypserv +with them, thereby enabling its 'securenets' features: you can +configure +.Nm ypserv +to only handle resquests from machines listed +in the +.Pa tcpwrapper +configuration files, which would help limit vulnerability to the +first limitation listed above. +.Pp +.Ss NIS servers that are also NIS clients +Care must be taken when running +.Nm ypserv +in a multi-server domain where the server machines are also +NIS clients. It is generally a good idea to force the servers to +bind to themselves rather than allowing them to broadcast bind +requests and possibly become bound to each other: strange failure +modes can result if one server goes down and +others are dependent upon on it. (Eventually all the clients will +time out and attempt to bind to other servers, but the delay +involved can be considerable and the failure mode is still present +since the servers might bind to each other all over again). +.Pp +Refer to the +.Xr ypbind 8 +man page for details on how to force it to bind to a particular +server. +.Sh OPTIONS +The following options are supported by +.Nm ypserv : +.Bl -tag -width flag +.It Fl n +This option affects the way +.Nm ypserv +handles yp_match requests for the +.Pa hosts.byname +and +.Pa hosts.byaddress +maps. By default, if +.Nm ypserv +can't find an entry for a given host in its hosts maps, it will +return an error and perform no further processing. With the +.Fl n +flag, +.Nm ypserv +will go one step further: rather than giving up immediately, it +will try to resolve the hostname or address using a DNS nameserver +query. If the query is successful, +.Nm ypserv +will construct a fake database record and return it to the client, +thereby making it seem as though the client's yp_match request +succeeded. +.Pp +This feature is provided for compatiblity with SunOS 4.1.x, +which has brain-damaged resolver functions in its standard C +library that depend on NIS for hostname and address resolution. +FreeBSD's resolver can be configured to do DNS +queries directly, therefore it is not necessary to enable this +option when serving only FreeBSD NIS clients. +.It Fl d +Causes the server to run in debugging mode. Normally, +.Nm ypserv +reports only unusual errors (access violations, file access failures) +using the +.Xr syslog 3 +facility. In debug mode, the server does not background +itself and prints extra status messages to stderr for each +request that it revceives. Also, while running in debug mode, +.Nm ypserv +will not spawn any additional subprocesses as it normally does +when handling yp_all requests or doing DNS lookups. (These actions +often take a fair amount of time to complete and are therefore handled +in subprocesses, allowing the parent server process to go on handling +other requests.) This makes it easier to trace the server with +a debugging tool. +.It Fl k +This flag is provided for compatibility with SunOS 4. The +.Xr ypbind 8 +command in SunOS 4 apparently expects to obtain a response from an +NIS v1 server. Starting +.Xr ypserv 8 +with the +.Fl k +flag causes it to register itself as an NIS v1 server and +respond to YPPROC_DOMAIN_NONACK requests. Note carefully: this is +merely a kludge (hence the 'k') to pacify SunOS 4's +.Xr ypbind 8 +command: attempts to make the server actually handle NIS v1 queries +will undoubtedly fail quite miserably. +.It Fl p Ar path +Normally, +.Nm ypserv +assumes that all NIS maps are stored under +.Pa /var/yp . +The +.Fl p +flag may be used to specify an alternate NIS root path, allowing +the system administrator to move the map files to a different place +within the filesystem. +.El +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /var/yp/[domainname]/[maps] +The NIS maps. +.It Pa /etc/host.conf +Resolver configuration file. +.El +.Sh SEE ALSO +.Xr ypbind 8 , +.Xr yppasswdd 8 , +.Xr yppush 8 , +.Xr ypxfr 8 , +.Xr ypcat 1 , +.Xr yp 8 , +.Xr db 3 +.Sh AUTHOR +Bill Paul <wpaul@ctr.columbia.edu> +.Sh HISTORY +This version of +.Nm ypserv +first appeared in FreeBSD 2.1. |