1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  *  sec_svc.c, Server-side rpc security interface.
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate #ifdef _KERNEL
33*0Sstevel@tonic-gate #include <sys/param.h>
34*0Sstevel@tonic-gate #include <sys/types.h>
35*0Sstevel@tonic-gate #include <sys/debug.h>
36*0Sstevel@tonic-gate #include <sys/systm.h>
37*0Sstevel@tonic-gate #include <rpc/types.h>
38*0Sstevel@tonic-gate #include <netinet/in.h>
39*0Sstevel@tonic-gate #include <rpc/xdr.h>
40*0Sstevel@tonic-gate #include <rpc/auth.h>
41*0Sstevel@tonic-gate #include <rpc/clnt.h>
42*0Sstevel@tonic-gate #include <rpc/rpc_msg.h>
43*0Sstevel@tonic-gate #include <sys/tiuser.h>
44*0Sstevel@tonic-gate #include <sys/tihdr.h>
45*0Sstevel@tonic-gate #include <sys/t_kuser.h>
46*0Sstevel@tonic-gate #include <sys/cmn_err.h>
47*0Sstevel@tonic-gate #include <rpc/auth_des.h>
48*0Sstevel@tonic-gate #include <rpc/auth_sys.h>
49*0Sstevel@tonic-gate #include <rpc/rpcsec_gss.h>
50*0Sstevel@tonic-gate #include <rpc/svc_auth.h>
51*0Sstevel@tonic-gate #include <rpc/svc.h>
52*0Sstevel@tonic-gate #else
53*0Sstevel@tonic-gate #include <rpc/rpc.h>
54*0Sstevel@tonic-gate #endif
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 
57*0Sstevel@tonic-gate enum auth_stat _svcauth_null(struct svc_req *, struct rpc_msg *);
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /*
60*0Sstevel@tonic-gate  *  NO-OP server wrap/unwrap svc_authany_ops using no-op svc_authany_wrap().
61*0Sstevel@tonic-gate  */
62*0Sstevel@tonic-gate /* ARGSUSED */
63*0Sstevel@tonic-gate static int
64*0Sstevel@tonic-gate svc_authany_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere)
65*0Sstevel@tonic-gate {
66*0Sstevel@tonic-gate 	return (*xfunc)(xdrs, xwhere);
67*0Sstevel@tonic-gate }
68*0Sstevel@tonic-gate 
69*0Sstevel@tonic-gate struct svc_auth_ops svc_authany_ops = {
70*0Sstevel@tonic-gate 	svc_authany_wrap,
71*0Sstevel@tonic-gate 	svc_authany_wrap
72*0Sstevel@tonic-gate };
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate /*
76*0Sstevel@tonic-gate  * The call rpc message, msg has been obtained from the wire.  The msg contains
77*0Sstevel@tonic-gate  * the raw form of credentials and verifiers.  authenticate returns AUTH_OK
78*0Sstevel@tonic-gate  * if the msg is successfully authenticated.  If AUTH_OK then the routine also
79*0Sstevel@tonic-gate  * does the following things:
80*0Sstevel@tonic-gate  * set rqst->rq_xprt->verf to the appropriate response verifier;
81*0Sstevel@tonic-gate  * sets rqst->rq_client_cred to the "cooked" form of the credentials.
82*0Sstevel@tonic-gate  *
83*0Sstevel@tonic-gate  * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
84*0Sstevel@tonic-gate  * its length is set appropriately.
85*0Sstevel@tonic-gate  *
86*0Sstevel@tonic-gate  * The caller still owns and is responsible for msg->u.cmb.cred and
87*0Sstevel@tonic-gate  * msg->u.cmb.verf.  The authentication system retains ownership of
88*0Sstevel@tonic-gate  * rqst->rq_client_cred, the cooked credentials.
89*0Sstevel@tonic-gate  *
90*0Sstevel@tonic-gate  * There is an assumption that any flavor less than AUTH_NULL is
91*0Sstevel@tonic-gate  * invalid.
92*0Sstevel@tonic-gate  */
93*0Sstevel@tonic-gate enum auth_stat
94*0Sstevel@tonic-gate sec_svc_msg(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch)
95*0Sstevel@tonic-gate {
96*0Sstevel@tonic-gate 	int cred_flavor;
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate 	rqst->rq_cred = msg->rm_call.cb_cred;
99*0Sstevel@tonic-gate 	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
100*0Sstevel@tonic-gate 	rqst->rq_xprt->xp_verf.oa_length = 0;
101*0Sstevel@tonic-gate 	/*
102*0Sstevel@tonic-gate 	 * Init the xp_auth to be no-op for all the flavors.
103*0Sstevel@tonic-gate 	 * Flavor specific routines will revise this when appropriate.
104*0Sstevel@tonic-gate 	 */
105*0Sstevel@tonic-gate 	rqst->rq_xprt->xp_auth.svc_ah_ops = svc_authany_ops;
106*0Sstevel@tonic-gate 	rqst->rq_xprt->xp_auth.svc_ah_private = NULL;
107*0Sstevel@tonic-gate 	*no_dispatch = FALSE;
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 	cred_flavor = rqst->rq_cred.oa_flavor;
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 	switch (cred_flavor) {
112*0Sstevel@tonic-gate 	case AUTH_NULL:
113*0Sstevel@tonic-gate 		rqst->rq_xprt->xp_cookie = (void *) AUTH_NULL;
114*0Sstevel@tonic-gate 		return (_svcauth_null(rqst, msg));
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 	case AUTH_UNIX:
117*0Sstevel@tonic-gate 		rqst->rq_xprt->xp_cookie = (void *) AUTH_UNIX;
118*0Sstevel@tonic-gate 		return (_svcauth_unix(rqst, msg));
119*0Sstevel@tonic-gate 
120*0Sstevel@tonic-gate 	case AUTH_SHORT:
121*0Sstevel@tonic-gate 		rqst->rq_xprt->xp_cookie = (void *) AUTH_SHORT;
122*0Sstevel@tonic-gate 		return (_svcauth_short(rqst, msg));
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	case AUTH_DES:
125*0Sstevel@tonic-gate 		rqst->rq_xprt->xp_cookie = (void *) AUTH_DES;
126*0Sstevel@tonic-gate 		return (_svcauth_des(rqst, msg));
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate 	case RPCSEC_GSS:
129*0Sstevel@tonic-gate 		/*
130*0Sstevel@tonic-gate 		 * RPCSEC_GSS flavor routine takes an additional
131*0Sstevel@tonic-gate 		 * boolean parameter that gets set to TRUE when
132*0Sstevel@tonic-gate 		 * the call is not to be dispatched to the server.
133*0Sstevel@tonic-gate 		 */
134*0Sstevel@tonic-gate 		return (__svcrpcsec_gss(rqst, msg, no_dispatch));
135*0Sstevel@tonic-gate 	}
136*0Sstevel@tonic-gate 	return (AUTH_REJECTEDCRED);
137*0Sstevel@tonic-gate }
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate /*
140*0Sstevel@tonic-gate  *  sec_svc_getcred() gets unix cred of incoming security rpc requests.
141*0Sstevel@tonic-gate  *  It also returns the prinicipal name and a cookie which is application
142*0Sstevel@tonic-gate  *  dependent e.g. for nfs, it is the pseudo flavor.
143*0Sstevel@tonic-gate  *
144*0Sstevel@tonic-gate  *  return 0 on failure
145*0Sstevel@tonic-gate  */
146*0Sstevel@tonic-gate int
147*0Sstevel@tonic-gate sec_svc_getcred(struct svc_req *req, cred_t *cr, caddr_t *principal,
148*0Sstevel@tonic-gate 	int *secmod)
149*0Sstevel@tonic-gate {
150*0Sstevel@tonic-gate 	struct authunix_parms *aup;
151*0Sstevel@tonic-gate 	struct authdes_cred *adc;
152*0Sstevel@tonic-gate 	int flavor, stat;
153*0Sstevel@tonic-gate 	rpc_gss_rawcred_t *rcred;
154*0Sstevel@tonic-gate 	rpc_gss_ucred_t	*ucred;
155*0Sstevel@tonic-gate 	void *cookie;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	stat = 1;
158*0Sstevel@tonic-gate 	flavor = req->rq_cred.oa_flavor;
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	*principal = NULL;
161*0Sstevel@tonic-gate 	switch (flavor) {
162*0Sstevel@tonic-gate 	case AUTH_UNIX:
163*0Sstevel@tonic-gate 		*secmod = AUTH_UNIX;
164*0Sstevel@tonic-gate 		aup = (struct authunix_parms *)req->rq_clntcred;
165*0Sstevel@tonic-gate 		if (crsetugid(cr, aup->aup_uid, aup->aup_gid) != 0 ||
166*0Sstevel@tonic-gate 		    crsetgroups(cr, aup->aup_len, aup->aup_gids) != 0)
167*0Sstevel@tonic-gate 			stat = 0;
168*0Sstevel@tonic-gate 		break;
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	case AUTH_NONE:
171*0Sstevel@tonic-gate 		*secmod = AUTH_NONE;
172*0Sstevel@tonic-gate 		break;
173*0Sstevel@tonic-gate 
174*0Sstevel@tonic-gate 	case AUTH_DES:
175*0Sstevel@tonic-gate 		*secmod = AUTH_DES;
176*0Sstevel@tonic-gate 		adc = (struct authdes_cred *)req->rq_clntcred;
177*0Sstevel@tonic-gate 		stat = kauthdes_getucred(adc, cr);
178*0Sstevel@tonic-gate 		*principal = adc->adc_fullname.name;
179*0Sstevel@tonic-gate 		break;
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	case RPCSEC_GSS:
182*0Sstevel@tonic-gate 		stat = rpc_gss_getcred(req, &rcred, &ucred, &cookie);
183*0Sstevel@tonic-gate 		*secmod = (int)(uintptr_t)cookie;	/* XX64 */
184*0Sstevel@tonic-gate 		if (ucred != NULL) {
185*0Sstevel@tonic-gate 			if (crsetugid(cr, ucred->uid, ucred->gid) != 0 ||
186*0Sstevel@tonic-gate 			    crsetgroups(cr, ucred->gidlen, ucred->gidlist) != 0)
187*0Sstevel@tonic-gate 				stat = 0;
188*0Sstevel@tonic-gate 		} else {
189*0Sstevel@tonic-gate 			(void) crsetugid(cr, UID_NOBODY, GID_NOBODY);
190*0Sstevel@tonic-gate 			(void) crsetgroups(cr, 0, NULL);
191*0Sstevel@tonic-gate 		}
192*0Sstevel@tonic-gate 		*principal = (caddr_t)rcred->client_principal;
193*0Sstevel@tonic-gate 		break;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 	default:
196*0Sstevel@tonic-gate 		stat = 0;
197*0Sstevel@tonic-gate 		break;
198*0Sstevel@tonic-gate 	}
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	return (stat);
201*0Sstevel@tonic-gate }
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate /* ARGSUSED */
205*0Sstevel@tonic-gate enum auth_stat
206*0Sstevel@tonic-gate _svcauth_null(struct svc_req *rqst, struct rpc_msg *msg)
207*0Sstevel@tonic-gate {
208*0Sstevel@tonic-gate 	return (AUTH_OK);
209*0Sstevel@tonic-gate }
210*0Sstevel@tonic-gate 
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate /*
213*0Sstevel@tonic-gate  *  Load root principal names from user space to kernel space.
214*0Sstevel@tonic-gate  *
215*0Sstevel@tonic-gate  *  flavor - security flavor
216*0Sstevel@tonic-gate  *  count - number of principal names to be loaded
217*0Sstevel@tonic-gate  *  proots - address of the array of root names.
218*0Sstevel@tonic-gate  *		input is the array address in the user space,
219*0Sstevel@tonic-gate  *		output is the kernel address.
220*0Sstevel@tonic-gate  *
221*0Sstevel@tonic-gate  *  return 0 on failure.
222*0Sstevel@tonic-gate  */
223*0Sstevel@tonic-gate int
224*0Sstevel@tonic-gate sec_svc_loadrootnames(int flavor, int count, caddr_t **proots, model_t model)
225*0Sstevel@tonic-gate {
226*0Sstevel@tonic-gate 	caddr_t *roots, *oroots, root;
227*0Sstevel@tonic-gate 	char netname[MAXNETNAMELEN+1];
228*0Sstevel@tonic-gate 	struct rpc_gss_principal gsstmp, *gssname;
229*0Sstevel@tonic-gate 	uint_t i, j;
230*0Sstevel@tonic-gate 	size_t len, allocsz, oallocsz;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate #ifdef lint
233*0Sstevel@tonic-gate 	model = model;
234*0Sstevel@tonic-gate #endif
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 	/*
237*0Sstevel@tonic-gate 	 * Get list of names from user space
238*0Sstevel@tonic-gate 	 */
239*0Sstevel@tonic-gate 	allocsz = count * sizeof (caddr_t);
240*0Sstevel@tonic-gate 	oallocsz = count * SIZEOF_PTR(model);
241*0Sstevel@tonic-gate 
242*0Sstevel@tonic-gate 	/*
243*0Sstevel@tonic-gate 	 * And now copy each individual principal name
244*0Sstevel@tonic-gate 	 */
245*0Sstevel@tonic-gate 	switch (flavor) {
246*0Sstevel@tonic-gate 	case AUTH_DES:
247*0Sstevel@tonic-gate 		roots = kmem_zalloc(allocsz, KM_SLEEP);
248*0Sstevel@tonic-gate 		oroots = kmem_alloc(oallocsz, KM_SLEEP);
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate 		if (copyin(*proots, oroots, oallocsz))
251*0Sstevel@tonic-gate 			goto done;
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 		for (i = 0; i < count; i++) {
254*0Sstevel@tonic-gate 			/*
255*0Sstevel@tonic-gate 			 * copyinstr copies the complete string (including the
256*0Sstevel@tonic-gate 			 * NULL) and returns the len with the NULL byte
257*0Sstevel@tonic-gate 			 * included in the calculation as long as the max
258*0Sstevel@tonic-gate 			 * length is not exceeded.
259*0Sstevel@tonic-gate 			 */
260*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
261*0Sstevel@tonic-gate 			if (model != DATAMODEL_NATIVE) {
262*0Sstevel@tonic-gate 				caddr32_t *tmp;
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 				tmp = (caddr32_t *)oroots;
265*0Sstevel@tonic-gate 				root = (caddr_t)(uintptr_t)tmp[i];
266*0Sstevel@tonic-gate 			} else
267*0Sstevel@tonic-gate #endif
268*0Sstevel@tonic-gate 				root = oroots[i];
269*0Sstevel@tonic-gate 			if (copyinstr(root, netname, sizeof (netname), &len)) {
270*0Sstevel@tonic-gate 				for (j = 0; j < i; j++) {
271*0Sstevel@tonic-gate 					if (roots[j] != NULL)
272*0Sstevel@tonic-gate 						kmem_free(roots[j],
273*0Sstevel@tonic-gate 						    strlen(roots[j]) + 1);
274*0Sstevel@tonic-gate 				}
275*0Sstevel@tonic-gate 				goto done;
276*0Sstevel@tonic-gate 			}
277*0Sstevel@tonic-gate 			roots[i] = kmem_alloc(len, KM_SLEEP);
278*0Sstevel@tonic-gate 			bcopy(netname, roots[i], len);
279*0Sstevel@tonic-gate 		}
280*0Sstevel@tonic-gate 		kmem_free(oroots, oallocsz);
281*0Sstevel@tonic-gate 		*proots = roots;
282*0Sstevel@tonic-gate 		return (1);
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	case RPCSEC_GSS:
285*0Sstevel@tonic-gate 		roots = kmem_alloc(allocsz, KM_SLEEP);
286*0Sstevel@tonic-gate 		oroots = kmem_alloc(oallocsz, KM_SLEEP);
287*0Sstevel@tonic-gate 
288*0Sstevel@tonic-gate 		if (copyin(*proots, oroots, oallocsz))
289*0Sstevel@tonic-gate 			goto done;
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 		for (i = 0; i < count; i++) {
292*0Sstevel@tonic-gate #ifdef _SYSCALL32_IMPL
293*0Sstevel@tonic-gate 			if (model != DATAMODEL_NATIVE) {
294*0Sstevel@tonic-gate 				caddr32_t *tmp;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 				tmp = (caddr32_t *)oroots;
297*0Sstevel@tonic-gate 				root = (caddr_t)(uintptr_t)tmp[i];
298*0Sstevel@tonic-gate 			} else
299*0Sstevel@tonic-gate #endif
300*0Sstevel@tonic-gate 				root = oroots[i];
301*0Sstevel@tonic-gate 
302*0Sstevel@tonic-gate 			if (copyin(root, &gsstmp, sizeof (gsstmp))) {
303*0Sstevel@tonic-gate 				kmem_free(oroots, oallocsz);
304*0Sstevel@tonic-gate 				goto gssfreeup;
305*0Sstevel@tonic-gate 			}
306*0Sstevel@tonic-gate 			len = sizeof (gsstmp.len) + gsstmp.len;
307*0Sstevel@tonic-gate 			gssname = kmem_alloc(len, KM_SLEEP);
308*0Sstevel@tonic-gate 			if (copyin(root, gssname, len)) {
309*0Sstevel@tonic-gate 				kmem_free(gssname, len);
310*0Sstevel@tonic-gate 				kmem_free(oroots, oallocsz);
311*0Sstevel@tonic-gate 				goto gssfreeup;
312*0Sstevel@tonic-gate 			}
313*0Sstevel@tonic-gate 			roots[i] = (caddr_t)gssname;
314*0Sstevel@tonic-gate 		}
315*0Sstevel@tonic-gate 		kmem_free(oroots, oallocsz);
316*0Sstevel@tonic-gate 		*proots = roots;
317*0Sstevel@tonic-gate 		return (1);
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	default:
320*0Sstevel@tonic-gate 		return (0);
321*0Sstevel@tonic-gate 	}
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate gssfreeup:
324*0Sstevel@tonic-gate 	for (j = 0; j < i; j++) {
325*0Sstevel@tonic-gate 		if (roots[j] != NULL) {
326*0Sstevel@tonic-gate 			gssname = (rpc_gss_principal_t)roots[j];
327*0Sstevel@tonic-gate 			kmem_free(roots[j], gssname->len +
328*0Sstevel@tonic-gate 			    sizeof (gssname->len));
329*0Sstevel@tonic-gate 		}
330*0Sstevel@tonic-gate 	}
331*0Sstevel@tonic-gate done:
332*0Sstevel@tonic-gate 	kmem_free(roots, allocsz);
333*0Sstevel@tonic-gate 	return (0);
334*0Sstevel@tonic-gate }
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate /*
338*0Sstevel@tonic-gate  * Figure out everything we allocated in a root principal name list in
339*0Sstevel@tonic-gate  * order to free it up.
340*0Sstevel@tonic-gate  */
341*0Sstevel@tonic-gate void
342*0Sstevel@tonic-gate sec_svc_freerootnames(int flavor, int count, caddr_t *proots)
343*0Sstevel@tonic-gate {
344*0Sstevel@tonic-gate 	int i;
345*0Sstevel@tonic-gate 	rpc_gss_principal_t gssname;
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	switch (flavor) {
348*0Sstevel@tonic-gate 	case AUTH_DES:
349*0Sstevel@tonic-gate 		for (i = 0; i < count; i++)
350*0Sstevel@tonic-gate 			if (proots[i] != NULL)
351*0Sstevel@tonic-gate 				kmem_free(proots[i], strlen(proots[i]) + 1);
352*0Sstevel@tonic-gate 		break;
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate 	case RPCSEC_GSS:
355*0Sstevel@tonic-gate 		for (i = 0; i < count; i++) {
356*0Sstevel@tonic-gate 			if (proots[i] == NULL)
357*0Sstevel@tonic-gate 				continue;
358*0Sstevel@tonic-gate 			gssname = (rpc_gss_principal_t)proots[i];
359*0Sstevel@tonic-gate 			kmem_free(proots[i], gssname->len + sizeof (int));
360*0Sstevel@tonic-gate 		}
361*0Sstevel@tonic-gate 		break;
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate 	}
364*0Sstevel@tonic-gate 	kmem_free(proots, count * sizeof (caddr_t));
365*0Sstevel@tonic-gate }
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate /*
368*0Sstevel@tonic-gate  * Check if the  given principal name is in the root principal list
369*0Sstevel@tonic-gate  */
370*0Sstevel@tonic-gate bool_t
371*0Sstevel@tonic-gate sec_svc_inrootlist(int flavor, caddr_t rootname, int count, caddr_t *roots)
372*0Sstevel@tonic-gate {
373*0Sstevel@tonic-gate 	int i, tmp_len;
374*0Sstevel@tonic-gate 	rpc_gss_principal_t gssp, tmp_gssp;
375*0Sstevel@tonic-gate 	size_t namelen;
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 	switch (flavor) {
378*0Sstevel@tonic-gate 	case AUTH_DES:
379*0Sstevel@tonic-gate 		namelen = strlen(rootname) + 1;
380*0Sstevel@tonic-gate 		for (i = 0; i < count; i++)
381*0Sstevel@tonic-gate 			if (bcmp(rootname, roots[i], namelen) == 0)
382*0Sstevel@tonic-gate 				return (TRUE);
383*0Sstevel@tonic-gate 		break;
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate 	case RPCSEC_GSS:
386*0Sstevel@tonic-gate 		gssp = (rpc_gss_principal_t)rootname;
387*0Sstevel@tonic-gate 		namelen = gssp->len;
388*0Sstevel@tonic-gate 		for (i = 0; i < count; i++) {
389*0Sstevel@tonic-gate 			tmp_gssp = (rpc_gss_principal_t)roots[i];
390*0Sstevel@tonic-gate 			tmp_len = tmp_gssp->len;
391*0Sstevel@tonic-gate 			if ((namelen == tmp_len) &&
392*0Sstevel@tonic-gate 			    (bcmp(&gssp->name[0],
393*0Sstevel@tonic-gate 			    &tmp_gssp->name[0], namelen) == 0))
394*0Sstevel@tonic-gate 				return (TRUE);
395*0Sstevel@tonic-gate 		}
396*0Sstevel@tonic-gate 		break;
397*0Sstevel@tonic-gate 	}
398*0Sstevel@tonic-gate 	return (FALSE);
399*0Sstevel@tonic-gate }
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate /*
402*0Sstevel@tonic-gate  * Miscellaneout "control" functions manipulating global RPC security
403*0Sstevel@tonic-gate  * attributes for server applications.
404*0Sstevel@tonic-gate  */
405*0Sstevel@tonic-gate bool_t
406*0Sstevel@tonic-gate sec_svc_control(uint_t cmd, void *argp)
407*0Sstevel@tonic-gate {
408*0Sstevel@tonic-gate 	bool_t result = FALSE;		/* be paranoid */
409*0Sstevel@tonic-gate 
410*0Sstevel@tonic-gate 	switch (cmd) {
411*0Sstevel@tonic-gate 	case RPC_SVC_SET_GSS_CALLBACK:
412*0Sstevel@tonic-gate 		result = rpc_gss_set_callback((rpc_gss_callback_t *)argp);
413*0Sstevel@tonic-gate 		break;
414*0Sstevel@tonic-gate 	default:
415*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "sec_svc_control: bad command (%d)", cmd);
416*0Sstevel@tonic-gate 		result = FALSE;
417*0Sstevel@tonic-gate 		break;
418*0Sstevel@tonic-gate 	}
419*0Sstevel@tonic-gate 
420*0Sstevel@tonic-gate 	return (result);
421*0Sstevel@tonic-gate }
422