17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate /*
317c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
327c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
337c478bd9Sstevel@tonic-gate  */
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /*
367c478bd9Sstevel@tonic-gate  * auth_loopb.c, implements UNIX style authentication parameters in the
377c478bd9Sstevel@tonic-gate  * kernel.  Interfaces with svc_auth_loopback on the server.  See
387c478bd9Sstevel@tonic-gate  * auth_loopb.c for the user level implementation of the loopback auth.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <sys/param.h>
437c478bd9Sstevel@tonic-gate #include <sys/time.h>
447c478bd9Sstevel@tonic-gate #include <sys/types.h>
457c478bd9Sstevel@tonic-gate #include <sys/systm.h>
467c478bd9Sstevel@tonic-gate #include <sys/user.h>
477c478bd9Sstevel@tonic-gate #include <sys/proc.h>
487c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
497c478bd9Sstevel@tonic-gate #include <sys/cred.h>
507c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
517c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
527c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #include <rpc/types.h>
557c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
567c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
577c478bd9Sstevel@tonic-gate #include <rpc/auth_unix.h>
587c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
597c478bd9Sstevel@tonic-gate #include <rpc/rpc_msg.h>
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * Unix authenticator operations vector
637c478bd9Sstevel@tonic-gate  */
647c478bd9Sstevel@tonic-gate static void	authloopback_nextverf(AUTH *);
657c478bd9Sstevel@tonic-gate static bool_t	authloopback_marshal(AUTH *, XDR *, struct cred *);
667c478bd9Sstevel@tonic-gate static bool_t	authloopback_validate(AUTH *, struct opaque_auth *);
677c478bd9Sstevel@tonic-gate static bool_t	authloopback_refresh(AUTH *, struct rpc_msg *, cred_t *);
687c478bd9Sstevel@tonic-gate static void	authloopback_destroy(AUTH *);
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate static struct auth_ops authloopback_ops = {
717c478bd9Sstevel@tonic-gate 	authloopback_nextverf,
727c478bd9Sstevel@tonic-gate 	authloopback_marshal,
737c478bd9Sstevel@tonic-gate 	authloopback_validate,
747c478bd9Sstevel@tonic-gate 	authloopback_refresh,
757c478bd9Sstevel@tonic-gate 	authloopback_destroy,
767c478bd9Sstevel@tonic-gate 	authany_wrap,
777c478bd9Sstevel@tonic-gate 	authany_unwrap
787c478bd9Sstevel@tonic-gate };
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate  * Create a kernel unix style authenticator.
827c478bd9Sstevel@tonic-gate  * Returns an auth handle.
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate AUTH *
authloopback_create(void)857c478bd9Sstevel@tonic-gate authloopback_create(void)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate 	/*
887c478bd9Sstevel@tonic-gate 	 * Allocate and set up auth handle
897c478bd9Sstevel@tonic-gate 	 */
907c478bd9Sstevel@tonic-gate 	return (kmem_cache_alloc(authloopback_cache, KM_SLEEP));
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate /*
947c478bd9Sstevel@tonic-gate  *  The constructor of the authloopback_cache.
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate /* ARGSUSED */
977c478bd9Sstevel@tonic-gate int
authloopback_init(void * buf,void * cdrarg,int kmflags)987c478bd9Sstevel@tonic-gate authloopback_init(void *buf, void *cdrarg, int kmflags)
997c478bd9Sstevel@tonic-gate {
1007c478bd9Sstevel@tonic-gate 	AUTH *auth = (AUTH *)buf;
1017c478bd9Sstevel@tonic-gate 
1027c478bd9Sstevel@tonic-gate 	auth->ah_ops = &authloopback_ops;
1037c478bd9Sstevel@tonic-gate 	auth->ah_cred.oa_flavor = AUTH_LOOPBACK;
1047c478bd9Sstevel@tonic-gate 	auth->ah_verf = _null_auth;
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	return (0);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate /*
1107c478bd9Sstevel@tonic-gate  * authloopback operations
1117c478bd9Sstevel@tonic-gate  */
1127c478bd9Sstevel@tonic-gate /* ARGSUSED */
1137c478bd9Sstevel@tonic-gate static void
authloopback_nextverf(AUTH * auth)1147c478bd9Sstevel@tonic-gate authloopback_nextverf(AUTH *auth)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	/* no action necessary */
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate static bool_t
authloopback_marshal(AUTH * auth,XDR * xdrs,struct cred * cr)1217c478bd9Sstevel@tonic-gate authloopback_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	char *sercred;
1247c478bd9Sstevel@tonic-gate 	XDR xdrm;
125*6dd72a43SMarcel Telka 	bool_t ret;
126*6dd72a43SMarcel Telka 	uint32_t gidlen, credsize, namelen, rounded_namelen;
1277c478bd9Sstevel@tonic-gate 	int32_t *ptr;
128*6dd72a43SMarcel Telka 	char *nodename = uts_nodename();
129*6dd72a43SMarcel Telka 	uint32_t maxgidlen;
130*6dd72a43SMarcel Telka 	uint_t startpos;
131*6dd72a43SMarcel Telka 
132*6dd72a43SMarcel Telka 	ASSERT(xdrs->x_op == XDR_ENCODE);
133*6dd72a43SMarcel Telka 	ASSERT(auth->ah_cred.oa_flavor == AUTH_LOOPBACK);
134*6dd72a43SMarcel Telka 	ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE);
135*6dd72a43SMarcel Telka 	ASSERT(auth->ah_verf.oa_length == 0);
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	/*
1387c478bd9Sstevel@tonic-gate 	 * First we try a fast path to get through
1397c478bd9Sstevel@tonic-gate 	 * this very common operation.
1407c478bd9Sstevel@tonic-gate 	 */
141*6dd72a43SMarcel Telka 	namelen = (uint32_t)strlen(nodename);
142*6dd72a43SMarcel Telka 	if (namelen > MAX_MACHINE_NAME)
143*6dd72a43SMarcel Telka 		return (FALSE);
144*6dd72a43SMarcel Telka 	rounded_namelen = RNDUP(namelen);
145*6dd72a43SMarcel Telka 
146*6dd72a43SMarcel Telka 	/*
147*6dd72a43SMarcel Telka 	 * NFIELDS is a number of the following fields we are going to encode:
148*6dd72a43SMarcel Telka 	 *   - stamp
149*6dd72a43SMarcel Telka 	 *   - strlen(machinename)
150*6dd72a43SMarcel Telka 	 *   - uid
151*6dd72a43SMarcel Telka 	 *   - gid
152*6dd72a43SMarcel Telka 	 *   - the number of gids
153*6dd72a43SMarcel Telka 	 */
154*6dd72a43SMarcel Telka #define	NFIELDS	5
155*6dd72a43SMarcel Telka 	CTASSERT(NFIELDS * BYTES_PER_XDR_UNIT + RNDUP(MAX_MACHINE_NAME) <=
156*6dd72a43SMarcel Telka 	    MAX_AUTH_BYTES);
157*6dd72a43SMarcel Telka 	maxgidlen = (MAX_AUTH_BYTES - NFIELDS * BYTES_PER_XDR_UNIT -
158*6dd72a43SMarcel Telka 	    rounded_namelen) / BYTES_PER_XDR_UNIT;
159*6dd72a43SMarcel Telka 
1607c478bd9Sstevel@tonic-gate 	gidlen = crgetngroups(cr);
161*6dd72a43SMarcel Telka 	if (gidlen > maxgidlen)
1627c478bd9Sstevel@tonic-gate 		return (FALSE);
1637c478bd9Sstevel@tonic-gate 
164*6dd72a43SMarcel Telka 	credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen +
165*6dd72a43SMarcel Telka 	    gidlen * BYTES_PER_XDR_UNIT;
166*6dd72a43SMarcel Telka 	ASSERT(credsize <= MAX_AUTH_BYTES);
167*6dd72a43SMarcel Telka #undef	NFIELDS
168*6dd72a43SMarcel Telka 
169*6dd72a43SMarcel Telka 	/*
170*6dd72a43SMarcel Telka 	 * We need to marshal both cred and verf parts of the rpc_msg body
171*6dd72a43SMarcel Telka 	 * (call_body).  For the cred part we need to inline the auth_flavor
172*6dd72a43SMarcel Telka 	 * and the opaque auth body size.  Then we inline the credsize bytes of
173*6dd72a43SMarcel Telka 	 * the opaque auth body for the cred part.  Finally we add the
174*6dd72a43SMarcel Telka 	 * AUTH_NONE verifier (its auth_flavor and the opaque auth body size).
175*6dd72a43SMarcel Telka 	 */
176*6dd72a43SMarcel Telka 	ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize +
177*6dd72a43SMarcel Telka 	    2 * BYTES_PER_XDR_UNIT);
178*6dd72a43SMarcel Telka 	if (ptr != NULL) {
1797c478bd9Sstevel@tonic-gate 		/*
1807c478bd9Sstevel@tonic-gate 		 * We can do the fast path.
1817c478bd9Sstevel@tonic-gate 		 */
182*6dd72a43SMarcel Telka 		const gid_t *gp = crgetgroups(cr);
183*6dd72a43SMarcel Telka 
184*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, AUTH_LOOPBACK);	/* cred flavor */
185*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, credsize);	/* cred len */
186*6dd72a43SMarcel Telka 
1877c478bd9Sstevel@tonic-gate 		IXDR_PUT_INT32(ptr, gethrestime_sec());
188*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, namelen);
189*6dd72a43SMarcel Telka 		bcopy(nodename, ptr, namelen);
190*6dd72a43SMarcel Telka 		if ((rounded_namelen - namelen) > 0)
191*6dd72a43SMarcel Telka 			bzero((char *)ptr + namelen, rounded_namelen - namelen);
1927c478bd9Sstevel@tonic-gate 		ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
193*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, crgetuid(cr));
194*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, crgetgid(cr));
195*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, gidlen);
196*6dd72a43SMarcel Telka 		while (gidlen-- > 0)
197*6dd72a43SMarcel Telka 			IXDR_PUT_U_INT32(ptr, *gp++);
198*6dd72a43SMarcel Telka 
199*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, AUTH_NONE);	/* verf flavor */
200*6dd72a43SMarcel Telka 		IXDR_PUT_U_INT32(ptr, 0);		/* verf len */
201*6dd72a43SMarcel Telka 
2027c478bd9Sstevel@tonic-gate 		return (TRUE);
2037c478bd9Sstevel@tonic-gate 	}
204*6dd72a43SMarcel Telka 
2057c478bd9Sstevel@tonic-gate 	sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
206*6dd72a43SMarcel Telka 
2077c478bd9Sstevel@tonic-gate 	/*
208*6dd72a43SMarcel Telka 	 * Serialize the auth body data into sercred.
2097c478bd9Sstevel@tonic-gate 	 */
2107c478bd9Sstevel@tonic-gate 	xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
211*6dd72a43SMarcel Telka 	startpos = XDR_GETPOS(&xdrm);
212*6dd72a43SMarcel Telka 	if (!xdr_authloopback(&xdrm, cr)) {
2137c478bd9Sstevel@tonic-gate 		printf("authloopback_marshal: xdr_authloopback failed\n");
2147c478bd9Sstevel@tonic-gate 		ret = FALSE;
2157c478bd9Sstevel@tonic-gate 		goto done;
2167c478bd9Sstevel@tonic-gate 	}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	/*
219*6dd72a43SMarcel Telka 	 * Make opaque auth credentials to point at the serialized auth body
220*6dd72a43SMarcel Telka 	 * data.
2217c478bd9Sstevel@tonic-gate 	 */
222*6dd72a43SMarcel Telka 	auth->ah_cred.oa_base = sercred;
223*6dd72a43SMarcel Telka 	auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos;
224*6dd72a43SMarcel Telka 	ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES);
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	/*
227*6dd72a43SMarcel Telka 	 * serialize credentials and verifier (null)
2287c478bd9Sstevel@tonic-gate 	 */
2297c478bd9Sstevel@tonic-gate 	if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
2307c478bd9Sstevel@tonic-gate 	    (xdr_opaque_auth(xdrs, &(auth->ah_verf))))
2317c478bd9Sstevel@tonic-gate 		ret = TRUE;
2327c478bd9Sstevel@tonic-gate 	else
2337c478bd9Sstevel@tonic-gate 		ret = FALSE;
234*6dd72a43SMarcel Telka 
2357c478bd9Sstevel@tonic-gate done:
236*6dd72a43SMarcel Telka 	XDR_DESTROY(&xdrm);
2377c478bd9Sstevel@tonic-gate 	kmem_free(sercred, MAX_AUTH_BYTES);
238*6dd72a43SMarcel Telka 
2397c478bd9Sstevel@tonic-gate 	return (ret);
2407c478bd9Sstevel@tonic-gate }
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate /* ARGSUSED */
2437c478bd9Sstevel@tonic-gate static bool_t
authloopback_validate(AUTH * auth,struct opaque_auth * verf)2447c478bd9Sstevel@tonic-gate authloopback_validate(AUTH *auth, struct opaque_auth *verf)
2457c478bd9Sstevel@tonic-gate {
2467c478bd9Sstevel@tonic-gate 	return (TRUE);
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate /* ARGSUSED */
2507c478bd9Sstevel@tonic-gate static bool_t
authloopback_refresh(AUTH * auth,struct rpc_msg * msg,cred_t * cr)2517c478bd9Sstevel@tonic-gate authloopback_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	return (FALSE);
2547c478bd9Sstevel@tonic-gate }
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate static void
authloopback_destroy(register AUTH * auth)2577c478bd9Sstevel@tonic-gate authloopback_destroy(register AUTH *auth)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate 	kmem_cache_free(authloopback_cache, auth);
2607c478bd9Sstevel@tonic-gate }
261