svcauth.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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/module.h>
  13. #include <linux/sunrpc/types.h>
  14. #include <linux/sunrpc/xdr.h>
  15. #include <linux/sunrpc/svcsock.h>
  16. #include <linux/sunrpc/svcauth.h>
  17. #include <linux/err.h>
  18. #include <linux/hash.h>
  19. #define RPCDBG_FACILITY RPCDBG_AUTH
  20. /*
  21. * Table of authenticators
  22. */
  23. extern struct auth_ops svcauth_null;
  24. extern struct auth_ops svcauth_unix;
  25. static DEFINE_SPINLOCK(authtab_lock);
  26. static struct auth_ops *authtab[RPC_AUTH_MAXFLAVOR] = {
  27. [0] = &svcauth_null,
  28. [1] = &svcauth_unix,
  29. };
  30. int
  31. svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
  32. {
  33. rpc_authflavor_t flavor;
  34. struct auth_ops *aops;
  35. *authp = rpc_auth_ok;
  36. flavor = svc_getnl(&rqstp->rq_arg.head[0]);
  37. dprintk("svc: svc_authenticate (%d)\n", flavor);
  38. spin_lock(&authtab_lock);
  39. if (flavor >= RPC_AUTH_MAXFLAVOR || !(aops = authtab[flavor]) ||
  40. !try_module_get(aops->owner)) {
  41. spin_unlock(&authtab_lock);
  42. *authp = rpc_autherr_badcred;
  43. return SVC_DENIED;
  44. }
  45. spin_unlock(&authtab_lock);
  46. rqstp->rq_auth_slack = 0;
  47. rqstp->rq_authop = aops;
  48. return aops->accept(rqstp, authp);
  49. }
  50. EXPORT_SYMBOL_GPL(svc_authenticate);
  51. int svc_set_client(struct svc_rqst *rqstp)
  52. {
  53. return rqstp->rq_authop->set_client(rqstp);
  54. }
  55. EXPORT_SYMBOL_GPL(svc_set_client);
  56. /* A request, which was authenticated, has now executed.
  57. * Time to finalise the credentials and verifier
  58. * and release and resources
  59. */
  60. int svc_authorise(struct svc_rqst *rqstp)
  61. {
  62. struct auth_ops *aops = rqstp->rq_authop;
  63. int rv = 0;
  64. rqstp->rq_authop = NULL;
  65. if (aops) {
  66. rv = aops->release(rqstp);
  67. module_put(aops->owner);
  68. }
  69. return rv;
  70. }
  71. int
  72. svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
  73. {
  74. int rv = -EINVAL;
  75. spin_lock(&authtab_lock);
  76. if (flavor < RPC_AUTH_MAXFLAVOR && authtab[flavor] == NULL) {
  77. authtab[flavor] = aops;
  78. rv = 0;
  79. }
  80. spin_unlock(&authtab_lock);
  81. return rv;
  82. }
  83. EXPORT_SYMBOL_GPL(svc_auth_register);
  84. void
  85. svc_auth_unregister(rpc_authflavor_t flavor)
  86. {
  87. spin_lock(&authtab_lock);
  88. if (flavor < RPC_AUTH_MAXFLAVOR)
  89. authtab[flavor] = NULL;
  90. spin_unlock(&authtab_lock);
  91. }
  92. EXPORT_SYMBOL_GPL(svc_auth_unregister);
  93. /**************************************************
  94. * 'auth_domains' are stored in a hash table indexed by name.
  95. * When the last reference to an 'auth_domain' is dropped,
  96. * the object is unhashed and freed.
  97. * If auth_domain_lookup fails to find an entry, it will return
  98. * it's second argument 'new'. If this is non-null, it will
  99. * have been atomically linked into the table.
  100. */
  101. #define DN_HASHBITS 6
  102. #define DN_HASHMAX (1<<DN_HASHBITS)
  103. static struct hlist_head auth_domain_table[DN_HASHMAX];
  104. static spinlock_t auth_domain_lock =
  105. __SPIN_LOCK_UNLOCKED(auth_domain_lock);
  106. void auth_domain_put(struct auth_domain *dom)
  107. {
  108. if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
  109. hlist_del(&dom->hash);
  110. dom->flavour->domain_release(dom);
  111. spin_unlock(&auth_domain_lock);
  112. }
  113. }
  114. EXPORT_SYMBOL_GPL(auth_domain_put);
  115. struct auth_domain *
  116. auth_domain_lookup(char *name, struct auth_domain *new)
  117. {
  118. struct auth_domain *hp;
  119. struct hlist_head *head;
  120. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  121. spin_lock(&auth_domain_lock);
  122. hlist_for_each_entry(hp, head, hash) {
  123. if (strcmp(hp->name, name)==0) {
  124. kref_get(&hp->ref);
  125. spin_unlock(&auth_domain_lock);
  126. return hp;
  127. }
  128. }
  129. if (new)
  130. hlist_add_head(&new->hash, head);
  131. spin_unlock(&auth_domain_lock);
  132. return new;
  133. }
  134. EXPORT_SYMBOL_GPL(auth_domain_lookup);
  135. struct auth_domain *auth_domain_find(char *name)
  136. {
  137. return auth_domain_lookup(name, NULL);
  138. }
  139. EXPORT_SYMBOL_GPL(auth_domain_find);