xref: /illumos-gate/usr/src/cmd/rpcbind/rpcb_svc.c (revision 342440ec94087b8c751c580ab9ed6c693d31d418)
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  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29  * University Copyright- Copyright (c) 1982, 1986, 1988
30  * The Regents of the University of California
31  * All Rights Reserved
32  *
33  * University Acknowledgment- Portions of this document are derived from
34  * software developed by the University of California, Berkeley, and its
35  * contributors.
36  */
37 
38 #pragma ident	"%Z%%M%	%I%	%E% SMI"
39 
40 /*
41  * rpcb_svc.c
42  * The server procedure for the version 3 rpcbind (TLI).
43  *
44  * It maintains a separate list of all the registered services with the
45  * version 3 of rpcbind.
46  */
47 #include <stdio.h>
48 #include <strings.h>
49 #include <sys/types.h>
50 #include <rpc/rpc.h>
51 #include <rpc/rpcb_prot.h>
52 #include <netconfig.h>
53 #include <syslog.h>
54 #include <netdir.h>
55 #include <stdlib.h>
56 #include "rpcbind.h"
57 
58 /*
59  * Called by svc_getreqset. There is a separate server handle for
60  * every transport that it waits on.
61  */
62 void
63 rpcb_service_3(rqstp, transp)
64 	register struct svc_req *rqstp;
65 	register SVCXPRT *transp;
66 {
67 	union {
68 		RPCB rpcbproc_set_3_arg;
69 		RPCB rpcbproc_unset_3_arg;
70 		RPCB rpcbproc_getaddr_3_arg;
71 		struct rpcb_rmtcallargs rpcbproc_callit_3_arg;
72 		char *rpcbproc_uaddr2taddr_3_arg;
73 		struct netbuf rpcbproc_taddr2uaddr_3_arg;
74 	} argument;
75 	char *result;
76 	bool_t (*xdr_argument)(), (*xdr_result)();
77 	char *(*local)();
78 
79 	rpcbs_procinfo((ulong_t)RPCBVERS_3_STAT, rqstp->rq_proc);
80 
81 	RPCB_CHECK(transp, rqstp->rq_proc);
82 
83 	switch (rqstp->rq_proc) {
84 	case NULLPROC:
85 		/*
86 		 * Null proc call
87 		 */
88 #ifdef RPCBIND_DEBUG
89 		fprintf(stderr, "RPCBPROC_NULL\n");
90 #endif
91 		(void) svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
92 		return;
93 
94 	case RPCBPROC_SET:
95 		/*
96 		 * Check to see whether the message came from
97 		 * loopback transports (for security reasons)
98 		 */
99 		if (strcasecmp(transp->xp_netid, loopback_dg) &&
100 			strcasecmp(transp->xp_netid, loopback_vc) &&
101 			strcasecmp(transp->xp_netid, loopback_vc_ord)) {
102 			char *uaddr;
103 
104 			uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
105 					svc_getrpccaller(transp));
106 			syslog(LOG_ERR, "non-local attempt to set from %s",
107 				uaddr);
108 			free(uaddr);
109 			svcerr_weakauth(transp);
110 			return;
111 		}
112 		xdr_argument = xdr_rpcb;
113 		xdr_result = xdr_bool;
114 		local = (char *(*)()) rpcbproc_set_com;
115 		break;
116 
117 	case RPCBPROC_UNSET:
118 		/*
119 		 * Check to see whether the message came from
120 		 * loopback transports (for security reasons)
121 		 */
122 		if (strcasecmp(transp->xp_netid, loopback_dg) &&
123 			strcasecmp(transp->xp_netid, loopback_vc) &&
124 			strcasecmp(transp->xp_netid, loopback_vc_ord)) {
125 			char *uaddr;
126 
127 			uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
128 					svc_getrpccaller(transp));
129 			syslog(LOG_ERR, "non-local attempt to unset from %s",
130 				uaddr);
131 			free(uaddr);
132 			svcerr_weakauth(transp);
133 			return;
134 		}
135 		xdr_argument = xdr_rpcb;
136 		xdr_result = xdr_bool;
137 		local = (char *(*)()) rpcbproc_unset_com;
138 		break;
139 
140 	case RPCBPROC_GETADDR:
141 		xdr_argument = xdr_rpcb;
142 		xdr_result = xdr_wrapstring;
143 		local = (char *(*)()) rpcbproc_getaddr_3;
144 		break;
145 
146 	case RPCBPROC_DUMP:
147 #ifdef RPCBIND_DEBUG
148 		fprintf(stderr, "RPCBPROC_DUMP\n");
149 #endif
150 		xdr_argument = xdr_void;
151 		xdr_result = xdr_rpcblist_ptr;
152 		local = (char *(*)()) rpcbproc_dump_3;
153 		break;
154 
155 	case RPCBPROC_CALLIT:
156 		rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
157 		return;
158 
159 	case RPCBPROC_GETTIME:
160 #ifdef RPCBIND_DEBUG
161 		fprintf(stderr, "RPCBPROC_GETTIME\n");
162 #endif
163 		xdr_argument = xdr_void;
164 		xdr_result = xdr_u_long;
165 		local = (char *(*)()) rpcbproc_gettime_com;
166 		break;
167 
168 	case RPCBPROC_UADDR2TADDR:
169 #ifdef RPCBIND_DEBUG
170 		fprintf(stderr, "RPCBPROC_UADDR2TADDR\n");
171 #endif
172 		xdr_argument = xdr_wrapstring;
173 		xdr_result = xdr_netbuf;
174 		local = (char *(*)()) rpcbproc_uaddr2taddr_com;
175 		break;
176 
177 	case RPCBPROC_TADDR2UADDR:
178 #ifdef RPCBIND_DEBUG
179 		fprintf(stderr, "RPCBPROC_TADDR2UADDR\n");
180 #endif
181 		xdr_argument = xdr_netbuf;
182 		xdr_result = xdr_wrapstring;
183 		local = (char *(*)()) rpcbproc_taddr2uaddr_com;
184 		break;
185 
186 	default:
187 		svcerr_noproc(transp);
188 		return;
189 	}
190 	(void) memset((char *)&argument, 0, sizeof (argument));
191 	if (!svc_getargs(transp, (xdrproc_t)xdr_argument,
192 				(char *)&argument)) {
193 		svcerr_decode(transp);
194 		if (debugging)
195 			(void) fprintf(stderr, "rpcbind: could not decode\n");
196 		return;
197 	}
198 	result = (*local)(&argument, rqstp, transp, RPCBVERS);
199 	if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result,
200 						result)) {
201 		svcerr_systemerr(transp);
202 		if (debugging) {
203 			(void) fprintf(stderr, "rpcbind: svc_sendreply\n");
204 			if (doabort) {
205 				rpcbind_abort();
206 			}
207 		}
208 	}
209 	if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)
210 				&argument)) {
211 		if (debugging) {
212 			(void) fprintf(stderr, "unable to free arguments\n");
213 			if (doabort) {
214 				rpcbind_abort();
215 			}
216 		}
217 	}
218 }
219 
220 /*
221  * Lookup the mapping for a program, version and return its
222  * address. Assuming that the caller wants the address of the
223  * server running on the transport on which the request came.
224  *
225  * We also try to resolve the universal address in terms of
226  * address of the caller.
227  */
228 /* ARGSUSED */
229 char **
230 rpcbproc_getaddr_3(regp, rqstp, transp)
231 	RPCB *regp;
232 	struct svc_req *rqstp;	/* Not used here */
233 	SVCXPRT *transp;
234 {
235 #ifdef RPCBIND_DEBUG
236 	char *uaddr;
237 
238 	uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
239 			    svc_getrpccaller(transp));
240 	fprintf(stderr, "RPCB_GETADDR request for (%lu, %lu, %s) from %s : ",
241 		regp->r_prog, regp->r_vers, transp->xp_netid, uaddr);
242 	free(uaddr);
243 #endif
244 	return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS,
245 					(ulong_t)RPCB_ALLVERS));
246 }
247 
248 /* ARGSUSED */
249 rpcblist_ptr *
250 rpcbproc_dump_3()
251 {
252 	return ((rpcblist_ptr *)&list_rbl);
253 }
254