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