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]
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>
43 #include <sys/types.h>
44 #include <sys/systm.h>
49 #include <sys/sysmacros.h>
50 #include <sys/cmn_err.h>
51 #include <sys/utsname.h>
53 #include <rpc/types.h>
56 #include <rpc/auth_unix.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
= {
80 * Create a kernel unix style authenticator.
81 * Returns an auth handle.
87 * Allocate and set up auth handle
89 return (kmem_cache_alloc(authkern_cache
, KM_SLEEP
));
93 * The constructor of the authkern_cache.
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
;
109 * authkern operations
113 authkern_nextverf(AUTH
*auth
)
115 /* no action necessary */
119 authkern_marshal(AUTH
*auth
, XDR
*xdrs
, struct cred
*cr
)
124 uint32_t gidlen
, credsize
, namelen
, rounded_namelen
;
126 char *nodename
= uts_nodename();
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
)
141 rounded_namelen
= RNDUP(namelen
);
144 * NFIELDS is a number of the following fields we are going to encode:
146 * - strlen(machinename)
149 * - the number of gids
152 CTASSERT((NFIELDS
+ NGRPS
) * BYTES_PER_XDR_UNIT
+
153 RNDUP(MAX_MACHINE_NAME
) <= MAX_AUTH_BYTES
);
155 gidlen
= crgetngroups(cr
);
159 credsize
= NFIELDS
* BYTES_PER_XDR_UNIT
+ rounded_namelen
+
160 gidlen
* BYTES_PER_XDR_UNIT
;
161 ASSERT(credsize
<= MAX_AUTH_BYTES
);
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
);
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
);
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 */
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");
214 * Make opaque auth credentials to point at the serialized auth body
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
))))
232 kmem_free(sercred
, MAX_AUTH_BYTES
);
239 authkern_validate(AUTH
*auth
, struct opaque_auth
*verf
)
246 authkern_refresh(AUTH
*auth
, struct rpc_msg
*msg
, cred_t
*cr
)
252 authkern_destroy(AUTH
*auth
)
254 kmem_cache_free(authkern_cache
, auth
);