174462Salfred/*	$NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $	*/
274462Salfred
3261057Smav/*-
4261057Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261057Smav * All rights reserved.
68870Srgrimes *
7261057Smav * Redistribution and use in source and binary forms, with or without
8261057Smav * modification, are permitted provided that the following conditions are met:
9261057Smav * - Redistributions of source code must retain the above copyright notice,
10261057Smav *   this list of conditions and the following disclaimer.
11261057Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261057Smav *   this list of conditions and the following disclaimer in the documentation
13261057Smav *   and/or other materials provided with the distribution.
14261057Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261057Smav *   contributors may be used to endorse or promote products derived
16261057Smav *   from this software without specific prior written permission.
17261057Smav *
18261057Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261057Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261057Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261057Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261057Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261057Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261057Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261057Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261057Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261057Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261057Smav * POSSIBILITY OF SUCH DAMAGE.
291901Swollman */
301901Swollman
311901Swollman#if defined(LIBC_SCCS) && !defined(lint)
32136581Sobrienstatic char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
3374462Salfredstatic char *sccsid = "@(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";
341901Swollman#endif
3592990Sobrien#include <sys/cdefs.h>
3692990Sobrien__FBSDID("$FreeBSD$");
371901Swollman
381901Swollman/*
398870Srgrimes * auth_unix.c, Implements UNIX style authentication parameters.
408870Srgrimes *
411901Swollman * Copyright (C) 1984, Sun Microsystems, Inc.
421901Swollman *
431901Swollman * The system is very weak.  The client uses no encryption for it's
441901Swollman * credentials and only sends null verifiers.  The server sends backs
451901Swollman * null verifiers or optionally a verifier that suggests a new short hand
461901Swollman * for the credentials.
471901Swollman *
481901Swollman */
491901Swollman
5075094Siedowse#include "namespace.h"
5174462Salfred#include "reentrant.h"
5274462Salfred#include <sys/param.h>
5374462Salfred
5474462Salfred#include <assert.h>
5574462Salfred#include <err.h>
561901Swollman#include <stdio.h>
571901Swollman#include <stdlib.h>
5811666Sphk#include <unistd.h>
5911666Sphk#include <string.h>
601901Swollman
611901Swollman#include <rpc/types.h>
621901Swollman#include <rpc/xdr.h>
631901Swollman#include <rpc/auth.h>
641901Swollman#include <rpc/auth_unix.h>
6574462Salfred#include "un-namespace.h"
66156090Sdeischen#include "mt_misc.h"
671901Swollman
6874462Salfred/* auth_unix.c */
6974462Salfredstatic void authunix_nextverf (AUTH *);
7074462Salfredstatic bool_t authunix_marshal (AUTH *, XDR *);
7174462Salfredstatic bool_t authunix_validate (AUTH *, struct opaque_auth *);
7274462Salfredstatic bool_t authunix_refresh (AUTH *, void *);
7374462Salfredstatic void authunix_destroy (AUTH *);
7474462Salfredstatic void marshal_new_auth (AUTH *);
7574462Salfredstatic struct auth_ops *authunix_ops (void);
761901Swollman
771901Swollman/*
781901Swollman * This struct is pointed to by the ah_private field of an auth_handle.
791901Swollman */
801901Swollmanstruct audata {
811901Swollman	struct opaque_auth	au_origcred;	/* original credentials */
821901Swollman	struct opaque_auth	au_shcred;	/* short hand cred */
831901Swollman	u_long			au_shfaults;	/* short hand cache faults */
841901Swollman	char			au_marshed[MAX_AUTH_BYTES];
851901Swollman	u_int			au_mpos;	/* xdr pos at end of marshed */
861901Swollman};
871901Swollman#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
881901Swollman
891994Swollman/*
901901Swollman * Create a unix style authenticator.
911901Swollman * Returns an auth handle with the given stuff in it.
921901Swollman */
931901SwollmanAUTH *
941901Swollmanauthunix_create(machname, uid, gid, len, aup_gids)
951901Swollman	char *machname;
96241309Spfg	u_int uid;
97241309Spfg	u_int gid;
9874462Salfred	int len;
99241309Spfg	u_int *aup_gids;
1001901Swollman{
1011901Swollman	struct authunix_parms aup;
1021901Swollman	char mymem[MAX_AUTH_BYTES];
1031901Swollman	struct timeval now;
1041901Swollman	XDR xdrs;
10574462Salfred	AUTH *auth;
10674462Salfred	struct audata *au;
1071901Swollman
1081901Swollman	/*
1091901Swollman	 * Allocate and set up auth handle
1101901Swollman	 */
11174462Salfred	au = NULL;
11274462Salfred	auth = mem_alloc(sizeof(*auth));
11355206Speter#ifndef _KERNEL
1141901Swollman	if (auth == NULL) {
11574462Salfred		warnx("authunix_create: out of memory");
11674462Salfred		goto cleanup_authunix_create;
1171901Swollman	}
1181901Swollman#endif
11974462Salfred	au = mem_alloc(sizeof(*au));
12055206Speter#ifndef _KERNEL
1211901Swollman	if (au == NULL) {
12274462Salfred		warnx("authunix_create: out of memory");
12374462Salfred		goto cleanup_authunix_create;
1241901Swollman	}
1251901Swollman#endif
12674462Salfred	auth->ah_ops = authunix_ops();
1271901Swollman	auth->ah_private = (caddr_t)au;
1281901Swollman	auth->ah_verf = au->au_shcred = _null_auth;
1291901Swollman	au->au_shfaults = 0;
13074462Salfred	au->au_origcred.oa_base = NULL;
1311901Swollman
1321901Swollman	/*
1331901Swollman	 * fill in param struct from the given params
1341901Swollman	 */
13574462Salfred	(void)gettimeofday(&now, NULL);
1361901Swollman	aup.aup_time = now.tv_sec;
1371901Swollman	aup.aup_machname = machname;
1381901Swollman	aup.aup_uid = uid;
1391901Swollman	aup.aup_gid = gid;
14074462Salfred	aup.aup_len = (u_int)len;
1411901Swollman	aup.aup_gids = aup_gids;
1421901Swollman
1431901Swollman	/*
1441901Swollman	 * Serialize the parameters into origcred
1451901Swollman	 */
1461901Swollman	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
14774462Salfred	if (! xdr_authunix_parms(&xdrs, &aup))
1481901Swollman		abort();
1491901Swollman	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
1501901Swollman	au->au_origcred.oa_flavor = AUTH_UNIX;
15155206Speter#ifdef _KERNEL
1521901Swollman	au->au_origcred.oa_base = mem_alloc((u_int) len);
1531901Swollman#else
1541901Swollman	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
15574462Salfred		warnx("authunix_create: out of memory");
15674462Salfred		goto cleanup_authunix_create;
1571901Swollman	}
1581901Swollman#endif
15974462Salfred	memmove(au->au_origcred.oa_base, mymem, (size_t)len);
1601901Swollman
1611901Swollman	/*
1621901Swollman	 * set auth handle to reflect new cred.
1631901Swollman	 */
1641901Swollman	auth->ah_cred = au->au_origcred;
1651901Swollman	marshal_new_auth(auth);
1661901Swollman	return (auth);
16774462Salfred#ifndef _KERNEL
16874462Salfred cleanup_authunix_create:
16974462Salfred	if (auth)
17074462Salfred		mem_free(auth, sizeof(*auth));
17174462Salfred	if (au) {
17274462Salfred		if (au->au_origcred.oa_base)
17374462Salfred			mem_free(au->au_origcred.oa_base, (u_int)len);
17474462Salfred		mem_free(au, sizeof(*au));
17574462Salfred	}
17674462Salfred	return (NULL);
17774462Salfred#endif
1781901Swollman}
1791901Swollman
1801901Swollman/*
1811901Swollman * Returns an auth handle with parameters determined by doing lots of
1821901Swollman * syscalls.
1831901Swollman */
1841901SwollmanAUTH *
1851901Swollmanauthunix_create_default()
1861901Swollman{
187235466Skib	AUTH *auth;
188194494Sbrooks	int ngids;
189194494Sbrooks	long ngids_max;
19074462Salfred	char machname[MAXHOSTNAMELEN + 1];
191241309Spfg	u_int uid;
192241309Spfg	u_int gid;
193241309Spfg	u_int *gids;
1941901Swollman
195194494Sbrooks	ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
196194494Sbrooks	gids = malloc(sizeof(gid_t) * ngids_max);
197194494Sbrooks	if (gids == NULL)
198194494Sbrooks		return (NULL);
199194494Sbrooks
20074462Salfred	if (gethostname(machname, sizeof machname) == -1)
2011901Swollman		abort();
20274462Salfred	machname[sizeof(machname) - 1] = 0;
20374462Salfred	uid = geteuid();
20474462Salfred	gid = getegid();
205194494Sbrooks	if ((ngids = getgroups(ngids_max, gids)) < 0)
2061901Swollman		abort();
207194494Sbrooks	if (ngids > NGRPS)
208194494Sbrooks		ngids = NGRPS;
209241309Spfg	/* XXX: interface problem; we should translate from uid_t and gid_t */
210241309Spfg	auth = authunix_create(machname, uid, gid, ngids, gids);
211235466Skib	free(gids);
212235466Skib	return (auth);
2131901Swollman}
2141901Swollman
2151901Swollman/*
2161901Swollman * authunix operations
2171901Swollman */
2181901Swollman
21974462Salfred/* ARGSUSED */
2201901Swollmanstatic void
2211901Swollmanauthunix_nextverf(auth)
2221901Swollman	AUTH *auth;
2231901Swollman{
2241901Swollman	/* no action necessary */
2251901Swollman}
2261901Swollman
2271901Swollmanstatic bool_t
2281901Swollmanauthunix_marshal(auth, xdrs)
2291901Swollman	AUTH *auth;
2301901Swollman	XDR *xdrs;
2311901Swollman{
23274462Salfred	struct audata *au;
2331901Swollman
23474462Salfred	assert(auth != NULL);
23574462Salfred	assert(xdrs != NULL);
23674462Salfred
23774462Salfred	au = AUTH_PRIVATE(auth);
2381901Swollman	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
2391901Swollman}
2401901Swollman
2411901Swollmanstatic bool_t
2421901Swollmanauthunix_validate(auth, verf)
24374462Salfred	AUTH *auth;
24474462Salfred	struct opaque_auth *verf;
2451901Swollman{
24674462Salfred	struct audata *au;
2471901Swollman	XDR xdrs;
2481901Swollman
24974462Salfred	assert(auth != NULL);
25074462Salfred	assert(verf != NULL);
25174462Salfred
25274462Salfred	if (verf->oa_flavor == AUTH_SHORT) {
2531901Swollman		au = AUTH_PRIVATE(auth);
25474462Salfred		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
25574462Salfred		    XDR_DECODE);
2561901Swollman
2571901Swollman		if (au->au_shcred.oa_base != NULL) {
2581901Swollman			mem_free(au->au_shcred.oa_base,
2591901Swollman			    au->au_shcred.oa_length);
2601901Swollman			au->au_shcred.oa_base = NULL;
2611901Swollman		}
2621901Swollman		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
2631901Swollman			auth->ah_cred = au->au_shcred;
2641901Swollman		} else {
2651901Swollman			xdrs.x_op = XDR_FREE;
2661901Swollman			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
2671901Swollman			au->au_shcred.oa_base = NULL;
2681901Swollman			auth->ah_cred = au->au_origcred;
2691901Swollman		}
2701901Swollman		marshal_new_auth(auth);
2711901Swollman	}
2721901Swollman	return (TRUE);
2731901Swollman}
2741901Swollman
2751901Swollmanstatic bool_t
27674462Salfredauthunix_refresh(AUTH *auth, void *dummy)
2771901Swollman{
27874462Salfred	struct audata *au = AUTH_PRIVATE(auth);
2791901Swollman	struct authunix_parms aup;
2801901Swollman	struct timeval now;
2811901Swollman	XDR xdrs;
28274462Salfred	int stat;
2831901Swollman
28474462Salfred	assert(auth != NULL);
28574462Salfred
2861901Swollman	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
2871901Swollman		/* there is no hope.  Punt */
2881901Swollman		return (FALSE);
2891901Swollman	}
2901901Swollman	au->au_shfaults ++;
2911901Swollman
2921901Swollman	/* first deserialize the creds back into a struct authunix_parms */
2931901Swollman	aup.aup_machname = NULL;
29474462Salfred	aup.aup_gids = NULL;
2951901Swollman	xdrmem_create(&xdrs, au->au_origcred.oa_base,
2961901Swollman	    au->au_origcred.oa_length, XDR_DECODE);
2971901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
2988870Srgrimes	if (! stat)
2991901Swollman		goto done;
3001901Swollman
3011901Swollman	/* update the time and serialize in place */
30274462Salfred	(void)gettimeofday(&now, NULL);
3031901Swollman	aup.aup_time = now.tv_sec;
3041901Swollman	xdrs.x_op = XDR_ENCODE;
3051901Swollman	XDR_SETPOS(&xdrs, 0);
3061901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
3071901Swollman	if (! stat)
3081901Swollman		goto done;
3091901Swollman	auth->ah_cred = au->au_origcred;
3101901Swollman	marshal_new_auth(auth);
3111901Swollmandone:
3121901Swollman	/* free the struct authunix_parms created by deserializing */
3131901Swollman	xdrs.x_op = XDR_FREE;
3141901Swollman	(void)xdr_authunix_parms(&xdrs, &aup);
3151901Swollman	XDR_DESTROY(&xdrs);
3161901Swollman	return (stat);
3171901Swollman}
3181901Swollman
3191901Swollmanstatic void
3201901Swollmanauthunix_destroy(auth)
32174462Salfred	AUTH *auth;
3221901Swollman{
32374462Salfred	struct audata *au;
3241901Swollman
32574462Salfred	assert(auth != NULL);
32674462Salfred
32774462Salfred	au = AUTH_PRIVATE(auth);
3281901Swollman	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
3291901Swollman
3301901Swollman	if (au->au_shcred.oa_base != NULL)
3311901Swollman		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
3321901Swollman
3331901Swollman	mem_free(auth->ah_private, sizeof(struct audata));
3341901Swollman
3351901Swollman	if (auth->ah_verf.oa_base != NULL)
3361901Swollman		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
3371901Swollman
33874462Salfred	mem_free(auth, sizeof(*auth));
3391901Swollman}
3401901Swollman
3411901Swollman/*
3421901Swollman * Marshals (pre-serializes) an auth struct.
3431901Swollman * sets private data, au_marshed and au_mpos
3441901Swollman */
34511666Sphkstatic void
3461901Swollmanmarshal_new_auth(auth)
34774462Salfred	AUTH *auth;
3481901Swollman{
34974462Salfred	XDR	xdr_stream;
35074462Salfred	XDR	*xdrs = &xdr_stream;
35174462Salfred	struct audata *au;
3521901Swollman
35374462Salfred	assert(auth != NULL);
35474462Salfred
35574462Salfred	au = AUTH_PRIVATE(auth);
3561901Swollman	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
3571901Swollman	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
35874462Salfred	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
35974462Salfred		warnx("auth_none.c - Fatal marshalling problem");
36074462Salfred	else
3611901Swollman		au->au_mpos = XDR_GETPOS(xdrs);
3621901Swollman	XDR_DESTROY(xdrs);
3631901Swollman}
36474462Salfred
36574462Salfredstatic struct auth_ops *
36674462Salfredauthunix_ops()
36774462Salfred{
36874462Salfred	static struct auth_ops ops;
36974462Salfred
37074462Salfred	/* VARIABLES PROTECTED BY ops_lock: ops */
37174462Salfred
37274462Salfred	mutex_lock(&ops_lock);
37374462Salfred	if (ops.ah_nextverf == NULL) {
37474462Salfred		ops.ah_nextverf = authunix_nextverf;
37574462Salfred		ops.ah_marshal = authunix_marshal;
37674462Salfred		ops.ah_validate = authunix_validate;
37774462Salfred		ops.ah_refresh = authunix_refresh;
37874462Salfred		ops.ah_destroy = authunix_destroy;
37974462Salfred	}
38074462Salfred	mutex_unlock(&ops_lock);
38174462Salfred	return (&ops);
38274462Salfred}
383