svcauth.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. init_svc_cred(&rqstp->rq_cred);
  48. rqstp->rq_authop = aops;
  49. return aops->accept(rqstp, authp);
  50. }
  51. EXPORT_SYMBOL_GPL(svc_authenticate);
  52. int svc_set_client(struct svc_rqst *rqstp)
  53. {
  54. rqstp->rq_client = NULL;
  55. return rqstp->rq_authop->set_client(rqstp);
  56. }
  57. EXPORT_SYMBOL_GPL(svc_set_client);
  58. /* A request, which was authenticated, has now executed.
  59. * Time to finalise the credentials and verifier
  60. * and release and resources
  61. */
  62. int svc_authorise(struct svc_rqst *rqstp)
  63. {
  64. struct auth_ops *aops = rqstp->rq_authop;
  65. int rv = 0;
  66. rqstp->rq_authop = NULL;
  67. if (aops) {
  68. rv = aops->release(rqstp);
  69. module_put(aops->owner);
  70. }
  71. return rv;
  72. }
  73. int
  74. svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
  75. {
  76. int rv = -EINVAL;
  77. spin_lock(&authtab_lock);
  78. if (flavor < RPC_AUTH_MAXFLAVOR && authtab[flavor] == NULL) {
  79. authtab[flavor] = aops;
  80. rv = 0;
  81. }
  82. spin_unlock(&authtab_lock);
  83. return rv;
  84. }
  85. EXPORT_SYMBOL_GPL(svc_auth_register);
  86. void
  87. svc_auth_unregister(rpc_authflavor_t flavor)
  88. {
  89. spin_lock(&authtab_lock);
  90. if (flavor < RPC_AUTH_MAXFLAVOR)
  91. authtab[flavor] = NULL;
  92. spin_unlock(&authtab_lock);
  93. }
  94. EXPORT_SYMBOL_GPL(svc_auth_unregister);
  95. /**************************************************
  96. * 'auth_domains' are stored in a hash table indexed by name.
  97. * When the last reference to an 'auth_domain' is dropped,
  98. * the object is unhashed and freed.
  99. * If auth_domain_lookup fails to find an entry, it will return
  100. * it's second argument 'new'. If this is non-null, it will
  101. * have been atomically linked into the table.
  102. */
  103. #define DN_HASHBITS 6
  104. #define DN_HASHMAX (1<<DN_HASHBITS)
  105. static struct hlist_head auth_domain_table[DN_HASHMAX];
  106. static DEFINE_SPINLOCK(auth_domain_lock);
  107. static void auth_domain_release(struct kref *kref)
  108. {
  109. struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
  110. hlist_del(&dom->hash);
  111. dom->flavour->domain_release(dom);
  112. spin_unlock(&auth_domain_lock);
  113. }
  114. void auth_domain_put(struct auth_domain *dom)
  115. {
  116. kref_put_lock(&dom->ref, auth_domain_release, &auth_domain_lock);
  117. }
  118. EXPORT_SYMBOL_GPL(auth_domain_put);
  119. struct auth_domain *
  120. auth_domain_lookup(char *name, struct auth_domain *new)
  121. {
  122. struct auth_domain *hp;
  123. struct hlist_head *head;
  124. head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
  125. spin_lock(&auth_domain_lock);
  126. hlist_for_each_entry(hp, head, hash) {
  127. if (strcmp(hp->name, name)==0) {
  128. kref_get(&hp->ref);
  129. spin_unlock(&auth_domain_lock);
  130. return hp;
  131. }
  132. }
  133. if (new)
  134. hlist_add_head(&new->hash, head);
  135. spin_unlock(&auth_domain_lock);
  136. return new;
  137. }
  138. EXPORT_SYMBOL_GPL(auth_domain_lookup);
  139. struct auth_domain *auth_domain_find(char *name)
  140. {
  141. return auth_domain_lookup(name, NULL);
  142. }
  143. EXPORT_SYMBOL_GPL(auth_domain_find);