1 /*
2  * Copyright (c) 2010, 2011, Oracle America, Inc.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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.
17  *
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.
30  */
31 /*
32  * auth_unix.c, Implements UNIX style authentication parameters.
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.
38  */
39 
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 <time.h>
47 #include <libintl.h>
48 #include <sys/param.h>
49 #include <wchar.h>
50 #include <shlib-compat.h>
51 
52 #include <rpc/types.h>
53 #include <rpc/xdr.h>
54 #include <rpc/auth.h>
55 #include <rpc/auth_unix.h>
56 
57 
58 /*
59  * Unix authenticator operations vector
60  */
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 *);
66 
67 static const 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 (AUTH *);
88 
89 
90 /*
91  * Create a unix style authenticator.
92  * Returns an auth handle with the given stuff in it.
93  */
94 AUTH *
authunix_create(char * machname,uid_t uid,gid_t gid,int len,gid_t * aup_gids)95 authunix_create (char *machname, uid_t uid, gid_t gid, int len,
96 		 gid_t *aup_gids)
97 {
98   struct authunix_parms aup;
99   char mymem[MAX_AUTH_BYTES];
100   struct timespec now;
101   XDR xdrs;
102   AUTH *auth;
103   struct audata *au;
104 
105   /*
106    * Allocate and set up auth handle
107    */
108   auth = (AUTH *) mem_alloc (sizeof (*auth));
109   au = (struct audata *) mem_alloc (sizeof (*au));
110   if (auth == NULL || au == NULL)
111     {
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;
117     }
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;
122 
123   /*
124    * fill in param struct from the given params
125    */
126   __clock_gettime (CLOCK_REALTIME, &now);
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;
133 
134   /*
135    * Serialize the parameters into origcred
136    */
137   xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
138   if (!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);
146 
147   /*
148    * set auth handle to reflect new cred.
149    */
150   auth->ah_cred = au->au_origcred;
151   marshal_new_auth (auth);
152   return auth;
153 }
libc_hidden_nolink_sunrpc(authunix_create,GLIBC_2_0)154 libc_hidden_nolink_sunrpc (authunix_create, GLIBC_2_0)
155 
156 /*
157  * Returns an auth handle with parameters determined by doing lots of
158  * syscalls.
159  */
160 AUTH *
161 authunix_create_default (void)
162 {
163   char machname[MAX_MACHINE_NAME + 1];
164 
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 ();
170 
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);
180 
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
187     {
188       gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
189       if (gids == NULL)
190 	return NULL;
191     }
192 
193   int len = __getgroups (max_nr_groups, gids);
194   if (len == -1)
195     {
196       if (errno == EINVAL)
197 	{
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;
203 	}
204       /* No other error can happen.  */
205       abort ();
206     }
207 
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 = authunix_create (machname, uid, gid, MIN (NGRPS, len), gids);
212 
213   if (max_nr_groups >= ALLOCA_LIMIT || retry)
214     free (gids);
215 
216   return result;
217 }
218 #ifdef EXPORT_RPC_SYMBOLS
libc_hidden_def(authunix_create_default)219 libc_hidden_def (authunix_create_default)
220 #else
221 libc_hidden_nolink_sunrpc (authunix_create_default, GLIBC_2_0)
222 #endif
223 
224 /*
225  * authunix operations
226  */
227 
228 static void
229 authunix_nextverf (AUTH *auth)
230 {
231   /* no action necessary */
232 }
233 
234 static bool_t
authunix_marshal(AUTH * auth,XDR * xdrs)235 authunix_marshal (AUTH *auth, XDR *xdrs)
236 {
237   struct audata *au = AUTH_PRIVATE (auth);
238 
239   return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
240 }
241 
242 static bool_t
authunix_validate(AUTH * auth,struct opaque_auth * verf)243 authunix_validate (AUTH *auth, struct opaque_auth *verf)
244 {
245   struct audata *au;
246   XDR xdrs;
247 
248   if (verf->oa_flavor == AUTH_SHORT)
249     {
250       au = AUTH_PRIVATE (auth);
251       xdrmem_create (&xdrs, verf->oa_base, verf->oa_length, XDR_DECODE);
252 
253       if (au->au_shcred.oa_base != NULL)
254 	{
255 	  mem_free (au->au_shcred.oa_base,
256 		    au->au_shcred.oa_length);
257 	  au->au_shcred.oa_base = NULL;
258 	}
259       if (xdr_opaque_auth (&xdrs, &au->au_shcred))
260 	{
261 	  auth->ah_cred = au->au_shcred;
262 	}
263       else
264 	{
265 	  xdrs.x_op = XDR_FREE;
266 	  (void) xdr_opaque_auth (&xdrs, &au->au_shcred);
267 	  au->au_shcred.oa_base = NULL;
268 	  auth->ah_cred = au->au_origcred;
269 	}
270       marshal_new_auth (auth);
271     }
272   return TRUE;
273 }
274 
275 static bool_t
authunix_refresh(AUTH * auth)276 authunix_refresh (AUTH *auth)
277 {
278   struct audata *au = AUTH_PRIVATE (auth);
279   struct authunix_parms aup;
280   struct timespec now;
281   XDR xdrs;
282   int stat;
283 
284   if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
285     {
286       /* there is no hope.  Punt */
287       return FALSE;
288     }
289   au->au_shfaults++;
290 
291   /* first deserialize the creds back into a struct authunix_parms */
292   aup.aup_machname = NULL;
293   aup.aup_gids = (gid_t *) NULL;
294   xdrmem_create (&xdrs, au->au_origcred.oa_base,
295 		 au->au_origcred.oa_length, XDR_DECODE);
296   stat = xdr_authunix_parms (&xdrs, &aup);
297   if (!stat)
298     goto done;
299 
300   /* update the time and serialize in place */
301   __clock_gettime (CLOCK_REALTIME, &now);
302   aup.aup_time = now.tv_sec;
303   xdrs.x_op = XDR_ENCODE;
304   XDR_SETPOS (&xdrs, 0);
305   stat = xdr_authunix_parms (&xdrs, &aup);
306   if (!stat)
307     goto done;
308   auth->ah_cred = au->au_origcred;
309   marshal_new_auth (auth);
310 done:
311   /* free the struct authunix_parms created by deserializing */
312   xdrs.x_op = XDR_FREE;
313   (void) xdr_authunix_parms (&xdrs, &aup);
314   XDR_DESTROY (&xdrs);
315   return stat;
316 }
317 
318 static void
authunix_destroy(AUTH * auth)319 authunix_destroy (AUTH *auth)
320 {
321   struct audata *au = AUTH_PRIVATE (auth);
322 
323   mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
324 
325   if (au->au_shcred.oa_base != NULL)
326     mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
327 
328   mem_free (auth->ah_private, sizeof (struct audata));
329 
330   if (auth->ah_verf.oa_base != NULL)
331     mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
332 
333   mem_free ((caddr_t) auth, sizeof (*auth));
334 }
335 
336 /*
337  * Marshals (pre-serializes) an auth struct.
338  * sets private data, au_marshed and au_mpos
339  */
340 static bool_t
marshal_new_auth(AUTH * auth)341 marshal_new_auth (AUTH *auth)
342 {
343   XDR xdr_stream;
344   XDR *xdrs = &xdr_stream;
345   struct audata *au = AUTH_PRIVATE (auth);
346 
347   xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
348   if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) ||
349       (!xdr_opaque_auth (xdrs, &(auth->ah_verf))))
350     perror (_("auth_unix.c: Fatal marshalling problem"));
351   else
352     au->au_mpos = XDR_GETPOS (xdrs);
353 
354   XDR_DESTROY (xdrs);
355 
356   return TRUE;
357 }
358