174462Salfred/*	$NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $	*/
274462Salfred
3261046Smav/*-
4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc.
5261046Smav * All rights reserved.
68870Srgrimes *
7261046Smav * Redistribution and use in source and binary forms, with or without
8261046Smav * modification, are permitted provided that the following conditions are met:
9261046Smav * - Redistributions of source code must retain the above copyright notice,
10261046Smav *   this list of conditions and the following disclaimer.
11261046Smav * - Redistributions in binary form must reproduce the above copyright notice,
12261046Smav *   this list of conditions and the following disclaimer in the documentation
13261046Smav *   and/or other materials provided with the distribution.
14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its
15261046Smav *   contributors may be used to endorse or promote products derived
16261046Smav *   from this software without specific prior written permission.
17261046Smav *
18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28261046Smav * 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: stable/10/lib/libc/rpc/auth_unix.c 309487 2016-12-03 17:27:28Z ngie $");
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 *
94309487Sngieauthunix_create(char *machname, u_int uid, u_int gid, int len, u_int *aup_gids)
951901Swollman{
961901Swollman	struct authunix_parms aup;
971901Swollman	char mymem[MAX_AUTH_BYTES];
981901Swollman	struct timeval now;
991901Swollman	XDR xdrs;
10074462Salfred	AUTH *auth;
10174462Salfred	struct audata *au;
1021901Swollman
1031901Swollman	/*
1041901Swollman	 * Allocate and set up auth handle
1051901Swollman	 */
10674462Salfred	au = NULL;
10774462Salfred	auth = mem_alloc(sizeof(*auth));
10855206Speter#ifndef _KERNEL
1091901Swollman	if (auth == NULL) {
11074462Salfred		warnx("authunix_create: out of memory");
11174462Salfred		goto cleanup_authunix_create;
1121901Swollman	}
1131901Swollman#endif
11474462Salfred	au = mem_alloc(sizeof(*au));
11555206Speter#ifndef _KERNEL
1161901Swollman	if (au == NULL) {
11774462Salfred		warnx("authunix_create: out of memory");
11874462Salfred		goto cleanup_authunix_create;
1191901Swollman	}
1201901Swollman#endif
12174462Salfred	auth->ah_ops = authunix_ops();
1221901Swollman	auth->ah_private = (caddr_t)au;
1231901Swollman	auth->ah_verf = au->au_shcred = _null_auth;
1241901Swollman	au->au_shfaults = 0;
12574462Salfred	au->au_origcred.oa_base = NULL;
1261901Swollman
1271901Swollman	/*
1281901Swollman	 * fill in param struct from the given params
1291901Swollman	 */
13074462Salfred	(void)gettimeofday(&now, NULL);
1311901Swollman	aup.aup_time = now.tv_sec;
1321901Swollman	aup.aup_machname = machname;
1331901Swollman	aup.aup_uid = uid;
1341901Swollman	aup.aup_gid = gid;
13574462Salfred	aup.aup_len = (u_int)len;
1361901Swollman	aup.aup_gids = aup_gids;
1371901Swollman
1381901Swollman	/*
1391901Swollman	 * Serialize the parameters into origcred
1401901Swollman	 */
1411901Swollman	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
14274462Salfred	if (! xdr_authunix_parms(&xdrs, &aup))
1431901Swollman		abort();
1441901Swollman	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
1451901Swollman	au->au_origcred.oa_flavor = AUTH_UNIX;
14655206Speter#ifdef _KERNEL
1471901Swollman	au->au_origcred.oa_base = mem_alloc((u_int) len);
1481901Swollman#else
1491901Swollman	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
15074462Salfred		warnx("authunix_create: out of memory");
15174462Salfred		goto cleanup_authunix_create;
1521901Swollman	}
1531901Swollman#endif
15474462Salfred	memmove(au->au_origcred.oa_base, mymem, (size_t)len);
1551901Swollman
1561901Swollman	/*
1571901Swollman	 * set auth handle to reflect new cred.
1581901Swollman	 */
1591901Swollman	auth->ah_cred = au->au_origcred;
1601901Swollman	marshal_new_auth(auth);
1611901Swollman	return (auth);
16274462Salfred#ifndef _KERNEL
16374462Salfred cleanup_authunix_create:
16474462Salfred	if (auth)
16574462Salfred		mem_free(auth, sizeof(*auth));
16674462Salfred	if (au) {
16774462Salfred		if (au->au_origcred.oa_base)
16874462Salfred			mem_free(au->au_origcred.oa_base, (u_int)len);
16974462Salfred		mem_free(au, sizeof(*au));
17074462Salfred	}
17174462Salfred	return (NULL);
17274462Salfred#endif
1731901Swollman}
1741901Swollman
1751901Swollman/*
1761901Swollman * Returns an auth handle with parameters determined by doing lots of
1771901Swollman * syscalls.
1781901Swollman */
1791901SwollmanAUTH *
180309487Sngieauthunix_create_default(void)
1811901Swollman{
182235143Skib	AUTH *auth;
183194494Sbrooks	int ngids;
184194494Sbrooks	long ngids_max;
18574462Salfred	char machname[MAXHOSTNAMELEN + 1];
18674462Salfred	uid_t uid;
18774462Salfred	gid_t gid;
188194494Sbrooks	gid_t *gids;
1891901Swollman
190194494Sbrooks	ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
191194494Sbrooks	gids = malloc(sizeof(gid_t) * ngids_max);
192194494Sbrooks	if (gids == NULL)
193194494Sbrooks		return (NULL);
194194494Sbrooks
19574462Salfred	if (gethostname(machname, sizeof machname) == -1)
1961901Swollman		abort();
19774462Salfred	machname[sizeof(machname) - 1] = 0;
19874462Salfred	uid = geteuid();
19974462Salfred	gid = getegid();
200194494Sbrooks	if ((ngids = getgroups(ngids_max, gids)) < 0)
2011901Swollman		abort();
202194494Sbrooks	if (ngids > NGRPS)
203194494Sbrooks		ngids = NGRPS;
204241181Spfg	/* XXX: interface problem; we should translate from uid_t and gid_t */
205241141Spfg	auth = authunix_create(machname, uid, gid, ngids, gids);
206235143Skib	free(gids);
207235143Skib	return (auth);
2081901Swollman}
2091901Swollman
2101901Swollman/*
2111901Swollman * authunix operations
2121901Swollman */
2131901Swollman
21474462Salfred/* ARGSUSED */
2151901Swollmanstatic void
216309487Sngieauthunix_nextverf(AUTH *auth)
2171901Swollman{
2181901Swollman	/* no action necessary */
2191901Swollman}
2201901Swollman
2211901Swollmanstatic bool_t
222309487Sngieauthunix_marshal(AUTH *auth, XDR *xdrs)
2231901Swollman{
22474462Salfred	struct audata *au;
2251901Swollman
22674462Salfred	assert(auth != NULL);
22774462Salfred	assert(xdrs != NULL);
22874462Salfred
22974462Salfred	au = AUTH_PRIVATE(auth);
2301901Swollman	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
2311901Swollman}
2321901Swollman
2331901Swollmanstatic bool_t
234309487Sngieauthunix_validate(AUTH *auth, struct opaque_auth *verf)
2351901Swollman{
23674462Salfred	struct audata *au;
2371901Swollman	XDR xdrs;
2381901Swollman
23974462Salfred	assert(auth != NULL);
24074462Salfred	assert(verf != NULL);
24174462Salfred
24274462Salfred	if (verf->oa_flavor == AUTH_SHORT) {
2431901Swollman		au = AUTH_PRIVATE(auth);
24474462Salfred		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
24574462Salfred		    XDR_DECODE);
2461901Swollman
2471901Swollman		if (au->au_shcred.oa_base != NULL) {
2481901Swollman			mem_free(au->au_shcred.oa_base,
2491901Swollman			    au->au_shcred.oa_length);
2501901Swollman			au->au_shcred.oa_base = NULL;
2511901Swollman		}
2521901Swollman		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
2531901Swollman			auth->ah_cred = au->au_shcred;
2541901Swollman		} else {
2551901Swollman			xdrs.x_op = XDR_FREE;
2561901Swollman			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
2571901Swollman			au->au_shcred.oa_base = NULL;
2581901Swollman			auth->ah_cred = au->au_origcred;
2591901Swollman		}
2601901Swollman		marshal_new_auth(auth);
2611901Swollman	}
2621901Swollman	return (TRUE);
2631901Swollman}
2641901Swollman
2651901Swollmanstatic bool_t
26674462Salfredauthunix_refresh(AUTH *auth, void *dummy)
2671901Swollman{
26874462Salfred	struct audata *au = AUTH_PRIVATE(auth);
2691901Swollman	struct authunix_parms aup;
2701901Swollman	struct timeval now;
2711901Swollman	XDR xdrs;
27274462Salfred	int stat;
2731901Swollman
27474462Salfred	assert(auth != NULL);
27574462Salfred
2761901Swollman	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
2771901Swollman		/* there is no hope.  Punt */
2781901Swollman		return (FALSE);
2791901Swollman	}
2801901Swollman	au->au_shfaults ++;
2811901Swollman
2821901Swollman	/* first deserialize the creds back into a struct authunix_parms */
2831901Swollman	aup.aup_machname = NULL;
28474462Salfred	aup.aup_gids = NULL;
2851901Swollman	xdrmem_create(&xdrs, au->au_origcred.oa_base,
2861901Swollman	    au->au_origcred.oa_length, XDR_DECODE);
2871901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
2888870Srgrimes	if (! stat)
2891901Swollman		goto done;
2901901Swollman
2911901Swollman	/* update the time and serialize in place */
29274462Salfred	(void)gettimeofday(&now, NULL);
2931901Swollman	aup.aup_time = now.tv_sec;
2941901Swollman	xdrs.x_op = XDR_ENCODE;
2951901Swollman	XDR_SETPOS(&xdrs, 0);
2961901Swollman	stat = xdr_authunix_parms(&xdrs, &aup);
2971901Swollman	if (! stat)
2981901Swollman		goto done;
2991901Swollman	auth->ah_cred = au->au_origcred;
3001901Swollman	marshal_new_auth(auth);
3011901Swollmandone:
3021901Swollman	/* free the struct authunix_parms created by deserializing */
3031901Swollman	xdrs.x_op = XDR_FREE;
3041901Swollman	(void)xdr_authunix_parms(&xdrs, &aup);
3051901Swollman	XDR_DESTROY(&xdrs);
3061901Swollman	return (stat);
3071901Swollman}
3081901Swollman
3091901Swollmanstatic void
310309487Sngieauthunix_destroy(AUTH *auth)
3111901Swollman{
31274462Salfred	struct audata *au;
3131901Swollman
31474462Salfred	assert(auth != NULL);
31574462Salfred
31674462Salfred	au = AUTH_PRIVATE(auth);
3171901Swollman	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
3181901Swollman
3191901Swollman	if (au->au_shcred.oa_base != NULL)
3201901Swollman		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
3211901Swollman
3221901Swollman	mem_free(auth->ah_private, sizeof(struct audata));
3231901Swollman
3241901Swollman	if (auth->ah_verf.oa_base != NULL)
3251901Swollman		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
3261901Swollman
32774462Salfred	mem_free(auth, sizeof(*auth));
3281901Swollman}
3291901Swollman
3301901Swollman/*
3311901Swollman * Marshals (pre-serializes) an auth struct.
3321901Swollman * sets private data, au_marshed and au_mpos
3331901Swollman */
33411666Sphkstatic void
335309487Sngiemarshal_new_auth(AUTH *auth)
3361901Swollman{
33774462Salfred	XDR	xdr_stream;
33874462Salfred	XDR	*xdrs = &xdr_stream;
33974462Salfred	struct audata *au;
3401901Swollman
34174462Salfred	assert(auth != NULL);
34274462Salfred
34374462Salfred	au = AUTH_PRIVATE(auth);
3441901Swollman	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
3451901Swollman	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
34674462Salfred	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
34774462Salfred		warnx("auth_none.c - Fatal marshalling problem");
34874462Salfred	else
3491901Swollman		au->au_mpos = XDR_GETPOS(xdrs);
3501901Swollman	XDR_DESTROY(xdrs);
3511901Swollman}
35274462Salfred
35374462Salfredstatic struct auth_ops *
354309487Sngieauthunix_ops(void)
35574462Salfred{
35674462Salfred	static struct auth_ops ops;
35774462Salfred
35874462Salfred	/* VARIABLES PROTECTED BY ops_lock: ops */
35974462Salfred
36074462Salfred	mutex_lock(&ops_lock);
36174462Salfred	if (ops.ah_nextverf == NULL) {
36274462Salfred		ops.ah_nextverf = authunix_nextverf;
36374462Salfred		ops.ah_marshal = authunix_marshal;
36474462Salfred		ops.ah_validate = authunix_validate;
36574462Salfred		ops.ah_refresh = authunix_refresh;
36674462Salfred		ops.ah_destroy = authunix_destroy;
36774462Salfred	}
36874462Salfred	mutex_unlock(&ops_lock);
36974462Salfred	return (&ops);
37074462Salfred}
371