diff options
Diffstat (limited to 'usr.sbin')
-rw-r--r-- | usr.sbin/ypserv/yp_access.c | 158 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_extern.h | 3 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_main.c | 11 | ||||
-rw-r--r-- | usr.sbin/ypserv/yp_server.c | 5 | ||||
-rw-r--r-- | usr.sbin/ypserv/ypserv.8 | 90 |
5 files changed, 228 insertions, 39 deletions
diff --git a/usr.sbin/ypserv/yp_access.c b/usr.sbin/ypserv/yp_access.c index cdd69ef..7efb880 100644 --- a/usr.sbin/ypserv/yp_access.c +++ b/usr.sbin/ypserv/yp_access.c @@ -32,18 +32,25 @@ */ #include <rpc/rpc.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/yppasswd.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 <errno.h> #include <sys/param.h> #include "yp_extern.h" #ifdef TCP_WRAPPER #include "tcpd.h" #endif +#ifndef lint +static const char rcsid[] = "$Id$"; +#endif + extern int debug; char *yp_procs[] = { "ypproc_null" , @@ -60,6 +67,99 @@ char *yp_procs[] = { "ypproc_null" , "ypproc_maplist" }; +#ifdef TCP_WRAPPER +void load_securenets() +{ +} +#else +struct securenet { + struct in_addr net; + struct in_addr mask; + struct securenet *next; +}; + +struct securenet *securenets; + +#define LINEBUFSZ 1024 + +/* + * Read /var/yp/securenets file and initialize the securenets + * list. If the file doesn't exist, we set up a dummy entry that + * allows all hosts to connect. + */ +void load_securenets() +{ + FILE *fp; + char path[MAXPATHLEN + 2]; + char linebuf[1024 + 2]; + struct securenet *tmp; + + /* + * If securenets is not NULL, we are being called to reload + * the list; free the existing list before re-reading the + * securenets file. + */ + if (securenets != NULL) { + while(securenets) { + tmp = securenets->next; + free(securenets->net); + free(securenets->mask); + free(securenets); + securenets = tmp; + } + } + + snprintf(path, MAXPATHLEN, "%s/securenets", yp_dir); + + if ((fp = fopen(path, "r")) == NULL) { + if (errno == ENOENT) { + securenets = (struct securenet *)malloc(sizeof(struct securenet)); + securenets->net.s_addr = INADDR_ANY; + securenets->mask.s_addr = INADDR_BROADCAST; + securenets->next = NULL; + return; + } else { + yp_error("fopen(%s) failed: %s", path, strerror(errno)); + exit(1); + } + } + + securenets = NULL; + + while(fgets(linebuf, LINEBUFSZ, fp)) { + char addr1[20], addr2[20]; + + if (linebuf[0] == '#') + continue; + if (sscanf(linebuf, "%s %s", addr1, addr2) < 2) { + yp_error("badly formatted securenets entry: %s", + linebuf); + continue; + } + + tmp = (struct securenet *)malloc(sizeof(struct securenet)); + + if (!inet_aton((char *)&addr1, (struct in_addr *)&tmp->net)) { + yp_error("badly formatted securenets entry: %s", addr1); + free(tmp); + continue; + } + + if (!inet_aton((char *)&addr2, (struct in_addr *)&tmp->mask)) { + yp_error("badly formatted securenets entry: %s", addr2); + free(tmp); + continue; + } + + tmp->next = securenets; + securenets = tmp; + } + + fclose(fp); + +} +#endif + /* * Access control functions. * @@ -71,10 +171,19 @@ char *yp_procs[] = { "ypproc_null" , * 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 client's IP address is checked against the securenets rules. + * There are two kinds of securenets support: the built-in support, + * which is very simple and depends on the presense of a + * /var/yp/securenets file, and tcp-wrapper support, which requires + * Wietse Venema's libwrap.a and tcpd.h. (Since the tcp-wrapper + * package does not ship with FreeBSD, we use the built-in support + * by default. Users can recompile the server the tcp-wrapper library + * if they already have it installed and want to use hosts.allow and + * hosts.deny to control access instead od having a seperate securenets + * file.) + * + * If no /var/yp/securenets file is present, the host access checks + * are bypassed and all hosts are allowed to connect. * * 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 @@ -87,15 +196,19 @@ int yp_access(map, rqstp) const struct svc_req *rqstp; { struct sockaddr_in *rqhost; -#ifdef TCP_WRAPPER int status = 0; unsigned long oldaddr; +#ifndef TCP_WRAPPER + struct securenet *tmp; #endif rqhost = svc_getcaller(rqstp->rq_xprt); if (debug) { yp_error("Procedure %s called from %s:%d", + /* Hack to allow rpc.yppasswdd to use this routine */ + rqstp->rq_prog == YPPASSWDPROG ? + "yppasswdproc_update" : yp_procs[rqstp->rq_proc], inet_ntoa(rqhost->sin_addr), ntohs(rqhost->sin_port)); if (map != NULL) @@ -104,24 +217,41 @@ int yp_access(map, rqstp) /* Check the map name if one was supplied. */ if (map != NULL) { - if (strstr(map, "master.passwd.") && ntohs(rqhost->sin_port) > 1023) { + if ((strstr(map, "master.passwd.") || + rqstp->rq_proc == YPPROC_XFR) && + 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, ""); + inet_ntoa(rqhost->sin_addr), ""); +#else + tmp = securenets; + while(tmp) { + if (((rqhost->sin_addr.s_addr & ~tmp->mask.s_addr) + | tmp->net.s_addr) == rqhost->sin_addr.s_addr) { + status = 1; + break; + } + tmp = tmp->next; + } +#endif - 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; + if (!status) { + if (rqhost->sin_addr.s_addr != oldaddr) { + yp_error("connect from %s:%d to procedure %s refused", + inet_ntoa(rqhost->sin_addr), + ntohs(rqhost->sin_port), + rqstp->rq_prog == YPPASSWDPROG ? + "yppasswdproc_update" : + yp_procs[rqstp->rq_proc]); + oldaddr = rqhost->sin_addr.s_addr; + } return(1); } -#endif return(0); } @@ -134,7 +264,7 @@ int yp_validdomain(domain) if (domain == NULL || strstr(domain, "binding") || !strcmp(domain, ".") || !strcmp(domain, "..") || - strchr(domain, '/')) + strchr(domain, '/') || strlen(domain) > YPMAXDOMAIN) return(1); snprintf(dompath, sizeof(dompath), "%s/%s", yp_dir, domain); diff --git a/usr.sbin/ypserv/yp_extern.h b/usr.sbin/ypserv/yp_extern.h index e94d253..9e5a39f 100644 --- a/usr.sbin/ypserv/yp_extern.h +++ b/usr.sbin/ypserv/yp_extern.h @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: yp_extern.h,v 1.1.1.1 1995/12/16 20:54:17 wpaul Exp $ + * $Id: yp_extern.h,v 1.2 1995/12/23 21:35:30 wpaul Exp $ */ #include <stdio.h> #include <string.h> @@ -72,3 +72,4 @@ 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 *)); +extern void load_securenets __P(( void )); diff --git a/usr.sbin/ypserv/yp_main.c b/usr.sbin/ypserv/yp_main.c index 94956b7..17296dc 100644 --- a/usr.sbin/ypserv/yp_main.c +++ b/usr.sbin/ypserv/yp_main.c @@ -29,7 +29,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: yp_main.c,v 1.1.1.1 1995/12/16 20:54:17 wpaul Exp $ + * $Id: yp_main.c,v 1.2 1995/12/23 21:35:32 wpaul Exp $ */ /* @@ -65,7 +65,7 @@ #define _RPCSVC_CLOSEDOWN 120 #ifndef lint -static char rcsid[] = "$Id: yp_main.c,v 1.1.1.1 1995/12/16 20:54:17 wpaul Exp $"; +static char rcsid[] = "$Id: yp_main.c,v 1.2 1995/12/23 21:35:32 wpaul Exp $"; #endif /* not lint */ int _rpcpmstart; /* Started by a port monitor ? */ static int _rpcfdtype; @@ -147,6 +147,11 @@ static void reaper(sig) { int status; + if (sig == SIGHUP) { + load_securenets(); + return; + } + if (sig == SIGCHLD) { while (wait3(&status, WNOHANG, NULL) > 0) children--; @@ -223,6 +228,8 @@ main(argc, argv) } } + load_securenets(); + if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { int ssize = sizeof (int); diff --git a/usr.sbin/ypserv/yp_server.c b/usr.sbin/ypserv/yp_server.c index 3ac7e2e..dfe6eef 100644 --- a/usr.sbin/ypserv/yp_server.c +++ b/usr.sbin/ypserv/yp_server.c @@ -45,7 +45,7 @@ #include <rpc/rpc.h> #ifndef lint -static char rcsid[] = "$Id: yp_server.c,v 1.3 1996/01/10 16:07:39 wpaul Exp $"; +static char rcsid[] = "$Id: yp_server.c,v 1.2 1995/12/23 21:35:35 wpaul Exp $"; #endif /* not lint */ int forked = 0; @@ -408,6 +408,9 @@ ypproc_clear_2_svc(void *argp, struct svc_req *rqstp) if (yp_access(NULL, (struct svc_req *)rqstp)) return (NULL); + /* Re-read the securenets database for the hell of it. */ + load_securenets(); + result = &rval; return((void *) &result); } diff --git a/usr.sbin/ypserv/ypserv.8 b/usr.sbin/ypserv/ypserv.8 index 953eea5..e878d2b 100644 --- a/usr.sbin/ypserv/ypserv.8 +++ b/usr.sbin/ypserv/ypserv.8 @@ -28,7 +28,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: ypserv.8,v 1.2 1996/01/30 13:52:50 mpp Exp $ +.\" $Id: ypserv.8,v 1.1.1.1 1995/12/16 20:54:17 wpaul Exp $ .\" .Dd February 4, 1995 .Dt YPSERV 8 @@ -68,7 +68,7 @@ using the command. The clients must also run .Xr ypbind 8 in order to attach to a particular server, since it is possible to -have several servers within a single NIS domain. +have serveral servers within a single NIS domain. .Pp The databases distributed by .Nm ypserv @@ -114,7 +114,7 @@ To make up for this, the FreeBSD version of handles the .Pa master.passwd.byname and -.Pa master.passwd.byuid +.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 @@ -125,7 +125,7 @@ Any requests made by non-privileged users are therefore rejected. .Pp Furthermore, the .Xr getpwent 3 -routines in FreeBSD's standard C library will only attempt to retrieve +routines in FreeBSD's standard C libarary will only attempt to retrieve data from the .Pa master.passwd.byname and @@ -167,15 +167,58 @@ This will cause the standard and .Pa passwd.byuid maps to be generated with valid encrypted password fields, which is -necessary in order for non-FreeBSD clients to perform user +neccesary in order for non-FreeBSD clients to perform user authentication through NIS. .El .Pp .Ss Security +In general, any remote user can issue an RPC to +.Nm ypserv +and retrieve the contents of your NIS maps, provided the remote user +knows your domain name. To prevent such unauthorized transactions, +.Nm ypserv +supports a feature called +.Pa securenets +which can be used to restrict access to a given set of hosts. +At startup, +.Nm ypserv +will attempt to load the securenets information from a file +called +.Nm /var/yp/securenets . +(Note that this path varies depending on the path specified with +the +.Fl p +option, which is explained below.) This file contains entries +that consist of a network specification and a network mask separated +by white space. +Lines starting with ``#'' are considered to be comments. A +sample securenets file might look like this: +.Bd -unfilled -offset indent +# allow connections from local host -- mandatory +127.0.0.1 255.255.255.255 +# allow connections from any host +# on the 129.168.128.0 network +192.168.128.0 255.255.255.0 +# allow connections from any host +# between 10.0.0.0 to 10.0.15.255 +10.0.0.0 255.255.240.0 +.Ed +.Pp +If +.Nm ypserv +receives a request from an address that matches one of these rules, +it will process the request normally. If the address fails to match +a rule, the request will be ignored and a warning message will be +logged. If the +.Pa /var/yp/securenets +file does not exist, .Nm ypserv -has support for Wietse Venema's +will allow connections from any host. +.Pp +.Nm Ypserv +also has support for Wietse Venema's .Pa tcpwrapper -package built in, though it is not compiled in by default since +package, though it is not compiled in by default since the .Pa tcpwrapper package is not distributed with FreeBSD. However, if you have @@ -184,14 +227,17 @@ 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 requests from machines listed -in the -.Pa tcpwrapper -configuration files, which would help limit vulnerability to the -first limitation listed above. +with them. This allows the administrator to use the tcpwrapper +configuration files ( +.Pa /etc/hosts.allow +and +.Pa /etc/hosts.deny ) +for access control instead of +.Pa /var/yp/securenets . +.Pp +Note: while both of these access control mechanisms provide some +security, they, like the privileged port test, are both vulnerable +to ``IP spoofing'' attacks. .Pp .Ss NIS servers that are also NIS clients Care must be taken when running @@ -236,7 +282,7 @@ 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 compatibility with SunOS 4.1.x, +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 @@ -250,7 +296,7 @@ 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 receives. Also, while running in debug mode, +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 @@ -289,15 +335,17 @@ within the filesystem. The NIS maps. .It Pa /etc/host.conf Resolver configuration file. +.It Pa /var/yp/securenets +Host access control file .El .Sh SEE ALSO -.Xr ypcat 1 , -.Xr db 3 , -.Xr yp 4 , .Xr ypbind 8 , .Xr yppasswdd 8 , .Xr yppush 8 , -.Xr ypxfr 8 +.Xr ypxfr 8 , +.Xr ypcat 1 , +.Xr yp 8 , +.Xr db 3 .Sh AUTHOR Bill Paul <wpaul@ctr.columbia.edu> .Sh HISTORY |