xref: /freebsd/lib/libc/rpc/auth_unix.c (revision 4cf49a43559ed9fdad601bdcccd2c55963008675)
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";*/
33 static char *rcsid = "$FreeBSD$";
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 #include <unistd.h>
51 #include <string.h>
52 
53 #include <sys/param.h>
54 #include <rpc/types.h>
55 #include <rpc/xdr.h>
56 #include <rpc/auth.h>
57 #include <rpc/auth_unix.h>
58 
59 /*
60  * Unix authenticator operations vector
61  */
62 static void	authunix_nextverf();
63 static bool_t	authunix_marshal();
64 static bool_t	authunix_validate();
65 static bool_t	authunix_refresh();
66 static void	authunix_destroy();
67 
68 static struct auth_ops auth_unix_ops = {
69 	authunix_nextverf,
70 	authunix_marshal,
71 	authunix_validate,
72 	authunix_refresh,
73 	authunix_destroy
74 };
75 
76 /*
77  * This struct is pointed to by the ah_private field of an auth_handle.
78  */
79 struct audata {
80 	struct opaque_auth	au_origcred;	/* original credentials */
81 	struct opaque_auth	au_shcred;	/* short hand cred */
82 	u_long			au_shfaults;	/* short hand cache faults */
83 	char			au_marshed[MAX_AUTH_BYTES];
84 	u_int			au_mpos;	/* xdr pos at end of marshed */
85 };
86 #define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private)
87 
88 static void marshal_new_auth();
89 
90 /*
91  * This goop is here because some servers refuse to accept a
92  * credential with more than some number (usually 8) supplementary
93  * groups.  Blargh!
94  */
95 static int authunix_maxgrouplist = 0;
96 
97 void
98 set_rpc_maxgrouplist(int num)
99 {
100 	authunix_maxgrouplist = num;
101 }
102 
103 /*
104  * Create a unix style authenticator.
105  * Returns an auth handle with the given stuff in it.
106  */
107 AUTH *
108 authunix_create(machname, uid, gid, len, aup_gids)
109 	char *machname;
110 	int uid;
111 	int gid;
112 	register int len;
113 	int *aup_gids;
114 {
115 	struct authunix_parms aup;
116 	char mymem[MAX_AUTH_BYTES];
117 	struct timeval now;
118 	XDR xdrs;
119 	register AUTH *auth;
120 	register struct audata *au;
121 
122 	/*
123 	 * Allocate and set up auth handle
124 	 */
125 	auth = (AUTH *)mem_alloc(sizeof(*auth));
126 #ifndef KERNEL
127 	if (auth == NULL) {
128 		(void)fprintf(stderr, "authunix_create: out of memory\n");
129 		return (NULL);
130 	}
131 #endif
132 	au = (struct audata *)mem_alloc(sizeof(*au));
133 #ifndef KERNEL
134 	if (au == NULL) {
135 		(void)fprintf(stderr, "authunix_create: out of memory\n");
136 		return (NULL);
137 	}
138 #endif
139 	auth->ah_ops = &auth_unix_ops;
140 	auth->ah_private = (caddr_t)au;
141 	auth->ah_verf = au->au_shcred = _null_auth;
142 	au->au_shfaults = 0;
143 
144 	/*
145 	 * fill in param struct from the given params
146 	 */
147 	(void)gettimeofday(&now,  (struct timezone *)0);
148 	aup.aup_time = now.tv_sec;
149 	aup.aup_machname = machname;
150 	aup.aup_uid = uid;
151 	aup.aup_gid = gid;
152 	/* GW: continuation of max group list hack */
153 	if(authunix_maxgrouplist != 0) {
154 		aup.aup_len = ((len < authunix_maxgrouplist) ? len
155 			       : authunix_maxgrouplist);
156 	} else {
157 		aup.aup_len = (u_int)len;
158 	}
159 	aup.aup_gids = aup_gids;
160 
161 	/*
162 	 * Serialize the parameters into origcred
163 	 */
164 	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
165 	if (! xdr_authunix_parms(&xdrs, &aup))
166 		abort();
167 	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
168 	au->au_origcred.oa_flavor = AUTH_UNIX;
169 #ifdef KERNEL
170 	au->au_origcred.oa_base = mem_alloc((u_int) len);
171 #else
172 	if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
173 		(void)fprintf(stderr, "authunix_create: out of memory\n");
174 		return (NULL);
175 	}
176 #endif
177 	memcpy(au->au_origcred.oa_base, mymem, (u_int)len);
178 
179 	/*
180 	 * set auth handle to reflect new cred.
181 	 */
182 	auth->ah_cred = au->au_origcred;
183 	marshal_new_auth(auth);
184 	return (auth);
185 }
186 
187 /*
188  * Returns an auth handle with parameters determined by doing lots of
189  * syscalls.
190  */
191 AUTH *
192 authunix_create_default()
193 {
194 	register int len;
195 	char machname[MAX_MACHINE_NAME + 1];
196 	register int uid;
197 	register int gid;
198 	int gids[NGRPS];
199 	int i;
200 	gid_t real_gids[NGROUPS];
201 
202 	if (gethostname(machname, MAX_MACHINE_NAME) == -1)
203 		abort();
204 	machname[MAX_MACHINE_NAME] = 0;
205 	uid = (int)geteuid();
206 	gid = (int)getegid();
207 	if ((len = getgroups(NGROUPS, real_gids)) < 0)
208 		abort();
209 	if(len > NGRPS) len = NGRPS; /* GW: turn `gid_t's into `int's */
210 	for(i = 0; i < len; i++) {
211 		gids[i] = (int)real_gids[i];
212 	}
213 	return (authunix_create(machname, uid, gid, len, gids));
214 }
215 
216 /*
217  * authunix operations
218  */
219 
220 static void
221 authunix_nextverf(auth)
222 	AUTH *auth;
223 {
224 	/* no action necessary */
225 }
226 
227 static bool_t
228 authunix_marshal(auth, xdrs)
229 	AUTH *auth;
230 	XDR *xdrs;
231 {
232 	register struct audata *au = AUTH_PRIVATE(auth);
233 
234 	return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
235 }
236 
237 static bool_t
238 authunix_validate(auth, verf)
239 	register AUTH *auth;
240 	struct opaque_auth verf;
241 {
242 	register struct audata *au;
243 	XDR xdrs;
244 
245 	if (verf.oa_flavor == AUTH_SHORT) {
246 		au = AUTH_PRIVATE(auth);
247 		xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
248 
249 		if (au->au_shcred.oa_base != NULL) {
250 			mem_free(au->au_shcred.oa_base,
251 			    au->au_shcred.oa_length);
252 			au->au_shcred.oa_base = NULL;
253 		}
254 		if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
255 			auth->ah_cred = au->au_shcred;
256 		} else {
257 			xdrs.x_op = XDR_FREE;
258 			(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
259 			au->au_shcred.oa_base = NULL;
260 			auth->ah_cred = au->au_origcred;
261 		}
262 		marshal_new_auth(auth);
263 	}
264 	return (TRUE);
265 }
266 
267 static bool_t
268 authunix_refresh(auth)
269 	register AUTH *auth;
270 {
271 	register struct audata *au = AUTH_PRIVATE(auth);
272 	struct authunix_parms aup;
273 	struct timeval now;
274 	XDR xdrs;
275 	register int stat;
276 
277 	if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
278 		/* there is no hope.  Punt */
279 		return (FALSE);
280 	}
281 	au->au_shfaults ++;
282 
283 	/* first deserialize the creds back into a struct authunix_parms */
284 	aup.aup_machname = NULL;
285 	aup.aup_gids = (int *)NULL;
286 	xdrmem_create(&xdrs, au->au_origcred.oa_base,
287 	    au->au_origcred.oa_length, XDR_DECODE);
288 	stat = xdr_authunix_parms(&xdrs, &aup);
289 	if (! stat)
290 		goto done;
291 
292 	/* update the time and serialize in place */
293 	(void)gettimeofday(&now, (struct timezone *)0);
294 	aup.aup_time = now.tv_sec;
295 	xdrs.x_op = XDR_ENCODE;
296 	XDR_SETPOS(&xdrs, 0);
297 	stat = xdr_authunix_parms(&xdrs, &aup);
298 	if (! stat)
299 		goto done;
300 	auth->ah_cred = au->au_origcred;
301 	marshal_new_auth(auth);
302 done:
303 	/* free the struct authunix_parms created by deserializing */
304 	xdrs.x_op = XDR_FREE;
305 	(void)xdr_authunix_parms(&xdrs, &aup);
306 	XDR_DESTROY(&xdrs);
307 	return (stat);
308 }
309 
310 static void
311 authunix_destroy(auth)
312 	register AUTH *auth;
313 {
314 	register struct audata *au = AUTH_PRIVATE(auth);
315 
316 	mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
317 
318 	if (au->au_shcred.oa_base != NULL)
319 		mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
320 
321 	mem_free(auth->ah_private, sizeof(struct audata));
322 
323 	if (auth->ah_verf.oa_base != NULL)
324 		mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
325 
326 	mem_free((caddr_t)auth, sizeof(*auth));
327 }
328 
329 /*
330  * Marshals (pre-serializes) an auth struct.
331  * sets private data, au_marshed and au_mpos
332  */
333 static void
334 marshal_new_auth(auth)
335 	register AUTH *auth;
336 {
337 	XDR		xdr_stream;
338 	register XDR	*xdrs = &xdr_stream;
339 	register struct audata *au = AUTH_PRIVATE(auth);
340 
341 	xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
342 	if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
343 	    (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
344 		perror("auth_none.c - Fatal marshalling problem");
345 	} else {
346 		au->au_mpos = XDR_GETPOS(xdrs);
347 	}
348 	XDR_DESTROY(xdrs);
349 }
350