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 * 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 907c478bd9Sstevel@tonic-gate struct proc_map { 917c478bd9Sstevel@tonic-gate rpcproc_t code; 927c478bd9Sstevel@tonic-gate const char *proc; 937c478bd9Sstevel@tonic-gate }; 94*8f6d9daeSMarcel Telka 95*8f6d9daeSMarcel Telka static const struct proc_map pmapmap[] = { 967c478bd9Sstevel@tonic-gate PMAPPROC_CALLIT, "callit", 977c478bd9Sstevel@tonic-gate PMAPPROC_DUMP, "dump", 987c478bd9Sstevel@tonic-gate PMAPPROC_GETPORT, "getport", 997c478bd9Sstevel@tonic-gate PMAPPROC_SET, "set", 1007c478bd9Sstevel@tonic-gate PMAPPROC_UNSET, "unset", 1017c478bd9Sstevel@tonic-gate NULLPROC, "null", 1027c478bd9Sstevel@tonic-gate }; 103*8f6d9daeSMarcel Telka 104*8f6d9daeSMarcel Telka static const struct proc_map rpcbmap[] = { 1057c478bd9Sstevel@tonic-gate RPCBPROC_SET, "set", 1067c478bd9Sstevel@tonic-gate RPCBPROC_UNSET, "unset", 1077c478bd9Sstevel@tonic-gate RPCBPROC_GETADDR, "getaddr", 1087c478bd9Sstevel@tonic-gate RPCBPROC_DUMP, "dump", 1097c478bd9Sstevel@tonic-gate RPCBPROC_CALLIT, "callit", 1107c478bd9Sstevel@tonic-gate RPCBPROC_GETTIME, "gettime", 1117c478bd9Sstevel@tonic-gate RPCBPROC_UADDR2TADDR, "uaddr2taddr", 1127c478bd9Sstevel@tonic-gate RPCBPROC_TADDR2UADDR, "taddr2uaddr", 1137c478bd9Sstevel@tonic-gate RPCBPROC_GETVERSADDR, "getversaddr", 1147c478bd9Sstevel@tonic-gate RPCBPROC_INDIRECT, "indirect", 1157c478bd9Sstevel@tonic-gate RPCBPROC_GETADDRLIST, "getaddrlist", 1167c478bd9Sstevel@tonic-gate RPCBPROC_GETSTAT, "getstat", 1177c478bd9Sstevel@tonic-gate NULLPROC, "null", 1187c478bd9Sstevel@tonic-gate }; 1197c478bd9Sstevel@tonic-gate 120*8f6d9daeSMarcel Telka /* 121*8f6d9daeSMarcel Telka * find_procname - map rpcb/pmap procedure number to name 122*8f6d9daeSMarcel Telka */ 123*8f6d9daeSMarcel Telka static const char * 124*8f6d9daeSMarcel Telka find_procname(rpcproc_t procnum, boolean_t pm) 125*8f6d9daeSMarcel Telka { 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 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) { 1787c478bd9Sstevel@tonic-gate 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 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) { 2137c478bd9Sstevel@tonic-gate 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); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate } 227*8f6d9daeSMarcel Telka } 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