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> 1305c4b26eSIan Dowse #include <stdio.h> 148360efbdSAlfred Perlstein #include <stdlib.h> 158360efbdSAlfred Perlstein #include <string.h> 168360efbdSAlfred Perlstein #include <unistd.h> 178360efbdSAlfred Perlstein #include <libutil.h> 188360efbdSAlfred Perlstein #include <syslog.h> 198360efbdSAlfred Perlstein #include <netdb.h> 208360efbdSAlfred Perlstein 218360efbdSAlfred Perlstein /* 228360efbdSAlfred Perlstein * XXX for special case checks in check_callit. 238360efbdSAlfred Perlstein */ 248360efbdSAlfred Perlstein #include <rpcsvc/mount.h> 258360efbdSAlfred Perlstein #include <rpcsvc/rquota.h> 268360efbdSAlfred Perlstein #include <rpcsvc/nfs_prot.h> 278360efbdSAlfred Perlstein #include <rpcsvc/yp.h> 288360efbdSAlfred Perlstein #include <rpcsvc/ypclnt.h> 298360efbdSAlfred Perlstein #include <rpcsvc/yppasswd.h> 308360efbdSAlfred Perlstein 318360efbdSAlfred Perlstein #include "rpcbind.h" 328360efbdSAlfred Perlstein 338360efbdSAlfred Perlstein #ifdef LIBWRAP 348360efbdSAlfred Perlstein # include <tcpd.h> 358360efbdSAlfred Perlstein #ifndef LIBWRAP_ALLOW_FACILITY 368360efbdSAlfred Perlstein # define LIBWRAP_ALLOW_FACILITY LOG_AUTH 378360efbdSAlfred Perlstein #endif 388360efbdSAlfred Perlstein #ifndef LIBWRAP_ALLOW_SEVERITY 398360efbdSAlfred Perlstein # define LIBWRAP_ALLOW_SEVERITY LOG_INFO 408360efbdSAlfred Perlstein #endif 418360efbdSAlfred Perlstein #ifndef LIBWRAP_DENY_FACILITY 428360efbdSAlfred Perlstein # define LIBWRAP_DENY_FACILITY LOG_AUTH 438360efbdSAlfred Perlstein #endif 448360efbdSAlfred Perlstein #ifndef LIBWRAP_DENY_SEVERITY 458360efbdSAlfred Perlstein # define LIBWRAP_DENY_SEVERITY LOG_WARNING 468360efbdSAlfred Perlstein #endif 478360efbdSAlfred Perlstein int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 488360efbdSAlfred Perlstein int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 498360efbdSAlfred Perlstein #endif 508360efbdSAlfred Perlstein 518360efbdSAlfred Perlstein #ifndef PORTMAP_LOG_FACILITY 528360efbdSAlfred Perlstein # define PORTMAP_LOG_FACILITY LOG_AUTH 538360efbdSAlfred Perlstein #endif 548360efbdSAlfred Perlstein #ifndef PORTMAP_LOG_SEVERITY 558360efbdSAlfred Perlstein # define PORTMAP_LOG_SEVERITY LOG_INFO 568360efbdSAlfred Perlstein #endif 578360efbdSAlfred Perlstein int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY; 588360efbdSAlfred Perlstein 598360efbdSAlfred Perlstein extern int verboselog; 608360efbdSAlfred Perlstein 618360efbdSAlfred Perlstein int 628360efbdSAlfred Perlstein check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, int rpcbvers) 638360efbdSAlfred Perlstein { 648360efbdSAlfred Perlstein struct netbuf *caller = svc_getrpccaller(xprt); 658360efbdSAlfred Perlstein struct sockaddr *addr = (struct sockaddr *)caller->buf; 668360efbdSAlfred Perlstein #ifdef LIBWRAP 678360efbdSAlfred Perlstein struct request_info req; 688360efbdSAlfred Perlstein #endif 698360efbdSAlfred Perlstein rpcprog_t prog = 0; 708360efbdSAlfred Perlstein rpcb *rpcbp; 718360efbdSAlfred Perlstein struct pmap *pmap; 728360efbdSAlfred Perlstein 738360efbdSAlfred Perlstein /* 748360efbdSAlfred Perlstein * The older PMAP_* equivalents have the same numbers, so 758360efbdSAlfred Perlstein * they are accounted for here as well. 768360efbdSAlfred Perlstein */ 778360efbdSAlfred Perlstein switch (proc) { 788360efbdSAlfred Perlstein case RPCBPROC_GETADDR: 798360efbdSAlfred Perlstein case RPCBPROC_SET: 808360efbdSAlfred Perlstein case RPCBPROC_UNSET: 818360efbdSAlfred Perlstein if (rpcbvers > PMAPVERS) { 828360efbdSAlfred Perlstein rpcbp = (rpcb *)args; 838360efbdSAlfred Perlstein prog = rpcbp->r_prog; 848360efbdSAlfred Perlstein } else { 858360efbdSAlfred Perlstein pmap = (struct pmap *)args; 868360efbdSAlfred Perlstein prog = pmap->pm_prog; 878360efbdSAlfred Perlstein } 888360efbdSAlfred Perlstein if (proc == RPCBPROC_GETADDR) 898360efbdSAlfred Perlstein break; 908360efbdSAlfred Perlstein if (!insecure && !is_loopback(caller)) { 918360efbdSAlfred Perlstein if (verboselog) 928360efbdSAlfred Perlstein logit(log_severity, addr, proc, prog, 938360efbdSAlfred Perlstein " declined (non-loopback sender)"); 948360efbdSAlfred Perlstein return 0; 958360efbdSAlfred Perlstein } 968360efbdSAlfred Perlstein break; 978360efbdSAlfred Perlstein case RPCBPROC_CALLIT: 988360efbdSAlfred Perlstein case RPCBPROC_INDIRECT: 998360efbdSAlfred Perlstein case RPCBPROC_DUMP: 1008360efbdSAlfred Perlstein case RPCBPROC_GETTIME: 1018360efbdSAlfred Perlstein case RPCBPROC_UADDR2TADDR: 1028360efbdSAlfred Perlstein case RPCBPROC_TADDR2UADDR: 1038360efbdSAlfred Perlstein case RPCBPROC_GETVERSADDR: 1048360efbdSAlfred Perlstein case RPCBPROC_GETADDRLIST: 1058360efbdSAlfred Perlstein case RPCBPROC_GETSTAT: 1068360efbdSAlfred Perlstein default: 1078360efbdSAlfred Perlstein } 1088360efbdSAlfred Perlstein 1098360efbdSAlfred Perlstein #ifdef LIBWRAP 1108360efbdSAlfred Perlstein if (addr->sa_family == AF_LOCAL) 1118360efbdSAlfred Perlstein return 1; 1128360efbdSAlfred Perlstein request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0); 1138360efbdSAlfred Perlstein sock_methods(&req); 1148360efbdSAlfred Perlstein if(!hosts_access(&req)) { 1158360efbdSAlfred Perlstein logit(deny_severity, addr, proc, prog, ": request from unauthorized host"); 1168360efbdSAlfred Perlstein return 0; 1178360efbdSAlfred Perlstein } 1188360efbdSAlfred Perlstein #endif 1198360efbdSAlfred Perlstein if (verboselog) 1208360efbdSAlfred Perlstein logit(log_severity, addr, proc, prog, ""); 1218360efbdSAlfred Perlstein return 1; 1228360efbdSAlfred Perlstein } 1238360efbdSAlfred Perlstein 1248360efbdSAlfred Perlstein int 1258360efbdSAlfred Perlstein is_loopback(struct netbuf *nbuf) 1268360efbdSAlfred Perlstein { 1278360efbdSAlfred Perlstein struct sockaddr *addr = (struct sockaddr *)nbuf->buf; 1288360efbdSAlfred Perlstein struct sockaddr_in *sin; 1298360efbdSAlfred Perlstein #ifdef INET6 1308360efbdSAlfred Perlstein struct sockaddr_in6 *sin6; 1318360efbdSAlfred Perlstein #endif 1328360efbdSAlfred Perlstein 1338360efbdSAlfred Perlstein switch (addr->sa_family) { 1348360efbdSAlfred Perlstein case AF_INET: 1358360efbdSAlfred Perlstein if (!oldstyle_local) 1368360efbdSAlfred Perlstein return 0; 1378360efbdSAlfred Perlstein sin = (struct sockaddr_in *)addr; 1388360efbdSAlfred Perlstein return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) && 1398360efbdSAlfred Perlstein (ntohs(sin->sin_port) < IPPORT_RESERVED)); 1408360efbdSAlfred Perlstein #ifdef INET6 1418360efbdSAlfred Perlstein case AF_INET6: 1428360efbdSAlfred Perlstein if (!oldstyle_local) 1438360efbdSAlfred Perlstein return 0; 1448360efbdSAlfred Perlstein sin6 = (struct sockaddr_in6 *)addr; 1458360efbdSAlfred Perlstein return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) && 1468360efbdSAlfred Perlstein (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED)); 1478360efbdSAlfred Perlstein #endif 1488360efbdSAlfred Perlstein case AF_LOCAL: 1498360efbdSAlfred Perlstein return 1; 1508360efbdSAlfred Perlstein default: 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 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) 2158360efbdSAlfred Perlstein strcpy(fromname, "unix"); 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 2278360efbdSAlfred Perlstein check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum) 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: 2708360efbdSAlfred Perlstein } 2718360efbdSAlfred Perlstein default: 2728360efbdSAlfred Perlstein } 2738360efbdSAlfred Perlstein 2748360efbdSAlfred Perlstein return 1; 2758360efbdSAlfred Perlstein deny: 2768360efbdSAlfred Perlstein #ifdef LIBWRAP 2778360efbdSAlfred Perlstein logit(deny_severity, sa, args->rmt_proc, args->rmt_prog, 2788360efbdSAlfred Perlstein ": indirect call not allowed"); 2798360efbdSAlfred Perlstein #else 2808360efbdSAlfred Perlstein logit(0, sa, args->rmt_proc, args->rmt_prog, 2818360efbdSAlfred Perlstein ": indirect call not allowed"); 2828360efbdSAlfred Perlstein #endif 2838360efbdSAlfred Perlstein return 0; 2848360efbdSAlfred Perlstein } 285