174462Salfred/*	$NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $	*/
274462Salfred
31901Swollman/*
41901Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
51901Swollman * unrestricted use provided that this legend is included on all tape
61901Swollman * media and as a part of the software program in whole or part.  Users
71901Swollman * may copy or modify Sun RPC without charge, but are not authorized
81901Swollman * to license or distribute it to anyone else except as part of a product or
91901Swollman * program developed by the user.
108870Srgrimes *
111901Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
121901Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
131901Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
148870Srgrimes *
151901Swollman * Sun RPC is provided with no support and without any obligation on the
161901Swollman * part of Sun Microsystems, Inc. to assist in its use, correction,
171901Swollman * modification or enhancement.
181901Swollman *
191901Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
201901Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
211901Swollman * OR ANY PART THEREOF.
228870Srgrimes *
231901Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue
241901Swollman * or profits or other special, indirect and consequential damages, even if
251901Swollman * Sun has been advised of the possibility of such damages.
268870Srgrimes *
271901Swollman * Sun Microsystems, Inc.
281901Swollman * 2550 Garcia Avenue
291901Swollman * Mountain View, California  94043
301901Swollman */
311901Swollman
321901Swollman#if defined(LIBC_SCCS) && !defined(lint)
33136581Sobrienstatic char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
3474462Salfredstatic char *sccsid = "@(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";
351901Swollman#endif
3692990Sobrien#include <sys/cdefs.h>
3792990Sobrien__FBSDID("$FreeBSD$");
381901Swollman
391901Swollman/*
408870Srgrimes * auth_unix.c, Implements UNIX style authentication parameters.
418870Srgrimes *
421901Swollman * Copyright (C) 1984, Sun Microsystems, Inc.
431901Swollman *
441901Swollman * The system is very weak.  The client uses no encryption for it's
451901Swollman * credentials and only sends null verifiers.  The server sends backs
461901Swollman * null verifiers or optionally a verifier that suggests a new short hand
471901Swollman * for the credentials.
481901Swollman *
491901Swollman */
501901Swollman
5175094Siedowse#include "namespace.h"
5274462Salfred#include "reentrant.h"
5374462Salfred#include <sys/param.h>
5474462Salfred
5574462Salfred#include <assert.h>
5674462Salfred#include <err.h>
571901Swollman#include <stdio.h>
581901Swollman#include <stdlib.h>
5911666Sphk#include <unistd.h>
6011666Sphk#include <string.h>
611901Swollman
621901Swollman#include <rpc/types.h>
631901Swollman#include <rpc/xdr.h>
641901Swollman#include <rpc/auth.h>
651901Swollman#include <rpc/auth_unix.h>
6674462Salfred#include "un-namespace.h"
67156090Sdeischen#include "mt_misc.h"
681901Swollman
6974462Salfred/* auth_unix.c */
7074462Salfredstatic void authunix_nextverf (AUTH *);
7174462Salfredstatic bool_t authunix_marshal (AUTH *, XDR *);
7274462Salfredstatic bool_t authunix_validate (AUTH *, struct opaque_auth *);
7374462Salfredstatic bool_t authunix_refresh (AUTH *, void *);
7474462Salfredstatic void authunix_destroy (AUTH *);
7574462Salfredstatic void marshal_new_auth (AUTH *);
7674462Salfredstatic struct auth_ops *authunix_ops (void);
771901Swollman
781901Swollman/*
791901Swollman * This struct is pointed to by the ah_private field of an auth_handle.
801901Swollman */
811901Swollmanstruct audata {
821901Swollman	struct opaque_auth	au_origcred;	/* original credentials */
831901Swollman	struct opaque_auth	au_shcred;	/* short hand cred */
841901Swollman	u_long			au_shfaults;	/* short hand cache faults */
851901Swollman	char			au_marshed[MAX_AUTH_BYTES];
861901Swollman	u_int			au_mpos;	/* xdr pos at end of marshed */
871901Swollman};
881901Swollman#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
891901Swollman
901994Swollman/*
911901Swollman * Create a unix style authenticator.
921901Swollman * Returns an auth handle with the given stuff in it.
931901Swollman */
941901SwollmanAUTH *
951901Swollmanauthunix_create(machname, uid, gid, len, aup_gids)
961901Swollman	char *machname;
97241181Spfg	u_int uid;
98241181Spfg	u_int gid;
9974462Salfred	int len;
100241181Spfg	u_int *aup_gids;
1011901Swollman{
1021901Swollman	struct authunix_parms aup;
1031901Swollman	char mymem[MAX_AUTH_BYTES];
1041901Swollman	struct timeval now;
1051901Swollman	XDR xdrs;
10674462Salfred	AUTH *auth;
10774462Salfred	struct audata *au;
1081901Swollman
1091901Swollman	/*
1101901Swollman	 * Allocate and set up auth handle
1111901Swollman	 */
11274462Salfred	au = NULL;
11374462Salfred	auth = mem_alloc(sizeof(*auth));
11455206Speter#ifndef _KERNEL
1151901Swollman	if (auth == NULL) {
11674462Salfred		warnx("authunix_create: out of memory");
11774462Salfred		goto cleanup_authunix_create;
1181901Swollman	}
1191901Swollman#endif
12074462Salfred	au = mem_alloc(sizeof(*au));
12155206Speter#ifndef _KERNEL
1221901Swollman	if (au == NULL) {
12374462Salfred		warnx("authunix_create: out of memory");
12474462Salfred		goto cleanup_authunix_create;
1251901Swollman	}
1261901Swollman#endif
12774462Salfred	auth->ah_ops = authunix_ops();
1281901Swollman	auth->ah_private = (caddr_t)au;
1291901Swollman	auth->ah_verf = au->au_shcred = _null_auth;
1301901Swollman	au->au_shfaults = 0;
13174462Salfred	au->au_origcred.oa_base = NULL;
1321901Swollman
1331901Swollman	/*
1341901Swollman	 * fill in param struct from the given params
1351901Swollman	 */
13674462Salfred	(void)gettimeofday(&now, NULL);
1371901Swollman	aup.aup_time = now.tv_sec;
1381901Swollman	aup.aup_machname = machname;
1391901Swollman	aup.aup_uid = uid;
1401901Swollman	aup.aup_gid = gid;
14174462Salfred	aup.aup_len = (u_int)len;
1421901Swollman	aup.aup_gids = aup_gids;
1431901Swollman
1441901Swollman	/*
1451901Swollman	 * Serialize the parameters into origcred
1461901Swollman	 */
1471901Swollman	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
14874462Salfred	if (! xdr_authunix_parms(&xdrs, &aup))
1491901Swollman		abort();
1501901Swollman	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
1511901Swollman	au->au_origcred.oa_flavor = AUTH_UNIX;
15255206Speter#ifdef _KERNEL
1531901Swollman	au->au_origcred.oa_base = mem_alloc((u_int) len);
1541901Swollman#else
1551901Swollman	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
15674462Salfred		warnx("authunix_create: out of memory");
15774462Salfred		goto cleanup_authunix_create;
1581901Swollman	}
1591901Swollman#endif
16074462Salfred	memmove(au->au_origcred.oa_base, mymem, (size_t)len);
1611901Swollman
1621901Swollman	/*
1631901Swollman	 * set auth handle to reflect new cred.
1641901Swollman	 */
1651901Swollman	auth->ah_cred = au->au_origcred;
1661901Swollman	marshal_new_auth(auth);
1671901Swollman	return (auth);
16874462Salfred#ifndef _KERNEL
16974462Salfred cleanup_authunix_create:
17074462Salfred	if (auth)
17174462Salfred		mem_free(auth, sizeof(*auth));
17274462Salfred	if (au) {
17374462Salfred		if (au->au_origcred.oa_base)
17474462Salfred			mem_free(au->au_origcred.oa_base, (u_int)len);
17574462Salfred		mem_free(au, sizeof(*au));
17674462Salfred	}
17774462Salfred	return (NULL);
17874462Salfred#endif
1791901Swollman}
1801901Swollman
1811901Swollman/*
1821901Swollman * Returns an auth handle with parameters determined by doing lots of
1831901Swollman * syscalls.
1841901Swollman */
1851901SwollmanAUTH *
1861901Swollmanauthunix_create_default()
1871901Swollman{
188235143Skib	AUTH *auth;
189194494Sbrooks	int ngids;
190194494Sbrooks	long ngids_max;
19174462Salfred	char machname[MAXHOSTNAMELEN + 1];
19274462Salfred	uid_t uid;
19374462Salfred	gid_t gid;
194194494Sbrooks	gid_t *gids;
1951901Swollman
196194494Sbrooks	ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
197194494Sbrooks	gids = malloc(sizeof(gid_t) * ngids_max);
198194494Sbrooks	if (gids == NULL)
199194494Sbrooks		return (NULL);
200194494Sbrooks
20174462Salfred	if (gethostname(machname, sizeof machname) == -1)
2021901Swollman		abort();
20374462Salfred	machname[sizeof(machname) - 1] = 0;
20474462Salfred	uid = geteuid();
20574462Salfred	gid = getegid();
206194494Sbrooks	if ((ngids = getgroups(ngids_max, gids)) < 0)
2071901Swollman		abort();
208194494Sbrooks	if (ngids > NGRPS)
209194494Sbrooks		ngids = NGRPS;
210241181Spfg	/* XXX: interface problem; we should translate from uid_t and gid_t */
211241141Spfg	auth = authunix_create(machname, uid, gid, ngids, gids);
212235143Skib	free(gids);
213235143Skib	return (auth);
2141901Swollman}
2151901Swollman
2161901Swollman/*
2171901Swollman * authunix operations
2181901Swollman */
2191901Swollman
22074462Salfred/* ARGSUSED */
2211901Swollmanstatic void
2221901Swollmanauthunix_nextverf(auth)
2231901Swollman	AUTH *auth;
2241901Swollman{
2251901Swollman	/* no action necessary */
2261901Swollman}
2271901Swollman
2281901Swollmanstatic bool_t
2291901Swollmanauthunix_marshal(auth, xdrs)
2301901Swollman	AUTH *auth;
2311901Swollman	XDR *xdrs;
2321901Swollman{
23374462Salfred	struct audata *au;
2341901Swollman
23574462Salfred	assert(auth != NULL);
23674462Salfred	assert(xdrs != NULL);
23774462Salfred
23874462Salfred	au = AUTH_PRIVATE(auth);
2391901Swollman	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
2401901Swollman}
2411901Swollman
2421901Swollmanstatic bool_t
2431901Swollmanauthunix_validate(auth, verf)
24474462Salfred	AUTH *auth;
24574462Salfred	struct opaque_auth *verf;
2461901Swollman{
24774462Salfred	struct audata *au;
2481901Swollman	XDR xdrs;
2491901Swollman
25074462Salfred	assert(auth != NULL);
25174462Salfred	assert(verf != NULL);
25274462Salfred
25374462Salfred	if (verf->oa_flavor == AUTH_SHORT) {
2541901Swollman		au = AUTH_PRIVATE(auth);
25574462Salfred		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
25674462Salfred		    XDR_DECODE);
2571901Swollman
2581901Swollman		if (au->au_shcred.oa_base != NULL) {
2591901Swollman			mem_free(au->au_shcred.oa_base,
2601901Swollman			    au->au_shcred.oa_length);
2611901Swollman			au->au_shcred.oa_base = NULL;
2621901Swollman		}
2631901Swollman		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
2641901Swollman			auth->ah_cred = au->au_shcred;
2651901Swollman		} else {
2661901Swollman			xdrs.x_op = XDR_FREE;
2671901Swollman			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
2681901Swollman			au->au_shcred.oa_base = NULL;
2691901Swollman			auth->ah_cred = au->au_origcred;
2701901Swollman		}
2711901Swollman		marshal_new_auth(auth);
2721901Swollman	}
2731901Swollman	return (TRUE);
2741901Swollman}
2751901Swollman
2761901Swollmanstatic bool_t
27774462Salfredauthunix_refresh(AUTH *auth, void *dummy)
2781901Swollman{
27974462Salfred	struct audata *au = AUTH_PRIVATE(auth);
2801901Swollman	struct authunix_parms aup;
2811901Swollman	struct timeval now;
2821901Swollman	XDR xdrs;
28374462Salfred	int stat;
2841901Swollman
28574462Salfred	assert(auth != NULL);
28674462Salfred
2871901Swollman	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
2881901Swollman		/* there is no hope.  Punt */
2891901Swollman		return (FALSE);
2901901Swollman	}
2911901Swollman	au->au_shfaults ++;
2921901Swollman
2931901Swollman	/* first deserialize the creds back into a struct authunix_parms */
2941901Swollman	aup.aup_machname = NULL;
29574462Salfred	aup.aup_gids = NULL;
2961901Swollman	xdrmem_create(&xdrs, au->au_origcred.oa_base,
2971901Swollman	    au->au_origcred.oa_length, XDR_DECODE);
2981901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
2998870Srgrimes	if (! stat)
3001901Swollman		goto done;
3011901Swollman
3021901Swollman	/* update the time and serialize in place */
30374462Salfred	(void)gettimeofday(&now, NULL);
3041901Swollman	aup.aup_time = now.tv_sec;
3051901Swollman	xdrs.x_op = XDR_ENCODE;
3061901Swollman	XDR_SETPOS(&xdrs, 0);
3071901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
3081901Swollman	if (! stat)
3091901Swollman		goto done;
3101901Swollman	auth->ah_cred = au->au_origcred;
3111901Swollman	marshal_new_auth(auth);
3121901Swollmandone:
3131901Swollman	/* free the struct authunix_parms created by deserializing */
3141901Swollman	xdrs.x_op = XDR_FREE;
3151901Swollman	(void)xdr_authunix_parms(&xdrs, &aup);
3161901Swollman	XDR_DESTROY(&xdrs);
3171901Swollman	return (stat);
3181901Swollman}
3191901Swollman
3201901Swollmanstatic void
3211901Swollmanauthunix_destroy(auth)
32274462Salfred	AUTH *auth;
3231901Swollman{
32474462Salfred	struct audata *au;
3251901Swollman
32674462Salfred	assert(auth != NULL);
32774462Salfred
32874462Salfred	au = AUTH_PRIVATE(auth);
3291901Swollman	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
3301901Swollman
3311901Swollman	if (au->au_shcred.oa_base != NULL)
3321901Swollman		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
3331901Swollman
3341901Swollman	mem_free(auth->ah_private, sizeof(struct audata));
3351901Swollman
3361901Swollman	if (auth->ah_verf.oa_base != NULL)
3371901Swollman		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
3381901Swollman
33974462Salfred	mem_free(auth, sizeof(*auth));
3401901Swollman}
3411901Swollman
3421901Swollman/*
3431901Swollman * Marshals (pre-serializes) an auth struct.
3441901Swollman * sets private data, au_marshed and au_mpos
3451901Swollman */
34611666Sphkstatic void
3471901Swollmanmarshal_new_auth(auth)
34874462Salfred	AUTH *auth;
3491901Swollman{
35074462Salfred	XDR	xdr_stream;
35174462Salfred	XDR	*xdrs = &xdr_stream;
35274462Salfred	struct audata *au;
3531901Swollman
35474462Salfred	assert(auth != NULL);
35574462Salfred
35674462Salfred	au = AUTH_PRIVATE(auth);
3571901Swollman	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
3581901Swollman	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
35974462Salfred	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
36074462Salfred		warnx("auth_none.c - Fatal marshalling problem");
36174462Salfred	else
3621901Swollman		au->au_mpos = XDR_GETPOS(xdrs);
3631901Swollman	XDR_DESTROY(xdrs);
3641901Swollman}
36574462Salfred
36674462Salfredstatic struct auth_ops *
36774462Salfredauthunix_ops()
36874462Salfred{
36974462Salfred	static struct auth_ops ops;
37074462Salfred
37174462Salfred	/* VARIABLES PROTECTED BY ops_lock: ops */
37274462Salfred
37374462Salfred	mutex_lock(&ops_lock);
37474462Salfred	if (ops.ah_nextverf == NULL) {
37574462Salfred		ops.ah_nextverf = authunix_nextverf;
37674462Salfred		ops.ah_marshal = authunix_marshal;
37774462Salfred		ops.ah_validate = authunix_validate;
37874462Salfred		ops.ah_refresh = authunix_refresh;
37974462Salfred		ops.ah_destroy = authunix_destroy;
38074462Salfred	}
38174462Salfred	mutex_unlock(&ops_lock);
38274462Salfred	return (&ops);
38374462Salfred}
384