xref: /freebsd/usr.sbin/rpcbind/security.c (revision 4ee5e586)
18360efbdSAlfred Perlstein /*	$NetBSD: security.c,v 1.5 2000/06/08 09:01:05 fvdl Exp $	*/
28360efbdSAlfred Perlstein /*	$FreeBSD$ */
38360efbdSAlfred Perlstein 
48360efbdSAlfred Perlstein #include <sys/types.h>
58360efbdSAlfred Perlstein #include <sys/time.h>
68360efbdSAlfred Perlstein #include <sys/socket.h>
78360efbdSAlfred Perlstein #include <netinet/in.h>
88360efbdSAlfred Perlstein #include <arpa/inet.h>
98360efbdSAlfred Perlstein #include <rpc/rpc.h>
108360efbdSAlfred Perlstein #include <rpc/rpcb_prot.h>
118360efbdSAlfred Perlstein #include <rpc/pmap_prot.h>
128360efbdSAlfred Perlstein #include <err.h>
1305c4b26eSIan Dowse #include <stdio.h>
148360efbdSAlfred Perlstein #include <stdlib.h>
158360efbdSAlfred Perlstein #include <string.h>
168360efbdSAlfred Perlstein #include <unistd.h>
178360efbdSAlfred Perlstein #include <libutil.h>
188360efbdSAlfred Perlstein #include <syslog.h>
198360efbdSAlfred Perlstein #include <netdb.h>
208360efbdSAlfred Perlstein 
218360efbdSAlfred Perlstein /*
228360efbdSAlfred Perlstein  * XXX for special case checks in check_callit.
238360efbdSAlfred Perlstein  */
248360efbdSAlfred Perlstein #include <rpcsvc/mount.h>
258360efbdSAlfred Perlstein #include <rpcsvc/rquota.h>
268360efbdSAlfred Perlstein #include <rpcsvc/nfs_prot.h>
278360efbdSAlfred Perlstein #include <rpcsvc/yp.h>
288360efbdSAlfred Perlstein #include <rpcsvc/ypclnt.h>
298360efbdSAlfred Perlstein #include <rpcsvc/yppasswd.h>
308360efbdSAlfred Perlstein 
318360efbdSAlfred Perlstein #include "rpcbind.h"
328360efbdSAlfred Perlstein 
338360efbdSAlfred Perlstein #ifdef LIBWRAP
348360efbdSAlfred Perlstein # include <tcpd.h>
358360efbdSAlfred Perlstein #ifndef LIBWRAP_ALLOW_FACILITY
368360efbdSAlfred Perlstein # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
378360efbdSAlfred Perlstein #endif
388360efbdSAlfred Perlstein #ifndef LIBWRAP_ALLOW_SEVERITY
398360efbdSAlfred Perlstein # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
408360efbdSAlfred Perlstein #endif
418360efbdSAlfred Perlstein #ifndef LIBWRAP_DENY_FACILITY
428360efbdSAlfred Perlstein # define LIBWRAP_DENY_FACILITY LOG_AUTH
438360efbdSAlfred Perlstein #endif
448360efbdSAlfred Perlstein #ifndef LIBWRAP_DENY_SEVERITY
458360efbdSAlfred Perlstein # define LIBWRAP_DENY_SEVERITY LOG_WARNING
468360efbdSAlfred Perlstein #endif
478360efbdSAlfred Perlstein int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
488360efbdSAlfred Perlstein int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
498360efbdSAlfred Perlstein #endif
508360efbdSAlfred Perlstein 
518360efbdSAlfred Perlstein #ifndef PORTMAP_LOG_FACILITY
528360efbdSAlfred Perlstein # define PORTMAP_LOG_FACILITY LOG_AUTH
538360efbdSAlfred Perlstein #endif
548360efbdSAlfred Perlstein #ifndef PORTMAP_LOG_SEVERITY
558360efbdSAlfred Perlstein # define PORTMAP_LOG_SEVERITY LOG_INFO
568360efbdSAlfred Perlstein #endif
578360efbdSAlfred Perlstein int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
588360efbdSAlfred Perlstein 
598360efbdSAlfred Perlstein extern int verboselog;
608360efbdSAlfred Perlstein 
618360efbdSAlfred Perlstein int
624180788fSAlfred Perlstein check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, unsigned int rpcbvers)
638360efbdSAlfred Perlstein {
648360efbdSAlfred Perlstein 	struct netbuf *caller = svc_getrpccaller(xprt);
658360efbdSAlfred Perlstein 	struct sockaddr *addr = (struct sockaddr *)caller->buf;
668360efbdSAlfred Perlstein #ifdef LIBWRAP
678360efbdSAlfred Perlstein 	struct request_info req;
688360efbdSAlfred Perlstein #endif
698360efbdSAlfred Perlstein 	rpcprog_t prog = 0;
708360efbdSAlfred Perlstein 	rpcb *rpcbp;
718360efbdSAlfred Perlstein 	struct pmap *pmap;
728360efbdSAlfred Perlstein 
738360efbdSAlfred Perlstein 	/*
748360efbdSAlfred Perlstein 	 * The older PMAP_* equivalents have the same numbers, so
758360efbdSAlfred Perlstein 	 * they are accounted for here as well.
768360efbdSAlfred Perlstein 	 */
778360efbdSAlfred Perlstein 	switch (proc) {
788360efbdSAlfred Perlstein 	case RPCBPROC_GETADDR:
798360efbdSAlfred Perlstein 	case RPCBPROC_SET:
808360efbdSAlfred Perlstein 	case RPCBPROC_UNSET:
818360efbdSAlfred Perlstein 		if (rpcbvers > PMAPVERS) {
828360efbdSAlfred Perlstein 			rpcbp = (rpcb *)args;
838360efbdSAlfred Perlstein 			prog = rpcbp->r_prog;
848360efbdSAlfred Perlstein 		} else {
858360efbdSAlfred Perlstein 			pmap = (struct pmap *)args;
868360efbdSAlfred Perlstein 			prog = pmap->pm_prog;
878360efbdSAlfred Perlstein 		}
888360efbdSAlfred Perlstein 		if (proc == RPCBPROC_GETADDR)
898360efbdSAlfred Perlstein 			break;
908360efbdSAlfred Perlstein 		if (!insecure && !is_loopback(caller)) {
918360efbdSAlfred Perlstein 			if (verboselog)
928360efbdSAlfred Perlstein 				logit(log_severity, addr, proc, prog,
938360efbdSAlfred Perlstein 				    " declined (non-loopback sender)");
948360efbdSAlfred Perlstein 			return 0;
958360efbdSAlfred Perlstein 		}
968360efbdSAlfred Perlstein 		break;
978360efbdSAlfred Perlstein 	case RPCBPROC_CALLIT:
988360efbdSAlfred Perlstein 	case RPCBPROC_INDIRECT:
998360efbdSAlfred Perlstein 	case RPCBPROC_DUMP:
1008360efbdSAlfred Perlstein 	case RPCBPROC_GETTIME:
1018360efbdSAlfred Perlstein 	case RPCBPROC_UADDR2TADDR:
1028360efbdSAlfred Perlstein 	case RPCBPROC_TADDR2UADDR:
1038360efbdSAlfred Perlstein 	case RPCBPROC_GETVERSADDR:
1048360efbdSAlfred Perlstein 	case RPCBPROC_GETADDRLIST:
1058360efbdSAlfred Perlstein 	case RPCBPROC_GETSTAT:
1068360efbdSAlfred Perlstein 	default:
1074ee5e586SAlfred Perlstein 		break;
1088360efbdSAlfred Perlstein 	}
1098360efbdSAlfred Perlstein 
1108360efbdSAlfred Perlstein #ifdef LIBWRAP
1118360efbdSAlfred Perlstein 	if (addr->sa_family == AF_LOCAL)
1128360efbdSAlfred Perlstein 		return 1;
1138360efbdSAlfred Perlstein 	request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
1148360efbdSAlfred Perlstein 	sock_methods(&req);
1158360efbdSAlfred Perlstein 	if(!hosts_access(&req)) {
1168360efbdSAlfred Perlstein 		logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
1178360efbdSAlfred Perlstein 		return 0;
1188360efbdSAlfred Perlstein 	}
1198360efbdSAlfred Perlstein #endif
1208360efbdSAlfred Perlstein 	if (verboselog)
1218360efbdSAlfred Perlstein 		logit(log_severity, addr, proc, prog, "");
1228360efbdSAlfred Perlstein     	return 1;
1238360efbdSAlfred Perlstein }
1248360efbdSAlfred Perlstein 
1258360efbdSAlfred Perlstein int
1268360efbdSAlfred Perlstein is_loopback(struct netbuf *nbuf)
1278360efbdSAlfred Perlstein {
1288360efbdSAlfred Perlstein 	struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
1298360efbdSAlfred Perlstein 	struct sockaddr_in *sin;
1308360efbdSAlfred Perlstein #ifdef INET6
1318360efbdSAlfred Perlstein 	struct sockaddr_in6 *sin6;
1328360efbdSAlfred Perlstein #endif
1338360efbdSAlfred Perlstein 
1348360efbdSAlfred Perlstein 	switch (addr->sa_family) {
1358360efbdSAlfred Perlstein 	case AF_INET:
1368360efbdSAlfred Perlstein 		if (!oldstyle_local)
1378360efbdSAlfred Perlstein 			return 0;
1388360efbdSAlfred Perlstein 		sin = (struct sockaddr_in *)addr;
1398360efbdSAlfred Perlstein         	return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
1408360efbdSAlfred Perlstein 		    (ntohs(sin->sin_port) < IPPORT_RESERVED));
1418360efbdSAlfred Perlstein #ifdef INET6
1428360efbdSAlfred Perlstein 	case AF_INET6:
1438360efbdSAlfred Perlstein 		if (!oldstyle_local)
1448360efbdSAlfred Perlstein 			return 0;
1458360efbdSAlfred Perlstein 		sin6 = (struct sockaddr_in6 *)addr;
1468360efbdSAlfred Perlstein 		return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
1478360efbdSAlfred Perlstein 		    (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
1488360efbdSAlfred Perlstein #endif
1498360efbdSAlfred Perlstein 	case AF_LOCAL:
1508360efbdSAlfred Perlstein 		return 1;
1518360efbdSAlfred Perlstein 	default:
1524ee5e586SAlfred Perlstein 		break;
1538360efbdSAlfred Perlstein 	}
1548360efbdSAlfred Perlstein 
1558360efbdSAlfred Perlstein 	return 0;
1568360efbdSAlfred Perlstein }
1578360efbdSAlfred Perlstein 
1588360efbdSAlfred Perlstein 
1598360efbdSAlfred Perlstein /* logit - report events of interest via the syslog daemon */
1608360efbdSAlfred Perlstein void
1618360efbdSAlfred Perlstein logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
1628360efbdSAlfred Perlstein       const char *text)
1638360efbdSAlfred Perlstein {
1648360efbdSAlfred Perlstein 	const char *procname;
1658360efbdSAlfred Perlstein 	char	procbuf[32];
1668360efbdSAlfred Perlstein 	char   *progname;
1678360efbdSAlfred Perlstein 	char	progbuf[32];
1688360efbdSAlfred Perlstein 	char fromname[NI_MAXHOST];
1698360efbdSAlfred Perlstein 	struct rpcent *rpc;
1708360efbdSAlfred Perlstein 	static const char *procmap[] = {
1718360efbdSAlfred Perlstein 	/* RPCBPROC_NULL */		"null",
1728360efbdSAlfred Perlstein 	/* RPCBPROC_SET */		"set",
1738360efbdSAlfred Perlstein 	/* RPCBPROC_UNSET */		"unset",
1748360efbdSAlfred Perlstein 	/* RPCBPROC_GETADDR */		"getport/addr",
1758360efbdSAlfred Perlstein 	/* RPCBPROC_DUMP */		"dump",
1768360efbdSAlfred Perlstein 	/* RPCBPROC_CALLIT */		"callit",
1778360efbdSAlfred Perlstein 	/* RPCBPROC_GETTIME */		"gettime",
1788360efbdSAlfred Perlstein 	/* RPCBPROC_UADDR2TADDR */	"uaddr2taddr",
1798360efbdSAlfred Perlstein 	/* RPCBPROC_TADDR2UADDR */	"taddr2uaddr",
1808360efbdSAlfred Perlstein 	/* RPCBPROC_GETVERSADDR */	"getversaddr",
1818360efbdSAlfred Perlstein 	/* RPCBPROC_INDIRECT */		"indirect",
1828360efbdSAlfred Perlstein 	/* RPCBPROC_GETADDRLIST */	"getaddrlist",
1838360efbdSAlfred Perlstein 	/* RPCBPROC_GETSTAT */		"getstat"
1848360efbdSAlfred Perlstein 	};
1858360efbdSAlfred Perlstein 
1868360efbdSAlfred Perlstein 	/*
1878360efbdSAlfred Perlstein 	 * Fork off a process or the portmap daemon might hang while
1888360efbdSAlfred Perlstein 	 * getrpcbynumber() or syslog() does its thing.
1898360efbdSAlfred Perlstein 	 */
1908360efbdSAlfred Perlstein 
1918360efbdSAlfred Perlstein 	if (fork() == 0) {
1928360efbdSAlfred Perlstein 		setproctitle("logit");
1938360efbdSAlfred Perlstein 
1948360efbdSAlfred Perlstein 		/* Try to map program number to name. */
1958360efbdSAlfred Perlstein 
1968360efbdSAlfred Perlstein 		if (prognum == 0) {
1978360efbdSAlfred Perlstein 			progname = "";
1988360efbdSAlfred Perlstein 		} else if ((rpc = getrpcbynumber((int) prognum))) {
1998360efbdSAlfred Perlstein 			progname = rpc->r_name;
2008360efbdSAlfred Perlstein 		} else {
2018360efbdSAlfred Perlstein 			snprintf(progname = progbuf, sizeof(progbuf), "%u",
2028360efbdSAlfred Perlstein 			    (unsigned)prognum);
2038360efbdSAlfred Perlstein 		}
2048360efbdSAlfred Perlstein 
2058360efbdSAlfred Perlstein 		/* Try to map procedure number to name. */
2068360efbdSAlfred Perlstein 
20705c4b26eSIan Dowse 		if (procnum >= (sizeof procmap / sizeof (char *))) {
2088360efbdSAlfred Perlstein 			snprintf(procbuf, sizeof procbuf, "%u",
2098360efbdSAlfred Perlstein 			    (unsigned)procnum);
2108360efbdSAlfred Perlstein 			procname = procbuf;
2118360efbdSAlfred Perlstein 		} else
2128360efbdSAlfred Perlstein 			procname = procmap[procnum];
2138360efbdSAlfred Perlstein 
2148360efbdSAlfred Perlstein 		/* Write syslog record. */
2158360efbdSAlfred Perlstein 
2168360efbdSAlfred Perlstein 		if (addr->sa_family == AF_LOCAL)
2178360efbdSAlfred Perlstein 			strcpy(fromname, "unix");
2188360efbdSAlfred Perlstein 		else
2198360efbdSAlfred Perlstein 			getnameinfo(addr, addr->sa_len, fromname,
2208360efbdSAlfred Perlstein 			    sizeof fromname, NULL, 0, NI_NUMERICHOST);
2218360efbdSAlfred Perlstein 
2228360efbdSAlfred Perlstein 		syslog(severity, "connect from %s to %s(%s)%s",
2238360efbdSAlfred Perlstein 			fromname, procname, progname, text);
2248360efbdSAlfred Perlstein 		_exit(0);
2258360efbdSAlfred Perlstein 	}
2268360efbdSAlfred Perlstein }
2278360efbdSAlfred Perlstein 
2288360efbdSAlfred Perlstein int
2294180788fSAlfred Perlstein check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum __unused)
2308360efbdSAlfred Perlstein {
2318360efbdSAlfred Perlstein 	struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
2328360efbdSAlfred Perlstein 
2338360efbdSAlfred Perlstein 	/*
2348360efbdSAlfred Perlstein 	 * Always allow calling NULLPROC
2358360efbdSAlfred Perlstein 	 */
2368360efbdSAlfred Perlstein 	if (args->rmt_proc == 0)
2378360efbdSAlfred Perlstein 		return 1;
2388360efbdSAlfred Perlstein 
2398360efbdSAlfred Perlstein 	/*
2408360efbdSAlfred Perlstein 	 * XXX - this special casing sucks.
2418360efbdSAlfred Perlstein 	 */
2428360efbdSAlfred Perlstein 	switch (args->rmt_prog) {
2438360efbdSAlfred Perlstein 	case RPCBPROG:
2448360efbdSAlfred Perlstein 		/*
2458360efbdSAlfred Perlstein 		 * Allow indirect calls to ourselves in insecure mode.
2468360efbdSAlfred Perlstein 		 * The is_loopback checks aren't useful then anyway.
2478360efbdSAlfred Perlstein 		 */
2488360efbdSAlfred Perlstein 		if (!insecure)
2498360efbdSAlfred Perlstein 			goto deny;
2508360efbdSAlfred Perlstein 		break;
2518360efbdSAlfred Perlstein 	case MOUNTPROG:
2528360efbdSAlfred Perlstein 		if (args->rmt_proc != MOUNTPROC_MNT &&
2538360efbdSAlfred Perlstein 		    args->rmt_proc != MOUNTPROC_UMNT)
2548360efbdSAlfred Perlstein 			break;
2558360efbdSAlfred Perlstein 		goto deny;
2568360efbdSAlfred Perlstein 	case YPBINDPROG:
2578360efbdSAlfred Perlstein 		if (args->rmt_proc != YPBINDPROC_SETDOM)
2588360efbdSAlfred Perlstein 			break;
2598360efbdSAlfred Perlstein 		/* FALLTHROUGH */
2608360efbdSAlfred Perlstein 	case YPPASSWDPROG:
2618360efbdSAlfred Perlstein 	case NFS_PROGRAM:
2628360efbdSAlfred Perlstein 	case RQUOTAPROG:
2638360efbdSAlfred Perlstein 		goto deny;
2648360efbdSAlfred Perlstein 	case YPPROG:
2658360efbdSAlfred Perlstein 		switch (args->rmt_proc) {
2668360efbdSAlfred Perlstein 		case YPPROC_ALL:
2678360efbdSAlfred Perlstein 		case YPPROC_MATCH:
2688360efbdSAlfred Perlstein 		case YPPROC_FIRST:
2698360efbdSAlfred Perlstein 		case YPPROC_NEXT:
2708360efbdSAlfred Perlstein 			goto deny;
2718360efbdSAlfred Perlstein 		default:
2724ee5e586SAlfred Perlstein 			break;
2738360efbdSAlfred Perlstein 		}
2748360efbdSAlfred Perlstein 	default:
2754ee5e586SAlfred Perlstein 		break;
2768360efbdSAlfred Perlstein 	}
2778360efbdSAlfred Perlstein 
2788360efbdSAlfred Perlstein 	return 1;
2798360efbdSAlfred Perlstein deny:
2808360efbdSAlfred Perlstein #ifdef LIBWRAP
2818360efbdSAlfred Perlstein 	logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
2828360efbdSAlfred Perlstein 	    ": indirect call not allowed");
2838360efbdSAlfred Perlstein #else
2848360efbdSAlfred Perlstein 	logit(0, sa, args->rmt_proc, args->rmt_prog,
2858360efbdSAlfred Perlstein 	    ": indirect call not allowed");
2868360efbdSAlfred Perlstein #endif
2878360efbdSAlfred Perlstein 	return 0;
2888360efbdSAlfred Perlstein }
289