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