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