auth_unix.c revision 177685
1177633Sdfr/*	$NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $	*/
2177633Sdfr
3177633Sdfr/*
4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5177633Sdfr * unrestricted use provided that this legend is included on all tape
6177633Sdfr * media and as a part of the software program in whole or part.  Users
7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized
8177633Sdfr * to license or distribute it to anyone else except as part of a product or
9177633Sdfr * program developed by the user.
10177633Sdfr *
11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14177633Sdfr *
15177633Sdfr * Sun RPC is provided with no support and without any obligation on the
16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction,
17177633Sdfr * modification or enhancement.
18177633Sdfr *
19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21177633Sdfr * OR ANY PART THEREOF.
22177633Sdfr *
23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24177633Sdfr * or profits or other special, indirect and consequential damages, even if
25177633Sdfr * Sun has been advised of the possibility of such damages.
26177633Sdfr *
27177633Sdfr * Sun Microsystems, Inc.
28177633Sdfr * 2550 Garcia Avenue
29177633Sdfr * Mountain View, California  94043
30177633Sdfr */
31177633Sdfr
32177633Sdfr#if defined(LIBC_SCCS) && !defined(lint)
33177633Sdfrstatic char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
34177633Sdfrstatic char *sccsid = "@(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";
35177633Sdfr#endif
36177633Sdfr#include <sys/cdefs.h>
37177633Sdfr__FBSDID("$FreeBSD: head/sys/rpc/auth_unix.c 177685 2008-03-28 09:50:32Z dfr $");
38177633Sdfr
39177633Sdfr/*
40177633Sdfr * auth_unix.c, Implements UNIX style authentication parameters.
41177633Sdfr *
42177633Sdfr * Copyright (C) 1984, Sun Microsystems, Inc.
43177633Sdfr *
44177633Sdfr * The system is very weak.  The client uses no encryption for it's
45177633Sdfr * credentials and only sends null verifiers.  The server sends backs
46177633Sdfr * null verifiers or optionally a verifier that suggests a new short hand
47177633Sdfr * for the credentials.
48177633Sdfr *
49177633Sdfr */
50177633Sdfr
51177633Sdfr#include <sys/param.h>
52177633Sdfr#include <sys/systm.h>
53177633Sdfr#include <sys/lock.h>
54177633Sdfr#include <sys/malloc.h>
55177633Sdfr#include <sys/mutex.h>
56177633Sdfr#include <sys/ucred.h>
57177633Sdfr
58177633Sdfr#include <rpc/types.h>
59177633Sdfr#include <rpc/xdr.h>
60177633Sdfr#include <rpc/auth.h>
61177633Sdfr
62177685Sdfr#include <rpc/rpc_com.h>
63177633Sdfr
64177633Sdfr/* auth_unix.c */
65177633Sdfrstatic void authunix_nextverf (AUTH *);
66177633Sdfrstatic bool_t authunix_marshal (AUTH *, XDR *);
67177633Sdfrstatic bool_t authunix_validate (AUTH *, struct opaque_auth *);
68177633Sdfrstatic bool_t authunix_refresh (AUTH *, void *);
69177633Sdfrstatic void authunix_destroy (AUTH *);
70177633Sdfrstatic void marshal_new_auth (AUTH *);
71177633Sdfr
72177633Sdfrstatic struct auth_ops authunix_ops = {
73177633Sdfr	.ah_nextverf =		authunix_nextverf,
74177633Sdfr	.ah_marshal =		authunix_marshal,
75177633Sdfr	.ah_validate =		authunix_validate,
76177633Sdfr	.ah_refresh =		authunix_refresh,
77177633Sdfr	.ah_destroy =		authunix_destroy
78177633Sdfr};
79177633Sdfr
80177633Sdfr/*
81177633Sdfr * This struct is pointed to by the ah_private field of an auth_handle.
82177633Sdfr */
83177633Sdfrstruct audata {
84177633Sdfr	struct opaque_auth	au_origcred;	/* original credentials */
85177633Sdfr	struct opaque_auth	au_shcred;	/* short hand cred */
86177633Sdfr	u_long			au_shfaults;	/* short hand cache faults */
87177633Sdfr	char			au_marshed[MAX_AUTH_BYTES];
88177633Sdfr	u_int			au_mpos;	/* xdr pos at end of marshed */
89177633Sdfr};
90177633Sdfr#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
91177633Sdfr
92177633Sdfr/*
93177633Sdfr * Create a unix style authenticator.
94177633Sdfr * Returns an auth handle with the given stuff in it.
95177633Sdfr */
96177633SdfrAUTH *
97177633Sdfrauthunix_create(struct ucred *cred)
98177633Sdfr{
99177633Sdfr	struct xucred xcr;
100177633Sdfr	char mymem[MAX_AUTH_BYTES];
101177633Sdfr	XDR xdrs;
102177633Sdfr	AUTH *auth;
103177633Sdfr	struct audata *au;
104177633Sdfr	struct timeval now;
105177633Sdfr	uint32_t time;
106177633Sdfr	int len;
107177633Sdfr
108177633Sdfr	/*
109177633Sdfr	 * Allocate and set up auth handle
110177633Sdfr	 */
111177633Sdfr	au = NULL;
112177633Sdfr	auth = mem_alloc(sizeof(*auth));
113177633Sdfr#ifndef _KERNEL
114177633Sdfr	if (auth == NULL) {
115177633Sdfr		printf("authunix_create: out of memory");
116177633Sdfr		goto cleanup_authunix_create;
117177633Sdfr	}
118177633Sdfr#endif
119177633Sdfr	au = mem_alloc(sizeof(*au));
120177633Sdfr#ifndef _KERNEL
121177633Sdfr	if (au == NULL) {
122177633Sdfr		printf("authunix_create: out of memory");
123177633Sdfr		goto cleanup_authunix_create;
124177633Sdfr	}
125177633Sdfr#endif
126177633Sdfr	auth->ah_ops = &authunix_ops;
127177633Sdfr	auth->ah_private = (caddr_t)au;
128177633Sdfr	auth->ah_verf = au->au_shcred = _null_auth;
129177633Sdfr	au->au_shfaults = 0;
130177633Sdfr	au->au_origcred.oa_base = NULL;
131177633Sdfr
132177633Sdfr	getmicrotime(&now);
133177633Sdfr	time = now.tv_sec;
134177633Sdfr
135177633Sdfr	/*
136177633Sdfr	 * Serialize the parameters into origcred
137177633Sdfr	 */
138177633Sdfr	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
139177633Sdfr	cru2x(cred, &xcr);
140177633Sdfr	if (! xdr_authunix_parms(&xdrs, &time, &xcr))
141177633Sdfr		panic("authunix_create: failed to encode creds");
142177633Sdfr	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
143177633Sdfr	au->au_origcred.oa_flavor = AUTH_UNIX;
144177633Sdfr#ifdef _KERNEL
145177633Sdfr	au->au_origcred.oa_base = mem_alloc((u_int) len);
146177633Sdfr#else
147177633Sdfr	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
148177633Sdfr		printf("authunix_create: out of memory");
149177633Sdfr		goto cleanup_authunix_create;
150177633Sdfr	}
151177633Sdfr#endif
152177633Sdfr	memcpy(au->au_origcred.oa_base, mymem, (size_t)len);
153177633Sdfr
154177633Sdfr	/*
155177633Sdfr	 * set auth handle to reflect new cred.
156177633Sdfr	 */
157177633Sdfr	auth->ah_cred = au->au_origcred;
158177633Sdfr	marshal_new_auth(auth);
159177633Sdfr	return (auth);
160177633Sdfr#ifndef _KERNEL
161177633Sdfr cleanup_authunix_create:
162177633Sdfr	if (auth)
163177633Sdfr		mem_free(auth, sizeof(*auth));
164177633Sdfr	if (au) {
165177633Sdfr		if (au->au_origcred.oa_base)
166177633Sdfr			mem_free(au->au_origcred.oa_base, (u_int)len);
167177633Sdfr		mem_free(au, sizeof(*au));
168177633Sdfr	}
169177633Sdfr	return (NULL);
170177633Sdfr#endif
171177633Sdfr}
172177633Sdfr
173177633Sdfr/*
174177633Sdfr * authunix operations
175177633Sdfr */
176177633Sdfr
177177633Sdfr/* ARGSUSED */
178177633Sdfrstatic void
179177633Sdfrauthunix_nextverf(AUTH *auth)
180177633Sdfr{
181177633Sdfr	/* no action necessary */
182177633Sdfr}
183177633Sdfr
184177633Sdfrstatic bool_t
185177633Sdfrauthunix_marshal(AUTH *auth, XDR *xdrs)
186177633Sdfr{
187177633Sdfr	struct audata *au;
188177633Sdfr
189177633Sdfr	au = AUTH_PRIVATE(auth);
190177633Sdfr	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
191177633Sdfr}
192177633Sdfr
193177633Sdfrstatic bool_t
194177633Sdfrauthunix_validate(AUTH *auth, struct opaque_auth *verf)
195177633Sdfr{
196177633Sdfr	struct audata *au;
197177633Sdfr	XDR xdrs;
198177633Sdfr
199177633Sdfr	if (verf->oa_flavor == AUTH_SHORT) {
200177633Sdfr		au = AUTH_PRIVATE(auth);
201177633Sdfr		xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
202177633Sdfr		    XDR_DECODE);
203177633Sdfr
204177633Sdfr		if (au->au_shcred.oa_base != NULL) {
205177633Sdfr			mem_free(au->au_shcred.oa_base,
206177633Sdfr			    au->au_shcred.oa_length);
207177633Sdfr			au->au_shcred.oa_base = NULL;
208177633Sdfr		}
209177633Sdfr		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
210177633Sdfr			auth->ah_cred = au->au_shcred;
211177633Sdfr		} else {
212177633Sdfr			xdrs.x_op = XDR_FREE;
213177633Sdfr			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
214177633Sdfr			au->au_shcred.oa_base = NULL;
215177633Sdfr			auth->ah_cred = au->au_origcred;
216177633Sdfr		}
217177633Sdfr		marshal_new_auth(auth);
218177633Sdfr	}
219177633Sdfr	return (TRUE);
220177633Sdfr}
221177633Sdfr
222177633Sdfrstatic bool_t
223177633Sdfrauthunix_refresh(AUTH *auth, void *dummy)
224177633Sdfr{
225177633Sdfr	struct audata *au = AUTH_PRIVATE(auth);
226177633Sdfr	struct xucred xcr;
227177633Sdfr	uint32_t time;
228177633Sdfr	struct timeval now;
229177633Sdfr	XDR xdrs;
230177633Sdfr	int stat;
231177633Sdfr
232177633Sdfr	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
233177633Sdfr		/* there is no hope.  Punt */
234177633Sdfr		return (FALSE);
235177633Sdfr	}
236177633Sdfr	au->au_shfaults ++;
237177633Sdfr
238177633Sdfr	/* first deserialize the creds back into a struct ucred */
239177633Sdfr	xdrmem_create(&xdrs, au->au_origcred.oa_base,
240177633Sdfr	    au->au_origcred.oa_length, XDR_DECODE);
241177633Sdfr	stat = xdr_authunix_parms(&xdrs, &time, &xcr);
242177633Sdfr	if (! stat)
243177633Sdfr		goto done;
244177633Sdfr
245177633Sdfr	/* update the time and serialize in place */
246177633Sdfr	getmicrotime(&now);
247177633Sdfr	time = now.tv_sec;
248177633Sdfr	xdrs.x_op = XDR_ENCODE;
249177633Sdfr	XDR_SETPOS(&xdrs, 0);
250177633Sdfr
251177633Sdfr	stat = xdr_authunix_parms(&xdrs, &time, &xcr);
252177633Sdfr	if (! stat)
253177633Sdfr		goto done;
254177633Sdfr	auth->ah_cred = au->au_origcred;
255177633Sdfr	marshal_new_auth(auth);
256177633Sdfrdone:
257177633Sdfr	XDR_DESTROY(&xdrs);
258177633Sdfr	return (stat);
259177633Sdfr}
260177633Sdfr
261177633Sdfrstatic void
262177633Sdfrauthunix_destroy(AUTH *auth)
263177633Sdfr{
264177633Sdfr	struct audata *au;
265177633Sdfr
266177633Sdfr	au = AUTH_PRIVATE(auth);
267177633Sdfr	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
268177633Sdfr
269177633Sdfr	if (au->au_shcred.oa_base != NULL)
270177633Sdfr		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
271177633Sdfr
272177633Sdfr	mem_free(auth->ah_private, sizeof(struct audata));
273177633Sdfr
274177633Sdfr	if (auth->ah_verf.oa_base != NULL)
275177633Sdfr		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
276177633Sdfr
277177633Sdfr	mem_free(auth, sizeof(*auth));
278177633Sdfr}
279177633Sdfr
280177633Sdfr/*
281177633Sdfr * Marshals (pre-serializes) an auth struct.
282177633Sdfr * sets private data, au_marshed and au_mpos
283177633Sdfr */
284177633Sdfrstatic void
285177633Sdfrmarshal_new_auth(AUTH *auth)
286177633Sdfr{
287177633Sdfr	XDR	xdr_stream;
288177633Sdfr	XDR	*xdrs = &xdr_stream;
289177633Sdfr	struct audata *au;
290177633Sdfr
291177633Sdfr	au = AUTH_PRIVATE(auth);
292177633Sdfr	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
293177633Sdfr	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
294177633Sdfr	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
295177633Sdfr		printf("auth_none.c - Fatal marshalling problem");
296177633Sdfr	else
297177633Sdfr		au->au_mpos = XDR_GETPOS(xdrs);
298177633Sdfr	XDR_DESTROY(xdrs);
299177633Sdfr}
300