summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ypserv/yp_access.c158
-rw-r--r--usr.sbin/ypserv/yp_extern.h3
-rw-r--r--usr.sbin/ypserv/yp_main.c11
-rw-r--r--usr.sbin/ypserv/yp_server.c5
-rw-r--r--usr.sbin/ypserv/ypserv.890
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
OpenPOWER on IntegriCloud