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
567dbe2beSCasper H.S. Dik * Common Development and Distribution License (the "License").
667dbe2beSCasper H.S. Dik * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2267dbe2beSCasper H.S. Dik * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
317c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California.
327c478bd9Sstevel@tonic-gate */
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate * auth_kern.c, implements UNIX style authentication parameters in the kernel.
367c478bd9Sstevel@tonic-gate * Interfaces with svc_auth_unix on the server. See auth_unix.c for the user
377c478bd9Sstevel@tonic-gate * level implementation of unix auth.
387c478bd9Sstevel@tonic-gate *
397c478bd9Sstevel@tonic-gate */
407c478bd9Sstevel@tonic-gate
417c478bd9Sstevel@tonic-gate #include <sys/param.h>
427c478bd9Sstevel@tonic-gate #include <sys/time.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/systm.h>
457c478bd9Sstevel@tonic-gate #include <sys/user.h>
467c478bd9Sstevel@tonic-gate #include <sys/proc.h>
477c478bd9Sstevel@tonic-gate #include <sys/cred.h>
487c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
497c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
507c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
517c478bd9Sstevel@tonic-gate #include <sys/utsname.h>
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate #include <rpc/types.h>
547c478bd9Sstevel@tonic-gate #include <rpc/xdr.h>
557c478bd9Sstevel@tonic-gate #include <rpc/auth.h>
567c478bd9Sstevel@tonic-gate #include <rpc/auth_unix.h>
577c478bd9Sstevel@tonic-gate #include <rpc/clnt.h>
587c478bd9Sstevel@tonic-gate #include <rpc/rpc_msg.h>
597c478bd9Sstevel@tonic-gate
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * Unix authenticator operations vector
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate static void authkern_nextverf(AUTH *);
647c478bd9Sstevel@tonic-gate static bool_t authkern_marshal(AUTH *, XDR *, struct cred *);
657c478bd9Sstevel@tonic-gate static bool_t authkern_validate(AUTH *, struct opaque_auth *);
667c478bd9Sstevel@tonic-gate static bool_t authkern_refresh(AUTH *, struct rpc_msg *, cred_t *);
677c478bd9Sstevel@tonic-gate static void authkern_destroy(AUTH *);
687c478bd9Sstevel@tonic-gate
697c478bd9Sstevel@tonic-gate static struct auth_ops auth_kern_ops = {
707c478bd9Sstevel@tonic-gate authkern_nextverf,
717c478bd9Sstevel@tonic-gate authkern_marshal,
727c478bd9Sstevel@tonic-gate authkern_validate,
737c478bd9Sstevel@tonic-gate authkern_refresh,
747c478bd9Sstevel@tonic-gate authkern_destroy,
757c478bd9Sstevel@tonic-gate authany_wrap,
767c478bd9Sstevel@tonic-gate authany_unwrap
777c478bd9Sstevel@tonic-gate };
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate * Create a kernel unix style authenticator.
817c478bd9Sstevel@tonic-gate * Returns an auth handle.
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate AUTH *
authkern_create(void)847c478bd9Sstevel@tonic-gate authkern_create(void)
857c478bd9Sstevel@tonic-gate {
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate * Allocate and set up auth handle
887c478bd9Sstevel@tonic-gate */
897c478bd9Sstevel@tonic-gate return (kmem_cache_alloc(authkern_cache, KM_SLEEP));
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate * The constructor of the authkern_cache.
947c478bd9Sstevel@tonic-gate */
957c478bd9Sstevel@tonic-gate /* ARGSUSED */
967c478bd9Sstevel@tonic-gate int
authkern_init(void * buf,void * cdrarg,int kmflags)977c478bd9Sstevel@tonic-gate authkern_init(void *buf, void *cdrarg, int kmflags)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate AUTH *auth = (AUTH *)buf;
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate auth->ah_ops = &auth_kern_ops;
1027c478bd9Sstevel@tonic-gate auth->ah_cred.oa_flavor = AUTH_UNIX;
1037c478bd9Sstevel@tonic-gate auth->ah_verf = _null_auth;
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate return (0);
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * authkern operations
1107c478bd9Sstevel@tonic-gate */
1117c478bd9Sstevel@tonic-gate /* ARGSUSED */
1127c478bd9Sstevel@tonic-gate static void
authkern_nextverf(AUTH * auth)1137c478bd9Sstevel@tonic-gate authkern_nextverf(AUTH *auth)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate /* no action necessary */
1167c478bd9Sstevel@tonic-gate }
1177c478bd9Sstevel@tonic-gate
1187c478bd9Sstevel@tonic-gate static bool_t
authkern_marshal(AUTH * auth,XDR * xdrs,struct cred * cr)1197c478bd9Sstevel@tonic-gate authkern_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
1207c478bd9Sstevel@tonic-gate {
1217c478bd9Sstevel@tonic-gate char *sercred;
1227c478bd9Sstevel@tonic-gate XDR xdrm;
123*ecb6a1c2SMarcel Telka bool_t ret;
124*ecb6a1c2SMarcel Telka uint32_t gidlen, credsize, namelen, rounded_namelen;
1257c478bd9Sstevel@tonic-gate int32_t *ptr;
1267c478bd9Sstevel@tonic-gate char *nodename = uts_nodename();
127*ecb6a1c2SMarcel Telka uint_t startpos;
128*ecb6a1c2SMarcel Telka
129*ecb6a1c2SMarcel Telka ASSERT(xdrs->x_op == XDR_ENCODE);
130*ecb6a1c2SMarcel Telka ASSERT(auth->ah_cred.oa_flavor == AUTH_SYS);
131*ecb6a1c2SMarcel Telka ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE);
132*ecb6a1c2SMarcel Telka ASSERT(auth->ah_verf.oa_length == 0);
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate /*
1357c478bd9Sstevel@tonic-gate * First we try a fast path to get through
1367c478bd9Sstevel@tonic-gate * this very common operation.
1377c478bd9Sstevel@tonic-gate */
138*ecb6a1c2SMarcel Telka namelen = (uint32_t)strlen(nodename);
139*ecb6a1c2SMarcel Telka if (namelen > MAX_MACHINE_NAME)
140*ecb6a1c2SMarcel Telka return (FALSE);
141*ecb6a1c2SMarcel Telka rounded_namelen = RNDUP(namelen);
142*ecb6a1c2SMarcel Telka
143*ecb6a1c2SMarcel Telka /*
144*ecb6a1c2SMarcel Telka * NFIELDS is a number of the following fields we are going to encode:
145*ecb6a1c2SMarcel Telka * - stamp
146*ecb6a1c2SMarcel Telka * - strlen(machinename)
147*ecb6a1c2SMarcel Telka * - uid
148*ecb6a1c2SMarcel Telka * - gid
149*ecb6a1c2SMarcel Telka * - the number of gids
150*ecb6a1c2SMarcel Telka */
151*ecb6a1c2SMarcel Telka #define NFIELDS 5
152*ecb6a1c2SMarcel Telka CTASSERT((NFIELDS + NGRPS) * BYTES_PER_XDR_UNIT +
153*ecb6a1c2SMarcel Telka RNDUP(MAX_MACHINE_NAME) <= MAX_AUTH_BYTES);
154*ecb6a1c2SMarcel Telka
1557c478bd9Sstevel@tonic-gate gidlen = crgetngroups(cr);
1567c478bd9Sstevel@tonic-gate if (gidlen > NGRPS)
15767dbe2beSCasper H.S. Dik gidlen = NGRPS;
1587c478bd9Sstevel@tonic-gate
159*ecb6a1c2SMarcel Telka credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen +
160*ecb6a1c2SMarcel Telka gidlen * BYTES_PER_XDR_UNIT;
161*ecb6a1c2SMarcel Telka ASSERT(credsize <= MAX_AUTH_BYTES);
162*ecb6a1c2SMarcel Telka #undef NFIELDS
163*ecb6a1c2SMarcel Telka
164*ecb6a1c2SMarcel Telka /*
165*ecb6a1c2SMarcel Telka * We need to marshal both cred and verf parts of the rpc_msg body
166*ecb6a1c2SMarcel Telka * (call_body). For the cred part we need to inline the auth_flavor
167*ecb6a1c2SMarcel Telka * and the opaque auth body size. Then we inline the credsize bytes of
168*ecb6a1c2SMarcel Telka * the opaque auth body for the cred part. Finally we add the
169*ecb6a1c2SMarcel Telka * AUTH_NONE verifier (its auth_flavor and the opaque auth body size).
170*ecb6a1c2SMarcel Telka */
171*ecb6a1c2SMarcel Telka ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize +
172*ecb6a1c2SMarcel Telka 2 * BYTES_PER_XDR_UNIT);
173*ecb6a1c2SMarcel Telka if (ptr != NULL) {
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * We can do the fast path.
1767c478bd9Sstevel@tonic-gate */
177*ecb6a1c2SMarcel Telka const gid_t *gp = crgetgroups(cr);
178*ecb6a1c2SMarcel Telka
179*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, AUTH_SYS); /* cred flavor */
180*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, credsize); /* cred len */
181*ecb6a1c2SMarcel Telka
1827c478bd9Sstevel@tonic-gate IXDR_PUT_INT32(ptr, gethrestime_sec());
183*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, namelen);
184*ecb6a1c2SMarcel Telka bcopy(nodename, ptr, namelen);
185*ecb6a1c2SMarcel Telka if ((rounded_namelen - namelen) > 0)
186*ecb6a1c2SMarcel Telka bzero((char *)ptr + namelen, rounded_namelen - namelen);
1877c478bd9Sstevel@tonic-gate ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
188*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, crgetuid(cr));
189*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, crgetgid(cr));
190*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, gidlen);
191*ecb6a1c2SMarcel Telka while (gidlen-- > 0)
192*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, *gp++);
193*ecb6a1c2SMarcel Telka
194*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, AUTH_NULL); /* verf flavor */
195*ecb6a1c2SMarcel Telka IXDR_PUT_U_INT32(ptr, 0); /* verf len */
196*ecb6a1c2SMarcel Telka
1977c478bd9Sstevel@tonic-gate return (TRUE);
1987c478bd9Sstevel@tonic-gate }
199*ecb6a1c2SMarcel Telka
2007c478bd9Sstevel@tonic-gate sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
201*ecb6a1c2SMarcel Telka
2027c478bd9Sstevel@tonic-gate /*
203*ecb6a1c2SMarcel Telka * Serialize the auth body data into sercred.
2047c478bd9Sstevel@tonic-gate */
2057c478bd9Sstevel@tonic-gate xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
206*ecb6a1c2SMarcel Telka startpos = XDR_GETPOS(&xdrm);
207*ecb6a1c2SMarcel Telka if (!xdr_authkern(&xdrm, cr)) {
2087c478bd9Sstevel@tonic-gate printf("authkern_marshal: xdr_authkern failed\n");
2097c478bd9Sstevel@tonic-gate ret = FALSE;
2107c478bd9Sstevel@tonic-gate goto done;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate /*
214*ecb6a1c2SMarcel Telka * Make opaque auth credentials to point at the serialized auth body
215*ecb6a1c2SMarcel Telka * data.
2167c478bd9Sstevel@tonic-gate */
217*ecb6a1c2SMarcel Telka auth->ah_cred.oa_base = sercred;
218*ecb6a1c2SMarcel Telka auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos;
219*ecb6a1c2SMarcel Telka ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES);
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate /*
222*ecb6a1c2SMarcel Telka * serialize credentials and verifier (null)
2237c478bd9Sstevel@tonic-gate */
2247c478bd9Sstevel@tonic-gate if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
2257c478bd9Sstevel@tonic-gate (xdr_opaque_auth(xdrs, &(auth->ah_verf))))
2267c478bd9Sstevel@tonic-gate ret = TRUE;
2277c478bd9Sstevel@tonic-gate else
2287c478bd9Sstevel@tonic-gate ret = FALSE;
229*ecb6a1c2SMarcel Telka
2307c478bd9Sstevel@tonic-gate done:
231*ecb6a1c2SMarcel Telka XDR_DESTROY(&xdrm);
2327c478bd9Sstevel@tonic-gate kmem_free(sercred, MAX_AUTH_BYTES);
233*ecb6a1c2SMarcel Telka
2347c478bd9Sstevel@tonic-gate return (ret);
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /* ARGSUSED */
2387c478bd9Sstevel@tonic-gate static bool_t
authkern_validate(AUTH * auth,struct opaque_auth * verf)2397c478bd9Sstevel@tonic-gate authkern_validate(AUTH *auth, struct opaque_auth *verf)
2407c478bd9Sstevel@tonic-gate {
2417c478bd9Sstevel@tonic-gate return (TRUE);
2427c478bd9Sstevel@tonic-gate }
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate /* ARGSUSED */
2457c478bd9Sstevel@tonic-gate static bool_t
authkern_refresh(AUTH * auth,struct rpc_msg * msg,cred_t * cr)2467c478bd9Sstevel@tonic-gate authkern_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr)
2477c478bd9Sstevel@tonic-gate {
2487c478bd9Sstevel@tonic-gate return (FALSE);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate
2517c478bd9Sstevel@tonic-gate static void
authkern_destroy(AUTH * auth)2527c478bd9Sstevel@tonic-gate authkern_destroy(AUTH *auth)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate kmem_cache_free(authkern_cache, auth);
2557c478bd9Sstevel@tonic-gate }
256