svcauth.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. #include <linux/types.h>
  13. #include <linux/module.h>
  14. #include <linux/sunrpc/types.h>
  15. #include <linux/sunrpc/xdr.h>
  16. #include <linux/sunrpc/svcsock.h>
  17. #include <linux/sunrpc/svcauth.h>
  18. #include <linux/err.h>
  19. #include <linux/hash.h>
  20. #include <trace/events/sunrpc.h>
  21. #include "sunrpc.h"
  22. #define RPCDBG_FACILITY RPCDBG_AUTH
  23. /*
  24. * Table of authenticators
  25. */
  26. extern struct auth_ops svcauth_null;
  27. extern struct auth_ops svcauth_unix;
  28. static struct auth_ops __rcu *authtab[RPC_AUTH_MAXFLAVOR] = {
  29. [RPC_AUTH_NULL] = (struct auth_ops __force __rcu *)&svcauth_null,
  30. [RPC_AUTH_UNIX] = (struct auth_ops __force __rcu *)&svcauth_unix,
  31. };
  32. static struct auth_ops *
  33. svc_get_auth_ops(rpc_authflavor_t flavor)
  34. {
  35. struct auth_ops *aops;
  36. if (flavor >= RPC_AUTH_MAXFLAVOR)
  37. return NULL;
  38. rcu_read_lock();
  39. aops = rcu_dereference(authtab[flavor]);
  40. if (aops != NULL && !try_module_get(aops->owner))
  41. aops = NULL;
  42. rcu_read_unlock();
  43. return aops;
  44. }
  45. static void
  46. svc_put_auth_ops(struct auth_ops *aops)
  47. {
  48. module_put(aops->owner);
  49. }
  50. int
  51. svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
  52. {
  53. rpc_authflavor_t flavor;
  54. struct auth_ops *aops;
  55. *authp = rpc_auth_ok;
  56. flavor = svc_getnl(&rqstp->rq_arg.head[0]);
  57. dprintk("svc: svc_authenticate (%d)\n", flavor);
  58. aops = svc_get_auth_ops(flavor);
  59. if (aops == NULL) {
  60. *authp = rpc_autherr_badcred;
  61. return SVC_DENIED;
  62. }
  63. rqstp->rq_auth_slack = 0;
  64. init_svc_cred(&rqstp->rq_cred);
  65. rqstp->rq_authop = aops;
  66. return aops->accept(rqstp, authp);
  67. }
  68. EXPORT_SYMBOL_GPL(svc_authenticate);
  69. int svc_set_client(struct svc_rqst *rqstp)
  70. {
  71. rqstp->rq_client = NULL;
  72. return rqstp->rq_authop->set_client(rqstp);
  73. }
  74. EXPORT_SYMBOL_GPL(svc_set_client);
  75. /* A request, which was authenticated, has now executed.
  76. * Time to finalise the credentials and verifier
  77. * and release and resources
  78. */
  79. int svc_authorise(struct svc_rqst *rqstp)
  80. {
  81. struct auth_ops *aops = rqstp->rq_authop;
  82. int rv = 0;
  83. rqstp->rq_authop = NULL;
  84. if (aops) {
  85. rv = aops->release(rqstp);
  86. svc_put_auth_ops(aops);
  87. }
  88. return rv;
  89. }
  90. int
  91. svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
  92. {
  93. struct auth_ops *old;
  94. int rv = -EINVAL;
  95. if (flavor < RPC_AUTH_MAXFLAVOR) {
  96. old = cmpxchg((struct auth_ops ** __force)&authtab[flavor], NULL, aops);
  97. if (old == NULL || old == aops)
  98. rv = 0;
  99. }
  100. return rv;
  101. }
  102. EXPORT_SYMBOL_GPL(svc_auth_register);
  103. void
  104. svc_auth_unregister(rpc_authflavor_t flavor)
  105. {
  106. if (flavor < RPC_AUTH_MAXFLAVOR)
  107. rcu_assign_pointer(authtab[flavor], NULL);
  108. }
  109. EXPORT_SYMBOL_GPL(svc_auth_unregister);
  110. /**************************************************
  111. * 'auth_domains' are stored in a hash table indexed by name.
  112. * When the last reference to an 'auth_domain' is dropped,
  113. * the object is unhashed and freed.
  114. * If auth_domain_lookup fails to find an entry, it will return
  115. * it's second argument 'new'. If this is non-null, it will
  116. * have been atomically linked into the table.
  117. */
  118. #define DN_HASHBITS 6
  119. #define DN_HASHMAX (1<<DN_HASHBITS)
  120. static struct hlist_head auth_domain_table[DN_HASHMAX];
  121. static DEFINE_SPINLOCK(auth_domain_lock);
  122. static void auth_domain_release(struct kref *kref)
  123. __releases(&auth_domain_lock)
  124. {
  125. struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
  126. hlist_del_rcu(&dom->hash);
  127. dom->flavour->domain_release(dom);
  128. spin_unlock(&auth_domain_lock);
  129. }
  130. void auth_domain_put(struct auth_domain *dom)
  131. {
  132. kref_put_lock(&dom->ref, auth_domain_release, &auth_domain_lock);
  133. }
  134. EXPORT_SYMBOL_GPL(auth_domain_put);
  135. struct auth_domain *
  136. auth_domain_lookup(char *name, struct auth_domain *new)
  137. {
  138. struct auth_domain *hp;
  139. struct hlist_head *head;
  140. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  141. spin_lock(&auth_domain_lock);
  142. hlist_for_each_entry(hp, head, hash) {
  143. if (strcmp(hp->name, name)==0) {
  144. kref_get(&hp->ref);
  145. spin_unlock(&auth_domain_lock);
  146. return hp;
  147. }
  148. }
  149. if (new)
  150. hlist_add_head_rcu(&new->hash, head);
  151. spin_unlock(&auth_domain_lock);
  152. return new;
  153. }
  154. EXPORT_SYMBOL_GPL(auth_domain_lookup);
  155. struct auth_domain *auth_domain_find(char *name)
  156. {
  157. struct auth_domain *hp;
  158. struct hlist_head *head;
  159. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  160. rcu_read_lock();
  161. hlist_for_each_entry_rcu(hp, head, hash) {
  162. if (strcmp(hp->name, name)==0) {
  163. if (!kref_get_unless_zero(&hp->ref))
  164. hp = NULL;
  165. rcu_read_unlock();
  166. return hp;
  167. }
  168. }
  169. rcu_read_unlock();
  170. return NULL;
  171. }
  172. EXPORT_SYMBOL_GPL(auth_domain_find);
  173. /**
  174. * auth_domain_cleanup - check that the auth_domain table is empty
  175. *
  176. * On module unload the auth_domain_table must be empty. To make it
  177. * easier to catch bugs which don't clean up domains properly, we
  178. * warn if anything remains in the table at cleanup time.
  179. *
  180. * Note that we cannot proactively remove the domains at this stage.
  181. * The ->release() function might be in a module that has already been
  182. * unloaded.
  183. */
  184. void auth_domain_cleanup(void)
  185. {
  186. int h;
  187. struct auth_domain *hp;
  188. for (h = 0; h < DN_HASHMAX; h++)
  189. hlist_for_each_entry(hp, &auth_domain_table[h], hash)
  190. pr_warn("svc: domain %s still present at module unload.\n",
  191. hp->name);
  192. }