auth_unix.c revision 330897
1/*	$NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 2009, Sun Microsystems, Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * - Redistributions of source code must retain the above copyright notice,
12 *   this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 *   this list of conditions and the following disclaimer in the documentation
15 *   and/or other materials provided with the distribution.
16 * - Neither the name of Sun Microsystems, Inc. nor the names of its
17 *   contributors may be used to endorse or promote products derived
18 *   from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
35static char *sccsid = "@(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";
36#endif
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: stable/11/lib/libc/rpc/auth_unix.c 330897 2018-03-14 03:19:51Z eadler $");
39
40/*
41 * auth_unix.c, Implements UNIX style authentication parameters.
42 *
43 * Copyright (C) 1984, Sun Microsystems, Inc.
44 *
45 * The system is very weak.  The client uses no encryption for it's
46 * credentials and only sends null verifiers.  The server sends backs
47 * null verifiers or optionally a verifier that suggests a new short hand
48 * for the credentials.
49 *
50 */
51
52#include "namespace.h"
53#include "reentrant.h"
54#include <sys/param.h>
55
56#include <assert.h>
57#include <err.h>
58#include <stdio.h>
59#include <stdlib.h>
60#include <unistd.h>
61#include <string.h>
62
63#include <rpc/types.h>
64#include <rpc/xdr.h>
65#include <rpc/auth.h>
66#include <rpc/auth_unix.h>
67#include "un-namespace.h"
68#include "mt_misc.h"
69
70/* auth_unix.c */
71static void authunix_nextverf (AUTH *);
72static bool_t authunix_marshal (AUTH *, XDR *);
73static bool_t authunix_validate (AUTH *, struct opaque_auth *);
74static bool_t authunix_refresh (AUTH *, void *);
75static void authunix_destroy (AUTH *);
76static void marshal_new_auth (AUTH *);
77static struct auth_ops *authunix_ops (void);
78
79/*
80 * This struct is pointed to by the ah_private field of an auth_handle.
81 */
82struct audata {
83	struct opaque_auth	au_origcred;	/* original credentials */
84	struct opaque_auth	au_shcred;	/* short hand cred */
85	u_long			au_shfaults;	/* short hand cache faults */
86	char			au_marshed[MAX_AUTH_BYTES];
87	u_int			au_mpos;	/* xdr pos at end of marshed */
88};
89#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
90
91/*
92 * Create a unix style authenticator.
93 * Returns an auth handle with the given stuff in it.
94 */
95AUTH *
96authunix_create(char *machname, u_int uid, u_int gid, int len, u_int *aup_gids)
97{
98	struct authunix_parms aup;
99	char mymem[MAX_AUTH_BYTES];
100	struct timeval now;
101	XDR xdrs;
102	AUTH *auth;
103	struct audata *au;
104
105	/*
106	 * Allocate and set up auth handle
107	 */
108	au = NULL;
109	auth = mem_alloc(sizeof(*auth));
110#ifndef _KERNEL
111	if (auth == NULL) {
112		warnx("authunix_create: out of memory");
113		goto cleanup_authunix_create;
114	}
115#endif
116	au = mem_alloc(sizeof(*au));
117#ifndef _KERNEL
118	if (au == NULL) {
119		warnx("authunix_create: out of memory");
120		goto cleanup_authunix_create;
121	}
122#endif
123	auth->ah_ops = authunix_ops();
124	auth->ah_private = (caddr_t)au;
125	auth->ah_verf = au->au_shcred = _null_auth;
126	au->au_shfaults = 0;
127	au->au_origcred.oa_base = NULL;
128
129	/*
130	 * fill in param struct from the given params
131	 */
132	(void)gettimeofday(&now, NULL);
133	aup.aup_time = now.tv_sec;
134	aup.aup_machname = machname;
135	aup.aup_uid = uid;
136	aup.aup_gid = gid;
137	aup.aup_len = (u_int)len;
138	aup.aup_gids = aup_gids;
139
140	/*
141	 * Serialize the parameters into origcred
142	 */
143	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
144	if (! xdr_authunix_parms(&xdrs, &aup))
145		abort();
146	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
147	au->au_origcred.oa_flavor = AUTH_UNIX;
148#ifdef _KERNEL
149	au->au_origcred.oa_base = mem_alloc((u_int) len);
150#else
151	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
152		warnx("authunix_create: out of memory");
153		goto cleanup_authunix_create;
154	}
155#endif
156	memmove(au->au_origcred.oa_base, mymem, (size_t)len);
157
158	/*
159	 * set auth handle to reflect new cred.
160	 */
161	auth->ah_cred = au->au_origcred;
162	marshal_new_auth(auth);
163	return (auth);
164#ifndef _KERNEL
165 cleanup_authunix_create:
166	if (auth)
167		mem_free(auth, sizeof(*auth));
168	if (au) {
169		if (au->au_origcred.oa_base)
170			mem_free(au->au_origcred.oa_base, (u_int)len);
171		mem_free(au, sizeof(*au));
172	}
173	return (NULL);
174#endif
175}
176
177/*
178 * Returns an auth handle with parameters determined by doing lots of
179 * syscalls.
180 */
181AUTH *
182authunix_create_default(void)
183{
184	AUTH *auth;
185	int ngids;
186	long ngids_max;
187	char machname[MAXHOSTNAMELEN + 1];
188	uid_t uid;
189	gid_t gid;
190	gid_t *gids;
191
192	ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
193	gids = malloc(sizeof(gid_t) * ngids_max);
194	if (gids == NULL)
195		return (NULL);
196
197	if (gethostname(machname, sizeof machname) == -1)
198		abort();
199	machname[sizeof(machname) - 1] = 0;
200	uid = geteuid();
201	gid = getegid();
202	if ((ngids = getgroups(ngids_max, gids)) < 0)
203		abort();
204	if (ngids > NGRPS)
205		ngids = NGRPS;
206	/* XXX: interface problem; we should translate from uid_t and gid_t */
207	auth = authunix_create(machname, uid, gid, ngids, gids);
208	free(gids);
209	return (auth);
210}
211
212/*
213 * authunix operations
214 */
215
216/* ARGSUSED */
217static void
218authunix_nextverf(AUTH *auth)
219{
220	/* no action necessary */
221}
222
223static bool_t
224authunix_marshal(AUTH *auth, XDR *xdrs)
225{
226	struct audata *au;
227
228	assert(auth != NULL);
229	assert(xdrs != NULL);
230
231	au = AUTH_PRIVATE(auth);
232	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
233}
234
235static bool_t
236authunix_validate(AUTH *auth, struct opaque_auth *verf)
237{
238	struct audata *au;
239	XDR xdrs;
240
241	assert(auth != NULL);
242	assert(verf != NULL);
243
244	if (verf->oa_flavor == AUTH_SHORT) {
245		au = AUTH_PRIVATE(auth);
246		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
247		    XDR_DECODE);
248
249		if (au->au_shcred.oa_base != NULL) {
250			mem_free(au->au_shcred.oa_base,
251			    au->au_shcred.oa_length);
252			au->au_shcred.oa_base = NULL;
253		}
254		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
255			auth->ah_cred = au->au_shcred;
256		} else {
257			xdrs.x_op = XDR_FREE;
258			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
259			au->au_shcred.oa_base = NULL;
260			auth->ah_cred = au->au_origcred;
261		}
262		marshal_new_auth(auth);
263	}
264	return (TRUE);
265}
266
267static bool_t
268authunix_refresh(AUTH *auth, void *dummy)
269{
270	struct audata *au = AUTH_PRIVATE(auth);
271	struct authunix_parms aup;
272	struct timeval now;
273	XDR xdrs;
274	int stat;
275
276	assert(auth != NULL);
277
278	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
279		/* there is no hope.  Punt */
280		return (FALSE);
281	}
282	au->au_shfaults ++;
283
284	/* first deserialize the creds back into a struct authunix_parms */
285	aup.aup_machname = NULL;
286	aup.aup_gids = NULL;
287	xdrmem_create(&xdrs, au->au_origcred.oa_base,
288	    au->au_origcred.oa_length, XDR_DECODE);
289	stat = xdr_authunix_parms(&xdrs, &aup);
290	if (! stat)
291		goto done;
292
293	/* update the time and serialize in place */
294	(void)gettimeofday(&now, NULL);
295	aup.aup_time = now.tv_sec;
296	xdrs.x_op = XDR_ENCODE;
297	XDR_SETPOS(&xdrs, 0);
298	stat = xdr_authunix_parms(&xdrs, &aup);
299	if (! stat)
300		goto done;
301	auth->ah_cred = au->au_origcred;
302	marshal_new_auth(auth);
303done:
304	/* free the struct authunix_parms created by deserializing */
305	xdrs.x_op = XDR_FREE;
306	(void)xdr_authunix_parms(&xdrs, &aup);
307	XDR_DESTROY(&xdrs);
308	return (stat);
309}
310
311static void
312authunix_destroy(AUTH *auth)
313{
314	struct audata *au;
315
316	assert(auth != NULL);
317
318	au = AUTH_PRIVATE(auth);
319	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
320
321	if (au->au_shcred.oa_base != NULL)
322		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
323
324	mem_free(auth->ah_private, sizeof(struct audata));
325
326	if (auth->ah_verf.oa_base != NULL)
327		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
328
329	mem_free(auth, sizeof(*auth));
330}
331
332/*
333 * Marshals (pre-serializes) an auth struct.
334 * sets private data, au_marshed and au_mpos
335 */
336static void
337marshal_new_auth(AUTH *auth)
338{
339	XDR	xdr_stream;
340	XDR	*xdrs = &xdr_stream;
341	struct audata *au;
342
343	assert(auth != NULL);
344
345	au = AUTH_PRIVATE(auth);
346	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
347	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
348	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
349		warnx("auth_none.c - Fatal marshalling problem");
350	else
351		au->au_mpos = XDR_GETPOS(xdrs);
352	XDR_DESTROY(xdrs);
353}
354
355static struct auth_ops *
356authunix_ops(void)
357{
358	static struct auth_ops ops;
359
360	/* VARIABLES PROTECTED BY ops_lock: ops */
361
362	mutex_lock(&ops_lock);
363	if (ops.ah_nextverf == NULL) {
364		ops.ah_nextverf = authunix_nextverf;
365		ops.ah_marshal = authunix_marshal;
366		ops.ah_validate = authunix_validate;
367		ops.ah_refresh = authunix_refresh;
368		ops.ah_destroy = authunix_destroy;
369	}
370	mutex_unlock(&ops_lock);
371	return (&ops);
372}
373