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