yp_access.c revision 12891
1/*
2 * Copyright (c) 1995
3 *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 */
33
34#include <rpc/rpc.h>
35#include <sys/types.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39#include <sys/stat.h>
40#include <paths.h>
41#include <sys/param.h>
42#include "yp_extern.h"
43#ifdef TCP_WRAPPER
44#include "tcpd.h"
45#endif
46
47extern int debug;
48
49char *yp_procs[] = {	"ypproc_null" ,
50			"ypproc_domain",
51			"ypproc_domain_nonack",
52			"ypproc_match",
53			"ypproc_first",
54			"ypproc_next",
55			"ypproc_xfr",
56			"ypproc_clear",
57			"ypproc_all",
58			"ypproc_master",
59			"ypproc_order",
60			"ypproc_maplist"
61		   };
62
63/*
64 * Access control functions.
65 *
66 * yp_access() checks the mapname and client host address and watches for
67 * the following things:
68 *
69 * - If the client is referencing one of the master.passwd.* maps, it must
70 *   be using a privileged port to make its RPC to us. If it is, then we can
71 *   assume that the caller is root and allow the RPC to succeed. If it
72 *   isn't access is denied.
73 *
74 * - If we are compiled with the tcpwrapper package, we also check to see
75 *   if the host makes it past the libwrap checks and deny access if it
76 *   doesn't. Host address checks are disabled if not compiled with the
77 *   tcp_wrapper package.
78 *
79 * The yp_validdomain() functions checks the domain specified by the caller
80 * to make sure it's actually served by this server. This is more a sanity
81 * check than an a security check, but this seems to be the best place for
82 * it.
83 */
84
85int yp_access(map, rqstp)
86	const char *map;
87	const struct svc_req *rqstp;
88{
89	struct sockaddr_in *rqhost;
90#ifdef TCP_WRAPPER
91	int status = 0;
92	unsigned long oldaddr;
93#endif
94
95	rqhost = svc_getcaller(rqstp->rq_xprt);
96
97	if (debug) {
98		yp_error("Procedure %s called from %s:%d",
99			yp_procs[rqstp->rq_proc], inet_ntoa(rqhost->sin_addr),
100			ntohs(rqhost->sin_port));
101		if (map != NULL)
102			yp_error("Client is referencing map \"%s\".", map);
103	}
104
105	/* Check the map name if one was supplied. */
106	if (map != NULL) {
107		if (strstr(map, "master.passwd.") && ntohs(rqhost->sin_port) > 1023) {
108			yp_error("Access to %s denied -- client not privileged", map);
109			return(1);
110		}
111	}
112
113#ifdef TCP_WRAPPER
114	/* Check client address if TCP_WRAPPER is enalbled. */
115	status = hosts_ctl(progname, STRING_UNKNOWN,
116			   inet_ntoa(rqhost->sin_addr, "");
117
118	if (!status && rqhost->sin_addr.s_addr != oldaddr) {
119		yp_error("connect from %s:%d refused",
120			  inet_ntoa(rqhost->sin_addr, ntohs(rqhost->sin_port));
121		oldaddr = rqhost->sin_addr.s_addr;
122		return(1);
123	}
124#endif
125	return(0);
126
127}
128
129int yp_validdomain(domain)
130	const char *domain;
131{
132	struct stat statbuf;
133	char dompath[MAXPATHLEN + 2];
134
135	if (domain == NULL || strstr(domain, "binding") ||
136	    !strcmp(domain, ".") || !strcmp(domain, "..") ||
137	    strchr(domain, '/'))
138		return(1);
139
140	snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain);
141
142	if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
143		return(1);
144
145	return(0);
146}
147