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:
148*d50fc4baSGleb Smirnoff case AF_NETLINK:
1498360efbdSAlfred Perlstein return 1;
1508360efbdSAlfred Perlstein default:
1514ee5e586SAlfred Perlstein break;
1528360efbdSAlfred Perlstein }
1538360efbdSAlfred Perlstein
1548360efbdSAlfred Perlstein return 0;
1558360efbdSAlfred Perlstein }
1568360efbdSAlfred Perlstein
1578360efbdSAlfred Perlstein
1588360efbdSAlfred Perlstein /* logit - report events of interest via the syslog daemon */
1598360efbdSAlfred Perlstein void
logit(int severity,struct sockaddr * addr,rpcproc_t procnum,rpcprog_t prognum,const char * text)1608360efbdSAlfred Perlstein logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
1618360efbdSAlfred Perlstein const char *text)
1628360efbdSAlfred Perlstein {
1638360efbdSAlfred Perlstein const char *procname;
1648360efbdSAlfred Perlstein char procbuf[32];
1658360efbdSAlfred Perlstein char *progname;
1668360efbdSAlfred Perlstein char progbuf[32];
1678360efbdSAlfred Perlstein char fromname[NI_MAXHOST];
1688360efbdSAlfred Perlstein struct rpcent *rpc;
1698360efbdSAlfred Perlstein static const char *procmap[] = {
1708360efbdSAlfred Perlstein /* RPCBPROC_NULL */ "null",
1718360efbdSAlfred Perlstein /* RPCBPROC_SET */ "set",
1728360efbdSAlfred Perlstein /* RPCBPROC_UNSET */ "unset",
1738360efbdSAlfred Perlstein /* RPCBPROC_GETADDR */ "getport/addr",
1748360efbdSAlfred Perlstein /* RPCBPROC_DUMP */ "dump",
1758360efbdSAlfred Perlstein /* RPCBPROC_CALLIT */ "callit",
1768360efbdSAlfred Perlstein /* RPCBPROC_GETTIME */ "gettime",
1778360efbdSAlfred Perlstein /* RPCBPROC_UADDR2TADDR */ "uaddr2taddr",
1788360efbdSAlfred Perlstein /* RPCBPROC_TADDR2UADDR */ "taddr2uaddr",
1798360efbdSAlfred Perlstein /* RPCBPROC_GETVERSADDR */ "getversaddr",
1808360efbdSAlfred Perlstein /* RPCBPROC_INDIRECT */ "indirect",
1818360efbdSAlfred Perlstein /* RPCBPROC_GETADDRLIST */ "getaddrlist",
1828360efbdSAlfred Perlstein /* RPCBPROC_GETSTAT */ "getstat"
1838360efbdSAlfred Perlstein };
1848360efbdSAlfred Perlstein
1858360efbdSAlfred Perlstein /*
1868360efbdSAlfred Perlstein * Fork off a process or the portmap daemon might hang while
1878360efbdSAlfred Perlstein * getrpcbynumber() or syslog() does its thing.
1888360efbdSAlfred Perlstein */
1898360efbdSAlfred Perlstein
1908360efbdSAlfred Perlstein if (fork() == 0) {
1918360efbdSAlfred Perlstein setproctitle("logit");
1928360efbdSAlfred Perlstein
1938360efbdSAlfred Perlstein /* Try to map program number to name. */
1948360efbdSAlfred Perlstein
1958360efbdSAlfred Perlstein if (prognum == 0) {
1968360efbdSAlfred Perlstein progname = "";
1978360efbdSAlfred Perlstein } else if ((rpc = getrpcbynumber((int) prognum))) {
1988360efbdSAlfred Perlstein progname = rpc->r_name;
1998360efbdSAlfred Perlstein } else {
2008360efbdSAlfred Perlstein snprintf(progname = progbuf, sizeof(progbuf), "%u",
2018360efbdSAlfred Perlstein (unsigned)prognum);
2028360efbdSAlfred Perlstein }
2038360efbdSAlfred Perlstein
2048360efbdSAlfred Perlstein /* Try to map procedure number to name. */
2058360efbdSAlfred Perlstein
20605c4b26eSIan Dowse if (procnum >= (sizeof procmap / sizeof (char *))) {
2078360efbdSAlfred Perlstein snprintf(procbuf, sizeof procbuf, "%u",
2088360efbdSAlfred Perlstein (unsigned)procnum);
2098360efbdSAlfred Perlstein procname = procbuf;
2108360efbdSAlfred Perlstein } else
2118360efbdSAlfred Perlstein procname = procmap[procnum];
2128360efbdSAlfred Perlstein
2138360efbdSAlfred Perlstein /* Write syslog record. */
2148360efbdSAlfred Perlstein
2158360efbdSAlfred Perlstein if (addr->sa_family == AF_LOCAL)
216fb4c8061SMartin Blapp strcpy(fromname, "local");
2178360efbdSAlfred Perlstein else
2188360efbdSAlfred Perlstein getnameinfo(addr, addr->sa_len, fromname,
2198360efbdSAlfred Perlstein sizeof fromname, NULL, 0, NI_NUMERICHOST);
2208360efbdSAlfred Perlstein
2218360efbdSAlfred Perlstein syslog(severity, "connect from %s to %s(%s)%s",
2228360efbdSAlfred Perlstein fromname, procname, progname, text);
2238360efbdSAlfred Perlstein _exit(0);
2248360efbdSAlfred Perlstein }
2258360efbdSAlfred Perlstein }
2268360efbdSAlfred Perlstein
2278360efbdSAlfred Perlstein int
check_callit(SVCXPRT * xprt,struct r_rmtcall_args * args,int versnum __unused)2284180788fSAlfred Perlstein check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum __unused)
2298360efbdSAlfred Perlstein {
2308360efbdSAlfred Perlstein struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
2318360efbdSAlfred Perlstein
2328360efbdSAlfred Perlstein /*
2338360efbdSAlfred Perlstein * Always allow calling NULLPROC
2348360efbdSAlfred Perlstein */
2358360efbdSAlfred Perlstein if (args->rmt_proc == 0)
2368360efbdSAlfred Perlstein return 1;
2378360efbdSAlfred Perlstein
2388360efbdSAlfred Perlstein /*
2398360efbdSAlfred Perlstein * XXX - this special casing sucks.
2408360efbdSAlfred Perlstein */
2418360efbdSAlfred Perlstein switch (args->rmt_prog) {
2428360efbdSAlfred Perlstein case RPCBPROG:
2438360efbdSAlfred Perlstein /*
2448360efbdSAlfred Perlstein * Allow indirect calls to ourselves in insecure mode.
2458360efbdSAlfred Perlstein * The is_loopback checks aren't useful then anyway.
2468360efbdSAlfred Perlstein */
2478360efbdSAlfred Perlstein if (!insecure)
2488360efbdSAlfred Perlstein goto deny;
2498360efbdSAlfred Perlstein break;
2508360efbdSAlfred Perlstein case MOUNTPROG:
2518360efbdSAlfred Perlstein if (args->rmt_proc != MOUNTPROC_MNT &&
2528360efbdSAlfred Perlstein args->rmt_proc != MOUNTPROC_UMNT)
2538360efbdSAlfred Perlstein break;
2548360efbdSAlfred Perlstein goto deny;
2558360efbdSAlfred Perlstein case YPBINDPROG:
2568360efbdSAlfred Perlstein if (args->rmt_proc != YPBINDPROC_SETDOM)
2578360efbdSAlfred Perlstein break;
2588360efbdSAlfred Perlstein /* FALLTHROUGH */
2598360efbdSAlfred Perlstein case YPPASSWDPROG:
2608360efbdSAlfred Perlstein case NFS_PROGRAM:
2618360efbdSAlfred Perlstein case RQUOTAPROG:
2628360efbdSAlfred Perlstein goto deny;
2638360efbdSAlfred Perlstein case YPPROG:
2648360efbdSAlfred Perlstein switch (args->rmt_proc) {
2658360efbdSAlfred Perlstein case YPPROC_ALL:
2668360efbdSAlfred Perlstein case YPPROC_MATCH:
2678360efbdSAlfred Perlstein case YPPROC_FIRST:
2688360efbdSAlfred Perlstein case YPPROC_NEXT:
2698360efbdSAlfred Perlstein goto deny;
2708360efbdSAlfred Perlstein default:
2714ee5e586SAlfred Perlstein break;
2728360efbdSAlfred Perlstein }
2738360efbdSAlfred Perlstein default:
2744ee5e586SAlfred Perlstein break;
2758360efbdSAlfred Perlstein }
2768360efbdSAlfred Perlstein
2778360efbdSAlfred Perlstein return 1;
2788360efbdSAlfred Perlstein deny:
2798360efbdSAlfred Perlstein #ifdef LIBWRAP
2808360efbdSAlfred Perlstein logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
2818360efbdSAlfred Perlstein ": indirect call not allowed");
2828360efbdSAlfred Perlstein #else
2838360efbdSAlfred Perlstein logit(0, sa, args->rmt_proc, args->rmt_prog,
2848360efbdSAlfred Perlstein ": indirect call not allowed");
2858360efbdSAlfred Perlstein #endif
2868360efbdSAlfred Perlstein return 0;
2878360efbdSAlfred Perlstein }
288