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