8106 authloopback_marshal() can violate the RPC specification
[unleashed/tickless.git] / usr / src / uts / common / rpc / sec / auth_kern.c
blob2c3286d35db074bb6cecd2fe020cae9d0245f060
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley 4.3 BSD
31 * under license from the Regents of the University of California.
35 * auth_kern.c, implements UNIX style authentication parameters in the kernel.
36 * Interfaces with svc_auth_unix on the server. See auth_unix.c for the user
37 * level implementation of unix auth.
41 #include <sys/param.h>
42 #include <sys/time.h>
43 #include <sys/types.h>
44 #include <sys/systm.h>
45 #include <sys/user.h>
46 #include <sys/proc.h>
47 #include <sys/cred.h>
48 #include <sys/kmem.h>
49 #include <sys/sysmacros.h>
50 #include <sys/cmn_err.h>
51 #include <sys/utsname.h>
53 #include <rpc/types.h>
54 #include <rpc/xdr.h>
55 #include <rpc/auth.h>
56 #include <rpc/auth_unix.h>
57 #include <rpc/clnt.h>
58 #include <rpc/rpc_msg.h>
61 * Unix authenticator operations vector
63 static void authkern_nextverf(AUTH *);
64 static bool_t authkern_marshal(AUTH *, XDR *, struct cred *);
65 static bool_t authkern_validate(AUTH *, struct opaque_auth *);
66 static bool_t authkern_refresh(AUTH *, struct rpc_msg *, cred_t *);
67 static void authkern_destroy(AUTH *);
69 static struct auth_ops auth_kern_ops = {
70 authkern_nextverf,
71 authkern_marshal,
72 authkern_validate,
73 authkern_refresh,
74 authkern_destroy,
75 authany_wrap,
76 authany_unwrap
80 * Create a kernel unix style authenticator.
81 * Returns an auth handle.
83 AUTH *
84 authkern_create(void)
87 * Allocate and set up auth handle
89 return (kmem_cache_alloc(authkern_cache, KM_SLEEP));
93 * The constructor of the authkern_cache.
95 /* ARGSUSED */
96 int
97 authkern_init(void *buf, void *cdrarg, int kmflags)
99 AUTH *auth = (AUTH *)buf;
101 auth->ah_ops = &auth_kern_ops;
102 auth->ah_cred.oa_flavor = AUTH_UNIX;
103 auth->ah_verf = _null_auth;
105 return (0);
109 * authkern operations
111 /* ARGSUSED */
112 static void
113 authkern_nextverf(AUTH *auth)
115 /* no action necessary */
118 static bool_t
119 authkern_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
121 char *sercred;
122 XDR xdrm;
123 bool_t ret;
124 uint32_t gidlen, credsize, namelen, rounded_namelen;
125 int32_t *ptr;
126 char *nodename = uts_nodename();
127 uint_t startpos;
129 ASSERT(xdrs->x_op == XDR_ENCODE);
130 ASSERT(auth->ah_cred.oa_flavor == AUTH_SYS);
131 ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE);
132 ASSERT(auth->ah_verf.oa_length == 0);
135 * First we try a fast path to get through
136 * this very common operation.
138 namelen = (uint32_t)strlen(nodename);
139 if (namelen > MAX_MACHINE_NAME)
140 return (FALSE);
141 rounded_namelen = RNDUP(namelen);
144 * NFIELDS is a number of the following fields we are going to encode:
145 * - stamp
146 * - strlen(machinename)
147 * - uid
148 * - gid
149 * - the number of gids
151 #define NFIELDS 5
152 CTASSERT((NFIELDS + NGRPS) * BYTES_PER_XDR_UNIT +
153 RNDUP(MAX_MACHINE_NAME) <= MAX_AUTH_BYTES);
155 gidlen = crgetngroups(cr);
156 if (gidlen > NGRPS)
157 gidlen = NGRPS;
159 credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen +
160 gidlen * BYTES_PER_XDR_UNIT;
161 ASSERT(credsize <= MAX_AUTH_BYTES);
162 #undef NFIELDS
165 * We need to marshal both cred and verf parts of the rpc_msg body
166 * (call_body). For the cred part we need to inline the auth_flavor
167 * and the opaque auth body size. Then we inline the credsize bytes of
168 * the opaque auth body for the cred part. Finally we add the
169 * AUTH_NONE verifier (its auth_flavor and the opaque auth body size).
171 ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize +
172 2 * BYTES_PER_XDR_UNIT);
173 if (ptr != NULL) {
175 * We can do the fast path.
177 const gid_t *gp = crgetgroups(cr);
179 IXDR_PUT_U_INT32(ptr, AUTH_SYS); /* cred flavor */
180 IXDR_PUT_U_INT32(ptr, credsize); /* cred len */
182 IXDR_PUT_INT32(ptr, gethrestime_sec());
183 IXDR_PUT_U_INT32(ptr, namelen);
184 bcopy(nodename, ptr, namelen);
185 if ((rounded_namelen - namelen) > 0)
186 bzero((char *)ptr + namelen, rounded_namelen - namelen);
187 ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
188 IXDR_PUT_U_INT32(ptr, crgetuid(cr));
189 IXDR_PUT_U_INT32(ptr, crgetgid(cr));
190 IXDR_PUT_U_INT32(ptr, gidlen);
191 while (gidlen-- > 0)
192 IXDR_PUT_U_INT32(ptr, *gp++);
194 IXDR_PUT_U_INT32(ptr, AUTH_NULL); /* verf flavor */
195 IXDR_PUT_U_INT32(ptr, 0); /* verf len */
197 return (TRUE);
200 sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
203 * Serialize the auth body data into sercred.
205 xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
206 startpos = XDR_GETPOS(&xdrm);
207 if (!xdr_authkern(&xdrm, cr)) {
208 printf("authkern_marshal: xdr_authkern failed\n");
209 ret = FALSE;
210 goto done;
214 * Make opaque auth credentials to point at the serialized auth body
215 * data.
217 auth->ah_cred.oa_base = sercred;
218 auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos;
219 ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES);
222 * serialize credentials and verifier (null)
224 if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
225 (xdr_opaque_auth(xdrs, &(auth->ah_verf))))
226 ret = TRUE;
227 else
228 ret = FALSE;
230 done:
231 XDR_DESTROY(&xdrm);
232 kmem_free(sercred, MAX_AUTH_BYTES);
234 return (ret);
237 /* ARGSUSED */
238 static bool_t
239 authkern_validate(AUTH *auth, struct opaque_auth *verf)
241 return (TRUE);
244 /* ARGSUSED */
245 static bool_t
246 authkern_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr)
248 return (FALSE);
251 static void
252 authkern_destroy(AUTH *auth)
254 kmem_cache_free(authkern_cache, auth);