Back to index

glibc  2.9
auth_unix.c
Go to the documentation of this file.
00001 /*
00002  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
00003  * unrestricted use provided that this legend is included on all tape
00004  * media and as a part of the software program in whole or part.  Users
00005  * may copy or modify Sun RPC without charge, but are not authorized
00006  * to license or distribute it to anyone else except as part of a product or
00007  * program developed by the user.
00008  *
00009  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
00010  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
00011  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
00012  *
00013  * Sun RPC is provided with no support and without any obligation on the
00014  * part of Sun Microsystems, Inc. to assist in its use, correction,
00015  * modification or enhancement.
00016  *
00017  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
00018  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
00019  * OR ANY PART THEREOF.
00020  *
00021  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
00022  * or profits or other special, indirect and consequential damages, even if
00023  * Sun has been advised of the possibility of such damages.
00024  *
00025  * Sun Microsystems, Inc.
00026  * 2550 Garcia Avenue
00027  * Mountain View, California  94043
00028  */
00029 /*
00030  * Copyright (C) 1984, Sun Microsystems, Inc.
00031  */
00032 /*
00033  * auth_unix.c, Implements UNIX style authentication parameters.
00034  *
00035  * The system is very weak.  The client uses no encryption for it's
00036  * credentials and only sends null verifiers.  The server sends backs
00037  * null verifiers or optionally a verifier that suggests a new short hand
00038  * for the credentials.
00039  */
00040 
00041 #include <errno.h>
00042 #include <limits.h>
00043 #include <stdbool.h>
00044 #include <stdio.h>
00045 #include <string.h>
00046 #include <unistd.h>
00047 #include <libintl.h>
00048 #include <sys/param.h>
00049 
00050 #include <rpc/types.h>
00051 #include <rpc/xdr.h>
00052 #include <rpc/auth.h>
00053 #include <rpc/auth_unix.h>
00054 
00055 #ifdef USE_IN_LIBIO
00056 # include <wchar.h>
00057 #endif
00058 
00059 /*
00060  * Unix authenticator operations vector
00061  */
00062 static void authunix_nextverf (AUTH *);
00063 static bool_t authunix_marshal (AUTH *, XDR *);
00064 static bool_t authunix_validate (AUTH *, struct opaque_auth *);
00065 static bool_t authunix_refresh (AUTH *);
00066 static void authunix_destroy (AUTH *);
00067 
00068 static const struct auth_ops auth_unix_ops = {
00069   authunix_nextverf,
00070   authunix_marshal,
00071   authunix_validate,
00072   authunix_refresh,
00073   authunix_destroy
00074 };
00075 
00076 /*
00077  * This struct is pointed to by the ah_private field of an auth_handle.
00078  */
00079 struct audata {
00080   struct opaque_auth au_origcred;  /* original credentials */
00081   struct opaque_auth au_shcred;    /* short hand cred */
00082   u_long au_shfaults;              /* short hand cache faults */
00083   char au_marshed[MAX_AUTH_BYTES];
00084   u_int au_mpos;            /* xdr pos at end of marshed */
00085 };
00086 #define       AUTH_PRIVATE(auth)   ((struct audata *)auth->ah_private)
00087 
00088 static bool_t marshal_new_auth (AUTH *) internal_function;
00089 
00090 
00091 /*
00092  * Create a unix style authenticator.
00093  * Returns an auth handle with the given stuff in it.
00094  */
00095 AUTH *
00096 authunix_create (char *machname, uid_t uid, gid_t gid, int len,
00097                gid_t *aup_gids)
00098 {
00099   struct authunix_parms aup;
00100   char mymem[MAX_AUTH_BYTES];
00101   struct timeval now;
00102   XDR xdrs;
00103   AUTH *auth;
00104   struct audata *au;
00105 
00106   /*
00107    * Allocate and set up auth handle
00108    */
00109   auth = (AUTH *) mem_alloc (sizeof (*auth));
00110   au = (struct audata *) mem_alloc (sizeof (*au));
00111   if (auth == NULL || au == NULL)
00112     {
00113 no_memory:
00114       (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
00115       mem_free (auth, sizeof (*auth));
00116       mem_free (au, sizeof (*au));
00117       return NULL;
00118     }
00119   auth->ah_ops = (struct auth_ops *) &auth_unix_ops;
00120   auth->ah_private = (caddr_t) au;
00121   auth->ah_verf = au->au_shcred = _null_auth;
00122   au->au_shfaults = 0;
00123 
00124   /*
00125    * fill in param struct from the given params
00126    */
00127   (void) __gettimeofday (&now, (struct timezone *) 0);
00128   aup.aup_time = now.tv_sec;
00129   aup.aup_machname = machname;
00130   aup.aup_uid = uid;
00131   aup.aup_gid = gid;
00132   aup.aup_len = (u_int) len;
00133   aup.aup_gids = aup_gids;
00134 
00135   /*
00136    * Serialize the parameters into origcred
00137    */
00138   INTUSE(xdrmem_create) (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
00139   if (!INTUSE(xdr_authunix_parms) (&xdrs, &aup))
00140     abort ();
00141   au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs);
00142   au->au_origcred.oa_flavor = AUTH_UNIX;
00143   au->au_origcred.oa_base = mem_alloc ((u_int) len);
00144   if (au->au_origcred.oa_base == NULL)
00145     goto no_memory;
00146   memcpy(au->au_origcred.oa_base, mymem, (u_int) len);
00147 
00148   /*
00149    * set auth handle to reflect new cred.
00150    */
00151   auth->ah_cred = au->au_origcred;
00152   marshal_new_auth (auth);
00153   return auth;
00154 }
00155 INTDEF (authunix_create)
00156 
00157 /*
00158  * Returns an auth handle with parameters determined by doing lots of
00159  * syscalls.
00160  */
00161 AUTH *
00162 authunix_create_default (void)
00163 {
00164   char machname[MAX_MACHINE_NAME + 1];
00165 
00166   if (__gethostname (machname, MAX_MACHINE_NAME) == -1)
00167     abort ();
00168   machname[MAX_MACHINE_NAME] = 0;
00169   uid_t uid = __geteuid ();
00170   gid_t gid = __getegid ();
00171 
00172   int max_nr_groups;
00173   /* When we have to try a second time, do not use alloca() again.  We
00174      might have reached the stack limit already.  */
00175   bool retry = false;
00176  again:
00177   /* Ask the kernel how many groups there are exactly.  Note that we
00178      might have to redo all this if the number of groups has changed
00179      between the two calls.  */
00180   max_nr_groups = __getgroups (0, NULL);
00181 
00182   /* Just some random reasonable stack limit.  */
00183 #define ALLOCA_LIMIT (1024 / sizeof (gid_t))
00184   gid_t *gids = NULL;
00185   if (max_nr_groups < ALLOCA_LIMIT && ! retry)
00186     gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t));
00187   else
00188     {
00189       gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t));
00190       if (gids == NULL)
00191        return NULL;
00192     }
00193 
00194   int len = __getgroups (max_nr_groups, gids);
00195   if (len == -1)
00196     {
00197       if (errno == EINVAL)
00198        {
00199          /* New groups added in the meantime.  Try again.  */
00200          if (max_nr_groups >= ALLOCA_LIMIT || retry)
00201            free (gids);
00202          retry = true;
00203          goto again;
00204        }
00205       /* No other error can happen.  */
00206       abort ();
00207     }
00208 
00209   /* This braindamaged Sun code forces us here to truncate the
00210      list of groups to NGRPS members since the code in
00211      authuxprot.c transforms a fixed array.  Grrr.  */
00212   AUTH *result = INTUSE(authunix_create) (machname, uid, gid, MIN (NGRPS, len),
00213                                      gids);
00214 
00215   if (max_nr_groups >= ALLOCA_LIMIT || retry)
00216     free (gids);
00217 
00218   return result;
00219 }
00220 INTDEF (authunix_create_default)
00221 
00222 /*
00223  * authunix operations
00224  */
00225 
00226 static void
00227 authunix_nextverf (AUTH *auth)
00228 {
00229   /* no action necessary */
00230 }
00231 
00232 static bool_t
00233 authunix_marshal (AUTH *auth, XDR *xdrs)
00234 {
00235   struct audata *au = AUTH_PRIVATE (auth);
00236 
00237   return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos);
00238 }
00239 
00240 static bool_t
00241 authunix_validate (AUTH *auth, struct opaque_auth *verf)
00242 {
00243   struct audata *au;
00244   XDR xdrs;
00245 
00246   if (verf->oa_flavor == AUTH_SHORT)
00247     {
00248       au = AUTH_PRIVATE (auth);
00249       INTUSE(xdrmem_create) (&xdrs, verf->oa_base, verf->oa_length,
00250                           XDR_DECODE);
00251 
00252       if (au->au_shcred.oa_base != NULL)
00253        {
00254          mem_free (au->au_shcred.oa_base,
00255                   au->au_shcred.oa_length);
00256          au->au_shcred.oa_base = NULL;
00257        }
00258       if (INTUSE(xdr_opaque_auth) (&xdrs, &au->au_shcred))
00259        {
00260          auth->ah_cred = au->au_shcred;
00261        }
00262       else
00263        {
00264          xdrs.x_op = XDR_FREE;
00265          (void) INTUSE(xdr_opaque_auth) (&xdrs, &au->au_shcred);
00266          au->au_shcred.oa_base = NULL;
00267          auth->ah_cred = au->au_origcred;
00268        }
00269       marshal_new_auth (auth);
00270     }
00271   return TRUE;
00272 }
00273 
00274 static bool_t
00275 authunix_refresh (AUTH *auth)
00276 {
00277   struct audata *au = AUTH_PRIVATE (auth);
00278   struct authunix_parms aup;
00279   struct timeval now;
00280   XDR xdrs;
00281   int stat;
00282 
00283   if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
00284     {
00285       /* there is no hope.  Punt */
00286       return FALSE;
00287     }
00288   au->au_shfaults++;
00289 
00290   /* first deserialize the creds back into a struct authunix_parms */
00291   aup.aup_machname = NULL;
00292   aup.aup_gids = (gid_t *) NULL;
00293   INTUSE(xdrmem_create) (&xdrs, au->au_origcred.oa_base,
00294                       au->au_origcred.oa_length, XDR_DECODE);
00295   stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
00296   if (!stat)
00297     goto done;
00298 
00299   /* update the time and serialize in place */
00300   (void) __gettimeofday (&now, (struct timezone *) 0);
00301   aup.aup_time = now.tv_sec;
00302   xdrs.x_op = XDR_ENCODE;
00303   XDR_SETPOS (&xdrs, 0);
00304   stat = INTUSE(xdr_authunix_parms) (&xdrs, &aup);
00305   if (!stat)
00306     goto done;
00307   auth->ah_cred = au->au_origcred;
00308   marshal_new_auth (auth);
00309 done:
00310   /* free the struct authunix_parms created by deserializing */
00311   xdrs.x_op = XDR_FREE;
00312   (void) INTUSE(xdr_authunix_parms) (&xdrs, &aup);
00313   XDR_DESTROY (&xdrs);
00314   return stat;
00315 }
00316 
00317 static void
00318 authunix_destroy (AUTH *auth)
00319 {
00320   struct audata *au = AUTH_PRIVATE (auth);
00321 
00322   mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length);
00323 
00324   if (au->au_shcred.oa_base != NULL)
00325     mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length);
00326 
00327   mem_free (auth->ah_private, sizeof (struct audata));
00328 
00329   if (auth->ah_verf.oa_base != NULL)
00330     mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length);
00331 
00332   mem_free ((caddr_t) auth, sizeof (*auth));
00333 }
00334 
00335 /*
00336  * Marshals (pre-serializes) an auth struct.
00337  * sets private data, au_marshed and au_mpos
00338  */
00339 static bool_t
00340 internal_function
00341 marshal_new_auth (AUTH *auth)
00342 {
00343   XDR xdr_stream;
00344   XDR *xdrs = &xdr_stream;
00345   struct audata *au = AUTH_PRIVATE (auth);
00346 
00347   INTUSE(xdrmem_create) (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
00348   if ((!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_cred))) ||
00349       (!INTUSE(xdr_opaque_auth) (xdrs, &(auth->ah_verf))))
00350     perror (_("auth_unix.c: Fatal marshalling problem"));
00351   else
00352     au->au_mpos = XDR_GETPOS (xdrs);
00353 
00354   XDR_DESTROY (xdrs);
00355 
00356   return TRUE;
00357 }