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