xref: /freebsd/crypto/krb5/src/lib/rpc/svc.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* @(#)svc.c	2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright (c) 2010, Oracle America, Inc.
4*7f2fe78bSCy Schubert  *
5*7f2fe78bSCy Schubert  * All rights reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Redistribution and use in source and binary forms, with or without
8*7f2fe78bSCy Schubert  * modification, are permitted provided that the following conditions are met:
9*7f2fe78bSCy Schubert  *
10*7f2fe78bSCy Schubert  *     * Redistributions of source code must retain the above copyright
11*7f2fe78bSCy Schubert  *       notice, this list of conditions and the following disclaimer.
12*7f2fe78bSCy Schubert  *
13*7f2fe78bSCy Schubert  *     * Redistributions in binary form must reproduce the above copyright
14*7f2fe78bSCy Schubert  *       notice, this list of conditions and the following disclaimer in
15*7f2fe78bSCy Schubert  *       the documentation and/or other materials provided with the
16*7f2fe78bSCy Schubert  *       distribution.
17*7f2fe78bSCy Schubert  *
18*7f2fe78bSCy Schubert  *     * Neither the name of the "Oracle America, Inc." nor the names of
19*7f2fe78bSCy Schubert  *       its contributors may be used to endorse or promote products
20*7f2fe78bSCy Schubert  *       derived from this software without specific prior written permission.
21*7f2fe78bSCy Schubert  *
22*7f2fe78bSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23*7f2fe78bSCy Schubert  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24*7f2fe78bSCy Schubert  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25*7f2fe78bSCy Schubert  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26*7f2fe78bSCy Schubert  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27*7f2fe78bSCy Schubert  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28*7f2fe78bSCy Schubert  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29*7f2fe78bSCy Schubert  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30*7f2fe78bSCy Schubert  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31*7f2fe78bSCy Schubert  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32*7f2fe78bSCy Schubert  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33*7f2fe78bSCy Schubert  */
34*7f2fe78bSCy Schubert #if !defined(lint) && defined(SCCSIDS)
35*7f2fe78bSCy Schubert static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
36*7f2fe78bSCy Schubert #endif
37*7f2fe78bSCy Schubert 
38*7f2fe78bSCy Schubert /*
39*7f2fe78bSCy Schubert  * svc.c, Server-side remote procedure call interface.
40*7f2fe78bSCy Schubert  *
41*7f2fe78bSCy Schubert  * There are two sets of procedures here.  The xprt routines are
42*7f2fe78bSCy Schubert  * for handling transport handles.  The svc routines handle the
43*7f2fe78bSCy Schubert  * list of service routines.
44*7f2fe78bSCy Schubert  */
45*7f2fe78bSCy Schubert 
46*7f2fe78bSCy Schubert #include "autoconf.h"
47*7f2fe78bSCy Schubert #if HAVE_SYS_PARAM_H
48*7f2fe78bSCy Schubert #include <sys/param.h>
49*7f2fe78bSCy Schubert #endif
50*7f2fe78bSCy Schubert #include <gssrpc/rpc.h>
51*7f2fe78bSCy Schubert #include <gssrpc/pmap_clnt.h>
52*7f2fe78bSCy Schubert #include <stdio.h>
53*7f2fe78bSCy Schubert #include <string.h>
54*7f2fe78bSCy Schubert #include <errno.h>
55*7f2fe78bSCy Schubert 
56*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
57*7f2fe78bSCy Schubert static SVCXPRT **xports;
58*7f2fe78bSCy Schubert extern int gssrpc_svc_fdset_init;
59*7f2fe78bSCy Schubert #else
60*7f2fe78bSCy Schubert 
61*7f2fe78bSCy Schubert #ifdef NBBY
62*7f2fe78bSCy Schubert #define NOFILE (sizeof(int) * NBBY)
63*7f2fe78bSCy Schubert #else
64*7f2fe78bSCy Schubert #define NOFILE (sizeof(int) * 8)
65*7f2fe78bSCy Schubert #endif
66*7f2fe78bSCy Schubert 
67*7f2fe78bSCy Schubert static SVCXPRT *xports[NOFILE];
68*7f2fe78bSCy Schubert #endif /* def FD_SETSIZE */
69*7f2fe78bSCy Schubert 
70*7f2fe78bSCy Schubert #define NULL_SVC ((struct svc_callout *)0)
71*7f2fe78bSCy Schubert #define	RQCRED_SIZE	1024		/* this size is excessive */
72*7f2fe78bSCy Schubert 
73*7f2fe78bSCy Schubert /*
74*7f2fe78bSCy Schubert  * The services list
75*7f2fe78bSCy Schubert  * Each entry represents a set of procedures (an rpc program).
76*7f2fe78bSCy Schubert  * The dispatch routine takes request structs and runs the
77*7f2fe78bSCy Schubert  * appropriate procedure.
78*7f2fe78bSCy Schubert  */
79*7f2fe78bSCy Schubert static struct svc_callout {
80*7f2fe78bSCy Schubert 	struct svc_callout *sc_next;
81*7f2fe78bSCy Schubert 	rpcprog_t		    sc_prog;
82*7f2fe78bSCy Schubert 	rpcprog_t		    sc_vers;
83*7f2fe78bSCy Schubert 	void		    (*sc_dispatch)();
84*7f2fe78bSCy Schubert } *svc_head;
85*7f2fe78bSCy Schubert 
86*7f2fe78bSCy Schubert static struct svc_callout *svc_find(rpcprog_t, rpcvers_t,
87*7f2fe78bSCy Schubert 				    struct svc_callout **);
88*7f2fe78bSCy Schubert 
89*7f2fe78bSCy Schubert static void svc_do_xprt(SVCXPRT *xprt);
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert /* ***************  SVCXPRT related stuff **************** */
92*7f2fe78bSCy Schubert 
93*7f2fe78bSCy Schubert /*
94*7f2fe78bSCy Schubert  * Activate a transport handle.
95*7f2fe78bSCy Schubert  */
96*7f2fe78bSCy Schubert void
xprt_register(SVCXPRT * xprt)97*7f2fe78bSCy Schubert xprt_register(SVCXPRT *xprt)
98*7f2fe78bSCy Schubert {
99*7f2fe78bSCy Schubert 	int sock = xprt->xp_sock;
100*7f2fe78bSCy Schubert 
101*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
102*7f2fe78bSCy Schubert 	if (gssrpc_svc_fdset_init == 0) {
103*7f2fe78bSCy Schubert 		FD_ZERO(&svc_fdset);
104*7f2fe78bSCy Schubert 		gssrpc_svc_fdset_init++;
105*7f2fe78bSCy Schubert 	}
106*7f2fe78bSCy Schubert 	if (xports == NULL) {
107*7f2fe78bSCy Schubert 		xports = (SVCXPRT **)
108*7f2fe78bSCy Schubert 			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
109*7f2fe78bSCy Schubert 		memset(xports, 0, FD_SETSIZE * sizeof(SVCXPRT *));
110*7f2fe78bSCy Schubert 	}
111*7f2fe78bSCy Schubert 	if (sock < FD_SETSIZE) {
112*7f2fe78bSCy Schubert 		xports[sock] = xprt;
113*7f2fe78bSCy Schubert 		FD_SET(sock, &svc_fdset);
114*7f2fe78bSCy Schubert 		if (sock > svc_maxfd)
115*7f2fe78bSCy Schubert 			svc_maxfd = sock;
116*7f2fe78bSCy Schubert 	}
117*7f2fe78bSCy Schubert #else
118*7f2fe78bSCy Schubert 	if (sock < NOFILE) {
119*7f2fe78bSCy Schubert 		xports[sock] = xprt;
120*7f2fe78bSCy Schubert 		svc_fds |= (1 << sock);
121*7f2fe78bSCy Schubert 		if (sock > svc_maxfd)
122*7f2fe78bSCy Schubert 			svc_maxfd = sock;
123*7f2fe78bSCy Schubert 	}
124*7f2fe78bSCy Schubert #endif /* def FD_SETSIZE */
125*7f2fe78bSCy Schubert }
126*7f2fe78bSCy Schubert 
127*7f2fe78bSCy Schubert /*
128*7f2fe78bSCy Schubert  * De-activate a transport handle.
129*7f2fe78bSCy Schubert  */
130*7f2fe78bSCy Schubert void
xprt_unregister(SVCXPRT * xprt)131*7f2fe78bSCy Schubert xprt_unregister(SVCXPRT *xprt)
132*7f2fe78bSCy Schubert {
133*7f2fe78bSCy Schubert 	int sock = xprt->xp_sock;
134*7f2fe78bSCy Schubert 
135*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
136*7f2fe78bSCy Schubert 	if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) {
137*7f2fe78bSCy Schubert 		xports[sock] = (SVCXPRT *)0;
138*7f2fe78bSCy Schubert 		FD_CLR(sock, &svc_fdset);
139*7f2fe78bSCy Schubert 	}
140*7f2fe78bSCy Schubert #else
141*7f2fe78bSCy Schubert 	if ((sock < NOFILE) && (xports[sock] == xprt)) {
142*7f2fe78bSCy Schubert 		xports[sock] = (SVCXPRT *)0;
143*7f2fe78bSCy Schubert 		svc_fds &= ~(1 << sock);
144*7f2fe78bSCy Schubert 	}
145*7f2fe78bSCy Schubert #endif /* def FD_SETSIZE */
146*7f2fe78bSCy Schubert 	if (svc_maxfd <= sock) {
147*7f2fe78bSCy Schubert 		while ((svc_maxfd > 0) && xports[svc_maxfd] == 0)
148*7f2fe78bSCy Schubert 			svc_maxfd--;
149*7f2fe78bSCy Schubert 	}
150*7f2fe78bSCy Schubert }
151*7f2fe78bSCy Schubert 
152*7f2fe78bSCy Schubert 
153*7f2fe78bSCy Schubert /* ********************** CALLOUT list related stuff ************* */
154*7f2fe78bSCy Schubert 
155*7f2fe78bSCy Schubert /*
156*7f2fe78bSCy Schubert  * Add a service program to the callout list.
157*7f2fe78bSCy Schubert  * The dispatch routine will be called when a rpc request for this
158*7f2fe78bSCy Schubert  * program number comes in.
159*7f2fe78bSCy Schubert  */
160*7f2fe78bSCy Schubert bool_t
svc_register(SVCXPRT * xprt,rpcprog_t prog,rpcvers_t vers,void (* dispatch)(),int protocol)161*7f2fe78bSCy Schubert svc_register(
162*7f2fe78bSCy Schubert 	SVCXPRT *xprt,
163*7f2fe78bSCy Schubert 	rpcprog_t prog,
164*7f2fe78bSCy Schubert 	rpcvers_t vers,
165*7f2fe78bSCy Schubert 	void (*dispatch)(),
166*7f2fe78bSCy Schubert 	int protocol)
167*7f2fe78bSCy Schubert {
168*7f2fe78bSCy Schubert 	struct svc_callout *prev;
169*7f2fe78bSCy Schubert 	struct svc_callout *s;
170*7f2fe78bSCy Schubert 
171*7f2fe78bSCy Schubert 	if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
172*7f2fe78bSCy Schubert 		if (s->sc_dispatch == dispatch)
173*7f2fe78bSCy Schubert 			goto pmap_it;  /* he is registering another xptr */
174*7f2fe78bSCy Schubert 		return (FALSE);
175*7f2fe78bSCy Schubert 	}
176*7f2fe78bSCy Schubert 	s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
177*7f2fe78bSCy Schubert 	if (s == (struct svc_callout *)0) {
178*7f2fe78bSCy Schubert 		return (FALSE);
179*7f2fe78bSCy Schubert 	}
180*7f2fe78bSCy Schubert 	s->sc_prog = prog;
181*7f2fe78bSCy Schubert 	s->sc_vers = vers;
182*7f2fe78bSCy Schubert 	s->sc_dispatch = dispatch;
183*7f2fe78bSCy Schubert 	s->sc_next = svc_head;
184*7f2fe78bSCy Schubert 	svc_head = s;
185*7f2fe78bSCy Schubert pmap_it:
186*7f2fe78bSCy Schubert 	/* now register the information with the local binder service */
187*7f2fe78bSCy Schubert 	if (protocol) {
188*7f2fe78bSCy Schubert 		return (pmap_set(prog, vers, protocol, xprt->xp_port));
189*7f2fe78bSCy Schubert 	}
190*7f2fe78bSCy Schubert 	return (TRUE);
191*7f2fe78bSCy Schubert }
192*7f2fe78bSCy Schubert 
193*7f2fe78bSCy Schubert /*
194*7f2fe78bSCy Schubert  * Remove a service program from the callout list.
195*7f2fe78bSCy Schubert  */
196*7f2fe78bSCy Schubert void
svc_unregister(rpcprog_t prog,rpcvers_t vers)197*7f2fe78bSCy Schubert svc_unregister(
198*7f2fe78bSCy Schubert 	rpcprog_t prog,
199*7f2fe78bSCy Schubert 	rpcvers_t vers)
200*7f2fe78bSCy Schubert {
201*7f2fe78bSCy Schubert 	struct svc_callout *prev;
202*7f2fe78bSCy Schubert 	struct svc_callout *s;
203*7f2fe78bSCy Schubert 
204*7f2fe78bSCy Schubert 	if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
205*7f2fe78bSCy Schubert 		return;
206*7f2fe78bSCy Schubert 	if (prev == NULL_SVC) {
207*7f2fe78bSCy Schubert 		svc_head = s->sc_next;
208*7f2fe78bSCy Schubert 	} else {
209*7f2fe78bSCy Schubert 		prev->sc_next = s->sc_next;
210*7f2fe78bSCy Schubert 	}
211*7f2fe78bSCy Schubert 	s->sc_next = NULL_SVC;
212*7f2fe78bSCy Schubert 	mem_free((char *) s, (u_int) sizeof(struct svc_callout));
213*7f2fe78bSCy Schubert 	/* now unregister the information with the local binder service */
214*7f2fe78bSCy Schubert 	(void)pmap_unset(prog, vers);
215*7f2fe78bSCy Schubert }
216*7f2fe78bSCy Schubert 
217*7f2fe78bSCy Schubert /*
218*7f2fe78bSCy Schubert  * Search the callout list for a program number, return the callout
219*7f2fe78bSCy Schubert  * struct.
220*7f2fe78bSCy Schubert  */
221*7f2fe78bSCy Schubert static struct svc_callout *
svc_find(rpcprog_t prog,rpcvers_t vers,struct svc_callout ** prev)222*7f2fe78bSCy Schubert svc_find(
223*7f2fe78bSCy Schubert 	rpcprog_t prog,
224*7f2fe78bSCy Schubert 	rpcvers_t vers,
225*7f2fe78bSCy Schubert 	struct svc_callout **prev)
226*7f2fe78bSCy Schubert {
227*7f2fe78bSCy Schubert 	struct svc_callout *s, *p;
228*7f2fe78bSCy Schubert 
229*7f2fe78bSCy Schubert 	p = NULL_SVC;
230*7f2fe78bSCy Schubert 	for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
231*7f2fe78bSCy Schubert 		if ((s->sc_prog == prog) && (s->sc_vers == vers))
232*7f2fe78bSCy Schubert 			goto done;
233*7f2fe78bSCy Schubert 		p = s;
234*7f2fe78bSCy Schubert 	}
235*7f2fe78bSCy Schubert done:
236*7f2fe78bSCy Schubert 	*prev = p;
237*7f2fe78bSCy Schubert 	return (s);
238*7f2fe78bSCy Schubert }
239*7f2fe78bSCy Schubert 
240*7f2fe78bSCy Schubert /* ******************* REPLY GENERATION ROUTINES  ************ */
241*7f2fe78bSCy Schubert 
242*7f2fe78bSCy Schubert /*
243*7f2fe78bSCy Schubert  * Send a reply to an rpc request
244*7f2fe78bSCy Schubert  */
245*7f2fe78bSCy Schubert bool_t
svc_sendreply(SVCXPRT * xprt,xdrproc_t xdr_results,caddr_t xdr_location)246*7f2fe78bSCy Schubert svc_sendreply(
247*7f2fe78bSCy Schubert 	SVCXPRT *xprt,
248*7f2fe78bSCy Schubert 	xdrproc_t xdr_results,
249*7f2fe78bSCy Schubert 	caddr_t xdr_location)
250*7f2fe78bSCy Schubert {
251*7f2fe78bSCy Schubert 	struct rpc_msg rply;
252*7f2fe78bSCy Schubert 
253*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
254*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
255*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_verf = xprt->xp_verf;
256*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_stat = SUCCESS;
257*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_results.where = xdr_location;
258*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_results.proc = xdr_results;
259*7f2fe78bSCy Schubert 	return (SVC_REPLY(xprt, &rply));
260*7f2fe78bSCy Schubert }
261*7f2fe78bSCy Schubert 
262*7f2fe78bSCy Schubert /*
263*7f2fe78bSCy Schubert  * No procedure error reply
264*7f2fe78bSCy Schubert  */
265*7f2fe78bSCy Schubert void
svcerr_noproc(SVCXPRT * xprt)266*7f2fe78bSCy Schubert svcerr_noproc(SVCXPRT *xprt)
267*7f2fe78bSCy Schubert {
268*7f2fe78bSCy Schubert 	struct rpc_msg rply;
269*7f2fe78bSCy Schubert 
270*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
271*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
272*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_verf = xprt->xp_verf;
273*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_stat = PROC_UNAVAIL;
274*7f2fe78bSCy Schubert 	SVC_REPLY(xprt, &rply);
275*7f2fe78bSCy Schubert }
276*7f2fe78bSCy Schubert 
277*7f2fe78bSCy Schubert /*
278*7f2fe78bSCy Schubert  * Can't decode args error reply
279*7f2fe78bSCy Schubert  */
280*7f2fe78bSCy Schubert void
svcerr_decode(SVCXPRT * xprt)281*7f2fe78bSCy Schubert svcerr_decode(SVCXPRT *xprt)
282*7f2fe78bSCy Schubert {
283*7f2fe78bSCy Schubert 	struct rpc_msg rply;
284*7f2fe78bSCy Schubert 
285*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
286*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
287*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_verf = xprt->xp_verf;
288*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_stat = GARBAGE_ARGS;
289*7f2fe78bSCy Schubert 	SVC_REPLY(xprt, &rply);
290*7f2fe78bSCy Schubert }
291*7f2fe78bSCy Schubert 
292*7f2fe78bSCy Schubert /*
293*7f2fe78bSCy Schubert  * Some system error
294*7f2fe78bSCy Schubert  */
295*7f2fe78bSCy Schubert void
svcerr_systemerr(SVCXPRT * xprt)296*7f2fe78bSCy Schubert svcerr_systemerr(SVCXPRT *xprt)
297*7f2fe78bSCy Schubert {
298*7f2fe78bSCy Schubert 	struct rpc_msg rply;
299*7f2fe78bSCy Schubert 
300*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
301*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
302*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_verf = xprt->xp_verf;
303*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_stat = SYSTEM_ERR;
304*7f2fe78bSCy Schubert 	SVC_REPLY(xprt, &rply);
305*7f2fe78bSCy Schubert }
306*7f2fe78bSCy Schubert 
307*7f2fe78bSCy Schubert /*
308*7f2fe78bSCy Schubert  * Authentication error reply
309*7f2fe78bSCy Schubert  */
310*7f2fe78bSCy Schubert void
svcerr_auth(SVCXPRT * xprt,enum auth_stat why)311*7f2fe78bSCy Schubert svcerr_auth(
312*7f2fe78bSCy Schubert 	SVCXPRT *xprt,
313*7f2fe78bSCy Schubert 	enum auth_stat why)
314*7f2fe78bSCy Schubert {
315*7f2fe78bSCy Schubert 	struct rpc_msg rply;
316*7f2fe78bSCy Schubert 
317*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
318*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_DENIED;
319*7f2fe78bSCy Schubert 	rply.rjcted_rply.rj_stat = AUTH_ERROR;
320*7f2fe78bSCy Schubert 	rply.rjcted_rply.rj_why = why;
321*7f2fe78bSCy Schubert 	SVC_REPLY(xprt, &rply);
322*7f2fe78bSCy Schubert }
323*7f2fe78bSCy Schubert 
324*7f2fe78bSCy Schubert /*
325*7f2fe78bSCy Schubert  * Auth too weak error reply
326*7f2fe78bSCy Schubert  */
327*7f2fe78bSCy Schubert void
svcerr_weakauth(SVCXPRT * xprt)328*7f2fe78bSCy Schubert svcerr_weakauth(SVCXPRT *xprt)
329*7f2fe78bSCy Schubert {
330*7f2fe78bSCy Schubert 
331*7f2fe78bSCy Schubert 	svcerr_auth(xprt, AUTH_TOOWEAK);
332*7f2fe78bSCy Schubert }
333*7f2fe78bSCy Schubert 
334*7f2fe78bSCy Schubert /*
335*7f2fe78bSCy Schubert  * Program unavailable error reply
336*7f2fe78bSCy Schubert  */
337*7f2fe78bSCy Schubert void
svcerr_noprog(SVCXPRT * xprt)338*7f2fe78bSCy Schubert svcerr_noprog(SVCXPRT *xprt)
339*7f2fe78bSCy Schubert {
340*7f2fe78bSCy Schubert 	struct rpc_msg rply;
341*7f2fe78bSCy Schubert 
342*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
343*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
344*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_verf = xprt->xp_verf;
345*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_stat = PROG_UNAVAIL;
346*7f2fe78bSCy Schubert 	SVC_REPLY(xprt, &rply);
347*7f2fe78bSCy Schubert }
348*7f2fe78bSCy Schubert 
349*7f2fe78bSCy Schubert /*
350*7f2fe78bSCy Schubert  * Program version mismatch error reply
351*7f2fe78bSCy Schubert  */
352*7f2fe78bSCy Schubert void
svcerr_progvers(SVCXPRT * xprt,rpcvers_t low_vers,rpcvers_t high_vers)353*7f2fe78bSCy Schubert svcerr_progvers(
354*7f2fe78bSCy Schubert 	SVCXPRT *xprt,
355*7f2fe78bSCy Schubert 	rpcvers_t low_vers,
356*7f2fe78bSCy Schubert 	rpcvers_t high_vers)
357*7f2fe78bSCy Schubert {
358*7f2fe78bSCy Schubert 	struct rpc_msg rply;
359*7f2fe78bSCy Schubert 
360*7f2fe78bSCy Schubert 	rply.rm_direction = REPLY;
361*7f2fe78bSCy Schubert 	rply.rm_reply.rp_stat = MSG_ACCEPTED;
362*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_verf = xprt->xp_verf;
363*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_stat = PROG_MISMATCH;
364*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_vers.low = low_vers;
365*7f2fe78bSCy Schubert 	rply.acpted_rply.ar_vers.high = high_vers;
366*7f2fe78bSCy Schubert 	SVC_REPLY(xprt, &rply);
367*7f2fe78bSCy Schubert }
368*7f2fe78bSCy Schubert 
369*7f2fe78bSCy Schubert /* ******************* SERVER INPUT STUFF ******************* */
370*7f2fe78bSCy Schubert 
371*7f2fe78bSCy Schubert /*
372*7f2fe78bSCy Schubert  * Get server side input from some transport.
373*7f2fe78bSCy Schubert  *
374*7f2fe78bSCy Schubert  * Statement of authentication parameters management:
375*7f2fe78bSCy Schubert  * This function owns and manages all authentication parameters, specifically
376*7f2fe78bSCy Schubert  * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
377*7f2fe78bSCy Schubert  * the "cooked" credentials (rqst->rq_clntcred).
378*7f2fe78bSCy Schubert  * However, this function does not know the structure of the cooked
379*7f2fe78bSCy Schubert  * credentials, so it make the following assumptions:
380*7f2fe78bSCy Schubert  *   a) the structure is contiguous (no pointers), and
381*7f2fe78bSCy Schubert  *   b) the cred structure size does not exceed RQCRED_SIZE bytes.
382*7f2fe78bSCy Schubert  * In all events, all three parameters are freed upon exit from this routine.
383*7f2fe78bSCy Schubert  * The storage is trivially management on the call stack in user land, but
384*7f2fe78bSCy Schubert  * is mallocated in kernel land.
385*7f2fe78bSCy Schubert  */
386*7f2fe78bSCy Schubert 
387*7f2fe78bSCy Schubert void
svc_getreq(int rdfds)388*7f2fe78bSCy Schubert svc_getreq(int rdfds)
389*7f2fe78bSCy Schubert {
390*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
391*7f2fe78bSCy Schubert 	fd_set readfds;
392*7f2fe78bSCy Schubert 	int	i, mask;
393*7f2fe78bSCy Schubert 
394*7f2fe78bSCy Schubert 	FD_ZERO(&readfds);
395*7f2fe78bSCy Schubert 	for (i=0, mask=1; rdfds; i++, mask <<=1) {
396*7f2fe78bSCy Schubert 		if (rdfds & mask)
397*7f2fe78bSCy Schubert 			FD_SET(i, &readfds);
398*7f2fe78bSCy Schubert 		rdfds &= ~mask;
399*7f2fe78bSCy Schubert 	}
400*7f2fe78bSCy Schubert 	svc_getreqset(&readfds);
401*7f2fe78bSCy Schubert #else
402*7f2fe78bSCy Schubert 	int readfds = rdfds & svc_fds;
403*7f2fe78bSCy Schubert 
404*7f2fe78bSCy Schubert 	svc_getreqset(&readfds);
405*7f2fe78bSCy Schubert #endif /* def FD_SETSIZE */
406*7f2fe78bSCy Schubert }
407*7f2fe78bSCy Schubert 
408*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
409*7f2fe78bSCy Schubert #define FDSET_TYPE fd_set
410*7f2fe78bSCy Schubert #else
411*7f2fe78bSCy Schubert #define FDSET_TYPE int
412*7f2fe78bSCy Schubert #endif
413*7f2fe78bSCy Schubert 
414*7f2fe78bSCy Schubert void
svc_getreqset(FDSET_TYPE * readfds)415*7f2fe78bSCy Schubert svc_getreqset(FDSET_TYPE *readfds)
416*7f2fe78bSCy Schubert {
417*7f2fe78bSCy Schubert #ifndef FD_SETSIZE
418*7f2fe78bSCy Schubert 	int readfds_local = *readfds;
419*7f2fe78bSCy Schubert #endif
420*7f2fe78bSCy Schubert 	SVCXPRT *xprt;
421*7f2fe78bSCy Schubert 	int sock;
422*7f2fe78bSCy Schubert 
423*7f2fe78bSCy Schubert #ifdef FD_SETSIZE
424*7f2fe78bSCy Schubert 	for (sock = 0; sock <= svc_maxfd; sock++) {
425*7f2fe78bSCy Schubert 		if (!FD_ISSET(sock, readfds))
426*7f2fe78bSCy Schubert 			continue;
427*7f2fe78bSCy Schubert 		/* sock has input waiting */
428*7f2fe78bSCy Schubert 		xprt = xports[sock];
429*7f2fe78bSCy Schubert 		/* now receive msgs from xprtprt (support batch calls) */
430*7f2fe78bSCy Schubert 		svc_do_xprt(xprt);
431*7f2fe78bSCy Schubert 	}
432*7f2fe78bSCy Schubert #else
433*7f2fe78bSCy Schubert 	for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
434*7f2fe78bSCy Schubert 		if ((readfds_local & 1) == 0)
435*7f2fe78bSCy Schubert 			continue;
436*7f2fe78bSCy Schubert 		/* sock has input waiting */
437*7f2fe78bSCy Schubert 		xprt = xports[sock];
438*7f2fe78bSCy Schubert 		/* now receive msgs from xprtprt (support batch calls) */
439*7f2fe78bSCy Schubert 		svc_do_xprt(xprt);
440*7f2fe78bSCy Schubert 	}
441*7f2fe78bSCy Schubert #endif
442*7f2fe78bSCy Schubert }
443*7f2fe78bSCy Schubert 
444*7f2fe78bSCy Schubert extern struct svc_auth_ops svc_auth_gss_ops;
445*7f2fe78bSCy Schubert 
446*7f2fe78bSCy Schubert static void
svc_do_xprt(SVCXPRT * xprt)447*7f2fe78bSCy Schubert svc_do_xprt(SVCXPRT *xprt)
448*7f2fe78bSCy Schubert {
449*7f2fe78bSCy Schubert 	caddr_t rawcred, rawverf, cookedcred;
450*7f2fe78bSCy Schubert 	struct rpc_msg msg;
451*7f2fe78bSCy Schubert 	struct svc_req r;
452*7f2fe78bSCy Schubert         bool_t no_dispatch;
453*7f2fe78bSCy Schubert 	int prog_found;
454*7f2fe78bSCy Schubert 	rpcvers_t low_vers;
455*7f2fe78bSCy Schubert 	rpcvers_t high_vers;
456*7f2fe78bSCy Schubert 	enum xprt_stat stat;
457*7f2fe78bSCy Schubert 
458*7f2fe78bSCy Schubert 	rawcred = mem_alloc(MAX_AUTH_BYTES);
459*7f2fe78bSCy Schubert 	rawverf = mem_alloc(MAX_AUTH_BYTES);
460*7f2fe78bSCy Schubert 	cookedcred = mem_alloc(RQCRED_SIZE);
461*7f2fe78bSCy Schubert 
462*7f2fe78bSCy Schubert 	if (rawcred == NULL || rawverf == NULL || cookedcred == NULL)
463*7f2fe78bSCy Schubert 		return;
464*7f2fe78bSCy Schubert 
465*7f2fe78bSCy Schubert 	msg.rm_call.cb_cred.oa_base = rawcred;
466*7f2fe78bSCy Schubert 	msg.rm_call.cb_verf.oa_base = rawverf;
467*7f2fe78bSCy Schubert 	r.rq_clntcred = cookedcred;
468*7f2fe78bSCy Schubert 
469*7f2fe78bSCy Schubert 	do {
470*7f2fe78bSCy Schubert 		struct svc_callout *s;
471*7f2fe78bSCy Schubert 		enum auth_stat why;
472*7f2fe78bSCy Schubert 
473*7f2fe78bSCy Schubert 		if (!SVC_RECV(xprt, &msg))
474*7f2fe78bSCy Schubert 			goto call_done;
475*7f2fe78bSCy Schubert 
476*7f2fe78bSCy Schubert 		/* now find the exported program and call it */
477*7f2fe78bSCy Schubert 
478*7f2fe78bSCy Schubert 		r.rq_xprt = xprt;
479*7f2fe78bSCy Schubert 		r.rq_prog = msg.rm_call.cb_prog;
480*7f2fe78bSCy Schubert 		r.rq_vers = msg.rm_call.cb_vers;
481*7f2fe78bSCy Schubert 		r.rq_proc = msg.rm_call.cb_proc;
482*7f2fe78bSCy Schubert 		r.rq_cred = msg.rm_call.cb_cred;
483*7f2fe78bSCy Schubert 
484*7f2fe78bSCy Schubert 		no_dispatch = FALSE;
485*7f2fe78bSCy Schubert 
486*7f2fe78bSCy Schubert 		/* first authenticate the message */
487*7f2fe78bSCy Schubert 		why = gssrpc__authenticate(&r, &msg, &no_dispatch);
488*7f2fe78bSCy Schubert 		if (why != AUTH_OK) {
489*7f2fe78bSCy Schubert 			svcerr_auth(xprt, why);
490*7f2fe78bSCy Schubert 			goto call_done;
491*7f2fe78bSCy Schubert 		} else if (no_dispatch) {
492*7f2fe78bSCy Schubert 			goto call_done;
493*7f2fe78bSCy Schubert 		}
494*7f2fe78bSCy Schubert 
495*7f2fe78bSCy Schubert 		/* now match message with a registered service*/
496*7f2fe78bSCy Schubert 		prog_found = FALSE;
497*7f2fe78bSCy Schubert 		low_vers = (rpcvers_t) -1L;
498*7f2fe78bSCy Schubert 		high_vers = 0;
499*7f2fe78bSCy Schubert 		for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
500*7f2fe78bSCy Schubert 			if (s->sc_prog == r.rq_prog) {
501*7f2fe78bSCy Schubert 				if (s->sc_vers == r.rq_vers) {
502*7f2fe78bSCy Schubert 					(*s->sc_dispatch)(&r, xprt);
503*7f2fe78bSCy Schubert 					goto call_done;
504*7f2fe78bSCy Schubert 				}  /* found correct version */
505*7f2fe78bSCy Schubert 				prog_found = TRUE;
506*7f2fe78bSCy Schubert 				if (s->sc_vers < low_vers)
507*7f2fe78bSCy Schubert 					low_vers = s->sc_vers;
508*7f2fe78bSCy Schubert 				if (s->sc_vers > high_vers)
509*7f2fe78bSCy Schubert 					high_vers = s->sc_vers;
510*7f2fe78bSCy Schubert 			}   /* found correct program */
511*7f2fe78bSCy Schubert 		}
512*7f2fe78bSCy Schubert 		/*
513*7f2fe78bSCy Schubert 		 * if we got here, the program or version
514*7f2fe78bSCy Schubert 		 * is not served ...
515*7f2fe78bSCy Schubert 		 */
516*7f2fe78bSCy Schubert 		if (prog_found)
517*7f2fe78bSCy Schubert 			svcerr_progvers(xprt,
518*7f2fe78bSCy Schubert 					low_vers, high_vers);
519*7f2fe78bSCy Schubert 		else
520*7f2fe78bSCy Schubert 			svcerr_noprog(xprt);
521*7f2fe78bSCy Schubert 		/* Fall through to ... */
522*7f2fe78bSCy Schubert 
523*7f2fe78bSCy Schubert 	call_done:
524*7f2fe78bSCy Schubert 		if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
525*7f2fe78bSCy Schubert 			SVC_DESTROY(xprt);
526*7f2fe78bSCy Schubert 			break;
527*7f2fe78bSCy Schubert 		} else if ((xprt->xp_auth != NULL) &&
528*7f2fe78bSCy Schubert 			   (xprt->xp_auth->svc_ah_ops != &svc_auth_gss_ops)) {
529*7f2fe78bSCy Schubert 			xprt->xp_auth = NULL;
530*7f2fe78bSCy Schubert 		}
531*7f2fe78bSCy Schubert 	} while (stat == XPRT_MOREREQS);
532*7f2fe78bSCy Schubert 
533*7f2fe78bSCy Schubert 	mem_free(rawcred, MAX_AUTH_BYTES);
534*7f2fe78bSCy Schubert 	mem_free(rawverf, MAX_AUTH_BYTES);
535*7f2fe78bSCy Schubert 	mem_free(cookedcred, RQCRED_SIZE);
536*7f2fe78bSCy Schubert }
537