xref: /titanic_44/usr/src/cmd/rpcbind/rpcb_check.c (revision ea8dc4b6d2251b437950c0056bc626b311c73c27)
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