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
50ea5e3a5Sjjj * Common Development and Distribution License (the "License").
60ea5e3a5Sjjj * 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 *
450ea5e3a5Sjjj * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
467c478bd9Sstevel@tonic-gate * Use is subject to license terms.
477c478bd9Sstevel@tonic-gate */
48*8f6d9daeSMarcel Telka /*
49*8f6d9daeSMarcel Telka * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
50*8f6d9daeSMarcel Telka */
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include <stdio.h>
537c478bd9Sstevel@tonic-gate #include <stdlib.h>
547c478bd9Sstevel@tonic-gate #include <unistd.h>
557c478bd9Sstevel@tonic-gate #include <string.h>
567c478bd9Sstevel@tonic-gate #include <syslog.h>
577c478bd9Sstevel@tonic-gate #include <errno.h>
587c478bd9Sstevel@tonic-gate #include <netconfig.h>
597c478bd9Sstevel@tonic-gate #include <netdb.h>
607c478bd9Sstevel@tonic-gate #include <netdir.h>
617c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
627c478bd9Sstevel@tonic-gate #include <netinet/in.h>
637c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
647c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h>
657c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h>
66*8f6d9daeSMarcel Telka #include <thread.h>
67*8f6d9daeSMarcel Telka #include <synch.h>
68*8f6d9daeSMarcel Telka #include <tcpd.h>
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate #include "rpcbind.h"
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate /*
737c478bd9Sstevel@tonic-gate * These are globally visible so that they can be modified by the wrapper's
747c478bd9Sstevel@tonic-gate * language extension routines.
757c478bd9Sstevel@tonic-gate */
767c478bd9Sstevel@tonic-gate int allow_severity = LOG_INFO;
777c478bd9Sstevel@tonic-gate int deny_severity = LOG_WARNING;
787c478bd9Sstevel@tonic-gate
79*8f6d9daeSMarcel Telka static mutex_t hosts_ctl_lock = DEFAULTMUTEX;
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate /*
827c478bd9Sstevel@tonic-gate * "inet_ntoa/inet_pton" for struct sockaddr_gen
837c478bd9Sstevel@tonic-gate */
847c478bd9Sstevel@tonic-gate static const char *
sgen_toa(struct sockaddr_gen * addr,char * buf,size_t bufsize)85*8f6d9daeSMarcel Telka sgen_toa(struct sockaddr_gen *addr, char *buf, size_t bufsize)
867c478bd9Sstevel@tonic-gate {
87*8f6d9daeSMarcel Telka return (inet_ntop(SGFAM(addr), SGADDRP(addr), buf, bufsize));
887c478bd9Sstevel@tonic-gate }
897c478bd9Sstevel@tonic-gate
90*8f6d9daeSMarcel Telka struct proc_map {
91*8f6d9daeSMarcel Telka rpcproc_t code;
92*8f6d9daeSMarcel Telka const char *proc;
93*8f6d9daeSMarcel Telka };
94*8f6d9daeSMarcel Telka
95*8f6d9daeSMarcel Telka static const struct proc_map pmapmap[] = {
96*8f6d9daeSMarcel Telka PMAPPROC_CALLIT, "callit",
97*8f6d9daeSMarcel Telka PMAPPROC_DUMP, "dump",
98*8f6d9daeSMarcel Telka PMAPPROC_GETPORT, "getport",
99*8f6d9daeSMarcel Telka PMAPPROC_SET, "set",
100*8f6d9daeSMarcel Telka PMAPPROC_UNSET, "unset",
101*8f6d9daeSMarcel Telka NULLPROC, "null",
102*8f6d9daeSMarcel Telka };
103*8f6d9daeSMarcel Telka
104*8f6d9daeSMarcel Telka static const struct proc_map rpcbmap[] = {
105*8f6d9daeSMarcel Telka RPCBPROC_SET, "set",
106*8f6d9daeSMarcel Telka RPCBPROC_UNSET, "unset",
107*8f6d9daeSMarcel Telka RPCBPROC_GETADDR, "getaddr",
108*8f6d9daeSMarcel Telka RPCBPROC_DUMP, "dump",
109*8f6d9daeSMarcel Telka RPCBPROC_CALLIT, "callit",
110*8f6d9daeSMarcel Telka RPCBPROC_GETTIME, "gettime",
111*8f6d9daeSMarcel Telka RPCBPROC_UADDR2TADDR, "uaddr2taddr",
112*8f6d9daeSMarcel Telka RPCBPROC_TADDR2UADDR, "taddr2uaddr",
113*8f6d9daeSMarcel Telka RPCBPROC_GETVERSADDR, "getversaddr",
114*8f6d9daeSMarcel Telka RPCBPROC_INDIRECT, "indirect",
115*8f6d9daeSMarcel Telka RPCBPROC_GETADDRLIST, "getaddrlist",
116*8f6d9daeSMarcel Telka RPCBPROC_GETSTAT, "getstat",
117*8f6d9daeSMarcel Telka NULLPROC, "null",
118*8f6d9daeSMarcel Telka };
119*8f6d9daeSMarcel Telka
1207c478bd9Sstevel@tonic-gate /*
1217c478bd9Sstevel@tonic-gate * find_procname - map rpcb/pmap procedure number to name
1227c478bd9Sstevel@tonic-gate */
1237c478bd9Sstevel@tonic-gate static const char *
find_procname(rpcproc_t procnum,boolean_t pm)1247c478bd9Sstevel@tonic-gate find_procname(rpcproc_t procnum, boolean_t pm)
1257c478bd9Sstevel@tonic-gate {
1267c478bd9Sstevel@tonic-gate int nitems, i;
127*8f6d9daeSMarcel Telka const struct proc_map *procp;
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate if (pm) {
1307c478bd9Sstevel@tonic-gate procp = pmapmap;
1317c478bd9Sstevel@tonic-gate nitems = sizeof (pmapmap)/sizeof (struct proc_map);
1327c478bd9Sstevel@tonic-gate } else {
1337c478bd9Sstevel@tonic-gate procp = rpcbmap;
1347c478bd9Sstevel@tonic-gate nitems = sizeof (rpcbmap)/sizeof (struct proc_map);
1357c478bd9Sstevel@tonic-gate }
1367c478bd9Sstevel@tonic-gate
1377c478bd9Sstevel@tonic-gate for (i = 0; i < nitems; i++) {
1387c478bd9Sstevel@tonic-gate if (procp[i].code == procnum)
1397c478bd9Sstevel@tonic-gate return (procp[i].proc);
1407c478bd9Sstevel@tonic-gate }
141*8f6d9daeSMarcel Telka return (NULL);
1427c478bd9Sstevel@tonic-gate }
1437c478bd9Sstevel@tonic-gate
1447c478bd9Sstevel@tonic-gate /*
1457c478bd9Sstevel@tonic-gate * rpcb_log - log request for service
1467c478bd9Sstevel@tonic-gate */
1477c478bd9Sstevel@tonic-gate void
rpcb_log(boolean_t verdict,SVCXPRT * transp,rpcproc_t proc,rpcprog_t prog,boolean_t pm)1487c478bd9Sstevel@tonic-gate rpcb_log(boolean_t verdict, SVCXPRT *transp, rpcproc_t proc, rpcprog_t prog,
1497c478bd9Sstevel@tonic-gate boolean_t pm)
1507c478bd9Sstevel@tonic-gate {
1517c478bd9Sstevel@tonic-gate struct netconfig *conf;
1527c478bd9Sstevel@tonic-gate const char *client = "unknown";
1537c478bd9Sstevel@tonic-gate char *uaddr;
1547c478bd9Sstevel@tonic-gate char buf[BUFSIZ];
155*8f6d9daeSMarcel Telka char toabuf[INET6_ADDRSTRLEN];
156*8f6d9daeSMarcel Telka const char *procname;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate /*
1597c478bd9Sstevel@tonic-gate * Transform the transport address into something printable.
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) {
1627c478bd9Sstevel@tonic-gate syslog(LOG_WARNING,
1637c478bd9Sstevel@tonic-gate "unknown transport (rpcbind_get_conf failed)");
1647c478bd9Sstevel@tonic-gate } else if (strcmp(conf->nc_protofmly, "inet") == 0 ||
1657c478bd9Sstevel@tonic-gate strcmp(conf->nc_protofmly, "inet6") == 0) {
166*8f6d9daeSMarcel Telka client = sgen_toa(svc_getgencaller(transp), toabuf,
167*8f6d9daeSMarcel Telka sizeof (toabuf));
1687c478bd9Sstevel@tonic-gate } else if ((uaddr = taddr2uaddr(conf, &(transp->xp_rtaddr))) == NULL) {
1697c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "unknown address (taddr2uaddr failed)");
1707c478bd9Sstevel@tonic-gate } else {
1717c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s(%s)",
1727c478bd9Sstevel@tonic-gate conf->nc_protofmly, uaddr);
1737c478bd9Sstevel@tonic-gate free(uaddr);
1747c478bd9Sstevel@tonic-gate client = buf;
1757c478bd9Sstevel@tonic-gate }
176*8f6d9daeSMarcel Telka
177*8f6d9daeSMarcel Telka if ((procname = find_procname(proc, pm)) == NULL) {
178*8f6d9daeSMarcel Telka qsyslog(verdict ? allow_severity : deny_severity,
179*8f6d9daeSMarcel Telka "%sconnect from %s to %s-%lu(%lu)",
180*8f6d9daeSMarcel Telka verdict ? "" : "refused ", client, pm ? "pmap" : "rpcb",
181*8f6d9daeSMarcel Telka (ulong_t)proc, (ulong_t)prog);
182*8f6d9daeSMarcel Telka } else {
183*8f6d9daeSMarcel Telka qsyslog(verdict ? allow_severity : deny_severity,
184*8f6d9daeSMarcel Telka "%sconnect from %s to %s(%lu)", verdict ? "" : "refused ",
185*8f6d9daeSMarcel Telka client, procname, (ulong_t)prog);
186*8f6d9daeSMarcel Telka }
1877c478bd9Sstevel@tonic-gate }
1887c478bd9Sstevel@tonic-gate
1897c478bd9Sstevel@tonic-gate /*
1907c478bd9Sstevel@tonic-gate * rpcb_check; the rpcbind/portmap access check function.
1917c478bd9Sstevel@tonic-gate */
1927c478bd9Sstevel@tonic-gate boolean_t
rpcb_check(SVCXPRT * transp,rpcproc_t procnum,boolean_t ispmap)1937c478bd9Sstevel@tonic-gate rpcb_check(SVCXPRT *transp, rpcproc_t procnum, boolean_t ispmap)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate struct netconfig *conf;
1967c478bd9Sstevel@tonic-gate boolean_t res = B_TRUE;
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) {
1997c478bd9Sstevel@tonic-gate syslog(LOG_ERR,
2007c478bd9Sstevel@tonic-gate "rpcbind_get_conf failed: no client address checks");
2017c478bd9Sstevel@tonic-gate return (B_TRUE);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate /*
2057c478bd9Sstevel@tonic-gate * Require IPv4 for pmap calls; they're not defined for anything else.
2067c478bd9Sstevel@tonic-gate */
2077c478bd9Sstevel@tonic-gate if (ispmap && strcmp(conf->nc_protofmly, "inet") != 0) {
2087c478bd9Sstevel@tonic-gate res = B_FALSE;
2097c478bd9Sstevel@tonic-gate } else if (strcmp(conf->nc_protofmly, "inet") == 0 ||
2107c478bd9Sstevel@tonic-gate strcmp(conf->nc_protofmly, "inet6") == 0) {
211*8f6d9daeSMarcel Telka if (!localxprt(transp, ispmap)) {
212*8f6d9daeSMarcel Telka if (local_only) {
213*8f6d9daeSMarcel Telka res = B_FALSE;
214*8f6d9daeSMarcel Telka } else {
215*8f6d9daeSMarcel Telka char buf[INET6_ADDRSTRLEN];
216*8f6d9daeSMarcel Telka const char *addr_string =
217*8f6d9daeSMarcel Telka sgen_toa(svc_getgencaller(transp), buf,
218*8f6d9daeSMarcel Telka sizeof (buf));
219*8f6d9daeSMarcel Telka
220*8f6d9daeSMarcel Telka (void) mutex_lock(&hosts_ctl_lock);
221*8f6d9daeSMarcel Telka if (hosts_ctl("rpcbind", addr_string,
222*8f6d9daeSMarcel Telka addr_string, "") == 0)
223*8f6d9daeSMarcel Telka res = B_FALSE;
224*8f6d9daeSMarcel Telka (void) mutex_unlock(&hosts_ctl_lock);
225*8f6d9daeSMarcel Telka }
2267c478bd9Sstevel@tonic-gate }
2277c478bd9Sstevel@tonic-gate }
228*8f6d9daeSMarcel Telka
2297c478bd9Sstevel@tonic-gate if (!res)
2307c478bd9Sstevel@tonic-gate svcerr_auth(transp, AUTH_FAILED);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate if (verboselog || !res)
2337c478bd9Sstevel@tonic-gate rpcb_log(res, transp, procnum, 0, ispmap);
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate return (res);
2367c478bd9Sstevel@tonic-gate }
237