auth_unix.c revision 194494
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: head/lib/libc/rpc/auth_unix.c 194494 2009-06-19 15:58:24Z brooks $");
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;
971901Swollman	int uid;
981901Swollman	int gid;
9974462Salfred	int len;
1001901Swollman	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{
188194494Sbrooks	int ngids;
189194494Sbrooks	long ngids_max;
19074462Salfred	char machname[MAXHOSTNAMELEN + 1];
19174462Salfred	uid_t uid;
19274462Salfred	gid_t gid;
193194494Sbrooks	gid_t *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;
20974462Salfred	/* XXX: interface problem; those should all have been unsigned */
210194494Sbrooks	return (authunix_create(machname, (int)uid, (int)gid, ngids,
21174462Salfred	    (int *)gids));
2121901Swollman}
2131901Swollman
2141901Swollman/*
2151901Swollman * authunix operations
2161901Swollman */
2171901Swollman
21874462Salfred/* ARGSUSED */
2191901Swollmanstatic void
2201901Swollmanauthunix_nextverf(auth)
2211901Swollman	AUTH *auth;
2221901Swollman{
2231901Swollman	/* no action necessary */
2241901Swollman}
2251901Swollman
2261901Swollmanstatic bool_t
2271901Swollmanauthunix_marshal(auth, xdrs)
2281901Swollman	AUTH *auth;
2291901Swollman	XDR *xdrs;
2301901Swollman{
23174462Salfred	struct audata *au;
2321901Swollman
23374462Salfred	assert(auth != NULL);
23474462Salfred	assert(xdrs != NULL);
23574462Salfred
23674462Salfred	au = AUTH_PRIVATE(auth);
2371901Swollman	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
2381901Swollman}
2391901Swollman
2401901Swollmanstatic bool_t
2411901Swollmanauthunix_validate(auth, verf)
24274462Salfred	AUTH *auth;
24374462Salfred	struct opaque_auth *verf;
2441901Swollman{
24574462Salfred	struct audata *au;
2461901Swollman	XDR xdrs;
2471901Swollman
24874462Salfred	assert(auth != NULL);
24974462Salfred	assert(verf != NULL);
25074462Salfred
25174462Salfred	if (verf->oa_flavor == AUTH_SHORT) {
2521901Swollman		au = AUTH_PRIVATE(auth);
25374462Salfred		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
25474462Salfred		    XDR_DECODE);
2551901Swollman
2561901Swollman		if (au->au_shcred.oa_base != NULL) {
2571901Swollman			mem_free(au->au_shcred.oa_base,
2581901Swollman			    au->au_shcred.oa_length);
2591901Swollman			au->au_shcred.oa_base = NULL;
2601901Swollman		}
2611901Swollman		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
2621901Swollman			auth->ah_cred = au->au_shcred;
2631901Swollman		} else {
2641901Swollman			xdrs.x_op = XDR_FREE;
2651901Swollman			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
2661901Swollman			au->au_shcred.oa_base = NULL;
2671901Swollman			auth->ah_cred = au->au_origcred;
2681901Swollman		}
2691901Swollman		marshal_new_auth(auth);
2701901Swollman	}
2711901Swollman	return (TRUE);
2721901Swollman}
2731901Swollman
2741901Swollmanstatic bool_t
27574462Salfredauthunix_refresh(AUTH *auth, void *dummy)
2761901Swollman{
27774462Salfred	struct audata *au = AUTH_PRIVATE(auth);
2781901Swollman	struct authunix_parms aup;
2791901Swollman	struct timeval now;
2801901Swollman	XDR xdrs;
28174462Salfred	int stat;
2821901Swollman
28374462Salfred	assert(auth != NULL);
28474462Salfred
2851901Swollman	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
2861901Swollman		/* there is no hope.  Punt */
2871901Swollman		return (FALSE);
2881901Swollman	}
2891901Swollman	au->au_shfaults ++;
2901901Swollman
2911901Swollman	/* first deserialize the creds back into a struct authunix_parms */
2921901Swollman	aup.aup_machname = NULL;
29374462Salfred	aup.aup_gids = NULL;
2941901Swollman	xdrmem_create(&xdrs, au->au_origcred.oa_base,
2951901Swollman	    au->au_origcred.oa_length, XDR_DECODE);
2961901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
2978870Srgrimes	if (! stat)
2981901Swollman		goto done;
2991901Swollman
3001901Swollman	/* update the time and serialize in place */
30174462Salfred	(void)gettimeofday(&now, NULL);
3021901Swollman	aup.aup_time = now.tv_sec;
3031901Swollman	xdrs.x_op = XDR_ENCODE;
3041901Swollman	XDR_SETPOS(&xdrs, 0);
3051901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
3061901Swollman	if (! stat)
3071901Swollman		goto done;
3081901Swollman	auth->ah_cred = au->au_origcred;
3091901Swollman	marshal_new_auth(auth);
3101901Swollmandone:
3111901Swollman	/* free the struct authunix_parms created by deserializing */
3121901Swollman	xdrs.x_op = XDR_FREE;
3131901Swollman	(void)xdr_authunix_parms(&xdrs, &aup);
3141901Swollman	XDR_DESTROY(&xdrs);
3151901Swollman	return (stat);
3161901Swollman}
3171901Swollman
3181901Swollmanstatic void
3191901Swollmanauthunix_destroy(auth)
32074462Salfred	AUTH *auth;
3211901Swollman{
32274462Salfred	struct audata *au;
3231901Swollman
32474462Salfred	assert(auth != NULL);
32574462Salfred
32674462Salfred	au = AUTH_PRIVATE(auth);
3271901Swollman	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
3281901Swollman
3291901Swollman	if (au->au_shcred.oa_base != NULL)
3301901Swollman		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
3311901Swollman
3321901Swollman	mem_free(auth->ah_private, sizeof(struct audata));
3331901Swollman
3341901Swollman	if (auth->ah_verf.oa_base != NULL)
3351901Swollman		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
3361901Swollman
33774462Salfred	mem_free(auth, sizeof(*auth));
3381901Swollman}
3391901Swollman
3401901Swollman/*
3411901Swollman * Marshals (pre-serializes) an auth struct.
3421901Swollman * sets private data, au_marshed and au_mpos
3431901Swollman */
34411666Sphkstatic void
3451901Swollmanmarshal_new_auth(auth)
34674462Salfred	AUTH *auth;
3471901Swollman{
34874462Salfred	XDR	xdr_stream;
34974462Salfred	XDR	*xdrs = &xdr_stream;
35074462Salfred	struct audata *au;
3511901Swollman
35274462Salfred	assert(auth != NULL);
35374462Salfred
35474462Salfred	au = AUTH_PRIVATE(auth);
3551901Swollman	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
3561901Swollman	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
35774462Salfred	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
35874462Salfred		warnx("auth_none.c - Fatal marshalling problem");
35974462Salfred	else
3601901Swollman		au->au_mpos = XDR_GETPOS(xdrs);
3611901Swollman	XDR_DESTROY(xdrs);
3621901Swollman}
36374462Salfred
36474462Salfredstatic struct auth_ops *
36574462Salfredauthunix_ops()
36674462Salfred{
36774462Salfred	static struct auth_ops ops;
36874462Salfred
36974462Salfred	/* VARIABLES PROTECTED BY ops_lock: ops */
37074462Salfred
37174462Salfred	mutex_lock(&ops_lock);
37274462Salfred	if (ops.ah_nextverf == NULL) {
37374462Salfred		ops.ah_nextverf = authunix_nextverf;
37474462Salfred		ops.ah_marshal = authunix_marshal;
37574462Salfred		ops.ah_validate = authunix_validate;
37674462Salfred		ops.ah_refresh = authunix_refresh;
37774462Salfred		ops.ah_destroy = authunix_destroy;
37874462Salfred	}
37974462Salfred	mutex_unlock(&ops_lock);
38074462Salfred	return (&ops);
38174462Salfred}
382