xref: /illumos-gate/usr/src/cmd/rpcbind/rpcb_check.c (revision 0ea5e3a5)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0ea5e3a5Sjjj  * Common Development and Distribution License (the "License").
6*0ea5e3a5Sjjj  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * Auxiliary routines to shield off random internet hosts and to report
237c478bd9Sstevel@tonic-gate  * service requests (verbose mode only) or violations (always).
247c478bd9Sstevel@tonic-gate  *
257c478bd9Sstevel@tonic-gate  * This code was extensively modifed from a version authored by:
267c478bd9Sstevel@tonic-gate  *
277c478bd9Sstevel@tonic-gate  * Wietse Venema, Eindhoven University of Technology, The Netherlands
287c478bd9Sstevel@tonic-gate  * and distributed as "rpcbind 2.1".
297c478bd9Sstevel@tonic-gate  *
307c478bd9Sstevel@tonic-gate  * Sun was granted permission to use, modify, including make
317c478bd9Sstevel@tonic-gate  * derivatives of, copy, reproduce and distribute this code.c in both
327c478bd9Sstevel@tonic-gate  * binary and source forms, directly and indirectly.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  * Modified for bundling with Solaris and IPv6.
357c478bd9Sstevel@tonic-gate  *
367c478bd9Sstevel@tonic-gate  * Solaris specific modifcations made are:
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  *	Double fork() logging replaced with qsyslog();
397c478bd9Sstevel@tonic-gate  *	Connection refusals are flagged with svcerr_auth(); this
407c478bd9Sstevel@tonic-gate  *	aids in quicker diagnosability of misconfigurations and quicker
417c478bd9Sstevel@tonic-gate  *	failures for /net automounts;
427c478bd9Sstevel@tonic-gate  *	Single function for pmap* and rpcb*;
437c478bd9Sstevel@tonic-gate  *	Local transport checks made using localxprt().
447c478bd9Sstevel@tonic-gate  *
45*0ea5e3a5Sjjj  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
467c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
477c478bd9Sstevel@tonic-gate  */
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <stdio.h>
527c478bd9Sstevel@tonic-gate #include <stdlib.h>
537c478bd9Sstevel@tonic-gate #include <unistd.h>
547c478bd9Sstevel@tonic-gate #include <string.h>
557c478bd9Sstevel@tonic-gate #include <syslog.h>
567c478bd9Sstevel@tonic-gate #include <errno.h>
577c478bd9Sstevel@tonic-gate #include <netconfig.h>
587c478bd9Sstevel@tonic-gate #include <netdb.h>
597c478bd9Sstevel@tonic-gate #include <netdir.h>
607c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
617c478bd9Sstevel@tonic-gate #include <netinet/in.h>
627c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
637c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
647c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate #include "rpcbind.h"
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate /*
697c478bd9Sstevel@tonic-gate  * These are globally visible so that they can be modified by the wrapper's
707c478bd9Sstevel@tonic-gate  * language extension routines.
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate int allow_severity = LOG_INFO;
737c478bd9Sstevel@tonic-gate int deny_severity = LOG_WARNING;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate extern int hosts_ctl();
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate  * "inet_ntoa/inet_pton" for struct sockaddr_gen
797c478bd9Sstevel@tonic-gate  */
807c478bd9Sstevel@tonic-gate static const char *
817c478bd9Sstevel@tonic-gate sgen_toa(struct sockaddr_gen *addr)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 	static char buf[INET6_ADDRSTRLEN];
847c478bd9Sstevel@tonic-gate 	return (inet_ntop(SGFAM(addr), SGADDRP(addr), buf, sizeof (buf)));
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * find_procname - map rpcb/pmap procedure number to name
897c478bd9Sstevel@tonic-gate  */
907c478bd9Sstevel@tonic-gate static const char *
917c478bd9Sstevel@tonic-gate find_procname(rpcproc_t procnum, boolean_t pm)
927c478bd9Sstevel@tonic-gate {
937c478bd9Sstevel@tonic-gate 	static char procbuf[6 + 3 * sizeof (ulong_t)];
947c478bd9Sstevel@tonic-gate 	struct proc_map {
957c478bd9Sstevel@tonic-gate 		rpcproc_t code;
967c478bd9Sstevel@tonic-gate 		const char *proc;
977c478bd9Sstevel@tonic-gate 	};
987c478bd9Sstevel@tonic-gate 	static struct proc_map pmapmap[] = {
997c478bd9Sstevel@tonic-gate 		PMAPPROC_CALLIT,	"callit",
1007c478bd9Sstevel@tonic-gate 		PMAPPROC_DUMP,		"dump",
1017c478bd9Sstevel@tonic-gate 		PMAPPROC_GETPORT,	"getport",
1027c478bd9Sstevel@tonic-gate 		PMAPPROC_SET,		"set",
1037c478bd9Sstevel@tonic-gate 		PMAPPROC_UNSET,		"unset",
1047c478bd9Sstevel@tonic-gate 		NULLPROC,		"null",
1057c478bd9Sstevel@tonic-gate 	};
1067c478bd9Sstevel@tonic-gate 	static struct proc_map rpcbmap[] = {
1077c478bd9Sstevel@tonic-gate 		RPCBPROC_SET,		"set",
1087c478bd9Sstevel@tonic-gate 		RPCBPROC_UNSET,		"unset",
1097c478bd9Sstevel@tonic-gate 		RPCBPROC_GETADDR,	"getaddr",
1107c478bd9Sstevel@tonic-gate 		RPCBPROC_DUMP,		"dump",
1117c478bd9Sstevel@tonic-gate 		RPCBPROC_CALLIT,	"callit",
1127c478bd9Sstevel@tonic-gate 		RPCBPROC_GETTIME,	"gettime",
1137c478bd9Sstevel@tonic-gate 		RPCBPROC_UADDR2TADDR,	"uaddr2taddr",
1147c478bd9Sstevel@tonic-gate 		RPCBPROC_TADDR2UADDR,	"taddr2uaddr",
1157c478bd9Sstevel@tonic-gate 		RPCBPROC_GETVERSADDR,	"getversaddr",
1167c478bd9Sstevel@tonic-gate 		RPCBPROC_INDIRECT,	"indirect",
1177c478bd9Sstevel@tonic-gate 		RPCBPROC_GETADDRLIST,	"getaddrlist",
1187c478bd9Sstevel@tonic-gate 		RPCBPROC_GETSTAT,	"getstat",
1197c478bd9Sstevel@tonic-gate 		NULLPROC,		"null",
1207c478bd9Sstevel@tonic-gate 	};
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	int nitems, i;
1237c478bd9Sstevel@tonic-gate 	struct proc_map *procp;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if (pm) {
1267c478bd9Sstevel@tonic-gate 		procp = pmapmap;
1277c478bd9Sstevel@tonic-gate 		nitems = sizeof (pmapmap)/sizeof (struct proc_map);
1287c478bd9Sstevel@tonic-gate 	} else {
1297c478bd9Sstevel@tonic-gate 		procp = rpcbmap;
1307c478bd9Sstevel@tonic-gate 		nitems = sizeof (rpcbmap)/sizeof (struct proc_map);
1317c478bd9Sstevel@tonic-gate 	}
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	for (i = 0; i < nitems; i++) {
1347c478bd9Sstevel@tonic-gate 		if (procp[i].code == procnum)
1357c478bd9Sstevel@tonic-gate 			return (procp[i].proc);
1367c478bd9Sstevel@tonic-gate 	}
1377c478bd9Sstevel@tonic-gate 	(void) snprintf(procbuf, sizeof (procbuf), "%s-%lu",
1387c478bd9Sstevel@tonic-gate 		pm ? "pmap" : "rpcb", (ulong_t)procnum);
1397c478bd9Sstevel@tonic-gate 	return (procbuf);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate  * find_progname - map rpc program number to name.
1447c478bd9Sstevel@tonic-gate  */
1457c478bd9Sstevel@tonic-gate static const char *
1467c478bd9Sstevel@tonic-gate find_progname(rpcprog_t prognum)
1477c478bd9Sstevel@tonic-gate {
1487c478bd9Sstevel@tonic-gate 	static char progbuf[1 + 3 * sizeof (ulong_t)];
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	if (prognum == 0)
1517c478bd9Sstevel@tonic-gate 		return ("");
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/*
1547c478bd9Sstevel@tonic-gate 	 * The original code contained a call to "getrpcbynumber()";
1557c478bd9Sstevel@tonic-gate 	 * this call was removed because it may cause a call to a
1567c478bd9Sstevel@tonic-gate 	 * nameservice.
1577c478bd9Sstevel@tonic-gate 	 */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	(void) snprintf(progbuf, sizeof (progbuf), "%lu", (ulong_t)prognum);
1607c478bd9Sstevel@tonic-gate 	return (progbuf);
1617c478bd9Sstevel@tonic-gate }
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * rpcb_log - log request for service
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate void
1677c478bd9Sstevel@tonic-gate rpcb_log(boolean_t verdict, SVCXPRT *transp, rpcproc_t proc, rpcprog_t prog,
1687c478bd9Sstevel@tonic-gate     boolean_t pm)
1697c478bd9Sstevel@tonic-gate {
1707c478bd9Sstevel@tonic-gate 	struct netconfig *conf;
1717c478bd9Sstevel@tonic-gate 	const char *client = "unknown";
1727c478bd9Sstevel@tonic-gate 	char *uaddr;
1737c478bd9Sstevel@tonic-gate 	char buf[BUFSIZ];
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	/*
1767c478bd9Sstevel@tonic-gate 	 * Transform the transport address into something printable.
1777c478bd9Sstevel@tonic-gate 	 */
1787c478bd9Sstevel@tonic-gate 	if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) {
1797c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING,
1807c478bd9Sstevel@tonic-gate 		    "unknown transport (rpcbind_get_conf failed)");
1817c478bd9Sstevel@tonic-gate 	} else if (strcmp(conf->nc_protofmly, "inet") == 0 ||
1827c478bd9Sstevel@tonic-gate 	    strcmp(conf->nc_protofmly, "inet6") == 0) {
1837c478bd9Sstevel@tonic-gate 		client = sgen_toa(svc_getgencaller(transp));
1847c478bd9Sstevel@tonic-gate 	} else if ((uaddr = taddr2uaddr(conf, &(transp->xp_rtaddr))) == NULL) {
1857c478bd9Sstevel@tonic-gate 		syslog(LOG_WARNING, "unknown address (taddr2uaddr failed)");
1867c478bd9Sstevel@tonic-gate 	} else {
1877c478bd9Sstevel@tonic-gate 		(void) snprintf(buf, sizeof (buf), "%s(%s)",
1887c478bd9Sstevel@tonic-gate 		    conf->nc_protofmly, uaddr);
1897c478bd9Sstevel@tonic-gate 		free(uaddr);
1907c478bd9Sstevel@tonic-gate 		client = buf;
1917c478bd9Sstevel@tonic-gate 	}
1927c478bd9Sstevel@tonic-gate 	qsyslog(verdict ? allow_severity : deny_severity,
1937c478bd9Sstevel@tonic-gate 	    "%sconnect from %s to %s(%s)", verdict ? "" : "refused ",
1947c478bd9Sstevel@tonic-gate 	    client, find_procname(proc, pm), find_progname(prog));
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate  * rpcb_check; the rpcbind/portmap access check function.
1997c478bd9Sstevel@tonic-gate  */
2007c478bd9Sstevel@tonic-gate boolean_t
2017c478bd9Sstevel@tonic-gate rpcb_check(SVCXPRT *transp, rpcproc_t procnum, boolean_t ispmap)
2027c478bd9Sstevel@tonic-gate {
2037c478bd9Sstevel@tonic-gate 	struct netconfig *conf;
2047c478bd9Sstevel@tonic-gate 	boolean_t res = B_TRUE;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) {
2077c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
2087c478bd9Sstevel@tonic-gate 		    "rpcbind_get_conf failed: no client address checks");
2097c478bd9Sstevel@tonic-gate 		return (B_TRUE);
2107c478bd9Sstevel@tonic-gate 	}
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 	/*
2137c478bd9Sstevel@tonic-gate 	 * Require IPv4 for pmap calls; they're not defined for anything else.
2147c478bd9Sstevel@tonic-gate 	 */
2157c478bd9Sstevel@tonic-gate 	if (ispmap && strcmp(conf->nc_protofmly, "inet") != 0) {
2167c478bd9Sstevel@tonic-gate 		res = B_FALSE;
2177c478bd9Sstevel@tonic-gate 	} else if (strcmp(conf->nc_protofmly, "inet") == 0 ||
2187c478bd9Sstevel@tonic-gate 	    strcmp(conf->nc_protofmly, "inet6") == 0) {
2197c478bd9Sstevel@tonic-gate 		const char *addr_string = sgen_toa(svc_getgencaller(transp));
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		if (!localxprt(transp, ispmap) &&
222*0ea5e3a5Sjjj 		    (local_only ||
223*0ea5e3a5Sjjj 		    hosts_ctl("rpcbind", addr_string, addr_string, "") == 0)) {
2247c478bd9Sstevel@tonic-gate 			res = B_FALSE;
2257c478bd9Sstevel@tonic-gate 		}
2267c478bd9Sstevel@tonic-gate 	}
2277c478bd9Sstevel@tonic-gate out:
2287c478bd9Sstevel@tonic-gate 	if (!res)
2297c478bd9Sstevel@tonic-gate 		svcerr_auth(transp, AUTH_FAILED);
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 	if (verboselog || !res)
2327c478bd9Sstevel@tonic-gate 		rpcb_log(res, transp, procnum, 0, ispmap);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	return (res);
2357c478bd9Sstevel@tonic-gate }
236