Deleted Added
full compact
yp_access.c (13375) yp_access.c (14240)
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

--- 18 unchanged lines hidden (view full) ---

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>
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

--- 18 unchanged lines hidden (view full) ---

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 <rpcsvc/yp.h>
36#include <rpcsvc/yppasswd.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>
37#include <sys/types.h>
38#include <sys/socket.h>
39#include <netinet/in.h>
40#include <arpa/inet.h>
41#include <sys/stat.h>
42#include <paths.h>
43#include <errno.h>
41#include <sys/param.h>
42#include "yp_extern.h"
43#ifdef TCP_WRAPPER
44#include "tcpd.h"
45#endif
46
44#include <sys/param.h>
45#include "yp_extern.h"
46#ifdef TCP_WRAPPER
47#include "tcpd.h"
48#endif
49
50#ifndef lint
51static const char rcsid[] = "$Id$";
52#endif
53
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
54extern int debug;
55
56char *yp_procs[] = { "ypproc_null" ,
57 "ypproc_domain",
58 "ypproc_domain_nonack",
59 "ypproc_match",
60 "ypproc_first",
61 "ypproc_next",
62 "ypproc_xfr",
63 "ypproc_clear",
64 "ypproc_all",
65 "ypproc_master",
66 "ypproc_order",
67 "ypproc_maplist"
68 };
69
70#ifdef TCP_WRAPPER
71void load_securenets()
72{
73}
74#else
75struct securenet {
76 struct in_addr net;
77 struct in_addr mask;
78 struct securenet *next;
79};
80
81struct securenet *securenets;
82
83#define LINEBUFSZ 1024
84
63/*
85/*
86 * Read /var/yp/securenets file and initialize the securenets
87 * list. If the file doesn't exist, we set up a dummy entry that
88 * allows all hosts to connect.
89 */
90void load_securenets()
91{
92 FILE *fp;
93 char path[MAXPATHLEN + 2];
94 char linebuf[1024 + 2];
95 struct securenet *tmp;
96
97 /*
98 * If securenets is not NULL, we are being called to reload
99 * the list; free the existing list before re-reading the
100 * securenets file.
101 */
102 if (securenets != NULL) {
103 while(securenets) {
104 tmp = securenets->next;
105 free(securenets->net);
106 free(securenets->mask);
107 free(securenets);
108 securenets = tmp;
109 }
110 }
111
112 snprintf(path, MAXPATHLEN, "%s/securenets", yp_dir);
113
114 if ((fp = fopen(path, "r")) == NULL) {
115 if (errno == ENOENT) {
116 securenets = (struct securenet *)malloc(sizeof(struct securenet));
117 securenets->net.s_addr = INADDR_ANY;
118 securenets->mask.s_addr = INADDR_BROADCAST;
119 securenets->next = NULL;
120 return;
121 } else {
122 yp_error("fopen(%s) failed: %s", path, strerror(errno));
123 exit(1);
124 }
125 }
126
127 securenets = NULL;
128
129 while(fgets(linebuf, LINEBUFSZ, fp)) {
130 char addr1[20], addr2[20];
131
132 if (linebuf[0] == '#')
133 continue;
134 if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) {
135 yp_error("badly formatted securenets entry: %s",
136 linebuf);
137 continue;
138 }
139
140 tmp = (struct securenet *)malloc(sizeof(struct securenet));
141
142 if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) {
143 yp_error("badly formatted securenets entry: %s", addr1);
144 free(tmp);
145 continue;
146 }
147
148 if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) {
149 yp_error("badly formatted securenets entry: %s", addr2);
150 free(tmp);
151 continue;
152 }
153
154 tmp->next = securenets;
155 securenets = tmp;
156 }
157
158 fclose(fp);
159
160}
161#endif
162
163/*
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 *
164 * Access control functions.
165 *
166 * yp_access() checks the mapname and client host address and watches for
167 * the following things:
168 *
169 * - If the client is referencing one of the master.passwd.* maps, it must
170 * be using a privileged port to make its RPC to us. If it is, then we can
171 * assume that the caller is root and allow the RPC to succeed. If it
172 * isn't access is denied.
173 *
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.
174 * - The client's IP address is checked against the securenets rules.
175 * There are two kinds of securenets support: the built-in support,
176 * which is very simple and depends on the presense of a
177 * /var/yp/securenets file, and tcp-wrapper support, which requires
178 * Wietse Venema's libwrap.a and tcpd.h. (Since the tcp-wrapper
179 * package does not ship with FreeBSD, we use the built-in support
180 * by default. Users can recompile the server the tcp-wrapper library
181 * if they already have it installed and want to use hosts.allow and
182 * hosts.deny to control access instead od having a seperate securenets
183 * file.)
78 *
184 *
185 * If no /var/yp/securenets file is present, the host access checks
186 * are bypassed and all hosts are allowed to connect.
187 *
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;
188 * The yp_validdomain() functions checks the domain specified by the caller
189 * to make sure it's actually served by this server. This is more a sanity
190 * check than an a security check, but this seems to be the best place for
191 * it.
192 */
193
194int yp_access(map, rqstp)
195 const char *map;
196 const struct svc_req *rqstp;
197{
198 struct sockaddr_in *rqhost;
90#ifdef TCP_WRAPPER
91 int status = 0;
92 unsigned long oldaddr;
199 int status = 0;
200 unsigned long oldaddr;
201#ifndef TCP_WRAPPER
202 struct securenet *tmp;
93#endif
94
95 rqhost = svc_getcaller(rqstp->rq_xprt);
96
97 if (debug) {
98 yp_error("Procedure %s called from %s:%d",
203#endif
204
205 rqhost = svc_getcaller(rqstp->rq_xprt);
206
207 if (debug) {
208 yp_error("Procedure %s called from %s:%d",
209 /* Hack to allow rpc.yppasswdd to use this routine */
210 rqstp->rq_prog == YPPASSWDPROG ?
211 "yppasswdproc_update" :
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) {
212 yp_procs[rqstp->rq_proc], inet_ntoa(rqhost->sin_addr),
213 ntohs(rqhost->sin_port));
214 if (map != NULL)
215 yp_error("Client is referencing map \"%s\".", map);
216 }
217
218 /* Check the map name if one was supplied. */
219 if (map != NULL) {
107 if (strstr(map, "master.passwd.") && ntohs(rqhost->sin_port) > 1023) {
220 if ((strstr(map, "master.passwd.") ||
221 rqstp->rq_proc == YPPROC_XFR) &&
222 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
223 yp_error("Access to %s denied -- client not privileged", map);
224 return(1);
225 }
226 }
227
228#ifdef TCP_WRAPPER
114 /* Check client address if TCP_WRAPPER is enalbled. */
115 status = hosts_ctl(progname, STRING_UNKNOWN,
229 status = hosts_ctl(progname, STRING_UNKNOWN,
116 inet_ntoa(rqhost->sin_addr, "");
230 inet_ntoa(rqhost->sin_addr), "");
231#else
232 tmp = securenets;
233 while(tmp) {
234 if (((rqhost->sin_addr.s_addr & ~tmp->mask.s_addr)
235 | tmp->net.s_addr) == rqhost->sin_addr.s_addr) {
236 status = 1;
237 break;
238 }
239 tmp = tmp->next;
240 }
241#endif
117
242
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;
243 if (!status) {
244 if (rqhost->sin_addr.s_addr != oldaddr) {
245 yp_error("connect from %s:%d to procedure %s refused",
246 inet_ntoa(rqhost->sin_addr),
247 ntohs(rqhost->sin_port),
248 rqstp->rq_prog == YPPASSWDPROG ?
249 "yppasswdproc_update" :
250 yp_procs[rqstp->rq_proc]);
251 oldaddr = rqhost->sin_addr.s_addr;
252 }
122 return(1);
123 }
253 return(1);
254 }
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, "..") ||
255 return(0);
256
257}
258
259int yp_validdomain(domain)
260 const char *domain;
261{
262 struct stat statbuf;
263 char dompath[MAXPATHLEN + 2];
264
265 if (domain == NULL || strstr(domain, "binding") ||
266 !strcmp(domain, ".") || !strcmp(domain, "..") ||
137 strchr(domain, '/'))
267 strchr(domain, '/') || strlen(domain) > YPMAXDOMAIN)
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}
268 return(1);
269
270 snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain);
271
272 if (stat(dompath, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
273 return(1);
274
275 return(0);
276}