yp_access.c revision 12891
112891Swpaul/*
212891Swpaul * Copyright (c) 1995
312891Swpaul *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
412891Swpaul *
512891Swpaul * Redistribution and use in source and binary forms, with or without
612891Swpaul * modification, are permitted provided that the following conditions
712891Swpaul * are met:
812891Swpaul * 1. Redistributions of source code must retain the above copyright
912891Swpaul *    notice, this list of conditions and the following disclaimer.
1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1112891Swpaul *    notice, this list of conditions and the following disclaimer in the
1212891Swpaul *    documentation and/or other materials provided with the distribution.
1312891Swpaul * 3. All advertising materials mentioning features or use of this software
1412891Swpaul *    must display the following acknowledgement:
1512891Swpaul *	This product includes software developed by Bill Paul.
1612891Swpaul * 4. Neither the name of the author nor the names of any co-contributors
1712891Swpaul *    may be used to endorse or promote products derived from this software
1812891Swpaul *    without specific prior written permission.
1912891Swpaul *
2012891Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2112891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2212891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2312891Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2412891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2512891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2612891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2712891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2812891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2912891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3012891Swpaul * SUCH DAMAGE.
3112891Swpaul *
3212891Swpaul */
3312891Swpaul
3412891Swpaul#include <rpc/rpc.h>
3512891Swpaul#include <sys/types.h>
3612891Swpaul#include <sys/socket.h>
3712891Swpaul#include <netinet/in.h>
3812891Swpaul#include <arpa/inet.h>
3912891Swpaul#include <sys/stat.h>
4012891Swpaul#include <paths.h>
4112891Swpaul#include <sys/param.h>
4212891Swpaul#include "yp_extern.h"
4312891Swpaul#ifdef TCP_WRAPPER
4412891Swpaul#include "tcpd.h"
4512891Swpaul#endif
4612891Swpaul
4712891Swpaulextern int debug;
4812891Swpaul
4912891Swpaulchar *yp_procs[] = {	"ypproc_null" ,
5012891Swpaul			"ypproc_domain",
5112891Swpaul			"ypproc_domain_nonack",
5212891Swpaul			"ypproc_match",
5312891Swpaul			"ypproc_first",
5412891Swpaul			"ypproc_next",
5512891Swpaul			"ypproc_xfr",
5612891Swpaul			"ypproc_clear",
5712891Swpaul			"ypproc_all",
5812891Swpaul			"ypproc_master",
5912891Swpaul			"ypproc_order",
6012891Swpaul			"ypproc_maplist"
6112891Swpaul		   };
6212891Swpaul
6312891Swpaul/*
6412891Swpaul * Access control functions.
6512891Swpaul *
6612891Swpaul * yp_access() checks the mapname and client host address and watches for
6712891Swpaul * the following things:
6812891Swpaul *
6912891Swpaul * - If the client is referencing one of the master.passwd.* maps, it must
7012891Swpaul *   be using a privileged port to make its RPC to us. If it is, then we can
7112891Swpaul *   assume that the caller is root and allow the RPC to succeed. If it
7212891Swpaul *   isn't access is denied.
7312891Swpaul *
7412891Swpaul * - If we are compiled with the tcpwrapper package, we also check to see
7512891Swpaul *   if the host makes it past the libwrap checks and deny access if it
7612891Swpaul *   doesn't. Host address checks are disabled if not compiled with the
7712891Swpaul *   tcp_wrapper package.
7812891Swpaul *
7912891Swpaul * The yp_validdomain() functions checks the domain specified by the caller
8012891Swpaul * to make sure it's actually served by this server. This is more a sanity
8112891Swpaul * check than an a security check, but this seems to be the best place for
8212891Swpaul * it.
8312891Swpaul */
8412891Swpaul
8512891Swpaulint yp_access(map, rqstp)
8612891Swpaul	const char *map;
8712891Swpaul	const struct svc_req *rqstp;
8812891Swpaul{
8912891Swpaul	struct sockaddr_in *rqhost;
9012891Swpaul#ifdef TCP_WRAPPER
9112891Swpaul	int status = 0;
9212891Swpaul	unsigned long oldaddr;
9312891Swpaul#endif
9412891Swpaul
9512891Swpaul	rqhost = svc_getcaller(rqstp->rq_xprt);
9612891Swpaul
9712891Swpaul	if (debug) {
9812891Swpaul		yp_error("Procedure %s called from %s:%d",
9912891Swpaul			yp_procs[rqstp->rq_proc], inet_ntoa(rqhost->sin_addr),
10012891Swpaul			ntohs(rqhost->sin_port));
10112891Swpaul		if (map != NULL)
10212891Swpaul			yp_error("Client is referencing map \"%s\".", map);
10312891Swpaul	}
10412891Swpaul
10512891Swpaul	/* Check the map name if one was supplied. */
10612891Swpaul	if (map != NULL) {
10712891Swpaul		if (strstr(map, "master.passwd.") && ntohs(rqhost->sin_port) > 1023) {
10812891Swpaul			yp_error("Access to %s denied -- client not privileged", map);
10912891Swpaul			return(1);
11012891Swpaul		}
11112891Swpaul	}
11212891Swpaul
11312891Swpaul#ifdef TCP_WRAPPER
11412891Swpaul	/* Check client address if TCP_WRAPPER is enalbled. */
11512891Swpaul	status = hosts_ctl(progname, STRING_UNKNOWN,
11612891Swpaul			   inet_ntoa(rqhost->sin_addr, "");
11712891Swpaul
11812891Swpaul	if (!status && rqhost->sin_addr.s_addr != oldaddr) {
11912891Swpaul		yp_error("connect from %s:%d refused",
12012891Swpaul			  inet_ntoa(rqhost->sin_addr, ntohs(rqhost->sin_port));
12112891Swpaul		oldaddr = rqhost->sin_addr.s_addr;
12212891Swpaul		return(1);
12312891Swpaul	}
12412891Swpaul#endif
12512891Swpaul	return(0);
12612891Swpaul
12712891Swpaul}
12812891Swpaul
12912891Swpaulint yp_validdomain(domain)
13012891Swpaul	const char *domain;
13112891Swpaul{
13212891Swpaul	struct stat statbuf;
13312891Swpaul	char dompath[MAXPATHLEN + 2];
13412891Swpaul
13512891Swpaul	if (domain == NULL || strstr(domain, "binding") ||
13612891Swpaul	    !strcmp(domain, ".") || !strcmp(domain, "..") ||
13712891Swpaul	    strchr(domain, '/'))
13812891Swpaul		return(1);
13912891Swpaul
14012891Swpaul	snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain);
14112891Swpaul
14212891Swpaul	if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
14312891Swpaul		return(1);
14412891Swpaul
14512891Swpaul	return(0);
14612891Swpaul}
147