2 * Copyright (c) 2009, Sun Microsystems, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
32 * auth_unix.c, Implements UNIX style authentication parameters.
34 * Copyright (C) 1984, Sun Microsystems, Inc.
36 * The system is very weak. The client uses no encryption for it's
37 * credentials and only sends null verifiers. The server sends backs
38 * null verifiers or optionally a verifier that suggests a new short hand
39 * for the credentials.
43 #include <reentrant.h>
44 #include <sys/param.h>
55 #include <rpc/types.h>
58 #include <rpc/auth_unix.h>
61 static void authunix_nextverf (AUTH *);
62 static bool_t authunix_marshal (AUTH *, XDR *);
63 static bool_t authunix_validate (AUTH *, struct opaque_auth *);
64 static bool_t authunix_refresh (AUTH *, void *);
65 static void authunix_destroy (AUTH *);
66 static void marshal_new_auth (AUTH *);
67 static struct auth_ops *authunix_ops (void);
70 * This struct is pointed to by the ah_private field of an auth_handle.
73 struct opaque_auth au_origcred; /* original credentials */
74 struct opaque_auth au_shcred; /* short hand cred */
75 u_long au_shfaults; /* short hand cache faults */
76 char au_marshed[MAX_AUTH_BYTES];
77 u_int au_mpos; /* xdr pos at end of marshed */
79 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
82 * Create a unix style authenticator.
83 * Returns an auth handle with the given stuff in it.
86 authunix_create(machname, uid, gid, len, aup_gids)
93 struct authunix_parms aup;
94 char mymem[MAX_AUTH_BYTES];
100 memset(&rpc_createerr, 0, sizeof(rpc_createerr));
103 * Allocate and set up auth handle
106 auth = mem_alloc(sizeof(*auth));
109 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
110 rpc_createerr.cf_error.re_errno = ENOMEM;
111 goto cleanup_authunix_create;
114 au = mem_alloc(sizeof(*au));
117 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
118 rpc_createerr.cf_error.re_errno = ENOMEM;
119 goto cleanup_authunix_create;
122 auth->ah_ops = authunix_ops();
123 auth->ah_private = (caddr_t)au;
124 auth->ah_verf = au->au_shcred = _null_auth;
126 au->au_origcred.oa_base = NULL;
129 * fill in param struct from the given params
131 (void)gettimeofday(&now, NULL);
132 aup.aup_time = now.tv_sec;
133 aup.aup_machname = machname;
136 aup.aup_len = (u_int)len;
137 aup.aup_gids = aup_gids;
140 * Serialize the parameters into origcred
142 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
143 if (!xdr_authunix_parms(&xdrs, &aup)) {
144 rpc_createerr.cf_stat = RPC_CANTENCODEARGS;
145 goto cleanup_authunix_create;
147 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
148 au->au_origcred.oa_flavor = AUTH_UNIX;
150 au->au_origcred.oa_base = mem_alloc((u_int) len);
152 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
153 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
154 rpc_createerr.cf_error.re_errno = ENOMEM;
155 goto cleanup_authunix_create;
158 memmove(au->au_origcred.oa_base, mymem, (size_t)len);
161 * set auth handle to reflect new cred.
163 auth->ah_cred = au->au_origcred;
164 marshal_new_auth(auth);
165 auth_get(auth); /* Reference for caller */
168 cleanup_authunix_create:
170 mem_free(auth, sizeof(*auth));
172 if (au->au_origcred.oa_base)
173 mem_free(au->au_origcred.oa_base, (u_int)len);
174 mem_free(au, sizeof(*au));
181 * Returns an auth handle with parameters determined by doing lots of
185 authunix_create_default()
188 char machname[MAXHOSTNAMELEN + 1];
193 memset(&rpc_createerr, 0, sizeof(rpc_createerr));
195 if (gethostname(machname, sizeof machname) == -1) {
196 rpc_createerr.cf_error.re_errno = errno;
199 machname[sizeof(machname) - 1] = 0;
203 /* According to glibc comments, an intervening setgroups(2)
204 * call can increase the number of supplemental groups between
205 * these two getgroups(2) calls. */
207 len = getgroups(0, NULL);
209 rpc_createerr.cf_error.re_errno = errno;
213 /* Bump allocation size. A zero allocation size may result in a
214 * NULL calloc(3) result, which is not reliably distinguishable
215 * from a memory allocation error. */
216 gids = calloc(len + 1, sizeof(gid_t));
218 rpc_createerr.cf_error.re_errno = ENOMEM;
222 len = getgroups(len, gids);
224 rpc_createerr.cf_error.re_errno = errno;
226 if (rpc_createerr.cf_error.re_errno == EINVAL) {
227 rpc_createerr.cf_error.re_errno = 0;
234 * AUTH_UNIX sends on the wire only the first NGRPS groups in the
235 * supplemental groups list.
240 /* XXX: interface problem; those should all have been unsigned */
241 result = authunix_create(machname, uid, gid, len, gids);
246 rpc_createerr.cf_stat = RPC_SYSTEMERROR;
251 * authunix operations
256 authunix_nextverf(auth)
259 /* no action necessary */
263 authunix_marshal(auth, xdrs)
269 assert(auth != NULL);
270 assert(xdrs != NULL);
272 au = AUTH_PRIVATE(auth);
273 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
277 authunix_validate(auth, verf)
279 struct opaque_auth *verf;
284 assert(auth != NULL);
285 assert(verf != NULL);
287 if (verf->oa_flavor == AUTH_SHORT) {
288 au = AUTH_PRIVATE(auth);
289 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
292 if (au->au_shcred.oa_base != NULL) {
293 mem_free(au->au_shcred.oa_base,
294 au->au_shcred.oa_length);
295 au->au_shcred.oa_base = NULL;
297 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
298 auth->ah_cred = au->au_shcred;
300 xdrs.x_op = XDR_FREE;
301 (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
302 au->au_shcred.oa_base = NULL;
303 auth->ah_cred = au->au_origcred;
305 marshal_new_auth(auth);
311 authunix_refresh(AUTH *auth, void *dummy)
313 struct audata *au = AUTH_PRIVATE(auth);
314 struct authunix_parms aup;
319 assert(auth != NULL);
321 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
322 /* there is no hope. Punt */
327 /* first deserialize the creds back into a struct authunix_parms */
328 aup.aup_machname = NULL;
330 xdrmem_create(&xdrs, au->au_origcred.oa_base,
331 au->au_origcred.oa_length, XDR_DECODE);
332 stat = xdr_authunix_parms(&xdrs, &aup);
336 /* update the time and serialize in place */
337 (void)gettimeofday(&now, NULL);
338 aup.aup_time = now.tv_sec;
339 xdrs.x_op = XDR_ENCODE;
340 XDR_SETPOS(&xdrs, 0);
341 stat = xdr_authunix_parms(&xdrs, &aup);
344 auth->ah_cred = au->au_origcred;
345 marshal_new_auth(auth);
347 /* free the struct authunix_parms created by deserializing */
348 xdrs.x_op = XDR_FREE;
349 (void)xdr_authunix_parms(&xdrs, &aup);
355 authunix_destroy(auth)
360 assert(auth != NULL);
362 au = AUTH_PRIVATE(auth);
363 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
365 if (au->au_shcred.oa_base != NULL)
366 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
368 mem_free(auth->ah_private, sizeof(struct audata));
370 if (auth->ah_verf.oa_base != NULL)
371 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
373 mem_free(auth, sizeof(*auth));
377 * Marshals (pre-serializes) an auth struct.
378 * sets private data, au_marshed and au_mpos
381 marshal_new_auth(auth)
385 XDR *xdrs = &xdr_stream;
388 assert(auth != NULL);
390 au = AUTH_PRIVATE(auth);
391 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
392 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
393 (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
394 warnx("auth_none.c - Fatal marshalling problem");
396 au->au_mpos = XDR_GETPOS(xdrs);
401 authunix_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere)
403 return ((*xfunc)(xdrs, xwhere));
406 static struct auth_ops *
409 static struct auth_ops ops;
410 extern mutex_t ops_lock;
412 /* VARIABLES PROTECTED BY ops_lock: ops */
414 mutex_lock(&ops_lock);
415 if (ops.ah_nextverf == NULL) {
416 ops.ah_nextverf = authunix_nextverf;
417 ops.ah_marshal = authunix_marshal;
418 ops.ah_validate = authunix_validate;
419 ops.ah_refresh = authunix_refresh;
420 ops.ah_destroy = authunix_destroy;
421 ops.ah_wrap = authunix_wrap;
422 ops.ah_unwrap = authunix_wrap;
424 mutex_unlock(&ops_lock);