auth_unix.c revision 1994
1/*
2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part.  Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
8 *
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12 *
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
16 *
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
20 *
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
24 *
25 * Sun Microsystems, Inc.
26 * 2550 Garcia Avenue
27 * Mountain View, California  94043
28 */
29
30#if defined(LIBC_SCCS) && !defined(lint)
31/*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
32/*static char *sccsid = "from: @(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";*/
33static char *rcsid = "$Id: auth_unix.c,v 1.1 1994/08/07 18:35:39 wollman Exp $";
34#endif
35
36/*
37 * auth_unix.c, Implements UNIX style authentication parameters.
38 *
39 * Copyright (C) 1984, Sun Microsystems, Inc.
40 *
41 * The system is very weak.  The client uses no encryption for it's
42 * credentials and only sends null verifiers.  The server sends backs
43 * null verifiers or optionally a verifier that suggests a new short hand
44 * for the credentials.
45 *
46 */
47
48#include <stdio.h>
49#include <stdlib.h>
50
51#include <sys/param.h>
52#include <rpc/types.h>
53#include <rpc/xdr.h>
54#include <rpc/auth.h>
55#include <rpc/auth_unix.h>
56
57/*
58 * Unix authenticator operations vector
59 */
60static void	authunix_nextverf();
61static bool_t	authunix_marshal();
62static bool_t	authunix_validate();
63static bool_t	authunix_refresh();
64static void	authunix_destroy();
65
66static struct auth_ops auth_unix_ops = {
67	authunix_nextverf,
68	authunix_marshal,
69	authunix_validate,
70	authunix_refresh,
71	authunix_destroy
72};
73
74/*
75 * This struct is pointed to by the ah_private field of an auth_handle.
76 */
77struct audata {
78	struct opaque_auth	au_origcred;	/* original credentials */
79	struct opaque_auth	au_shcred;	/* short hand cred */
80	u_long			au_shfaults;	/* short hand cache faults */
81	char			au_marshed[MAX_AUTH_BYTES];
82	u_int			au_mpos;	/* xdr pos at end of marshed */
83};
84#define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
85
86static bool_t marshal_new_auth();
87
88/*
89 * This goop is here because some servers refuse to accept a
90 * credential with more than some number (usually 8) supplementary
91 * groups.  Blargh!
92 */
93static int authunix_maxgrouplist = 0;
94
95int
96set_rpc_maxgrouplist(int num)
97{
98	authunix_maxgrouplist = num;
99}
100
101/*
102 * Create a unix style authenticator.
103 * Returns an auth handle with the given stuff in it.
104 */
105AUTH *
106authunix_create(machname, uid, gid, len, aup_gids)
107	char *machname;
108	int uid;
109	int gid;
110	register int len;
111	int *aup_gids;
112{
113	struct authunix_parms aup;
114	char mymem[MAX_AUTH_BYTES];
115	struct timeval now;
116	XDR xdrs;
117	register AUTH *auth;
118	register struct audata *au;
119
120	/*
121	 * Allocate and set up auth handle
122	 */
123	auth = (AUTH *)mem_alloc(sizeof(*auth));
124#ifndef KERNEL
125	if (auth == NULL) {
126		(void)fprintf(stderr, "authunix_create: out of memory\n");
127		return (NULL);
128	}
129#endif
130	au = (struct audata *)mem_alloc(sizeof(*au));
131#ifndef KERNEL
132	if (au == NULL) {
133		(void)fprintf(stderr, "authunix_create: out of memory\n");
134		return (NULL);
135	}
136#endif
137	auth->ah_ops = &auth_unix_ops;
138	auth->ah_private = (caddr_t)au;
139	auth->ah_verf = au->au_shcred = _null_auth;
140	au->au_shfaults = 0;
141
142	/*
143	 * fill in param struct from the given params
144	 */
145	(void)gettimeofday(&now,  (struct timezone *)0);
146	aup.aup_time = now.tv_sec;
147	aup.aup_machname = machname;
148	aup.aup_uid = uid;
149	aup.aup_gid = gid;
150	/* GW: continuation of max group list hack */
151	if(authunix_maxgrouplist != 0) {
152		aup.aup_len = ((len > authunix_maxgrouplist) ? len
153			       : authunix_maxgrouplist);
154	} else {
155		aup.aup_len = (u_int)len;
156	}
157	aup.aup_gids = aup_gids;
158
159	/*
160	 * Serialize the parameters into origcred
161	 */
162	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
163	if (! xdr_authunix_parms(&xdrs, &aup))
164		abort();
165	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
166	au->au_origcred.oa_flavor = AUTH_UNIX;
167#ifdef KERNEL
168	au->au_origcred.oa_base = mem_alloc((u_int) len);
169#else
170	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
171		(void)fprintf(stderr, "authunix_create: out of memory\n");
172		return (NULL);
173	}
174#endif
175	bcopy(mymem, au->au_origcred.oa_base, (u_int)len);
176
177	/*
178	 * set auth handle to reflect new cred.
179	 */
180	auth->ah_cred = au->au_origcred;
181	marshal_new_auth(auth);
182	return (auth);
183}
184
185/*
186 * Returns an auth handle with parameters determined by doing lots of
187 * syscalls.
188 */
189AUTH *
190authunix_create_default()
191{
192	register int len;
193	char machname[MAX_MACHINE_NAME + 1];
194	register int uid;
195	register int gid;
196	int gids[NGRPS];
197	int i;
198	gid_t real_gids[NGROUPS];
199
200	if (gethostname(machname, MAX_MACHINE_NAME) == -1)
201		abort();
202	machname[MAX_MACHINE_NAME] = 0;
203	uid = geteuid();
204	gid = getegid();
205	if ((len = getgroups(NGROUPS, real_gids)) < 0)
206		abort();
207	if(len > NGRPS) len = NGRPS; /* GW: turn `gid_t's into `int's */
208	for(i = 0; i < len; i++) {
209		gids[i] = real_gids[i];
210	}
211	return (authunix_create(machname, uid, gid, len, gids));
212}
213
214/*
215 * authunix operations
216 */
217
218static void
219authunix_nextverf(auth)
220	AUTH *auth;
221{
222	/* no action necessary */
223}
224
225static bool_t
226authunix_marshal(auth, xdrs)
227	AUTH *auth;
228	XDR *xdrs;
229{
230	register struct audata *au = AUTH_PRIVATE(auth);
231
232	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
233}
234
235static bool_t
236authunix_validate(auth, verf)
237	register AUTH *auth;
238	struct opaque_auth verf;
239{
240	register struct audata *au;
241	XDR xdrs;
242
243	if (verf.oa_flavor == AUTH_SHORT) {
244		au = AUTH_PRIVATE(auth);
245		xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
246
247		if (au->au_shcred.oa_base != NULL) {
248			mem_free(au->au_shcred.oa_base,
249			    au->au_shcred.oa_length);
250			au->au_shcred.oa_base = NULL;
251		}
252		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
253			auth->ah_cred = au->au_shcred;
254		} else {
255			xdrs.x_op = XDR_FREE;
256			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
257			au->au_shcred.oa_base = NULL;
258			auth->ah_cred = au->au_origcred;
259		}
260		marshal_new_auth(auth);
261	}
262	return (TRUE);
263}
264
265static bool_t
266authunix_refresh(auth)
267	register AUTH *auth;
268{
269	register struct audata *au = AUTH_PRIVATE(auth);
270	struct authunix_parms aup;
271	struct timeval now;
272	XDR xdrs;
273	register int stat;
274
275	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
276		/* there is no hope.  Punt */
277		return (FALSE);
278	}
279	au->au_shfaults ++;
280
281	/* first deserialize the creds back into a struct authunix_parms */
282	aup.aup_machname = NULL;
283	aup.aup_gids = (int *)NULL;
284	xdrmem_create(&xdrs, au->au_origcred.oa_base,
285	    au->au_origcred.oa_length, XDR_DECODE);
286	stat = xdr_authunix_parms(&xdrs, &aup);
287	if (! stat)
288		goto done;
289
290	/* update the time and serialize in place */
291	(void)gettimeofday(&now, (struct timezone *)0);
292	aup.aup_time = now.tv_sec;
293	xdrs.x_op = XDR_ENCODE;
294	XDR_SETPOS(&xdrs, 0);
295	stat = xdr_authunix_parms(&xdrs, &aup);
296	if (! stat)
297		goto done;
298	auth->ah_cred = au->au_origcred;
299	marshal_new_auth(auth);
300done:
301	/* free the struct authunix_parms created by deserializing */
302	xdrs.x_op = XDR_FREE;
303	(void)xdr_authunix_parms(&xdrs, &aup);
304	XDR_DESTROY(&xdrs);
305	return (stat);
306}
307
308static void
309authunix_destroy(auth)
310	register AUTH *auth;
311{
312	register struct audata *au = AUTH_PRIVATE(auth);
313
314	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
315
316	if (au->au_shcred.oa_base != NULL)
317		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
318
319	mem_free(auth->ah_private, sizeof(struct audata));
320
321	if (auth->ah_verf.oa_base != NULL)
322		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
323
324	mem_free((caddr_t)auth, sizeof(*auth));
325}
326
327/*
328 * Marshals (pre-serializes) an auth struct.
329 * sets private data, au_marshed and au_mpos
330 */
331static bool_t
332marshal_new_auth(auth)
333	register AUTH *auth;
334{
335	XDR		xdr_stream;
336	register XDR	*xdrs = &xdr_stream;
337	register struct audata *au = AUTH_PRIVATE(auth);
338
339	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
340	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
341	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
342		perror("auth_none.c - Fatal marshalling problem");
343	} else {
344		au->au_mpos = XDR_GETPOS(xdrs);
345	}
346	XDR_DESTROY(xdrs);
347}
348