Fix a hole in the portmap libwrap access control: programs on a host which

had been granted access to the portmapper via hosts.{allow,deny} could use
PMAPPROC_CALLIT to call PMAPPROC_{SET,UNSET} to (un)register services as if
they were running on the local host.

The new code disallows all indirect calls to the portmapper except for
PMAPPROC_NULL unless the -i (insecure) flag has been specified.

While there, add a new flag, -p (paranoid) which also disallows indirect calls
to a small number of other services, including key parts of NFS and NIS.  This
code hardcodes the services to be disallowed, and is thus somewhat of a hack,
but will serve for the time being (until portmap is replaced by rpcbind as part
of fvdl's current rpc work, due to happen before 1.5).

Problem pointed out by Frank van der Linden <fvdl@netbsd.org>, solution determined
in discussion with Frank van der Linden and with Bill Sommerfeld <sommerfeld@netbsd.org>.
Some inspiration drawn from the (less general) handling of this problem in Wietse
Venema's libwrap'ed portmap.
This commit is contained in:
jwise 2000-05-30 15:31:14 +00:00
parent f0112539bd
commit 21a51a33f7
1 changed files with 38 additions and 5 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: portmap.c,v 1.24 2000/04/10 20:26:31 tron Exp $ */
/* $NetBSD: portmap.c,v 1.25 2000/05/30 15:31:14 jwise Exp $ */
/*-
* Copyright (c) 1990, 1993
@ -44,7 +44,7 @@ __COPYRIGHT(
#if 0
static char sccsid[] = "@(#)portmap.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: portmap.c,v 1.24 2000/04/10 20:26:31 tron Exp $");
__RCSID("$NetBSD: portmap.c,v 1.25 2000/05/30 15:31:14 jwise Exp $");
#endif
#endif /* not lint */
@ -87,6 +87,8 @@ static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
* Mountain View, California 94043
*/
#define PARANOID_LIST
/* who to suid to if -s is given */
#define RUN_AS "daemon"
@ -111,6 +113,12 @@ static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro";
#include <unistd.h>
#include <util.h>
#ifdef PARANOID_LIST
#include <rpcsvc/mount.h>
#include <rpcsvc/nfs_prot.h>
#include <rpcsvc/yp_prot.h>
#endif
#ifdef LIBWRAP
# include <tcpd.h>
#ifndef LIBWRAP_ALLOW_FACILITY
@ -171,6 +179,9 @@ int debugging = 0;
int insecure = 0;
int runasdaemon = 0;
int verboselog = 0;
#ifdef PARANOID_LIST
int paranoid_hardcoded_service_list = 0;
#endif
int
main(argc, argv)
@ -184,7 +195,7 @@ main(argc, argv)
struct pmaplist *pml;
extern char *__progname;
while ((c = getopt(argc, argv, "dils")) != -1) {
while ((c = getopt(argc, argv, "dilps")) != -1) {
switch (c) {
case 'd':
@ -198,7 +209,11 @@ main(argc, argv)
case 'l':
verboselog = 1;
break;
#ifdef PARANOID_LIST
case 'p':
paranoid_hardcoded_service_list = 1;
break;
#endif
case 's':
runasdaemon = 1;
break;
@ -319,8 +334,8 @@ reg_service(rqstp, xprt)
if (debugging)
(void)fprintf(stderr, "server: about to do a switch\n");
switch (rqstp->rq_proc) {
switch (rqstp->rq_proc) {
case PMAPPROC_NULL:
/*
* Null proc call
@ -493,6 +508,7 @@ reg_service(rqstp, xprt)
* This procedure is only supported on rpc/udp and calls via
* rpc/udp. It passes null authentication parameters.
*/
callit(rqstp, xprt);
break;
@ -616,6 +632,23 @@ callit(rqstp, xprt)
/* host and service access control */
if (!check_access(svc_getcaller(xprt), rqstp->rq_proc, a.rmt_prog))
return;
if ((a.rmt_prog == PMAPPROG) && (a.rmt_proc != PMAPPROC_NULL) && !insecure) {
logit(deny_severity, svc_getcaller(xprt), a.rmt_proc, a.rmt_prog,
": attempt to call port mapper indirectly");
return;
}
#ifdef PARANOID_LIST
if (paranoid_hardcoded_service_list && (a.rmt_prog == NFS_PROGRAM ||
(a.rmt_prog == MOUNTPROG && a.rmt_proc == MOUNTPROC_MNT) ||
(a.rmt_prog == YPPROG && a.rmt_proc != YPPROC_DOMAIN_NONACK))) {
logit(deny_severity, svc_getcaller(xprt), a.rmt_proc, a.rmt_prog,
": attempt to call disallowed service indirectly");
return;
}
#endif
if ((pml = find_service(a.rmt_prog, a.rmt_vers,
(u_long)IPPROTO_UDP)) == NULL)
return;