svcauth.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. * 'auth_domains' are stored in a hash table indexed by name.
  92. * When the last reference to an 'auth_domain' is dropped,
  93. * the object is unhashed and freed.
  94. * If auth_domain_lookup fails to find an entry, it will return
  95. * it's second argument 'new'. If this is non-null, it will
  96. * have been atomically linked into the table.
  97. */
  98. #define DN_HASHBITS 6
  99. #define DN_HASHMAX (1<<DN_HASHBITS)
  100. #define DN_HASHMASK (DN_HASHMAX-1)
  101. static struct hlist_head auth_domain_table[DN_HASHMAX];
  102. static spinlock_t auth_domain_lock = SPIN_LOCK_UNLOCKED;
  103. void auth_domain_put(struct auth_domain *dom)
  104. {
  105. if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
  106. hlist_del(&dom->hash);
  107. dom->flavour->domain_release(dom);
  108. }
  109. }
  110. struct auth_domain *
  111. auth_domain_lookup(char *name, struct auth_domain *new)
  112. {
  113. struct auth_domain *hp;
  114. struct hlist_head *head;
  115. struct hlist_node *np;
  116. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  117. spin_lock(&auth_domain_lock);
  118. hlist_for_each_entry(hp, np, head, hash) {
  119. if (strcmp(hp->name, name)==0) {
  120. kref_get(&hp->ref);
  121. spin_unlock(&auth_domain_lock);
  122. return hp;
  123. }
  124. }
  125. if (new) {
  126. hlist_add_head(&new->hash, head);
  127. kref_get(&new->ref);
  128. }
  129. spin_unlock(&auth_domain_lock);
  130. return new;
  131. }
  132. struct auth_domain *auth_domain_find(char *name)
  133. {
  134. return auth_domain_lookup(name, NULL);
  135. }