Fix pthread_cond_*wait with requeue-PI on i386.
[glibc.git] / sunrpc / auth_unix.c
blob3a371c7f4b939e8a2e23b987305d433f79bd0a5b
1 /*
2 * Copyright (C) 1984, Sun Microsystems, Inc.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 * * Neither the name of Sun Microsystems, Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * auth_unix.c, Implements UNIX style authentication parameters.
34 * The system is very weak. The client uses no encryption for it's
35 * credentials and only sends null verifiers. The server sends backs
36 * null verifiers or optionally a verifier that suggests a new short hand
37 * for the credentials.
40 #include <errno.h>
41 #include <limits.h>
42 #include <stdbool.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <libintl.h>
47 #include <sys/param.h>
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51 #include <rpc/auth.h>
52 #include <rpc/auth_unix.h>
54 #ifdef USE_IN_LIBIO
55 # include <wchar.h>
56 #endif
59 * Unix authenticator operations vector
61 static void authunix_nextverf (AUTH *);
62 static bool_t authunix_marshal (AUTH *, XDR *);
63 static bool_t authunix_validate (AUTH *, struct opaque_auth *);
64 static bool_t authunix_refresh (AUTH *);
65 static void authunix_destroy (AUTH *);
67 static const struct auth_ops auth_unix_ops = {
68 authunix_nextverf,
69 authunix_marshal,
70 authunix_validate,
71 authunix_refresh,
72 authunix_destroy
76 * This struct is pointed to by the ah_private field of an auth_handle.
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 */
85 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
87 static bool_t marshal_new_auth (AUTH *) internal_function;
91 * Create a unix style authenticator.
92 * Returns an auth handle with the given stuff in it.
94 AUTH *
95 authunix_create (char *machname, uid_t uid, gid_t gid, int len,
96 gid_t *aup_gids)
98 struct authunix_parms aup;
99 char mymem[MAX_AUTH_BYTES];
100 struct timeval now;
101 XDR xdrs;
102 AUTH *auth;
103 struct audata *au;
106 * Allocate and set up auth handle
108 auth = (AUTH *) mem_alloc (sizeof (*auth));
109 au = (struct audata *) mem_alloc (sizeof (*au));
110 if (auth == NULL || au == NULL)
112 no_memory:
113 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
114 mem_free (auth, sizeof (*auth));
115 mem_free (au, sizeof (*au));
116 return NULL;
118 auth->ah_ops = (struct auth_ops *) &auth_unix_ops;
119 auth->ah_private = (caddr_t) au;
120 auth->ah_verf = au->au_shcred = _null_auth;
121 au->au_shfaults = 0;
124 * fill in param struct from the given params
126 (void) __gettimeofday (&now, (struct timezone *) 0);
127 aup.aup_time = now.tv_sec;
128 aup.aup_machname = machname;
129 aup.aup_uid = uid;
130 aup.aup_gid = gid;
131 aup.aup_len = (u_int) len;
132 aup.aup_gids = aup_gids;
135 * Serialize the parameters into origcred
137 INTUSE(xdrmem_create) (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
138 if (!INTUSE(xdr_authunix_parms) (&xdrs, &aup))
139 abort ();
140 au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
141 au->au_origcred.oa_flavor = AUTH_UNIX;
142 au->au_origcred.oa_base = mem_alloc ((u_int) len);
143 if (au->au_origcred.oa_base == NULL)
144 goto no_memory;
145 memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
148 * set auth handle to reflect new cred.
150 auth->ah_cred = au->au_origcred;
151 marshal_new_auth (auth);
152 return auth;
154 INTDEF (authunix_create)
157 * Returns an auth handle with parameters determined by doing lots of
158 * syscalls.
160 AUTH *
161 authunix_create_default (void)
163 char machname[MAX_MACHINE_NAME + 1];
165 if (__gethostname (machname, MAX_MACHINE_NAME) == -1)
166 abort ();
167 machname[MAX_MACHINE_NAME] = 0;
168 uid_t uid = __geteuid ();
169 gid_t gid = __getegid ();
171 int max_nr_groups;
172 /* When we have to try a second time, do not use alloca() again. We
173 might have reached the stack limit already. */
174 bool retry = false;
175 again:
176 /* Ask the kernel how many groups there are exactly. Note that we
177 might have to redo all this if the number of groups has changed
178 between the two calls. */
179 max_nr_groups = __getgroups (0, NULL);
181 /* Just some random reasonable stack limit. */
182 #define ALLOCA_LIMIT (1024 / sizeof (gid_t))
183 gid_t *gids = NULL;
184 if (max_nr_groups < ALLOCA_LIMIT && ! retry)
185 gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t));
186 else
188 gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
189 if (gids == NULL)
190 return NULL;
193 int len = __getgroups (max_nr_groups, gids);
194 if (len == -1)
196 if (errno == EINVAL)
198 /* New groups added in the meantime. Try again. */
199 if (max_nr_groups >= ALLOCA_LIMIT || retry)
200 free (gids);
201 retry = true;
202 goto again;
204 /* No other error can happen. */
205 abort ();
208 /* This braindamaged Sun code forces us here to truncate the
209 list of groups to NGRPS members since the code in
210 authuxprot.c transforms a fixed array. Grrr. */
211 AUTH *result = INTUSE(authunix_create) (machname, uid, gid, MIN (NGRPS, len),
212 gids);
214 if (max_nr_groups >= ALLOCA_LIMIT || retry)
215 free (gids);
217 return result;
219 INTDEF (authunix_create_default)
222 * authunix operations
225 static void
226 authunix_nextverf (AUTH *auth)
228 /* no action necessary */
231 static bool_t
232 authunix_marshal (AUTH *auth, XDR *xdrs)
234 struct audata *au = AUTH_PRIVATE (auth);
236 return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
239 static bool_t
240 authunix_validate (AUTH *auth, struct opaque_auth *verf)
242 struct audata *au;
243 XDR xdrs;
245 if (verf->oa_flavor == AUTH_SHORT)
247 au = AUTH_PRIVATE (auth);
248 INTUSE(xdrmem_create) (&xdrs, verf->oa_base, verf->oa_length,
249 XDR_DECODE);
251 if (au->au_shcred.oa_base != NULL)
253 mem_free (au->au_shcred.oa_base,
254 au->au_shcred.oa_length);
255 au->au_shcred.oa_base = NULL;
257 if (INTUSE(xdr_opaque_auth) (&xdrs, &au->au_shcred))
259 auth->ah_cred = au->au_shcred;
261 else
263 xdrs.x_op = XDR_FREE;
264 (void) INTUSE(xdr_opaque_auth) (&xdrs, &au->au_shcred);
265 au->au_shcred.oa_base = NULL;
266 auth->ah_cred = au->au_origcred;
268 marshal_new_auth (auth);
270 return TRUE;
273 static bool_t
274 authunix_refresh (AUTH *auth)
276 struct audata *au = AUTH_PRIVATE (auth);
277 struct authunix_parms aup;
278 struct timeval now;
279 XDR xdrs;
280 int stat;
282 if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
284 /* there is no hope. Punt */
285 return FALSE;
287 au->au_shfaults++;
289 /* first deserialize the creds back into a struct authunix_parms */
290 aup.aup_machname = NULL;
291 aup.aup_gids = (gid_t *) NULL;
292 INTUSE(xdrmem_create) (&xdrs, au->au_origcred.oa_base,
293 au->au_origcred.oa_length, XDR_DECODE);
294 stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
295 if (!stat)
296 goto done;
298 /* update the time and serialize in place */
299 (void) __gettimeofday (&now, (struct timezone *) 0);
300 aup.aup_time = now.tv_sec;
301 xdrs.x_op = XDR_ENCODE;
302 XDR_SETPOS (&xdrs, 0);
303 stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
304 if (!stat)
305 goto done;
306 auth->ah_cred = au->au_origcred;
307 marshal_new_auth (auth);
308 done:
309 /* free the struct authunix_parms created by deserializing */
310 xdrs.x_op = XDR_FREE;
311 (void) INTUSE(xdr_authunix_parms) (&xdrs, &aup);
312 XDR_DESTROY (&xdrs);
313 return stat;
316 static void
317 authunix_destroy (AUTH *auth)
319 struct audata *au = AUTH_PRIVATE (auth);
321 mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
323 if (au->au_shcred.oa_base != NULL)
324 mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
326 mem_free (auth->ah_private, sizeof (struct audata));
328 if (auth->ah_verf.oa_base != NULL)
329 mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
331 mem_free ((caddr_t) auth, sizeof (*auth));
335 * Marshals (pre-serializes) an auth struct.
336 * sets private data, au_marshed and au_mpos
338 static bool_t
339 internal_function
340 marshal_new_auth (AUTH *auth)
342 XDR xdr_stream;
343 XDR *xdrs = &xdr_stream;
344 struct audata *au = AUTH_PRIVATE (auth);
346 INTUSE(xdrmem_create) (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
347 if ((!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_cred))) ||
348 (!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_verf))))
349 perror (_("auth_unix.c: Fatal marshalling problem"));
350 else
351 au->au_mpos = XDR_GETPOS (xdrs);
353 XDR_DESTROY (xdrs);
355 return TRUE;