Subject: Re: libwrap (was Re: amd vulnerability: patch for 1.3.3)
To: matthew green <mrg@eterna.com.au>
From: Brian C. Grayson <bgrayson@marvin.ece.utexas.edu>
List: tech-security
Date: 10/18/1999 03:03:05
  by redmail.netbsd.org with SMTP; 18 Oct 1999 08:03:25 -0000
Message-ID: <19991018030305.A20667@marvin.ece.utexas.edu>
Date: Mon, 18 Oct 1999 03:03:05 -0500
From: "Brian C. Grayson" <bgrayson@marvin.ece.utexas.edu>
To: matthew green <mrg@eterna.com.au>
Cc: Manuel Bouyer <bouyer@antioche.lip6.fr>, tech-security@netbsd.org,
        itojun@iijlab.net
Subject: Re: libwrap (was Re: amd vulnerability: patch for 1.3.3)
References: <19991018014804.A19607@marvin.ece.utexas.edu> <16517.940229562@eterna.com.au>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
In-Reply-To: <16517.940229562@eterna.com.au>; from matthew green on Mon, Oct 18, 1999 at 04:52:42PM +1000

On Mon, Oct 18, 1999 at 04:52:42PM +1000, matthew green wrote:
>    
>      Thanks.  It should be feasible to check against both portmap
>    and the specific service, via two checks -- "portmap" and
>    getrpcbynumber(prog).  Would this be worth coding up?
> 
> wouldn't this require hacking each program ?  i'm not saying this
> _isn't_ worthwhile (mountd access lists would be nice, eg :-), but
> that it is not a localised change ...?

  I was under the impression that portmap was for RPC what
inetd was for TCP.  The man page says "When a client wishes to
make an RPC call to a given program number, it will first
contact portmap on the server machine to determine the port
number where RPC packets should be sent."  I'm not much of a
networking guy, though.

  But I tried it out, and it appears to work.  So there's
something to be said for naivete!  If all RPCs go through
portmap, then I think this is good.  If there are sneaky ways
to avoid portmap, then these changes may only provide a false
sense of security.

  Diff is attached, for proof-of-concept.  I added a
helper function to avoid lots of duplication.  Anyone have any
objections against committing it?

  Brian
------------------------------------------------------------
--- portmap.c.dist	Mon Oct 18 02:29:18 1999
+++ portmap.c	Mon Oct 18 02:53:36 1999
@@ -163,6 +163,8 @@
 static bool_t	xdr_rmtcall_result __P((XDR *, struct rmtcallargs *));
 void		logit __P((int, struct sockaddr_in *, u_long, u_long, char *));
 int		check_access __P((struct sockaddr_in *, u_long, u_long));
+int		check_access_helper __P((struct sockaddr_in *, u_long,
+					 u_long, char *));
 int		is_loopback __P((struct sockaddr_in *));
 
 
@@ -667,26 +669,66 @@
 }
 
 int 
-check_access(addr, proc, prog)
+check_access_helper(addr, proc, prog, matchstring)
 	struct sockaddr_in *addr; 
 	u_long  proc; 
 	u_long  prog;
+	char   *matchstring;
 {
 #ifdef LIBWRAP
 	struct request_info req;
-#endif
 
-#ifdef LIBWRAP
-	request_init(&req, RQ_DAEMON, "portmap", RQ_CLIENT_SIN, addr, 0);
+	request_init(&req, RQ_DAEMON, matchstring, RQ_CLIENT_SIN, addr, 0);
 	sock_methods(&req);
 	if(!hosts_access(&req)) {
 		logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
 		return 0;
 	}
 #endif
+	return 1;
+}
+
+int 
+check_access(addr, proc, prog)
+	struct sockaddr_in *addr; 
+	u_long  proc; 
+	u_long  prog;
+{
+#ifdef LIBWRAP
+	char	progbuf[256];
+	char   *progname;
+	struct rpcent *rpc = NULL;
+#endif
+
+#ifdef LIBWRAP
+	if (!check_access_helper(addr, proc, prog, "portmap"))
+		return 0;
+	if (prog == 0)
+		progname = "";
+	else if ((rpc = getrpcbynumber((int) prog))) {
+		progname = rpc->r_name;
+	} else {
+		snprintf(progname = progbuf, sizeof(progbuf), "%lu", prog);
+	}
+	if (!check_access_helper(addr, proc, prog, progname))
+		return 0;
+
+	/* If there are aliases, check those also! */
+	if (rpc && rpc->r_aliases) {
+		char **p = rpc->r_aliases;
+		while (*p) {
+			/* Only do a limited copy from the alias, to avoid
+			 * buffer overflows. */
+			strncpy(progname = progbuf, *p, sizeof(progbuf));
+			if (!check_access_helper(addr, proc, prog, *p))
+				return 0;
+			p++;
+		}
+	}
+#endif
 	if (verboselog)
 		logit(log_severity, addr, proc, prog, "");
-    	return 1;
+	return 1;
 }
 
 int