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 *
sgen_toa(struct sockaddr_gen * addr)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 *
find_procname(rpcproc_t procnum,boolean_t pm)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 *
find_progname(rpcprog_t prognum)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
rpcb_log(boolean_t verdict,SVCXPRT * transp,rpcproc_t proc,rpcprog_t prog,boolean_t pm)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
rpcb_check(SVCXPRT * transp,rpcproc_t procnum,boolean_t ispmap)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