root/net/sunrpc/svcauth.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. svc_get_auth_ops
  2. svc_put_auth_ops
  3. svc_authenticate
  4. svc_set_client
  5. svc_authorise
  6. svc_auth_register
  7. svc_auth_unregister
  8. auth_domain_release
  9. auth_domain_put
  10. auth_domain_lookup
  11. auth_domain_find

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * linux/net/sunrpc/svcauth.c
   4  *
   5  * The generic interface for RPC authentication on the server side.
   6  *
   7  * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
   8  *
   9  * CHANGES
  10  * 19-Apr-2000 Chris Evans      - Security fix
  11  */
  12 
  13 #include <linux/types.h>
  14 #include <linux/module.h>
  15 #include <linux/sunrpc/types.h>
  16 #include <linux/sunrpc/xdr.h>
  17 #include <linux/sunrpc/svcsock.h>
  18 #include <linux/sunrpc/svcauth.h>
  19 #include <linux/err.h>
  20 #include <linux/hash.h>
  21 
  22 #define RPCDBG_FACILITY RPCDBG_AUTH
  23 
  24 
  25 /*
  26  * Table of authenticators
  27  */
  28 extern struct auth_ops svcauth_null;
  29 extern struct auth_ops svcauth_unix;
  30 
  31 static struct auth_ops __rcu *authtab[RPC_AUTH_MAXFLAVOR] = {
  32         [RPC_AUTH_NULL] = (struct auth_ops __force __rcu *)&svcauth_null,
  33         [RPC_AUTH_UNIX] = (struct auth_ops __force __rcu *)&svcauth_unix,
  34 };
  35 
  36 static struct auth_ops *
  37 svc_get_auth_ops(rpc_authflavor_t flavor)
  38 {
  39         struct auth_ops         *aops;
  40 
  41         if (flavor >= RPC_AUTH_MAXFLAVOR)
  42                 return NULL;
  43         rcu_read_lock();
  44         aops = rcu_dereference(authtab[flavor]);
  45         if (aops != NULL && !try_module_get(aops->owner))
  46                 aops = NULL;
  47         rcu_read_unlock();
  48         return aops;
  49 }
  50 
  51 static void
  52 svc_put_auth_ops(struct auth_ops *aops)
  53 {
  54         module_put(aops->owner);
  55 }
  56 
  57 int
  58 svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
  59 {
  60         rpc_authflavor_t        flavor;
  61         struct auth_ops         *aops;
  62 
  63         *authp = rpc_auth_ok;
  64 
  65         flavor = svc_getnl(&rqstp->rq_arg.head[0]);
  66 
  67         dprintk("svc: svc_authenticate (%d)\n", flavor);
  68 
  69         aops = svc_get_auth_ops(flavor);
  70         if (aops == NULL) {
  71                 *authp = rpc_autherr_badcred;
  72                 return SVC_DENIED;
  73         }
  74 
  75         rqstp->rq_auth_slack = 0;
  76         init_svc_cred(&rqstp->rq_cred);
  77 
  78         rqstp->rq_authop = aops;
  79         return aops->accept(rqstp, authp);
  80 }
  81 EXPORT_SYMBOL_GPL(svc_authenticate);
  82 
  83 int svc_set_client(struct svc_rqst *rqstp)
  84 {
  85         rqstp->rq_client = NULL;
  86         return rqstp->rq_authop->set_client(rqstp);
  87 }
  88 EXPORT_SYMBOL_GPL(svc_set_client);
  89 
  90 /* A request, which was authenticated, has now executed.
  91  * Time to finalise the credentials and verifier
  92  * and release and resources
  93  */
  94 int svc_authorise(struct svc_rqst *rqstp)
  95 {
  96         struct auth_ops *aops = rqstp->rq_authop;
  97         int rv = 0;
  98 
  99         rqstp->rq_authop = NULL;
 100 
 101         if (aops) {
 102                 rv = aops->release(rqstp);
 103                 svc_put_auth_ops(aops);
 104         }
 105         return rv;
 106 }
 107 
 108 int
 109 svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
 110 {
 111         struct auth_ops *old;
 112         int rv = -EINVAL;
 113 
 114         if (flavor < RPC_AUTH_MAXFLAVOR) {
 115                 old = cmpxchg((struct auth_ops ** __force)&authtab[flavor], NULL, aops);
 116                 if (old == NULL || old == aops)
 117                         rv = 0;
 118         }
 119         return rv;
 120 }
 121 EXPORT_SYMBOL_GPL(svc_auth_register);
 122 
 123 void
 124 svc_auth_unregister(rpc_authflavor_t flavor)
 125 {
 126         if (flavor < RPC_AUTH_MAXFLAVOR)
 127                 rcu_assign_pointer(authtab[flavor], NULL);
 128 }
 129 EXPORT_SYMBOL_GPL(svc_auth_unregister);
 130 
 131 /**************************************************
 132  * 'auth_domains' are stored in a hash table indexed by name.
 133  * When the last reference to an 'auth_domain' is dropped,
 134  * the object is unhashed and freed.
 135  * If auth_domain_lookup fails to find an entry, it will return
 136  * it's second argument 'new'.  If this is non-null, it will
 137  * have been atomically linked into the table.
 138  */
 139 
 140 #define DN_HASHBITS     6
 141 #define DN_HASHMAX      (1<<DN_HASHBITS)
 142 
 143 static struct hlist_head        auth_domain_table[DN_HASHMAX];
 144 static DEFINE_SPINLOCK(auth_domain_lock);
 145 
 146 static void auth_domain_release(struct kref *kref)
 147         __releases(&auth_domain_lock)
 148 {
 149         struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
 150 
 151         hlist_del_rcu(&dom->hash);
 152         dom->flavour->domain_release(dom);
 153         spin_unlock(&auth_domain_lock);
 154 }
 155 
 156 void auth_domain_put(struct auth_domain *dom)
 157 {
 158         kref_put_lock(&dom->ref, auth_domain_release, &auth_domain_lock);
 159 }
 160 EXPORT_SYMBOL_GPL(auth_domain_put);
 161 
 162 struct auth_domain *
 163 auth_domain_lookup(char *name, struct auth_domain *new)
 164 {
 165         struct auth_domain *hp;
 166         struct hlist_head *head;
 167 
 168         head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
 169 
 170         spin_lock(&auth_domain_lock);
 171 
 172         hlist_for_each_entry(hp, head, hash) {
 173                 if (strcmp(hp->name, name)==0) {
 174                         kref_get(&hp->ref);
 175                         spin_unlock(&auth_domain_lock);
 176                         return hp;
 177                 }
 178         }
 179         if (new)
 180                 hlist_add_head_rcu(&new->hash, head);
 181         spin_unlock(&auth_domain_lock);
 182         return new;
 183 }
 184 EXPORT_SYMBOL_GPL(auth_domain_lookup);
 185 
 186 struct auth_domain *auth_domain_find(char *name)
 187 {
 188         struct auth_domain *hp;
 189         struct hlist_head *head;
 190 
 191         head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
 192 
 193         rcu_read_lock();
 194         hlist_for_each_entry_rcu(hp, head, hash) {
 195                 if (strcmp(hp->name, name)==0) {
 196                         if (!kref_get_unless_zero(&hp->ref))
 197                                 hp = NULL;
 198                         rcu_read_unlock();
 199                         return hp;
 200                 }
 201         }
 202         rcu_read_unlock();
 203         return NULL;
 204 }
 205 EXPORT_SYMBOL_GPL(auth_domain_find);

/* [<][>][^][v][top][bottom][index][help] */