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