]> git.ipfire.org Git - thirdparty/glibc.git/blame - sunrpc/auth_unix.c
sunrpc: Always obtain AF_INET addresses from NSS [BZ #20964]
[thirdparty/glibc.git] / sunrpc / auth_unix.c
CommitLineData
28f540f4 1/*
3ce1f295 2 * Copyright (c) 2010, 2011, Oracle America, Inc.
cb636bb2 3 *
a7ab6ec8
UD
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
cb636bb2 7 *
a7ab6ec8
UD
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 the "Oracle America, 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.
28f540f4 17 *
a7ab6ec8
UD
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.
f8afba91
UD
30 */
31/*
32 * auth_unix.c, Implements UNIX style authentication parameters.
28f540f4
RM
33 *
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.
28f540f4
RM
38 */
39
773640b4 40#include <errno.h>
11336c16 41#include <limits.h>
773640b4 42#include <stdbool.h>
28f540f4 43#include <stdio.h>
e7fd8a39 44#include <string.h>
11336c16 45#include <unistd.h>
4360eafd 46#include <libintl.h>
b33f91e9 47#include <sys/param.h>
3ce1f295 48#include <wchar.h>
28f540f4
RM
49
50#include <rpc/types.h>
51#include <rpc/xdr.h>
52#include <rpc/auth.h>
53#include <rpc/auth_unix.h>
54
51028f34 55
28f540f4
RM
56/*
57 * Unix authenticator operations vector
58 */
e7fd8a39
UD
59static void authunix_nextverf (AUTH *);
60static bool_t authunix_marshal (AUTH *, XDR *);
61static bool_t authunix_validate (AUTH *, struct opaque_auth *);
62static bool_t authunix_refresh (AUTH *);
63static void authunix_destroy (AUTH *);
64
55b6a4f2 65static const struct auth_ops auth_unix_ops = {
e7fd8a39
UD
66 authunix_nextverf,
67 authunix_marshal,
68 authunix_validate,
69 authunix_refresh,
70 authunix_destroy
28f540f4
RM
71};
72
73/*
74 * This struct is pointed to by the ah_private field of an auth_handle.
75 */
f8afba91
UD
76struct audata {
77 struct opaque_auth au_origcred; /* original credentials */
78 struct opaque_auth au_shcred; /* short hand cred */
79 u_long au_shfaults; /* short hand cache faults */
80 char au_marshed[MAX_AUTH_BYTES];
81 u_int au_mpos; /* xdr pos at end of marshed */
82};
28f540f4
RM
83#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
84
dfd2257a 85static bool_t marshal_new_auth (AUTH *) internal_function;
28f540f4
RM
86
87
88/*
89 * Create a unix style authenticator.
90 * Returns an auth handle with the given stuff in it.
91 */
92AUTH *
f8afba91
UD
93authunix_create (char *machname, uid_t uid, gid_t gid, int len,
94 gid_t *aup_gids)
28f540f4 95{
e7fd8a39
UD
96 struct authunix_parms aup;
97 char mymem[MAX_AUTH_BYTES];
98 struct timeval now;
99 XDR xdrs;
100 AUTH *auth;
101 struct audata *au;
102
103 /*
104 * Allocate and set up auth handle
105 */
106 auth = (AUTH *) mem_alloc (sizeof (*auth));
e7fd8a39 107 au = (struct audata *) mem_alloc (sizeof (*au));
51028f34 108 if (auth == NULL || au == NULL)
e7fd8a39 109 {
2e3e5db6 110no_memory:
1d20f7f8 111 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
2e3e5db6
UD
112 mem_free (auth, sizeof (*auth));
113 mem_free (au, sizeof (*au));
e7fd8a39
UD
114 return NULL;
115 }
55b6a4f2 116 auth->ah_ops = (struct auth_ops *) &auth_unix_ops;
e7fd8a39
UD
117 auth->ah_private = (caddr_t) au;
118 auth->ah_verf = au->au_shcred = _null_auth;
119 au->au_shfaults = 0;
120
121 /*
122 * fill in param struct from the given params
123 */
50304ef0 124 (void) __gettimeofday (&now, (struct timezone *) 0);
e7fd8a39
UD
125 aup.aup_time = now.tv_sec;
126 aup.aup_machname = machname;
127 aup.aup_uid = uid;
128 aup.aup_gid = gid;
129 aup.aup_len = (u_int) len;
130 aup.aup_gids = aup_gids;
131
132 /*
133 * Serialize the parameters into origcred
134 */
7b57bfe5
UD
135 xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
136 if (!xdr_authunix_parms (&xdrs, &aup))
e7fd8a39
UD
137 abort ();
138 au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
139 au->au_origcred.oa_flavor = AUTH_UNIX;
f8afba91
UD
140 au->au_origcred.oa_base = mem_alloc ((u_int) len);
141 if (au->au_origcred.oa_base == NULL)
2e3e5db6 142 goto no_memory;
f8afba91 143 memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
e7fd8a39
UD
144
145 /*
146 * set auth handle to reflect new cred.
147 */
148 auth->ah_cred = au->au_origcred;
149 marshal_new_auth (auth);
150 return auth;
28f540f4 151}
021db4be 152libc_hidden_nolink_sunrpc (authunix_create, GLIBC_2_0)
28f540f4
RM
153
154/*
155 * Returns an auth handle with parameters determined by doing lots of
156 * syscalls.
157 */
158AUTH *
e7fd8a39 159authunix_create_default (void)
28f540f4 160{
e7fd8a39 161 char machname[MAX_MACHINE_NAME + 1];
e7fd8a39 162
50304ef0 163 if (__gethostname (machname, MAX_MACHINE_NAME) == -1)
e7fd8a39
UD
164 abort ();
165 machname[MAX_MACHINE_NAME] = 0;
773640b4
UD
166 uid_t uid = __geteuid ();
167 gid_t gid = __getegid ();
168
169 int max_nr_groups;
170 /* When we have to try a second time, do not use alloca() again. We
171 might have reached the stack limit already. */
172 bool retry = false;
173 again:
174 /* Ask the kernel how many groups there are exactly. Note that we
175 might have to redo all this if the number of groups has changed
176 between the two calls. */
177 max_nr_groups = __getgroups (0, NULL);
178
179 /* Just some random reasonable stack limit. */
180#define ALLOCA_LIMIT (1024 / sizeof (gid_t))
181 gid_t *gids = NULL;
182 if (max_nr_groups < ALLOCA_LIMIT && ! retry)
183 gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t));
184 else
185 {
186 gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
187 if (gids == NULL)
188 return NULL;
189 }
190
191 int len = __getgroups (max_nr_groups, gids);
192 if (len == -1)
193 {
194 if (errno == EINVAL)
195 {
196 /* New groups added in the meantime. Try again. */
197 if (max_nr_groups >= ALLOCA_LIMIT || retry)
198 free (gids);
199 retry = true;
200 goto again;
201 }
202 /* No other error can happen. */
203 abort ();
204 }
e7fd8a39 205
e7fd8a39
UD
206 /* This braindamaged Sun code forces us here to truncate the
207 list of groups to NGRPS members since the code in
208 authuxprot.c transforms a fixed array. Grrr. */
7b57bfe5 209 AUTH *result = authunix_create (machname, uid, gid, MIN (NGRPS, len), gids);
773640b4
UD
210
211 if (max_nr_groups >= ALLOCA_LIMIT || retry)
212 free (gids);
213
214 return result;
28f540f4 215}
7b57bfe5
UD
216#ifdef EXPORT_RPC_SYMBOLS
217libc_hidden_def (authunix_create_default)
218#else
021db4be 219libc_hidden_nolink_sunrpc (authunix_create_default, GLIBC_2_0)
7b57bfe5 220#endif
28f540f4
RM
221
222/*
223 * authunix operations
224 */
225
226static void
e7fd8a39 227authunix_nextverf (AUTH *auth)
28f540f4 228{
e7fd8a39 229 /* no action necessary */
28f540f4
RM
230}
231
232static bool_t
e7fd8a39 233authunix_marshal (AUTH *auth, XDR *xdrs)
28f540f4 234{
e7fd8a39 235 struct audata *au = AUTH_PRIVATE (auth);
28f540f4 236
e7fd8a39 237 return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
28f540f4
RM
238}
239
240static bool_t
e7fd8a39 241authunix_validate (AUTH *auth, struct opaque_auth *verf)
28f540f4 242{
e7fd8a39
UD
243 struct audata *au;
244 XDR xdrs;
245
246 if (verf->oa_flavor == AUTH_SHORT)
247 {
248 au = AUTH_PRIVATE (auth);
7b57bfe5 249 xdrmem_create (&xdrs, verf->oa_base, verf->oa_length, XDR_DECODE);
e7fd8a39
UD
250
251 if (au->au_shcred.oa_base != NULL)
252 {
253 mem_free (au->au_shcred.oa_base,
254 au->au_shcred.oa_length);
255 au->au_shcred.oa_base = NULL;
256 }
7b57bfe5 257 if (xdr_opaque_auth (&xdrs, &au->au_shcred))
e7fd8a39
UD
258 {
259 auth->ah_cred = au->au_shcred;
28f540f4 260 }
e7fd8a39
UD
261 else
262 {
263 xdrs.x_op = XDR_FREE;
7b57bfe5 264 (void) xdr_opaque_auth (&xdrs, &au->au_shcred);
e7fd8a39
UD
265 au->au_shcred.oa_base = NULL;
266 auth->ah_cred = au->au_origcred;
267 }
268 marshal_new_auth (auth);
269 }
270 return TRUE;
28f540f4
RM
271}
272
273static bool_t
e7fd8a39 274authunix_refresh (AUTH *auth)
28f540f4 275{
e7fd8a39
UD
276 struct audata *au = AUTH_PRIVATE (auth);
277 struct authunix_parms aup;
278 struct timeval now;
279 XDR xdrs;
280 int stat;
281
282 if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
283 {
284 /* there is no hope. Punt */
285 return FALSE;
286 }
287 au->au_shfaults++;
288
289 /* first deserialize the creds back into a struct authunix_parms */
290 aup.aup_machname = NULL;
291 aup.aup_gids = (gid_t *) NULL;
7b57bfe5
UD
292 xdrmem_create (&xdrs, au->au_origcred.oa_base,
293 au->au_origcred.oa_length, XDR_DECODE);
294 stat = xdr_authunix_parms (&xdrs, &aup);
e7fd8a39
UD
295 if (!stat)
296 goto done;
297
298 /* update the time and serialize in place */
50304ef0 299 (void) __gettimeofday (&now, (struct timezone *) 0);
e7fd8a39
UD
300 aup.aup_time = now.tv_sec;
301 xdrs.x_op = XDR_ENCODE;
302 XDR_SETPOS (&xdrs, 0);
7b57bfe5 303 stat = xdr_authunix_parms (&xdrs, &aup);
e7fd8a39
UD
304 if (!stat)
305 goto done;
306 auth->ah_cred = au->au_origcred;
307 marshal_new_auth (auth);
28f540f4 308done:
e7fd8a39
UD
309 /* free the struct authunix_parms created by deserializing */
310 xdrs.x_op = XDR_FREE;
7b57bfe5 311 (void) xdr_authunix_parms (&xdrs, &aup);
e7fd8a39
UD
312 XDR_DESTROY (&xdrs);
313 return stat;
28f540f4
RM
314}
315
316static void
e7fd8a39 317authunix_destroy (AUTH *auth)
28f540f4 318{
e7fd8a39 319 struct audata *au = AUTH_PRIVATE (auth);
28f540f4 320
e7fd8a39 321 mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
28f540f4 322
e7fd8a39
UD
323 if (au->au_shcred.oa_base != NULL)
324 mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
28f540f4 325
e7fd8a39 326 mem_free (auth->ah_private, sizeof (struct audata));
28f540f4 327
e7fd8a39
UD
328 if (auth->ah_verf.oa_base != NULL)
329 mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
28f540f4 330
e7fd8a39 331 mem_free ((caddr_t) auth, sizeof (*auth));
28f540f4
RM
332}
333
334/*
335 * Marshals (pre-serializes) an auth struct.
336 * sets private data, au_marshed and au_mpos
337 */
338static bool_t
dfd2257a 339internal_function
e7fd8a39 340marshal_new_auth (AUTH *auth)
28f540f4 341{
e7fd8a39
UD
342 XDR xdr_stream;
343 XDR *xdrs = &xdr_stream;
344 struct audata *au = AUTH_PRIVATE (auth);
345
7b57bfe5
UD
346 xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
347 if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) ||
348 (!xdr_opaque_auth (xdrs, &(auth->ah_verf))))
11bf311e 349 perror (_("auth_unix.c: Fatal marshalling problem"));
e7fd8a39 350 else
f8afba91
UD
351 au->au_mpos = XDR_GETPOS (xdrs);
352
e7fd8a39
UD
353 XDR_DESTROY (xdrs);
354
355 return TRUE;
28f540f4 356}