svcauth.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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 <linux/user_namespace.h>
  21. #include <trace/events/sunrpc.h>
  22. #include "sunrpc.h"
  23. #define RPCDBG_FACILITY RPCDBG_AUTH
  24. /*
  25. * Table of authenticators
  26. */
  27. extern struct auth_ops svcauth_null;
  28. extern struct auth_ops svcauth_unix;
  29. extern struct auth_ops svcauth_tls;
  30. static struct auth_ops __rcu *authtab[RPC_AUTH_MAXFLAVOR] = {
  31. [RPC_AUTH_NULL] = (struct auth_ops __force __rcu *)&svcauth_null,
  32. [RPC_AUTH_UNIX] = (struct auth_ops __force __rcu *)&svcauth_unix,
  33. [RPC_AUTH_TLS] = (struct auth_ops __force __rcu *)&svcauth_tls,
  34. };
  35. static struct auth_ops *
  36. svc_get_auth_ops(rpc_authflavor_t flavor)
  37. {
  38. struct auth_ops *aops;
  39. if (flavor >= RPC_AUTH_MAXFLAVOR)
  40. return NULL;
  41. rcu_read_lock();
  42. aops = rcu_dereference(authtab[flavor]);
  43. if (aops != NULL && !try_module_get(aops->owner))
  44. aops = NULL;
  45. rcu_read_unlock();
  46. return aops;
  47. }
  48. static void
  49. svc_put_auth_ops(struct auth_ops *aops)
  50. {
  51. module_put(aops->owner);
  52. }
  53. /**
  54. * svc_authenticate - Initialize an outgoing credential
  55. * @rqstp: RPC execution context
  56. *
  57. * Return values:
  58. * %SVC_OK: XDR encoding of the result can begin
  59. * %SVC_DENIED: Credential or verifier is not valid
  60. * %SVC_GARBAGE: Failed to decode credential or verifier
  61. * %SVC_COMPLETE: GSS context lifetime event; no further action
  62. * %SVC_DROP: Drop this request; no further action
  63. * %SVC_CLOSE: Like drop, but also close transport connection
  64. */
  65. enum svc_auth_status svc_authenticate(struct svc_rqst *rqstp)
  66. {
  67. struct auth_ops *aops;
  68. u32 flavor;
  69. rqstp->rq_auth_stat = rpc_auth_ok;
  70. /*
  71. * Decode the Call credential's flavor field. The credential's
  72. * body field is decoded in the chosen ->accept method below.
  73. */
  74. if (xdr_stream_decode_u32(&rqstp->rq_arg_stream, &flavor) < 0)
  75. return SVC_GARBAGE;
  76. aops = svc_get_auth_ops(flavor);
  77. if (aops == NULL) {
  78. rqstp->rq_auth_stat = rpc_autherr_badcred;
  79. return SVC_DENIED;
  80. }
  81. rqstp->rq_auth_slack = 0;
  82. init_svc_cred(&rqstp->rq_cred);
  83. rqstp->rq_authop = aops;
  84. return aops->accept(rqstp);
  85. }
  86. /**
  87. * svc_set_client - Assign an appropriate 'auth_domain' as the client
  88. * @rqstp: RPC execution context
  89. *
  90. * Return values:
  91. * %SVC_OK: Client was found and assigned
  92. * %SVC_DENY: Client was explicitly denied
  93. * %SVC_DROP: Ignore this request
  94. * %SVC_CLOSE: Ignore this request and close the connection
  95. */
  96. enum svc_auth_status svc_set_client(struct svc_rqst *rqstp)
  97. {
  98. rqstp->rq_client = NULL;
  99. return rqstp->rq_authop->set_client(rqstp);
  100. }
  101. EXPORT_SYMBOL_GPL(svc_set_client);
  102. /**
  103. * svc_authorise - Finalize credentials/verifier and release resources
  104. * @rqstp: RPC execution context
  105. *
  106. * Returns zero on success, or a negative errno.
  107. */
  108. int svc_authorise(struct svc_rqst *rqstp)
  109. {
  110. struct auth_ops *aops = rqstp->rq_authop;
  111. int rv = 0;
  112. rqstp->rq_authop = NULL;
  113. if (aops) {
  114. rv = aops->release(rqstp);
  115. svc_put_auth_ops(aops);
  116. }
  117. return rv;
  118. }
  119. int
  120. svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
  121. {
  122. struct auth_ops *old;
  123. int rv = -EINVAL;
  124. if (flavor < RPC_AUTH_MAXFLAVOR) {
  125. old = cmpxchg((struct auth_ops ** __force)&authtab[flavor], NULL, aops);
  126. if (old == NULL || old == aops)
  127. rv = 0;
  128. }
  129. return rv;
  130. }
  131. EXPORT_SYMBOL_GPL(svc_auth_register);
  132. void
  133. svc_auth_unregister(rpc_authflavor_t flavor)
  134. {
  135. if (flavor < RPC_AUTH_MAXFLAVOR)
  136. rcu_assign_pointer(authtab[flavor], NULL);
  137. }
  138. EXPORT_SYMBOL_GPL(svc_auth_unregister);
  139. /**
  140. * svc_auth_flavor - return RPC transaction's RPC_AUTH flavor
  141. * @rqstp: RPC transaction context
  142. *
  143. * Returns an RPC flavor or GSS pseudoflavor.
  144. */
  145. rpc_authflavor_t svc_auth_flavor(struct svc_rqst *rqstp)
  146. {
  147. struct auth_ops *aops = rqstp->rq_authop;
  148. if (!aops->pseudoflavor)
  149. return aops->flavour;
  150. return aops->pseudoflavor(rqstp);
  151. }
  152. EXPORT_SYMBOL_GPL(svc_auth_flavor);
  153. /**
  154. * svcauth_map_clnt_to_svc_cred_local - maps a generic cred
  155. * to a svc_cred suitable for use in nfsd.
  156. * @clnt: rpc_clnt associated with nfs client
  157. * @cred: generic cred associated with nfs client
  158. * @svc: returned svc_cred that is suitable for use in nfsd
  159. */
  160. void svcauth_map_clnt_to_svc_cred_local(struct rpc_clnt *clnt,
  161. const struct cred *cred,
  162. struct svc_cred *svc)
  163. {
  164. struct user_namespace *userns = clnt->cl_cred ?
  165. clnt->cl_cred->user_ns : &init_user_ns;
  166. memset(svc, 0, sizeof(struct svc_cred));
  167. svc->cr_uid = KUIDT_INIT(from_kuid_munged(userns, cred->fsuid));
  168. svc->cr_gid = KGIDT_INIT(from_kgid_munged(userns, cred->fsgid));
  169. svc->cr_flavor = clnt->cl_auth->au_flavor;
  170. if (cred->group_info)
  171. svc->cr_group_info = get_group_info(cred->group_info);
  172. /* These aren't relevant for local (network is bypassed) */
  173. svc->cr_principal = NULL;
  174. svc->cr_gss_mech = NULL;
  175. }
  176. EXPORT_SYMBOL_GPL(svcauth_map_clnt_to_svc_cred_local);
  177. /**************************************************
  178. * 'auth_domains' are stored in a hash table indexed by name.
  179. * When the last reference to an 'auth_domain' is dropped,
  180. * the object is unhashed and freed.
  181. * If auth_domain_lookup fails to find an entry, it will return
  182. * it's second argument 'new'. If this is non-null, it will
  183. * have been atomically linked into the table.
  184. */
  185. #define DN_HASHBITS 6
  186. #define DN_HASHMAX (1<<DN_HASHBITS)
  187. static struct hlist_head auth_domain_table[DN_HASHMAX];
  188. static DEFINE_SPINLOCK(auth_domain_lock);
  189. static void auth_domain_release(struct kref *kref)
  190. __releases(&auth_domain_lock)
  191. {
  192. struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
  193. hlist_del_rcu(&dom->hash);
  194. dom->flavour->domain_release(dom);
  195. spin_unlock(&auth_domain_lock);
  196. }
  197. void auth_domain_put(struct auth_domain *dom)
  198. {
  199. kref_put_lock(&dom->ref, auth_domain_release, &auth_domain_lock);
  200. }
  201. EXPORT_SYMBOL_GPL(auth_domain_put);
  202. struct auth_domain *
  203. auth_domain_lookup(char *name, struct auth_domain *new)
  204. {
  205. struct auth_domain *hp;
  206. struct hlist_head *head;
  207. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  208. spin_lock(&auth_domain_lock);
  209. hlist_for_each_entry(hp, head, hash) {
  210. if (strcmp(hp->name, name)==0) {
  211. kref_get(&hp->ref);
  212. spin_unlock(&auth_domain_lock);
  213. return hp;
  214. }
  215. }
  216. if (new)
  217. hlist_add_head_rcu(&new->hash, head);
  218. spin_unlock(&auth_domain_lock);
  219. return new;
  220. }
  221. EXPORT_SYMBOL_GPL(auth_domain_lookup);
  222. struct auth_domain *auth_domain_find(char *name)
  223. {
  224. struct auth_domain *hp;
  225. struct hlist_head *head;
  226. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  227. rcu_read_lock();
  228. hlist_for_each_entry_rcu(hp, head, hash) {
  229. if (strcmp(hp->name, name)==0) {
  230. if (!kref_get_unless_zero(&hp->ref))
  231. hp = NULL;
  232. rcu_read_unlock();
  233. return hp;
  234. }
  235. }
  236. rcu_read_unlock();
  237. return NULL;
  238. }
  239. EXPORT_SYMBOL_GPL(auth_domain_find);
  240. /**
  241. * auth_domain_cleanup - check that the auth_domain table is empty
  242. *
  243. * On module unload the auth_domain_table must be empty. To make it
  244. * easier to catch bugs which don't clean up domains properly, we
  245. * warn if anything remains in the table at cleanup time.
  246. *
  247. * Note that we cannot proactively remove the domains at this stage.
  248. * The ->release() function might be in a module that has already been
  249. * unloaded.
  250. */
  251. void auth_domain_cleanup(void)
  252. {
  253. int h;
  254. struct auth_domain *hp;
  255. for (h = 0; h < DN_HASHMAX; h++)
  256. hlist_for_each_entry(hp, &auth_domain_table[h], hash)
  257. pr_warn("svc: domain %s still present at module unload.\n",
  258. hp->name);
  259. }