174462Salfred/*	$NetBSD: security.c,v 1.5 2000/06/08 09:01:05 fvdl Exp $	*/
274462Salfred/*	$FreeBSD$ */
374462Salfred
474462Salfred#include <sys/types.h>
574462Salfred#include <sys/time.h>
674462Salfred#include <sys/socket.h>
774462Salfred#include <netinet/in.h>
874462Salfred#include <arpa/inet.h>
974462Salfred#include <rpc/rpc.h>
1074462Salfred#include <rpc/rpcb_prot.h>
1174462Salfred#include <rpc/pmap_prot.h>
1274462Salfred#include <err.h>
1379721Siedowse#include <stdio.h>
1474462Salfred#include <stdlib.h>
1574462Salfred#include <string.h>
1674462Salfred#include <unistd.h>
1774462Salfred#include <libutil.h>
1874462Salfred#include <syslog.h>
1974462Salfred#include <netdb.h>
2074462Salfred
2174462Salfred/*
2274462Salfred * XXX for special case checks in check_callit.
2374462Salfred */
2474462Salfred#include <rpcsvc/mount.h>
2574462Salfred#include <rpcsvc/rquota.h>
2674462Salfred#include <rpcsvc/nfs_prot.h>
2774462Salfred#include <rpcsvc/yp.h>
2874462Salfred#include <rpcsvc/ypclnt.h>
2974462Salfred#include <rpcsvc/yppasswd.h>
3074462Salfred
3174462Salfred#include "rpcbind.h"
3274462Salfred
3374462Salfred#ifdef LIBWRAP
3474462Salfred# include <tcpd.h>
3574462Salfred#ifndef LIBWRAP_ALLOW_FACILITY
3674462Salfred# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
3774462Salfred#endif
3874462Salfred#ifndef LIBWRAP_ALLOW_SEVERITY
3974462Salfred# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
4074462Salfred#endif
4174462Salfred#ifndef LIBWRAP_DENY_FACILITY
4274462Salfred# define LIBWRAP_DENY_FACILITY LOG_AUTH
4374462Salfred#endif
4474462Salfred#ifndef LIBWRAP_DENY_SEVERITY
4574462Salfred# define LIBWRAP_DENY_SEVERITY LOG_WARNING
4674462Salfred#endif
4774462Salfredint allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
4874462Salfredint deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
4974462Salfred#endif
5074462Salfred
5174462Salfred#ifndef PORTMAP_LOG_FACILITY
5274462Salfred# define PORTMAP_LOG_FACILITY LOG_AUTH
5374462Salfred#endif
5474462Salfred#ifndef PORTMAP_LOG_SEVERITY
5574462Salfred# define PORTMAP_LOG_SEVERITY LOG_INFO
5674462Salfred#endif
5774462Salfredint log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
5874462Salfred
5974462Salfredextern int verboselog;
6074462Salfred
6174462Salfredint
62104592Salfredcheck_access(SVCXPRT *xprt, rpcproc_t proc, void *args, unsigned int rpcbvers)
6374462Salfred{
6474462Salfred	struct netbuf *caller = svc_getrpccaller(xprt);
6574462Salfred	struct sockaddr *addr = (struct sockaddr *)caller->buf;
6674462Salfred#ifdef LIBWRAP
6774462Salfred	struct request_info req;
6874462Salfred#endif
6974462Salfred	rpcprog_t prog = 0;
7074462Salfred	rpcb *rpcbp;
7174462Salfred	struct pmap *pmap;
7274462Salfred
7374462Salfred	/*
7474462Salfred	 * The older PMAP_* equivalents have the same numbers, so
7574462Salfred	 * they are accounted for here as well.
7674462Salfred	 */
7774462Salfred	switch (proc) {
7874462Salfred	case RPCBPROC_GETADDR:
7974462Salfred	case RPCBPROC_SET:
8074462Salfred	case RPCBPROC_UNSET:
8174462Salfred		if (rpcbvers > PMAPVERS) {
8274462Salfred			rpcbp = (rpcb *)args;
8374462Salfred			prog = rpcbp->r_prog;
8474462Salfred		} else {
8574462Salfred			pmap = (struct pmap *)args;
8674462Salfred			prog = pmap->pm_prog;
8774462Salfred		}
8874462Salfred		if (proc == RPCBPROC_GETADDR)
8974462Salfred			break;
9074462Salfred		if (!insecure && !is_loopback(caller)) {
9174462Salfred			if (verboselog)
9274462Salfred				logit(log_severity, addr, proc, prog,
9374462Salfred				    " declined (non-loopback sender)");
9474462Salfred			return 0;
9574462Salfred		}
9674462Salfred		break;
9774462Salfred	case RPCBPROC_CALLIT:
9874462Salfred	case RPCBPROC_INDIRECT:
9974462Salfred	case RPCBPROC_DUMP:
10074462Salfred	case RPCBPROC_GETTIME:
10174462Salfred	case RPCBPROC_UADDR2TADDR:
10274462Salfred	case RPCBPROC_TADDR2UADDR:
10374462Salfred	case RPCBPROC_GETVERSADDR:
10474462Salfred	case RPCBPROC_GETADDRLIST:
10574462Salfred	case RPCBPROC_GETSTAT:
10674462Salfred	default:
107104593Salfred		break;
10874462Salfred	}
10974462Salfred
11074462Salfred#ifdef LIBWRAP
11174462Salfred	if (addr->sa_family == AF_LOCAL)
11274462Salfred		return 1;
11374462Salfred	request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
11474462Salfred	sock_methods(&req);
11574462Salfred	if(!hosts_access(&req)) {
11674462Salfred		logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
11774462Salfred		return 0;
11874462Salfred	}
11974462Salfred#endif
12074462Salfred	if (verboselog)
12174462Salfred		logit(log_severity, addr, proc, prog, "");
12274462Salfred    	return 1;
12374462Salfred}
12474462Salfred
12574462Salfredint
12674462Salfredis_loopback(struct netbuf *nbuf)
12774462Salfred{
12874462Salfred	struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
12974462Salfred	struct sockaddr_in *sin;
13074462Salfred#ifdef INET6
13174462Salfred	struct sockaddr_in6 *sin6;
13274462Salfred#endif
13374462Salfred
13474462Salfred	switch (addr->sa_family) {
13574462Salfred	case AF_INET:
13674462Salfred		if (!oldstyle_local)
13774462Salfred			return 0;
13874462Salfred		sin = (struct sockaddr_in *)addr;
13974462Salfred        	return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
14074462Salfred		    (ntohs(sin->sin_port) < IPPORT_RESERVED));
14174462Salfred#ifdef INET6
14274462Salfred	case AF_INET6:
14374462Salfred		if (!oldstyle_local)
14474462Salfred			return 0;
14574462Salfred		sin6 = (struct sockaddr_in6 *)addr;
14674462Salfred		return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
14774462Salfred		    (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
14874462Salfred#endif
14974462Salfred	case AF_LOCAL:
15074462Salfred		return 1;
15174462Salfred	default:
152104593Salfred		break;
15374462Salfred	}
15474462Salfred
15574462Salfred	return 0;
15674462Salfred}
15774462Salfred
15874462Salfred
15974462Salfred/* logit - report events of interest via the syslog daemon */
16074462Salfredvoid
16174462Salfredlogit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
16274462Salfred      const char *text)
16374462Salfred{
16474462Salfred	const char *procname;
16574462Salfred	char	procbuf[32];
16674462Salfred	char   *progname;
16774462Salfred	char	progbuf[32];
16874462Salfred	char fromname[NI_MAXHOST];
16974462Salfred	struct rpcent *rpc;
17074462Salfred	static const char *procmap[] = {
17174462Salfred	/* RPCBPROC_NULL */		"null",
17274462Salfred	/* RPCBPROC_SET */		"set",
17374462Salfred	/* RPCBPROC_UNSET */		"unset",
17474462Salfred	/* RPCBPROC_GETADDR */		"getport/addr",
17574462Salfred	/* RPCBPROC_DUMP */		"dump",
17674462Salfred	/* RPCBPROC_CALLIT */		"callit",
17774462Salfred	/* RPCBPROC_GETTIME */		"gettime",
17874462Salfred	/* RPCBPROC_UADDR2TADDR */	"uaddr2taddr",
17974462Salfred	/* RPCBPROC_TADDR2UADDR */	"taddr2uaddr",
18074462Salfred	/* RPCBPROC_GETVERSADDR */	"getversaddr",
18174462Salfred	/* RPCBPROC_INDIRECT */		"indirect",
18274462Salfred	/* RPCBPROC_GETADDRLIST */	"getaddrlist",
18374462Salfred	/* RPCBPROC_GETSTAT */		"getstat"
18474462Salfred	};
18574462Salfred
18674462Salfred	/*
18774462Salfred	 * Fork off a process or the portmap daemon might hang while
18874462Salfred	 * getrpcbynumber() or syslog() does its thing.
18974462Salfred	 */
19074462Salfred
19174462Salfred	if (fork() == 0) {
19274462Salfred		setproctitle("logit");
19374462Salfred
19474462Salfred		/* Try to map program number to name. */
19574462Salfred
19674462Salfred		if (prognum == 0) {
19774462Salfred			progname = "";
19874462Salfred		} else if ((rpc = getrpcbynumber((int) prognum))) {
19974462Salfred			progname = rpc->r_name;
20074462Salfred		} else {
20174462Salfred			snprintf(progname = progbuf, sizeof(progbuf), "%u",
20274462Salfred			    (unsigned)prognum);
20374462Salfred		}
20474462Salfred
20574462Salfred		/* Try to map procedure number to name. */
20674462Salfred
20779721Siedowse		if (procnum >= (sizeof procmap / sizeof (char *))) {
20874462Salfred			snprintf(procbuf, sizeof procbuf, "%u",
20974462Salfred			    (unsigned)procnum);
21074462Salfred			procname = procbuf;
21174462Salfred		} else
21274462Salfred			procname = procmap[procnum];
21374462Salfred
21474462Salfred		/* Write syslog record. */
21574462Salfred
21674462Salfred		if (addr->sa_family == AF_LOCAL)
217107952Smbr			strcpy(fromname, "local");
21874462Salfred		else
21974462Salfred			getnameinfo(addr, addr->sa_len, fromname,
22074462Salfred			    sizeof fromname, NULL, 0, NI_NUMERICHOST);
22174462Salfred
22274462Salfred		syslog(severity, "connect from %s to %s(%s)%s",
22374462Salfred			fromname, procname, progname, text);
22474462Salfred		_exit(0);
22574462Salfred	}
22674462Salfred}
22774462Salfred
22874462Salfredint
229104592Salfredcheck_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum __unused)
23074462Salfred{
23174462Salfred	struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
23274462Salfred
23374462Salfred	/*
23474462Salfred	 * Always allow calling NULLPROC
23574462Salfred	 */
23674462Salfred	if (args->rmt_proc == 0)
23774462Salfred		return 1;
23874462Salfred
23974462Salfred	/*
24074462Salfred	 * XXX - this special casing sucks.
24174462Salfred	 */
24274462Salfred	switch (args->rmt_prog) {
24374462Salfred	case RPCBPROG:
24474462Salfred		/*
24574462Salfred		 * Allow indirect calls to ourselves in insecure mode.
24674462Salfred		 * The is_loopback checks aren't useful then anyway.
24774462Salfred		 */
24874462Salfred		if (!insecure)
24974462Salfred			goto deny;
25074462Salfred		break;
25174462Salfred	case MOUNTPROG:
25274462Salfred		if (args->rmt_proc != MOUNTPROC_MNT &&
25374462Salfred		    args->rmt_proc != MOUNTPROC_UMNT)
25474462Salfred			break;
25574462Salfred		goto deny;
25674462Salfred	case YPBINDPROG:
25774462Salfred		if (args->rmt_proc != YPBINDPROC_SETDOM)
25874462Salfred			break;
25974462Salfred		/* FALLTHROUGH */
26074462Salfred	case YPPASSWDPROG:
26174462Salfred	case NFS_PROGRAM:
26274462Salfred	case RQUOTAPROG:
26374462Salfred		goto deny;
26474462Salfred	case YPPROG:
26574462Salfred		switch (args->rmt_proc) {
26674462Salfred		case YPPROC_ALL:
26774462Salfred		case YPPROC_MATCH:
26874462Salfred		case YPPROC_FIRST:
26974462Salfred		case YPPROC_NEXT:
27074462Salfred			goto deny;
27174462Salfred		default:
272104593Salfred			break;
27374462Salfred		}
27474462Salfred	default:
275104593Salfred		break;
27674462Salfred	}
27774462Salfred
27874462Salfred	return 1;
27974462Salfreddeny:
28074462Salfred#ifdef LIBWRAP
28174462Salfred	logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
28274462Salfred	    ": indirect call not allowed");
28374462Salfred#else
28474462Salfred	logit(0, sa, args->rmt_proc, args->rmt_prog,
28574462Salfred	    ": indirect call not allowed");
28674462Salfred#endif
28774462Salfred	return 0;
28874462Salfred}
289