Home | History | Annotate | Line # | Download | only in rpcbind
security.c revision 1.2
      1  1.2  thorpej /*	$NetBSD: security.c,v 1.2 2000/06/04 04:51:50 thorpej Exp $	*/
      2  1.1     fvdl 
      3  1.1     fvdl #include <sys/types.h>
      4  1.1     fvdl #include <sys/time.h>
      5  1.1     fvdl #include <sys/socket.h>
      6  1.1     fvdl #include <netinet/in.h>
      7  1.1     fvdl #include <arpa/inet.h>
      8  1.1     fvdl #include <rpc/rpc.h>
      9  1.1     fvdl #include <rpc/rpcb_prot.h>
     10  1.1     fvdl #include <rpc/pmap_prot.h>
     11  1.1     fvdl #include <err.h>
     12  1.1     fvdl #include <stdlib.h>
     13  1.2  thorpej #include <string.h>
     14  1.1     fvdl #include <unistd.h>
     15  1.1     fvdl #include <util.h>
     16  1.1     fvdl #include <syslog.h>
     17  1.1     fvdl #include <netdb.h>
     18  1.1     fvdl 
     19  1.1     fvdl /*
     20  1.1     fvdl  * XXX for special case checks in check_callit.
     21  1.1     fvdl  */
     22  1.1     fvdl #include <rpcsvc/mount.h>
     23  1.1     fvdl #include <rpcsvc/rquota.h>
     24  1.1     fvdl #include <rpcsvc/nfs_prot.h>
     25  1.1     fvdl #include <rpcsvc/yp.h>
     26  1.1     fvdl #include <rpcsvc/ypclnt.h>
     27  1.1     fvdl #include <rpcsvc/yppasswd.h>
     28  1.1     fvdl 
     29  1.1     fvdl #include "rpcbind.h"
     30  1.1     fvdl 
     31  1.1     fvdl #ifdef LIBWRAP
     32  1.1     fvdl # include <tcpd.h>
     33  1.1     fvdl #ifndef LIBWRAP_ALLOW_FACILITY
     34  1.1     fvdl # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
     35  1.1     fvdl #endif
     36  1.1     fvdl #ifndef LIBWRAP_ALLOW_SEVERITY
     37  1.1     fvdl # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
     38  1.1     fvdl #endif
     39  1.1     fvdl #ifndef LIBWRAP_DENY_FACILITY
     40  1.1     fvdl # define LIBWRAP_DENY_FACILITY LOG_AUTH
     41  1.1     fvdl #endif
     42  1.1     fvdl #ifndef LIBWRAP_DENY_SEVERITY
     43  1.1     fvdl # define LIBWRAP_DENY_SEVERITY LOG_WARNING
     44  1.1     fvdl #endif
     45  1.1     fvdl int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
     46  1.1     fvdl int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
     47  1.1     fvdl #endif
     48  1.1     fvdl 
     49  1.1     fvdl #ifndef PORTMAP_LOG_FACILITY
     50  1.1     fvdl # define PORTMAP_LOG_FACILITY LOG_AUTH
     51  1.1     fvdl #endif
     52  1.1     fvdl #ifndef PORTMAP_LOG_SEVERITY
     53  1.1     fvdl # define PORTMAP_LOG_SEVERITY LOG_INFO
     54  1.1     fvdl #endif
     55  1.1     fvdl int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
     56  1.1     fvdl 
     57  1.1     fvdl extern int verboselog;
     58  1.1     fvdl 
     59  1.1     fvdl int
     60  1.1     fvdl check_access(SVCXPRT *xprt, rpcproc_t proc, void *args, int rpcbvers)
     61  1.1     fvdl {
     62  1.1     fvdl 	struct netbuf *caller = svc_getrpccaller(xprt);
     63  1.1     fvdl 	struct sockaddr *addr = (struct sockaddr *)caller->buf;
     64  1.1     fvdl #ifdef LIBWRAP
     65  1.1     fvdl 	struct request_info req;
     66  1.1     fvdl #endif
     67  1.1     fvdl 	rpcprog_t prog = 0;
     68  1.1     fvdl 	rpcb *rpcbp;
     69  1.1     fvdl 	struct pmap *pmap;
     70  1.1     fvdl 
     71  1.1     fvdl 	/*
     72  1.1     fvdl 	 * The older PMAP_* equivalents have the same numbers, so
     73  1.1     fvdl 	 * they are accounted for here as well.
     74  1.1     fvdl 	 */
     75  1.1     fvdl 	switch (proc) {
     76  1.1     fvdl 	case RPCBPROC_GETADDR:
     77  1.1     fvdl 	case RPCBPROC_SET:
     78  1.1     fvdl 	case RPCBPROC_UNSET:
     79  1.1     fvdl 		if (rpcbvers > PMAPVERS) {
     80  1.1     fvdl 			rpcbp = (rpcb *)args;
     81  1.1     fvdl 			prog = rpcbp->r_prog;
     82  1.1     fvdl 		} else {
     83  1.1     fvdl 			pmap = (struct pmap *)args;
     84  1.1     fvdl 			prog = pmap->pm_prog;
     85  1.1     fvdl 		}
     86  1.1     fvdl 		if (proc == RPCBPROC_GETADDR)
     87  1.1     fvdl 			break;
     88  1.1     fvdl 		if (!insecure && !is_loopback(caller)) {
     89  1.1     fvdl 			if (verboselog)
     90  1.1     fvdl 				logit(log_severity, addr, proc, prog,
     91  1.1     fvdl 				    " declined (non-loopback sender)");
     92  1.1     fvdl 			return 0;
     93  1.1     fvdl 		}
     94  1.1     fvdl 		break;
     95  1.1     fvdl 	case RPCBPROC_CALLIT:
     96  1.1     fvdl 	case RPCBPROC_INDIRECT:
     97  1.1     fvdl 	case RPCBPROC_DUMP:
     98  1.1     fvdl 	case RPCBPROC_GETTIME:
     99  1.1     fvdl 	case RPCBPROC_UADDR2TADDR:
    100  1.1     fvdl 	case RPCBPROC_TADDR2UADDR:
    101  1.1     fvdl 	case RPCBPROC_GETVERSADDR:
    102  1.1     fvdl 	case RPCBPROC_GETADDRLIST:
    103  1.1     fvdl 	case RPCBPROC_GETSTAT:
    104  1.1     fvdl 	default:
    105  1.1     fvdl 	}
    106  1.1     fvdl 
    107  1.1     fvdl #ifdef LIBWRAP
    108  1.1     fvdl 	request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
    109  1.1     fvdl 	sock_methods(&req);
    110  1.1     fvdl 	if(!hosts_access(&req)) {
    111  1.1     fvdl 		logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
    112  1.1     fvdl 		return 0;
    113  1.1     fvdl 	}
    114  1.1     fvdl #endif
    115  1.1     fvdl 	if (verboselog)
    116  1.1     fvdl 		logit(log_severity, addr, proc, prog, "");
    117  1.1     fvdl     	return 1;
    118  1.1     fvdl }
    119  1.1     fvdl 
    120  1.1     fvdl int
    121  1.1     fvdl is_loopback(struct netbuf *nbuf)
    122  1.1     fvdl {
    123  1.1     fvdl 	struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
    124  1.1     fvdl 	struct sockaddr_in *sin;
    125  1.1     fvdl #ifdef INET6
    126  1.1     fvdl 	struct sockaddr_in6 *sin6;
    127  1.1     fvdl #endif
    128  1.1     fvdl 
    129  1.1     fvdl 	switch (addr->sa_family) {
    130  1.1     fvdl 	case AF_INET:
    131  1.1     fvdl 		if (!oldstyle_local)
    132  1.1     fvdl 			return 0;
    133  1.1     fvdl 		sin = (struct sockaddr_in *)addr;
    134  1.1     fvdl         	return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
    135  1.1     fvdl 		    (sin->sin_port < IPPORT_RESERVED));
    136  1.1     fvdl #ifdef INET6
    137  1.1     fvdl 	case AF_INET6:
    138  1.1     fvdl 		if (!oldstyle_local)
    139  1.1     fvdl 			return 0;
    140  1.1     fvdl 		sin6 = (struct sockaddr_in6 *)addr;
    141  1.1     fvdl 		return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) &&
    142  1.1     fvdl 		    (sin6->sin6_port < IPPORT_RESERVED));
    143  1.1     fvdl #endif
    144  1.1     fvdl 	case AF_LOCAL:
    145  1.1     fvdl 		return 1;
    146  1.1     fvdl 	default:
    147  1.1     fvdl 	}
    148  1.1     fvdl 
    149  1.1     fvdl 	return 0;
    150  1.1     fvdl }
    151  1.1     fvdl 
    152  1.1     fvdl 
    153  1.1     fvdl /* logit - report events of interest via the syslog daemon */
    154  1.1     fvdl void
    155  1.1     fvdl logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
    156  1.1     fvdl       const char *text)
    157  1.1     fvdl {
    158  1.1     fvdl 	const char *procname;
    159  1.1     fvdl 	char	procbuf[32];
    160  1.1     fvdl 	char   *progname;
    161  1.1     fvdl 	char	progbuf[32];
    162  1.1     fvdl 	char fromname[NI_MAXHOST];
    163  1.1     fvdl 	struct rpcent *rpc;
    164  1.1     fvdl 	static const char *procmap[] = {
    165  1.1     fvdl 	/* RPCBPROC_NULL */		"null",
    166  1.1     fvdl 	/* RPCBPROC_SET */		"set",
    167  1.1     fvdl 	/* RPCBPROC_UNSET */		"unset",
    168  1.1     fvdl 	/* RPCBPROC_GETADDR */		"getport/addr",
    169  1.1     fvdl 	/* RPCBPROC_DUMP */		"dump",
    170  1.1     fvdl 	/* RPCBPROC_CALLIT */		"callit",
    171  1.1     fvdl 	/* RPCBPROC_GETTIME */		"gettime",
    172  1.1     fvdl 	/* RPCBPROC_UADDR2TADDR */	"uaddr2taddr",
    173  1.1     fvdl 	/* RPCBPROC_TADDR2UADDR */	"taddr2uaddr",
    174  1.1     fvdl 	/* RPCBPROC_GETVERSADDR */	"getversaddr",
    175  1.1     fvdl 	/* RPCBPROC_INDIRECT */		"indirect",
    176  1.1     fvdl 	/* RPCBPROC_GETADDRLIST */	"getaddrlist",
    177  1.1     fvdl 	/* RPCBPROC_GETSTAT */		"getstat"
    178  1.1     fvdl 	};
    179  1.1     fvdl 
    180  1.1     fvdl 	/*
    181  1.1     fvdl 	 * Fork off a process or the portmap daemon might hang while
    182  1.1     fvdl 	 * getrpcbynumber() or syslog() does its thing.
    183  1.1     fvdl 	 */
    184  1.1     fvdl 
    185  1.1     fvdl 	if (fork() == 0) {
    186  1.1     fvdl 		setproctitle("logit");
    187  1.1     fvdl 
    188  1.1     fvdl 		/* Try to map program number to name. */
    189  1.1     fvdl 
    190  1.1     fvdl 		if (prognum == 0) {
    191  1.1     fvdl 			progname = "";
    192  1.1     fvdl 		} else if ((rpc = getrpcbynumber((int) prognum))) {
    193  1.1     fvdl 			progname = rpc->r_name;
    194  1.1     fvdl 		} else {
    195  1.1     fvdl 			snprintf(progname = progbuf, sizeof(progbuf), "%u",
    196  1.1     fvdl 			    (unsigned)prognum);
    197  1.1     fvdl 		}
    198  1.1     fvdl 
    199  1.1     fvdl 		/* Try to map procedure number to name. */
    200  1.1     fvdl 
    201  1.1     fvdl 		if (procnum > (sizeof procmap / sizeof (char *))) {
    202  1.1     fvdl 			snprintf(procbuf, sizeof procbuf, "%u",
    203  1.1     fvdl 			    (unsigned)procnum);
    204  1.1     fvdl 			procname = procbuf;
    205  1.1     fvdl 		} else
    206  1.1     fvdl 			procname = procmap[procnum];
    207  1.1     fvdl 
    208  1.1     fvdl 		/* Write syslog record. */
    209  1.1     fvdl 
    210  1.1     fvdl 		if (addr->sa_family == AF_LOCAL)
    211  1.1     fvdl 			strcpy(fromname, "local");
    212  1.1     fvdl 		else
    213  1.1     fvdl 			getnameinfo(addr, addr->sa_len, fromname,
    214  1.1     fvdl 			    sizeof fromname, NULL, 0, NI_NUMERICHOST);
    215  1.1     fvdl 
    216  1.1     fvdl 		syslog(severity, "connect from %s to %s(%s)%s",
    217  1.1     fvdl 			fromname, procname, progname, text);
    218  1.1     fvdl 		_exit(0);
    219  1.1     fvdl 	}
    220  1.1     fvdl }
    221  1.1     fvdl 
    222  1.1     fvdl int
    223  1.1     fvdl check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum)
    224  1.1     fvdl {
    225  1.1     fvdl 	struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
    226  1.1     fvdl 
    227  1.1     fvdl 	/*
    228  1.1     fvdl 	 * Always allow calling NULLPROC
    229  1.1     fvdl 	 */
    230  1.1     fvdl 	if (args->rmt_proc == 0)
    231  1.1     fvdl 		return 1;
    232  1.1     fvdl 
    233  1.1     fvdl 	/*
    234  1.1     fvdl 	 * XXX - this special casing sucks.
    235  1.1     fvdl 	 */
    236  1.1     fvdl 	switch (args->rmt_prog) {
    237  1.1     fvdl 	case RPCBPROG:
    238  1.1     fvdl 		/*
    239  1.1     fvdl 		 * Allow indirect calls to ourselves in insecure mode.
    240  1.1     fvdl 		 * The is_loopback checks aren't useful then anyway.
    241  1.1     fvdl 		 */
    242  1.1     fvdl 		if (!insecure)
    243  1.1     fvdl 			goto deny;
    244  1.1     fvdl 		break;
    245  1.1     fvdl 	case MOUNTPROG:
    246  1.1     fvdl 		if (args->rmt_proc != MOUNTPROC_MNT &&
    247  1.1     fvdl 		    args->rmt_proc != MOUNTPROC_UMNT)
    248  1.1     fvdl 			break;
    249  1.1     fvdl 		goto deny;
    250  1.1     fvdl 	case YPBINDPROG:
    251  1.1     fvdl 		if (args->rmt_proc != YPBINDPROC_SETDOM)
    252  1.1     fvdl 			break;
    253  1.1     fvdl 		/* FALLTHROUGH */
    254  1.1     fvdl 	case YPPASSWDPROG:
    255  1.1     fvdl 	case NFS_PROGRAM:
    256  1.1     fvdl 	case RQUOTAPROG:
    257  1.1     fvdl 		goto deny;
    258  1.1     fvdl 	case YPPROG:
    259  1.1     fvdl 		switch (args->rmt_proc) {
    260  1.1     fvdl 		case YPPROC_ALL:
    261  1.1     fvdl 		case YPPROC_MATCH:
    262  1.1     fvdl 		case YPPROC_FIRST:
    263  1.1     fvdl 		case YPPROC_NEXT:
    264  1.1     fvdl 			goto deny;
    265  1.1     fvdl 		default:
    266  1.1     fvdl 		}
    267  1.1     fvdl 	default:
    268  1.1     fvdl 	}
    269  1.1     fvdl 
    270  1.1     fvdl 	return 1;
    271  1.1     fvdl deny:
    272  1.1     fvdl 	logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
    273  1.1     fvdl 	    ": indirect call not allowed");
    274  1.1     fvdl 
    275  1.1     fvdl 	return 0;
    276  1.1     fvdl }
    277