The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/rpc/auth_unix.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 2009, Sun Microsystems, Inc.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without 
    8  * modification, are permitted provided that the following conditions are met:
    9  * - Redistributions of source code must retain the above copyright notice, 
   10  *   this list of conditions and the following disclaimer.
   11  * - Redistributions in binary form must reproduce the above copyright notice, 
   12  *   this list of conditions and the following disclaimer in the documentation 
   13  *   and/or other materials 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.
   17  * 
   18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
   19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
   21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 
   22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
   23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
   24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
   25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 #if defined(LIBC_SCCS) && !defined(lint)
   32 static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
   33 static char *sccsid = "@(#)auth_unix.c  2.2 88/08/01 4.0 RPCSRC";
   34 #endif
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/10.4/sys/rpc/auth_unix.c 261046 2014-01-22 23:45:27Z mav $");
   37 
   38 /*
   39  * auth_unix.c, Implements UNIX style authentication parameters.
   40  *
   41  * Copyright (C) 1984, Sun Microsystems, Inc.
   42  *
   43  * The system is very weak.  The client uses no encryption for it's
   44  * credentials and only sends null verifiers.  The server sends backs
   45  * null verifiers or optionally a verifier that suggests a new short hand
   46  * for the credentials.
   47  *
   48  */
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/hash.h>
   53 #include <sys/kernel.h>
   54 #include <sys/lock.h>
   55 #include <sys/malloc.h>
   56 #include <sys/pcpu.h>
   57 #include <sys/refcount.h>
   58 #include <sys/sx.h>
   59 #include <sys/ucred.h>
   60 
   61 #include <rpc/types.h>
   62 #include <rpc/xdr.h>
   63 #include <rpc/auth.h>
   64 #include <rpc/clnt.h>
   65 
   66 #include <rpc/rpc_com.h>
   67 
   68 /* auth_unix.c */
   69 static void authunix_nextverf (AUTH *);
   70 static bool_t authunix_marshal (AUTH *, uint32_t, XDR *, struct mbuf *);
   71 static bool_t authunix_validate (AUTH *, uint32_t, struct opaque_auth *,
   72     struct mbuf **);
   73 static bool_t authunix_refresh (AUTH *, void *);
   74 static void authunix_destroy (AUTH *);
   75 static void marshal_new_auth (AUTH *);
   76 
   77 static struct auth_ops authunix_ops = {
   78         .ah_nextverf =          authunix_nextverf,
   79         .ah_marshal =           authunix_marshal,
   80         .ah_validate =          authunix_validate,
   81         .ah_refresh =           authunix_refresh,
   82         .ah_destroy =           authunix_destroy,
   83 };
   84 
   85 /*
   86  * This struct is pointed to by the ah_private field of an auth_handle.
   87  */
   88 struct audata {
   89         TAILQ_ENTRY(audata)     au_link;
   90         TAILQ_ENTRY(audata)     au_alllink;
   91         volatile u_int          au_refs;
   92         struct xucred           au_xcred;
   93         struct opaque_auth      au_origcred;    /* original credentials */
   94         struct opaque_auth      au_shcred;      /* short hand cred */
   95         u_long                  au_shfaults;    /* short hand cache faults */
   96         char                    au_marshed[MAX_AUTH_BYTES];
   97         u_int                   au_mpos;        /* xdr pos at end of marshed */
   98         AUTH                    *au_auth;       /* link back to AUTH */
   99 };
  100 TAILQ_HEAD(audata_list, audata);
  101 #define AUTH_PRIVATE(auth)      ((struct audata *)auth->ah_private)
  102 
  103 #define AUTH_UNIX_HASH_SIZE     16
  104 #define AUTH_UNIX_MAX           256
  105 static struct audata_list auth_unix_cache[AUTH_UNIX_HASH_SIZE];
  106 static struct audata_list auth_unix_all;
  107 static struct sx auth_unix_lock;
  108 static int auth_unix_count;
  109 
  110 static void
  111 authunix_init(void *dummy)
  112 {
  113         int i;
  114 
  115         for (i = 0; i < AUTH_UNIX_HASH_SIZE; i++)
  116                 TAILQ_INIT(&auth_unix_cache[i]);
  117         TAILQ_INIT(&auth_unix_all);
  118         sx_init(&auth_unix_lock, "auth_unix_lock");
  119 }
  120 SYSINIT(authunix_init, SI_SUB_KMEM, SI_ORDER_ANY, authunix_init, NULL);
  121 
  122 /*
  123  * Create a unix style authenticator.
  124  * Returns an auth handle with the given stuff in it.
  125  */
  126 AUTH *
  127 authunix_create(struct ucred *cred)
  128 {
  129         uint32_t h, th;
  130         struct xucred xcr;
  131         char mymem[MAX_AUTH_BYTES];
  132         XDR xdrs;
  133         AUTH *auth;
  134         struct audata *au, *tau;
  135         struct timeval now;
  136         uint32_t time;
  137         int len;
  138 
  139         if (auth_unix_count > AUTH_UNIX_MAX) {
  140                 while (auth_unix_count > AUTH_UNIX_MAX) {
  141                         sx_xlock(&auth_unix_lock);
  142                         tau = TAILQ_FIRST(&auth_unix_all);
  143                         th = HASHSTEP(HASHINIT, tau->au_xcred.cr_uid)
  144                                 % AUTH_UNIX_HASH_SIZE;
  145                         TAILQ_REMOVE(&auth_unix_cache[th], tau, au_link);
  146                         TAILQ_REMOVE(&auth_unix_all, tau, au_alllink);
  147                         auth_unix_count--;
  148                         sx_xunlock(&auth_unix_lock);
  149                         AUTH_DESTROY(tau->au_auth);
  150                 }
  151         }
  152 
  153         /*
  154          * Hash the uid to see if we already have an AUTH with this cred.
  155          */
  156         h = HASHSTEP(HASHINIT, cred->cr_uid) % AUTH_UNIX_HASH_SIZE;
  157         cru2x(cred, &xcr);
  158 again:
  159         sx_slock(&auth_unix_lock);
  160         TAILQ_FOREACH(au, &auth_unix_cache[h], au_link) {
  161                 if (!memcmp(&xcr, &au->au_xcred, sizeof(xcr))) {
  162                         refcount_acquire(&au->au_refs);
  163                         if (sx_try_upgrade(&auth_unix_lock)) {
  164                                 /*
  165                                  * Keep auth_unix_all LRU sorted.
  166                                  */
  167                                 TAILQ_REMOVE(&auth_unix_all, au, au_alllink);
  168                                 TAILQ_INSERT_TAIL(&auth_unix_all, au,
  169                                     au_alllink);
  170                                 sx_xunlock(&auth_unix_lock);
  171                         } else {
  172                                 sx_sunlock(&auth_unix_lock);
  173                         }
  174                         return (au->au_auth);
  175                 }
  176         }
  177 
  178         sx_sunlock(&auth_unix_lock);
  179 
  180         /*
  181          * Allocate and set up auth handle
  182          */
  183         au = NULL;
  184         auth = mem_alloc(sizeof(*auth));
  185         au = mem_alloc(sizeof(*au));
  186         auth->ah_ops = &authunix_ops;
  187         auth->ah_private = (caddr_t)au;
  188         auth->ah_verf = au->au_shcred = _null_auth;
  189         refcount_init(&au->au_refs, 1);
  190         au->au_xcred = xcr;
  191         au->au_shfaults = 0;
  192         au->au_origcred.oa_base = NULL;
  193         au->au_auth = auth;
  194 
  195         getmicrotime(&now);
  196         time = now.tv_sec;
  197 
  198         /*
  199          * Serialize the parameters into origcred
  200          */
  201         xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
  202         cru2x(cred, &xcr);
  203         if (! xdr_authunix_parms(&xdrs, &time, &xcr)) 
  204                 panic("authunix_create: failed to encode creds");
  205         au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
  206         au->au_origcred.oa_flavor = AUTH_UNIX;
  207         au->au_origcred.oa_base = mem_alloc((u_int) len);
  208         memcpy(au->au_origcred.oa_base, mymem, (size_t)len);
  209 
  210         /*
  211          * set auth handle to reflect new cred.
  212          */
  213         auth->ah_cred = au->au_origcred;
  214         marshal_new_auth(auth);
  215 
  216         sx_xlock(&auth_unix_lock);
  217         TAILQ_FOREACH(tau, &auth_unix_cache[h], au_link) {
  218                 if (!memcmp(&xcr, &tau->au_xcred, sizeof(xcr))) {
  219                         /*
  220                          * We lost a race to create the AUTH that
  221                          * matches this cred.
  222                          */
  223                         sx_xunlock(&auth_unix_lock);
  224                         AUTH_DESTROY(auth);
  225                         goto again;
  226                 }
  227         }
  228 
  229         auth_unix_count++;
  230         TAILQ_INSERT_TAIL(&auth_unix_cache[h], au, au_link);
  231         TAILQ_INSERT_TAIL(&auth_unix_all, au, au_alllink);
  232         refcount_acquire(&au->au_refs); /* one for the cache, one for user */
  233         sx_xunlock(&auth_unix_lock);
  234 
  235         return (auth);
  236 }
  237 
  238 /*
  239  * authunix operations
  240  */
  241 
  242 /* ARGSUSED */
  243 static void
  244 authunix_nextverf(AUTH *auth)
  245 {
  246         /* no action necessary */
  247 }
  248 
  249 static bool_t
  250 authunix_marshal(AUTH *auth, uint32_t xid, XDR *xdrs, struct mbuf *args)
  251 {
  252         struct audata *au;
  253 
  254         au = AUTH_PRIVATE(auth);
  255         if (!XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos))
  256                 return (FALSE);
  257 
  258         xdrmbuf_append(xdrs, args);
  259 
  260         return (TRUE);
  261 }
  262 
  263 static bool_t
  264 authunix_validate(AUTH *auth, uint32_t xid, struct opaque_auth *verf,
  265     struct mbuf **mrepp)
  266 {
  267         struct audata *au;
  268         XDR txdrs;
  269 
  270         if (!verf)
  271                 return (TRUE);
  272 
  273         if (verf->oa_flavor == AUTH_SHORT) {
  274                 au = AUTH_PRIVATE(auth);
  275                 xdrmem_create(&txdrs, verf->oa_base, verf->oa_length,
  276                     XDR_DECODE);
  277 
  278                 if (au->au_shcred.oa_base != NULL) {
  279                         mem_free(au->au_shcred.oa_base,
  280                             au->au_shcred.oa_length);
  281                         au->au_shcred.oa_base = NULL;
  282                 }
  283                 if (xdr_opaque_auth(&txdrs, &au->au_shcred)) {
  284                         auth->ah_cred = au->au_shcred;
  285                 } else {
  286                         txdrs.x_op = XDR_FREE;
  287                         (void)xdr_opaque_auth(&txdrs, &au->au_shcred);
  288                         au->au_shcred.oa_base = NULL;
  289                         auth->ah_cred = au->au_origcred;
  290                 }
  291                 marshal_new_auth(auth);
  292         }
  293 
  294         return (TRUE);
  295 }
  296 
  297 static bool_t
  298 authunix_refresh(AUTH *auth, void *dummy)
  299 {
  300         struct audata *au = AUTH_PRIVATE(auth);
  301         struct xucred xcr;
  302         uint32_t time;
  303         struct timeval now;
  304         XDR xdrs;
  305         int stat;
  306 
  307         if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
  308                 /* there is no hope.  Punt */
  309                 return (FALSE);
  310         }
  311         au->au_shfaults ++;
  312 
  313         /* first deserialize the creds back into a struct ucred */
  314         xdrmem_create(&xdrs, au->au_origcred.oa_base,
  315             au->au_origcred.oa_length, XDR_DECODE);
  316         stat = xdr_authunix_parms(&xdrs, &time, &xcr);
  317         if (! stat)
  318                 goto done;
  319 
  320         /* update the time and serialize in place */
  321         getmicrotime(&now);
  322         time = now.tv_sec;
  323         xdrs.x_op = XDR_ENCODE;
  324         XDR_SETPOS(&xdrs, 0);
  325 
  326         stat = xdr_authunix_parms(&xdrs, &time, &xcr);
  327         if (! stat)
  328                 goto done;
  329         auth->ah_cred = au->au_origcred;
  330         marshal_new_auth(auth);
  331 done:
  332         XDR_DESTROY(&xdrs);
  333         return (stat);
  334 }
  335 
  336 static void
  337 authunix_destroy(AUTH *auth)
  338 {
  339         struct audata *au;
  340 
  341         au = AUTH_PRIVATE(auth);
  342 
  343         if (!refcount_release(&au->au_refs))
  344                 return;
  345 
  346         mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
  347 
  348         if (au->au_shcred.oa_base != NULL)
  349                 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
  350 
  351         mem_free(auth->ah_private, sizeof(struct audata));
  352 
  353         if (auth->ah_verf.oa_base != NULL)
  354                 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
  355 
  356         mem_free(auth, sizeof(*auth));
  357 }
  358 
  359 /*
  360  * Marshals (pre-serializes) an auth struct.
  361  * sets private data, au_marshed and au_mpos
  362  */
  363 static void
  364 marshal_new_auth(AUTH *auth)
  365 {
  366         XDR     xdr_stream;
  367         XDR     *xdrs = &xdr_stream;
  368         struct audata *au;
  369 
  370         au = AUTH_PRIVATE(auth);
  371         xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
  372         if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
  373             (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
  374                 printf("auth_none.c - Fatal marshalling problem");
  375         else
  376                 au->au_mpos = XDR_GETPOS(xdrs);
  377         XDR_DESTROY(xdrs);
  378 }

Cache object: b0c602bd3e6922f6fd814feba956dca7


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.