svcauth.c 5.4 KB

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