svcauth.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * linux/net/sunrpc/svcauth.c
  3. *
  4. * The generic interface for RPC authentication on the server side.
  5. *
  6. * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
  7. *
  8. * CHANGES
  9. * 19-Apr-2000 Chris Evans - Security fix
  10. */
  11. #include <linux/types.h>
  12. #include <linux/sched.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. #define RPCDBG_FACILITY RPCDBG_AUTH
  21. /*
  22. * Table of authenticators
  23. */
  24. extern struct auth_ops svcauth_null;
  25. extern struct auth_ops svcauth_unix;
  26. static DEFINE_SPINLOCK(authtab_lock);
  27. static struct auth_ops *authtab[RPC_AUTH_MAXFLAVOR] = {
  28. [0] = &svcauth_null,
  29. [1] = &svcauth_unix,
  30. };
  31. int
  32. svc_authenticate(struct svc_rqst *rqstp, u32 *authp)
  33. {
  34. rpc_authflavor_t flavor;
  35. struct auth_ops *aops;
  36. *authp = rpc_auth_ok;
  37. flavor = ntohl(svc_getu32(&rqstp->rq_arg.head[0]));
  38. dprintk("svc: svc_authenticate (%d)\n", flavor);
  39. spin_lock(&authtab_lock);
  40. if (flavor >= RPC_AUTH_MAXFLAVOR || !(aops = authtab[flavor])
  41. || !try_module_get(aops->owner)) {
  42. spin_unlock(&authtab_lock);
  43. *authp = rpc_autherr_badcred;
  44. return SVC_DENIED;
  45. }
  46. spin_unlock(&authtab_lock);
  47. rqstp->rq_authop = aops;
  48. return aops->accept(rqstp, authp);
  49. }
  50. int svc_set_client(struct svc_rqst *rqstp)
  51. {
  52. return rqstp->rq_authop->set_client(rqstp);
  53. }
  54. /* A request, which was authenticated, has now executed.
  55. * Time to finalise the the credentials and verifier
  56. * and release and resources
  57. */
  58. int svc_authorise(struct svc_rqst *rqstp)
  59. {
  60. struct auth_ops *aops = rqstp->rq_authop;
  61. int rv = 0;
  62. rqstp->rq_authop = NULL;
  63. if (aops) {
  64. rv = aops->release(rqstp);
  65. module_put(aops->owner);
  66. }
  67. return rv;
  68. }
  69. int
  70. svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
  71. {
  72. int rv = -EINVAL;
  73. spin_lock(&authtab_lock);
  74. if (flavor < RPC_AUTH_MAXFLAVOR && authtab[flavor] == NULL) {
  75. authtab[flavor] = aops;
  76. rv = 0;
  77. }
  78. spin_unlock(&authtab_lock);
  79. return rv;
  80. }
  81. void
  82. svc_auth_unregister(rpc_authflavor_t flavor)
  83. {
  84. spin_lock(&authtab_lock);
  85. if (flavor < RPC_AUTH_MAXFLAVOR)
  86. authtab[flavor] = NULL;
  87. spin_unlock(&authtab_lock);
  88. }
  89. EXPORT_SYMBOL(svc_auth_unregister);
  90. /**************************************************
  91. * cache for domain name to auth_domain
  92. * Entries are only added by flavours which will normally
  93. * have a structure that 'inherits' from auth_domain.
  94. * e.g. when an IP -> domainname is given to auth_unix,
  95. * and the domain name doesn't exist, it will create a
  96. * auth_unix_domain and add it to this hash table.
  97. * If it finds the name does exist, but isn't AUTH_UNIX,
  98. * it will complain.
  99. */
  100. /*
  101. * Auth auth_domain cache is somewhat different to other caches,
  102. * largely because the entries are possibly of different types:
  103. * each auth flavour has it's own type.
  104. * One consequence of this that DefineCacheLookup cannot
  105. * allocate a new structure as it cannot know the size.
  106. * Notice that the "INIT" code fragment is quite different
  107. * from other caches. When auth_domain_lookup might be
  108. * creating a new domain, the new domain is passed in
  109. * complete and it is used as-is rather than being copied into
  110. * another structure.
  111. */
  112. #define DN_HASHBITS 6
  113. #define DN_HASHMAX (1<<DN_HASHBITS)
  114. #define DN_HASHMASK (DN_HASHMAX-1)
  115. static struct cache_head *auth_domain_table[DN_HASHMAX];
  116. static void auth_domain_drop(struct cache_head *item, struct cache_detail *cd)
  117. {
  118. struct auth_domain *dom = container_of(item, struct auth_domain, h);
  119. if (cache_put(item,cd))
  120. authtab[dom->flavour]->domain_release(dom);
  121. }
  122. struct cache_detail auth_domain_cache = {
  123. .owner = THIS_MODULE,
  124. .hash_size = DN_HASHMAX,
  125. .hash_table = auth_domain_table,
  126. .name = "auth.domain",
  127. .cache_put = auth_domain_drop,
  128. };
  129. void auth_domain_put(struct auth_domain *dom)
  130. {
  131. auth_domain_drop(&dom->h, &auth_domain_cache);
  132. }
  133. static inline int auth_domain_hash(struct auth_domain *item)
  134. {
  135. return hash_str(item->name, DN_HASHBITS);
  136. }
  137. static inline int auth_domain_match(struct auth_domain *tmp, struct auth_domain *item)
  138. {
  139. return strcmp(tmp->name, item->name) == 0;
  140. }
  141. struct auth_domain *
  142. auth_domain_lookup(struct auth_domain *item, int set)
  143. {
  144. struct auth_domain *tmp = NULL;
  145. struct cache_head **hp, **head;
  146. head = &auth_domain_cache.hash_table[auth_domain_hash(item)];
  147. if (set)
  148. write_lock(&auth_domain_cache.hash_lock);
  149. else
  150. read_lock(&auth_domain_cache.hash_lock);
  151. for (hp=head; *hp != NULL; hp = &tmp->h.next) {
  152. tmp = container_of(*hp, struct auth_domain, h);
  153. if (!auth_domain_match(tmp, item))
  154. continue;
  155. if (!set) {
  156. cache_get(&tmp->h);
  157. goto out_noset;
  158. }
  159. *hp = tmp->h.next;
  160. tmp->h.next = NULL;
  161. auth_domain_drop(&tmp->h, &auth_domain_cache);
  162. goto out_set;
  163. }
  164. /* Didn't find anything */
  165. if (!set)
  166. goto out_nada;
  167. auth_domain_cache.entries++;
  168. out_set:
  169. item->h.next = *head;
  170. *head = &item->h;
  171. cache_get(&item->h);
  172. write_unlock(&auth_domain_cache.hash_lock);
  173. cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
  174. cache_get(&item->h);
  175. return item;
  176. out_nada:
  177. tmp = NULL;
  178. out_noset:
  179. read_unlock(&auth_domain_cache.hash_lock);
  180. return tmp;
  181. }
  182. struct auth_domain *auth_domain_find(char *name)
  183. {
  184. struct auth_domain *rv, ad;
  185. ad.name = name;
  186. rv = auth_domain_lookup(&ad, 0);
  187. return rv;
  188. }