* wcsmbs/bits/wchar2.h: Add definitions for wcrtomb, mbsrtowcs,
[platform/upstream/glibc.git] / sunrpc / auth_unix.c
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.
8  *
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.
12  *
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.
16  *
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.
20  *
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.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  */
29 /*
30  * Copyright (C) 1984, Sun Microsystems, Inc.
31  */
32 /*
33  * auth_unix.c, Implements UNIX style authentication parameters.
34  *
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.
39  */
40
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>
49
50 #include <rpc/types.h>
51 #include <rpc/xdr.h>
52 #include <rpc/auth.h>
53 #include <rpc/auth_unix.h>
54
55 #ifdef USE_IN_LIBIO
56 # include <wchar.h>
57 #endif
58
59 /*
60  * Unix authenticator operations vector
61  */
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 *);
67
68 static struct auth_ops auth_unix_ops = {
69   authunix_nextverf,
70   authunix_marshal,
71   authunix_validate,
72   authunix_refresh,
73   authunix_destroy
74 };
75
76 /*
77  * This struct is pointed to by the ah_private field of an auth_handle.
78  */
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 */
85 };
86 #define AUTH_PRIVATE(auth)      ((struct audata *)auth->ah_private)
87
88 static bool_t marshal_new_auth (AUTH *) internal_function;
89
90
91 /*
92  * Create a unix style authenticator.
93  * Returns an auth handle with the given stuff in it.
94  */
95 AUTH *
96 authunix_create (char *machname, uid_t uid, gid_t gid, int len,
97                  gid_t *aup_gids)
98 {
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;
105
106   /*
107    * Allocate and set up auth handle
108    */
109   auth = (AUTH *) mem_alloc (sizeof (*auth));
110   au = (struct audata *) mem_alloc (sizeof (*au));
111   if (auth == NULL || au == NULL)
112     {
113 no_memory:
114       (void) __fxprintf (NULL, "%s", L"%s",
115                          _("authunix_create: out of memory\n"));
116       mem_free (auth, sizeof (*auth));
117       mem_free (au, sizeof (*au));
118       return NULL;
119     }
120   auth->ah_ops = &auth_unix_ops;
121   auth->ah_private = (caddr_t) au;
122   auth->ah_verf = au->au_shcred = _null_auth;
123   au->au_shfaults = 0;
124
125   /*
126    * fill in param struct from the given params
127    */
128   (void) __gettimeofday (&now, (struct timezone *) 0);
129   aup.aup_time = now.tv_sec;
130   aup.aup_machname = machname;
131   aup.aup_uid = uid;
132   aup.aup_gid = gid;
133   aup.aup_len = (u_int) len;
134   aup.aup_gids = aup_gids;
135
136   /*
137    * Serialize the parameters into origcred
138    */
139   INTUSE(xdrmem_create) (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
140   if (!INTUSE(xdr_authunix_parms) (&xdrs, &aup))
141     abort ();
142   au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
143   au->au_origcred.oa_flavor = AUTH_UNIX;
144   au->au_origcred.oa_base = mem_alloc ((u_int) len);
145   if (au->au_origcred.oa_base == NULL)
146     goto no_memory;
147   memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
148
149   /*
150    * set auth handle to reflect new cred.
151    */
152   auth->ah_cred = au->au_origcred;
153   marshal_new_auth (auth);
154   return auth;
155 }
156 INTDEF (authunix_create)
157
158 /*
159  * Returns an auth handle with parameters determined by doing lots of
160  * syscalls.
161  */
162 AUTH *
163 authunix_create_default (void)
164 {
165   char machname[MAX_MACHINE_NAME + 1];
166
167   if (__gethostname (machname, MAX_MACHINE_NAME) == -1)
168     abort ();
169   machname[MAX_MACHINE_NAME] = 0;
170   uid_t uid = __geteuid ();
171   gid_t gid = __getegid ();
172
173   int max_nr_groups;
174   /* When we have to try a second time, do not use alloca() again.  We
175      might have reached the stack limit already.  */
176   bool retry = false;
177  again:
178   /* Ask the kernel how many groups there are exactly.  Note that we
179      might have to redo all this if the number of groups has changed
180      between the two calls.  */
181   max_nr_groups = __getgroups (0, NULL);
182
183   /* Just some random reasonable stack limit.  */
184 #define ALLOCA_LIMIT (1024 / sizeof (gid_t))
185   gid_t *gids = NULL;
186   if (max_nr_groups < ALLOCA_LIMIT && ! retry)
187     gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t));
188   else
189     {
190       gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
191       if (gids == NULL)
192         return NULL;
193     }
194
195   int len = __getgroups (max_nr_groups, gids);
196   if (len == -1)
197     {
198       if (errno == EINVAL)
199         {
200           /* New groups added in the meantime.  Try again.  */
201           if (max_nr_groups >= ALLOCA_LIMIT || retry)
202             free (gids);
203           retry = true;
204           goto again;
205         }
206       /* No other error can happen.  */
207       abort ();
208     }
209
210   /* This braindamaged Sun code forces us here to truncate the
211      list of groups to NGRPS members since the code in
212      authuxprot.c transforms a fixed array.  Grrr.  */
213   AUTH *result = INTUSE(authunix_create) (machname, uid, gid, MIN (NGRPS, len),
214                                           gids);
215
216   if (max_nr_groups >= ALLOCA_LIMIT || retry)
217     free (gids);
218
219   return result;
220 }
221 INTDEF (authunix_create_default)
222
223 /*
224  * authunix operations
225  */
226
227 static void
228 authunix_nextverf (AUTH *auth)
229 {
230   /* no action necessary */
231 }
232
233 static bool_t
234 authunix_marshal (AUTH *auth, XDR *xdrs)
235 {
236   struct audata *au = AUTH_PRIVATE (auth);
237
238   return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
239 }
240
241 static bool_t
242 authunix_validate (AUTH *auth, struct opaque_auth *verf)
243 {
244   struct audata *au;
245   XDR xdrs;
246
247   if (verf->oa_flavor == AUTH_SHORT)
248     {
249       au = AUTH_PRIVATE (auth);
250       INTUSE(xdrmem_create) (&xdrs, verf->oa_base, verf->oa_length,
251                              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 (INTUSE(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) INTUSE(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
276 authunix_refresh (AUTH *auth)
277 {
278   struct audata *au = AUTH_PRIVATE (auth);
279   struct authunix_parms aup;
280   struct timeval 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   INTUSE(xdrmem_create) (&xdrs, au->au_origcred.oa_base,
295                          au->au_origcred.oa_length, XDR_DECODE);
296   stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
297   if (!stat)
298     goto done;
299
300   /* update the time and serialize in place */
301   (void) __gettimeofday (&now, (struct timezone *) 0);
302   aup.aup_time = now.tv_sec;
303   xdrs.x_op = XDR_ENCODE;
304   XDR_SETPOS (&xdrs, 0);
305   stat = INTUSE(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) INTUSE(xdr_authunix_parms) (&xdrs, &aup);
314   XDR_DESTROY (&xdrs);
315   return stat;
316 }
317
318 static void
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
341 internal_function
342 marshal_new_auth (AUTH *auth)
343 {
344   XDR xdr_stream;
345   XDR *xdrs = &xdr_stream;
346   struct audata *au = AUTH_PRIVATE (auth);
347
348   INTUSE(xdrmem_create) (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
349   if ((!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_cred))) ||
350       (!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_verf))))
351     perror (_("auth_none.c - Fatal marshalling problem"));
352   else
353     au->au_mpos = XDR_GETPOS (xdrs);
354
355   XDR_DESTROY (xdrs);
356
357   return TRUE;
358 }