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*0e91b739SMarcel Telka bool_t ret;
126*0e91b739SMarcel Telka uint32_t gidlen, credsize, namelen, rounded_namelen;
1277c478bd9Sstevel@tonic-gate int32_t *ptr;
128*0e91b739SMarcel Telka char *nodename = uts_nodename();
129*0e91b739SMarcel Telka uint32_t maxgidlen;
130*0e91b739SMarcel Telka uint_t startpos;
131*0e91b739SMarcel Telka
132*0e91b739SMarcel Telka ASSERT(xdrs->x_op == XDR_ENCODE);
133*0e91b739SMarcel Telka ASSERT(auth->ah_cred.oa_flavor == AUTH_LOOPBACK);
134*0e91b739SMarcel Telka ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE);
135*0e91b739SMarcel 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*0e91b739SMarcel Telka namelen = (uint32_t)strlen(nodename);
142*0e91b739SMarcel Telka if (namelen > MAX_MACHINE_NAME)
1437c478bd9Sstevel@tonic-gate return (FALSE);
1447c478bd9Sstevel@tonic-gate rounded_namelen = RNDUP(namelen);
145*0e91b739SMarcel Telka
146*0e91b739SMarcel Telka /*
147*0e91b739SMarcel Telka * NFIELDS is a number of the following fields we are going to encode:
148*0e91b739SMarcel Telka * - stamp
149*0e91b739SMarcel Telka * - strlen(machinename)
150*0e91b739SMarcel Telka * - uid
151*0e91b739SMarcel Telka * - gid
152*0e91b739SMarcel Telka * - the number of gids
153*0e91b739SMarcel Telka */
154*0e91b739SMarcel Telka #define NFIELDS 5
155*0e91b739SMarcel Telka CTASSERT(NFIELDS * BYTES_PER_XDR_UNIT + RNDUP(MAX_MACHINE_NAME) <=
156*0e91b739SMarcel Telka MAX_AUTH_BYTES);
157*0e91b739SMarcel Telka maxgidlen = (MAX_AUTH_BYTES - NFIELDS * BYTES_PER_XDR_UNIT -
158*0e91b739SMarcel Telka rounded_namelen) / BYTES_PER_XDR_UNIT;
159*0e91b739SMarcel Telka
160*0e91b739SMarcel Telka gidlen = crgetngroups(cr);
161*0e91b739SMarcel Telka if (gidlen > maxgidlen)
162*0e91b739SMarcel Telka return (FALSE);
163*0e91b739SMarcel Telka
164*0e91b739SMarcel Telka credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen +
165*0e91b739SMarcel Telka gidlen * BYTES_PER_XDR_UNIT;
166*0e91b739SMarcel Telka ASSERT(credsize <= MAX_AUTH_BYTES);
167*0e91b739SMarcel Telka #undef NFIELDS
168*0e91b739SMarcel Telka
169*0e91b739SMarcel Telka /*
170*0e91b739SMarcel Telka * We need to marshal both cred and verf parts of the rpc_msg body
171*0e91b739SMarcel Telka * (call_body). For the cred part we need to inline the auth_flavor
172*0e91b739SMarcel Telka * and the opaque auth body size. Then we inline the credsize bytes of
173*0e91b739SMarcel Telka * the opaque auth body for the cred part. Finally we add the
174*0e91b739SMarcel Telka * AUTH_NONE verifier (its auth_flavor and the opaque auth body size).
175*0e91b739SMarcel Telka */
176*0e91b739SMarcel Telka ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize +
177*0e91b739SMarcel Telka 2 * BYTES_PER_XDR_UNIT);
178*0e91b739SMarcel Telka if (ptr != NULL) {
1797c478bd9Sstevel@tonic-gate /*
1807c478bd9Sstevel@tonic-gate * We can do the fast path.
1817c478bd9Sstevel@tonic-gate */
182*0e91b739SMarcel Telka const gid_t *gp = crgetgroups(cr);
183*0e91b739SMarcel Telka
184*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, AUTH_LOOPBACK); /* cred flavor */
185*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, credsize); /* cred len */
186*0e91b739SMarcel Telka
1877c478bd9Sstevel@tonic-gate IXDR_PUT_INT32(ptr, gethrestime_sec());
188*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, namelen);
189*0e91b739SMarcel Telka bcopy(nodename, ptr, namelen);
190*0e91b739SMarcel Telka if ((rounded_namelen - namelen) > 0)
191*0e91b739SMarcel Telka bzero((char *)ptr + namelen, rounded_namelen - namelen);
1927c478bd9Sstevel@tonic-gate ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
193*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, crgetuid(cr));
194*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, crgetgid(cr));
195*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, gidlen);
196*0e91b739SMarcel Telka while (gidlen-- > 0)
197*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, *gp++);
198*0e91b739SMarcel Telka
199*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, AUTH_NONE); /* verf flavor */
200*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, 0); /* verf len */
201*0e91b739SMarcel Telka
2027c478bd9Sstevel@tonic-gate return (TRUE);
2037c478bd9Sstevel@tonic-gate }
204*0e91b739SMarcel Telka
2057c478bd9Sstevel@tonic-gate sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
206*0e91b739SMarcel Telka
2077c478bd9Sstevel@tonic-gate /*
208*0e91b739SMarcel Telka * Serialize the auth body data into sercred.
2097c478bd9Sstevel@tonic-gate */
2107c478bd9Sstevel@tonic-gate xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
211*0e91b739SMarcel Telka startpos = XDR_GETPOS(&xdrm);
212*0e91b739SMarcel 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*0e91b739SMarcel Telka * Make opaque auth credentials to point at the serialized auth body
220*0e91b739SMarcel Telka * data.
2217c478bd9Sstevel@tonic-gate */
222*0e91b739SMarcel Telka auth->ah_cred.oa_base = sercred;
223*0e91b739SMarcel Telka auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos;
224*0e91b739SMarcel Telka ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES);
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /*
227*0e91b739SMarcel 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*0e91b739SMarcel Telka
2357c478bd9Sstevel@tonic-gate done:
236*0e91b739SMarcel Telka XDR_DESTROY(&xdrm);
2377c478bd9Sstevel@tonic-gate kmem_free(sercred, MAX_AUTH_BYTES);
238*0e91b739SMarcel 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