1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Auxiliary routines to shield off random internet hosts and to report 24*7c478bd9Sstevel@tonic-gate * service requests (verbose mode only) or violations (always). 25*7c478bd9Sstevel@tonic-gate * 26*7c478bd9Sstevel@tonic-gate * This code was extensively modifed from a version authored by: 27*7c478bd9Sstevel@tonic-gate * 28*7c478bd9Sstevel@tonic-gate * Wietse Venema, Eindhoven University of Technology, The Netherlands 29*7c478bd9Sstevel@tonic-gate * and distributed as "rpcbind 2.1". 30*7c478bd9Sstevel@tonic-gate * 31*7c478bd9Sstevel@tonic-gate * Sun was granted permission to use, modify, including make 32*7c478bd9Sstevel@tonic-gate * derivatives of, copy, reproduce and distribute this code.c in both 33*7c478bd9Sstevel@tonic-gate * binary and source forms, directly and indirectly. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * Modified for bundling with Solaris and IPv6. 36*7c478bd9Sstevel@tonic-gate * 37*7c478bd9Sstevel@tonic-gate * Solaris specific modifcations made are: 38*7c478bd9Sstevel@tonic-gate * 39*7c478bd9Sstevel@tonic-gate * Double fork() logging replaced with qsyslog(); 40*7c478bd9Sstevel@tonic-gate * Connection refusals are flagged with svcerr_auth(); this 41*7c478bd9Sstevel@tonic-gate * aids in quicker diagnosability of misconfigurations and quicker 42*7c478bd9Sstevel@tonic-gate * failures for /net automounts; 43*7c478bd9Sstevel@tonic-gate * Single function for pmap* and rpcb*; 44*7c478bd9Sstevel@tonic-gate * Local transport checks made using localxprt(). 45*7c478bd9Sstevel@tonic-gate * 46*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 47*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 48*7c478bd9Sstevel@tonic-gate */ 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate #include <stdio.h> 53*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 54*7c478bd9Sstevel@tonic-gate #include <unistd.h> 55*7c478bd9Sstevel@tonic-gate #include <string.h> 56*7c478bd9Sstevel@tonic-gate #include <syslog.h> 57*7c478bd9Sstevel@tonic-gate #include <errno.h> 58*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 59*7c478bd9Sstevel@tonic-gate #include <netdb.h> 60*7c478bd9Sstevel@tonic-gate #include <netdir.h> 61*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 62*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 63*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 64*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h> 65*7c478bd9Sstevel@tonic-gate #include <rpc/rpcb_prot.h> 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate #include "rpcbind.h" 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate /* 70*7c478bd9Sstevel@tonic-gate * These are globally visible so that they can be modified by the wrapper's 71*7c478bd9Sstevel@tonic-gate * language extension routines. 72*7c478bd9Sstevel@tonic-gate */ 73*7c478bd9Sstevel@tonic-gate int allow_severity = LOG_INFO; 74*7c478bd9Sstevel@tonic-gate int deny_severity = LOG_WARNING; 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate extern int hosts_ctl(); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * "inet_ntoa/inet_pton" for struct sockaddr_gen 80*7c478bd9Sstevel@tonic-gate */ 81*7c478bd9Sstevel@tonic-gate static const char * 82*7c478bd9Sstevel@tonic-gate sgen_toa(struct sockaddr_gen *addr) 83*7c478bd9Sstevel@tonic-gate { 84*7c478bd9Sstevel@tonic-gate static char buf[INET6_ADDRSTRLEN]; 85*7c478bd9Sstevel@tonic-gate return (inet_ntop(SGFAM(addr), SGADDRP(addr), buf, sizeof (buf))); 86*7c478bd9Sstevel@tonic-gate } 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate /* 89*7c478bd9Sstevel@tonic-gate * find_procname - map rpcb/pmap procedure number to name 90*7c478bd9Sstevel@tonic-gate */ 91*7c478bd9Sstevel@tonic-gate static const char * 92*7c478bd9Sstevel@tonic-gate find_procname(rpcproc_t procnum, boolean_t pm) 93*7c478bd9Sstevel@tonic-gate { 94*7c478bd9Sstevel@tonic-gate static char procbuf[6 + 3 * sizeof (ulong_t)]; 95*7c478bd9Sstevel@tonic-gate struct proc_map { 96*7c478bd9Sstevel@tonic-gate rpcproc_t code; 97*7c478bd9Sstevel@tonic-gate const char *proc; 98*7c478bd9Sstevel@tonic-gate }; 99*7c478bd9Sstevel@tonic-gate static struct proc_map pmapmap[] = { 100*7c478bd9Sstevel@tonic-gate PMAPPROC_CALLIT, "callit", 101*7c478bd9Sstevel@tonic-gate PMAPPROC_DUMP, "dump", 102*7c478bd9Sstevel@tonic-gate PMAPPROC_GETPORT, "getport", 103*7c478bd9Sstevel@tonic-gate PMAPPROC_SET, "set", 104*7c478bd9Sstevel@tonic-gate PMAPPROC_UNSET, "unset", 105*7c478bd9Sstevel@tonic-gate NULLPROC, "null", 106*7c478bd9Sstevel@tonic-gate }; 107*7c478bd9Sstevel@tonic-gate static struct proc_map rpcbmap[] = { 108*7c478bd9Sstevel@tonic-gate RPCBPROC_SET, "set", 109*7c478bd9Sstevel@tonic-gate RPCBPROC_UNSET, "unset", 110*7c478bd9Sstevel@tonic-gate RPCBPROC_GETADDR, "getaddr", 111*7c478bd9Sstevel@tonic-gate RPCBPROC_DUMP, "dump", 112*7c478bd9Sstevel@tonic-gate RPCBPROC_CALLIT, "callit", 113*7c478bd9Sstevel@tonic-gate RPCBPROC_GETTIME, "gettime", 114*7c478bd9Sstevel@tonic-gate RPCBPROC_UADDR2TADDR, "uaddr2taddr", 115*7c478bd9Sstevel@tonic-gate RPCBPROC_TADDR2UADDR, "taddr2uaddr", 116*7c478bd9Sstevel@tonic-gate RPCBPROC_GETVERSADDR, "getversaddr", 117*7c478bd9Sstevel@tonic-gate RPCBPROC_INDIRECT, "indirect", 118*7c478bd9Sstevel@tonic-gate RPCBPROC_GETADDRLIST, "getaddrlist", 119*7c478bd9Sstevel@tonic-gate RPCBPROC_GETSTAT, "getstat", 120*7c478bd9Sstevel@tonic-gate NULLPROC, "null", 121*7c478bd9Sstevel@tonic-gate }; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate int nitems, i; 124*7c478bd9Sstevel@tonic-gate struct proc_map *procp; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate if (pm) { 127*7c478bd9Sstevel@tonic-gate procp = pmapmap; 128*7c478bd9Sstevel@tonic-gate nitems = sizeof (pmapmap)/sizeof (struct proc_map); 129*7c478bd9Sstevel@tonic-gate } else { 130*7c478bd9Sstevel@tonic-gate procp = rpcbmap; 131*7c478bd9Sstevel@tonic-gate nitems = sizeof (rpcbmap)/sizeof (struct proc_map); 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate for (i = 0; i < nitems; i++) { 135*7c478bd9Sstevel@tonic-gate if (procp[i].code == procnum) 136*7c478bd9Sstevel@tonic-gate return (procp[i].proc); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate (void) snprintf(procbuf, sizeof (procbuf), "%s-%lu", 139*7c478bd9Sstevel@tonic-gate pm ? "pmap" : "rpcb", (ulong_t)procnum); 140*7c478bd9Sstevel@tonic-gate return (procbuf); 141*7c478bd9Sstevel@tonic-gate } 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate /* 144*7c478bd9Sstevel@tonic-gate * find_progname - map rpc program number to name. 145*7c478bd9Sstevel@tonic-gate */ 146*7c478bd9Sstevel@tonic-gate static const char * 147*7c478bd9Sstevel@tonic-gate find_progname(rpcprog_t prognum) 148*7c478bd9Sstevel@tonic-gate { 149*7c478bd9Sstevel@tonic-gate static char progbuf[1 + 3 * sizeof (ulong_t)]; 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if (prognum == 0) 152*7c478bd9Sstevel@tonic-gate return (""); 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate /* 155*7c478bd9Sstevel@tonic-gate * The original code contained a call to "getrpcbynumber()"; 156*7c478bd9Sstevel@tonic-gate * this call was removed because it may cause a call to a 157*7c478bd9Sstevel@tonic-gate * nameservice. 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate (void) snprintf(progbuf, sizeof (progbuf), "%lu", (ulong_t)prognum); 161*7c478bd9Sstevel@tonic-gate return (progbuf); 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate /* 165*7c478bd9Sstevel@tonic-gate * rpcb_log - log request for service 166*7c478bd9Sstevel@tonic-gate */ 167*7c478bd9Sstevel@tonic-gate void 168*7c478bd9Sstevel@tonic-gate rpcb_log(boolean_t verdict, SVCXPRT *transp, rpcproc_t proc, rpcprog_t prog, 169*7c478bd9Sstevel@tonic-gate boolean_t pm) 170*7c478bd9Sstevel@tonic-gate { 171*7c478bd9Sstevel@tonic-gate struct netconfig *conf; 172*7c478bd9Sstevel@tonic-gate const char *client = "unknown"; 173*7c478bd9Sstevel@tonic-gate char *uaddr; 174*7c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate /* 177*7c478bd9Sstevel@tonic-gate * Transform the transport address into something printable. 178*7c478bd9Sstevel@tonic-gate */ 179*7c478bd9Sstevel@tonic-gate if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) { 180*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 181*7c478bd9Sstevel@tonic-gate "unknown transport (rpcbind_get_conf failed)"); 182*7c478bd9Sstevel@tonic-gate } else if (strcmp(conf->nc_protofmly, "inet") == 0 || 183*7c478bd9Sstevel@tonic-gate strcmp(conf->nc_protofmly, "inet6") == 0) { 184*7c478bd9Sstevel@tonic-gate client = sgen_toa(svc_getgencaller(transp)); 185*7c478bd9Sstevel@tonic-gate } else if ((uaddr = taddr2uaddr(conf, &(transp->xp_rtaddr))) == NULL) { 186*7c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, "unknown address (taddr2uaddr failed)"); 187*7c478bd9Sstevel@tonic-gate } else { 188*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), "%s(%s)", 189*7c478bd9Sstevel@tonic-gate conf->nc_protofmly, uaddr); 190*7c478bd9Sstevel@tonic-gate free(uaddr); 191*7c478bd9Sstevel@tonic-gate client = buf; 192*7c478bd9Sstevel@tonic-gate } 193*7c478bd9Sstevel@tonic-gate qsyslog(verdict ? allow_severity : deny_severity, 194*7c478bd9Sstevel@tonic-gate "%sconnect from %s to %s(%s)", verdict ? "" : "refused ", 195*7c478bd9Sstevel@tonic-gate client, find_procname(proc, pm), find_progname(prog)); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * rpcb_check; the rpcbind/portmap access check function. 200*7c478bd9Sstevel@tonic-gate */ 201*7c478bd9Sstevel@tonic-gate boolean_t 202*7c478bd9Sstevel@tonic-gate rpcb_check(SVCXPRT *transp, rpcproc_t procnum, boolean_t ispmap) 203*7c478bd9Sstevel@tonic-gate { 204*7c478bd9Sstevel@tonic-gate struct netconfig *conf; 205*7c478bd9Sstevel@tonic-gate boolean_t res = B_TRUE; 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate if ((conf = rpcbind_get_conf(transp->xp_netid)) == 0) { 208*7c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 209*7c478bd9Sstevel@tonic-gate "rpcbind_get_conf failed: no client address checks"); 210*7c478bd9Sstevel@tonic-gate return (B_TRUE); 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate /* 214*7c478bd9Sstevel@tonic-gate * Require IPv4 for pmap calls; they're not defined for anything else. 215*7c478bd9Sstevel@tonic-gate */ 216*7c478bd9Sstevel@tonic-gate if (ispmap && strcmp(conf->nc_protofmly, "inet") != 0) { 217*7c478bd9Sstevel@tonic-gate res = B_FALSE; 218*7c478bd9Sstevel@tonic-gate } else if (strcmp(conf->nc_protofmly, "inet") == 0 || 219*7c478bd9Sstevel@tonic-gate strcmp(conf->nc_protofmly, "inet6") == 0) { 220*7c478bd9Sstevel@tonic-gate const char *addr_string = sgen_toa(svc_getgencaller(transp)); 221*7c478bd9Sstevel@tonic-gate 222*7c478bd9Sstevel@tonic-gate if (!localxprt(transp, ispmap) && 223*7c478bd9Sstevel@tonic-gate hosts_ctl("rpcbind", addr_string, addr_string, "") == 0) { 224*7c478bd9Sstevel@tonic-gate res = B_FALSE; 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate out: 228*7c478bd9Sstevel@tonic-gate if (!res) 229*7c478bd9Sstevel@tonic-gate svcerr_auth(transp, AUTH_FAILED); 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate if (verboselog || !res) 232*7c478bd9Sstevel@tonic-gate rpcb_log(res, transp, procnum, 0, ispmap); 233*7c478bd9Sstevel@tonic-gate 234*7c478bd9Sstevel@tonic-gate return (res); 235*7c478bd9Sstevel@tonic-gate } 236