2007-09-13 H.J. Lu <hongjiu.lu@intel.com>
[glibc.git] / sunrpc / auth_unix.c
blob3eaf0a25ab80411d0c9c7cc8dccc52bf44d4fd7c
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.
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.
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.
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.
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.
25 * Sun Microsystems, Inc.
26 * 2550 Garcia Avenue
27 * Mountain View, California 94043
30 * Copyright (C) 1984, Sun Microsystems, Inc.
33 * auth_unix.c, Implements UNIX style authentication parameters.
35 * The system is very weak. The client uses no encryption for it's
36 * credentials and only sends null verifiers. The server sends backs
37 * null verifiers or optionally a verifier that suggests a new short hand
38 * for the credentials.
41 #include <errno.h>
42 #include <limits.h>
43 #include <stdbool.h>
44 #include <stdio.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <libintl.h>
48 #include <sys/param.h>
50 #include <rpc/types.h>
51 #include <rpc/xdr.h>
52 #include <rpc/auth.h>
53 #include <rpc/auth_unix.h>
55 #ifdef USE_IN_LIBIO
56 # include <wchar.h>
57 #endif
60 * Unix authenticator operations vector
62 static void authunix_nextverf (AUTH *);
63 static bool_t authunix_marshal (AUTH *, XDR *);
64 static bool_t authunix_validate (AUTH *, struct opaque_auth *);
65 static bool_t authunix_refresh (AUTH *);
66 static void authunix_destroy (AUTH *);
68 static const struct auth_ops auth_unix_ops = {
69 authunix_nextverf,
70 authunix_marshal,
71 authunix_validate,
72 authunix_refresh,
73 authunix_destroy
77 * This struct is pointed to by the ah_private field of an auth_handle.
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 */
86 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
88 static bool_t marshal_new_auth (AUTH *) internal_function;
92 * Create a unix style authenticator.
93 * Returns an auth handle with the given stuff in it.
95 AUTH *
96 authunix_create (char *machname, uid_t uid, gid_t gid, int len,
97 gid_t *aup_gids)
99 struct authunix_parms aup;
100 char mymem[MAX_AUTH_BYTES];
101 struct timeval now;
102 XDR xdrs;
103 AUTH *auth;
104 struct audata *au;
107 * Allocate and set up auth handle
109 auth = (AUTH *) mem_alloc (sizeof (*auth));
110 au = (struct audata *) mem_alloc (sizeof (*au));
111 if (auth == NULL || au == NULL)
113 no_memory:
114 (void) __fxprintf (NULL, "%s", _("authunix_create: out of memory\n"));
115 mem_free (auth, sizeof (*auth));
116 mem_free (au, sizeof (*au));
117 return NULL;
119 auth->ah_ops = (struct auth_ops *) &auth_unix_ops;
120 auth->ah_private = (caddr_t) au;
121 auth->ah_verf = au->au_shcred = _null_auth;
122 au->au_shfaults = 0;
125 * fill in param struct from the given params
127 (void) __gettimeofday (&now, (struct timezone *) 0);
128 aup.aup_time = now.tv_sec;
129 aup.aup_machname = machname;
130 aup.aup_uid = uid;
131 aup.aup_gid = gid;
132 aup.aup_len = (u_int) len;
133 aup.aup_gids = aup_gids;
136 * Serialize the parameters into origcred
138 INTUSE(xdrmem_create) (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
139 if (!INTUSE(xdr_authunix_parms) (&xdrs, &aup))
140 abort ();
141 au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
142 au->au_origcred.oa_flavor = AUTH_UNIX;
143 au->au_origcred.oa_base = mem_alloc ((u_int) len);
144 if (au->au_origcred.oa_base == NULL)
145 goto no_memory;
146 memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
149 * set auth handle to reflect new cred.
151 auth->ah_cred = au->au_origcred;
152 marshal_new_auth (auth);
153 return auth;
155 INTDEF (authunix_create)
158 * Returns an auth handle with parameters determined by doing lots of
159 * syscalls.
161 AUTH *
162 authunix_create_default (void)
164 char machname[MAX_MACHINE_NAME + 1];
166 if (__gethostname (machname, MAX_MACHINE_NAME) == -1)
167 abort ();
168 machname[MAX_MACHINE_NAME] = 0;
169 uid_t uid = __geteuid ();
170 gid_t gid = __getegid ();
172 int max_nr_groups;
173 /* When we have to try a second time, do not use alloca() again. We
174 might have reached the stack limit already. */
175 bool retry = false;
176 again:
177 /* Ask the kernel how many groups there are exactly. Note that we
178 might have to redo all this if the number of groups has changed
179 between the two calls. */
180 max_nr_groups = __getgroups (0, NULL);
182 /* Just some random reasonable stack limit. */
183 #define ALLOCA_LIMIT (1024 / sizeof (gid_t))
184 gid_t *gids = NULL;
185 if (max_nr_groups < ALLOCA_LIMIT && ! retry)
186 gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t));
187 else
189 gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
190 if (gids == NULL)
191 return NULL;
194 int len = __getgroups (max_nr_groups, gids);
195 if (len == -1)
197 if (errno == EINVAL)
199 /* New groups added in the meantime. Try again. */
200 if (max_nr_groups >= ALLOCA_LIMIT || retry)
201 free (gids);
202 retry = true;
203 goto again;
205 /* No other error can happen. */
206 abort ();
209 /* This braindamaged Sun code forces us here to truncate the
210 list of groups to NGRPS members since the code in
211 authuxprot.c transforms a fixed array. Grrr. */
212 AUTH *result = INTUSE(authunix_create) (machname, uid, gid, MIN (NGRPS, len),
213 gids);
215 if (max_nr_groups >= ALLOCA_LIMIT || retry)
216 free (gids);
218 return result;
220 INTDEF (authunix_create_default)
223 * authunix operations
226 static void
227 authunix_nextverf (AUTH *auth)
229 /* no action necessary */
232 static bool_t
233 authunix_marshal (AUTH *auth, XDR *xdrs)
235 struct audata *au = AUTH_PRIVATE (auth);
237 return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
240 static bool_t
241 authunix_validate (AUTH *auth, struct opaque_auth *verf)
243 struct audata *au;
244 XDR xdrs;
246 if (verf->oa_flavor == AUTH_SHORT)
248 au = AUTH_PRIVATE (auth);
249 INTUSE(xdrmem_create) (&xdrs, verf->oa_base, verf->oa_length,
250 XDR_DECODE);
252 if (au->au_shcred.oa_base != NULL)
254 mem_free (au->au_shcred.oa_base,
255 au->au_shcred.oa_length);
256 au->au_shcred.oa_base = NULL;
258 if (INTUSE(xdr_opaque_auth) (&xdrs, &au->au_shcred))
260 auth->ah_cred = au->au_shcred;
262 else
264 xdrs.x_op = XDR_FREE;
265 (void) INTUSE(xdr_opaque_auth) (&xdrs, &au->au_shcred);
266 au->au_shcred.oa_base = NULL;
267 auth->ah_cred = au->au_origcred;
269 marshal_new_auth (auth);
271 return TRUE;
274 static bool_t
275 authunix_refresh (AUTH *auth)
277 struct audata *au = AUTH_PRIVATE (auth);
278 struct authunix_parms aup;
279 struct timeval now;
280 XDR xdrs;
281 int stat;
283 if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
285 /* there is no hope. Punt */
286 return FALSE;
288 au->au_shfaults++;
290 /* first deserialize the creds back into a struct authunix_parms */
291 aup.aup_machname = NULL;
292 aup.aup_gids = (gid_t *) NULL;
293 INTUSE(xdrmem_create) (&xdrs, au->au_origcred.oa_base,
294 au->au_origcred.oa_length, XDR_DECODE);
295 stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
296 if (!stat)
297 goto done;
299 /* update the time and serialize in place */
300 (void) __gettimeofday (&now, (struct timezone *) 0);
301 aup.aup_time = now.tv_sec;
302 xdrs.x_op = XDR_ENCODE;
303 XDR_SETPOS (&xdrs, 0);
304 stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
305 if (!stat)
306 goto done;
307 auth->ah_cred = au->au_origcred;
308 marshal_new_auth (auth);
309 done:
310 /* free the struct authunix_parms created by deserializing */
311 xdrs.x_op = XDR_FREE;
312 (void) INTUSE(xdr_authunix_parms) (&xdrs, &aup);
313 XDR_DESTROY (&xdrs);
314 return stat;
317 static void
318 authunix_destroy (AUTH *auth)
320 struct audata *au = AUTH_PRIVATE (auth);
322 mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
324 if (au->au_shcred.oa_base != NULL)
325 mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
327 mem_free (auth->ah_private, sizeof (struct audata));
329 if (auth->ah_verf.oa_base != NULL)
330 mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
332 mem_free ((caddr_t) auth, sizeof (*auth));
336 * Marshals (pre-serializes) an auth struct.
337 * sets private data, au_marshed and au_mpos
339 static bool_t
340 internal_function
341 marshal_new_auth (AUTH *auth)
343 XDR xdr_stream;
344 XDR *xdrs = &xdr_stream;
345 struct audata *au = AUTH_PRIVATE (auth);
347 INTUSE(xdrmem_create) (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
348 if ((!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_cred))) ||
349 (!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_verf))))
350 perror (_("auth_unix.c: Fatal marshalling problem"));
351 else
352 au->au_mpos = XDR_GETPOS (xdrs);
354 XDR_DESTROY (xdrs);
356 return TRUE;