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