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