0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/types.h>
0014 #include <linux/module.h>
0015 #include <linux/sunrpc/types.h>
0016 #include <linux/sunrpc/xdr.h>
0017 #include <linux/sunrpc/svcsock.h>
0018 #include <linux/sunrpc/svcauth.h>
0019 #include <linux/err.h>
0020 #include <linux/hash.h>
0021
0022 #include <trace/events/sunrpc.h>
0023
0024 #include "sunrpc.h"
0025
0026 #define RPCDBG_FACILITY RPCDBG_AUTH
0027
0028
0029
0030
0031
0032 extern struct auth_ops svcauth_null;
0033 extern struct auth_ops svcauth_unix;
0034 extern struct auth_ops svcauth_tls;
0035
0036 static struct auth_ops __rcu *authtab[RPC_AUTH_MAXFLAVOR] = {
0037 [RPC_AUTH_NULL] = (struct auth_ops __force __rcu *)&svcauth_null,
0038 [RPC_AUTH_UNIX] = (struct auth_ops __force __rcu *)&svcauth_unix,
0039 [RPC_AUTH_TLS] = (struct auth_ops __force __rcu *)&svcauth_tls,
0040 };
0041
0042 static struct auth_ops *
0043 svc_get_auth_ops(rpc_authflavor_t flavor)
0044 {
0045 struct auth_ops *aops;
0046
0047 if (flavor >= RPC_AUTH_MAXFLAVOR)
0048 return NULL;
0049 rcu_read_lock();
0050 aops = rcu_dereference(authtab[flavor]);
0051 if (aops != NULL && !try_module_get(aops->owner))
0052 aops = NULL;
0053 rcu_read_unlock();
0054 return aops;
0055 }
0056
0057 static void
0058 svc_put_auth_ops(struct auth_ops *aops)
0059 {
0060 module_put(aops->owner);
0061 }
0062
0063 int
0064 svc_authenticate(struct svc_rqst *rqstp)
0065 {
0066 rpc_authflavor_t flavor;
0067 struct auth_ops *aops;
0068
0069 rqstp->rq_auth_stat = rpc_auth_ok;
0070
0071 flavor = svc_getnl(&rqstp->rq_arg.head[0]);
0072
0073 dprintk("svc: svc_authenticate (%d)\n", flavor);
0074
0075 aops = svc_get_auth_ops(flavor);
0076 if (aops == NULL) {
0077 rqstp->rq_auth_stat = rpc_autherr_badcred;
0078 return SVC_DENIED;
0079 }
0080
0081 rqstp->rq_auth_slack = 0;
0082 init_svc_cred(&rqstp->rq_cred);
0083
0084 rqstp->rq_authop = aops;
0085 return aops->accept(rqstp);
0086 }
0087 EXPORT_SYMBOL_GPL(svc_authenticate);
0088
0089 int svc_set_client(struct svc_rqst *rqstp)
0090 {
0091 rqstp->rq_client = NULL;
0092 return rqstp->rq_authop->set_client(rqstp);
0093 }
0094 EXPORT_SYMBOL_GPL(svc_set_client);
0095
0096
0097
0098
0099
0100 int svc_authorise(struct svc_rqst *rqstp)
0101 {
0102 struct auth_ops *aops = rqstp->rq_authop;
0103 int rv = 0;
0104
0105 rqstp->rq_authop = NULL;
0106
0107 if (aops) {
0108 rv = aops->release(rqstp);
0109 svc_put_auth_ops(aops);
0110 }
0111 return rv;
0112 }
0113
0114 int
0115 svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
0116 {
0117 struct auth_ops *old;
0118 int rv = -EINVAL;
0119
0120 if (flavor < RPC_AUTH_MAXFLAVOR) {
0121 old = cmpxchg((struct auth_ops ** __force)&authtab[flavor], NULL, aops);
0122 if (old == NULL || old == aops)
0123 rv = 0;
0124 }
0125 return rv;
0126 }
0127 EXPORT_SYMBOL_GPL(svc_auth_register);
0128
0129 void
0130 svc_auth_unregister(rpc_authflavor_t flavor)
0131 {
0132 if (flavor < RPC_AUTH_MAXFLAVOR)
0133 rcu_assign_pointer(authtab[flavor], NULL);
0134 }
0135 EXPORT_SYMBOL_GPL(svc_auth_unregister);
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146 #define DN_HASHBITS 6
0147 #define DN_HASHMAX (1<<DN_HASHBITS)
0148
0149 static struct hlist_head auth_domain_table[DN_HASHMAX];
0150 static DEFINE_SPINLOCK(auth_domain_lock);
0151
0152 static void auth_domain_release(struct kref *kref)
0153 __releases(&auth_domain_lock)
0154 {
0155 struct auth_domain *dom = container_of(kref, struct auth_domain, ref);
0156
0157 hlist_del_rcu(&dom->hash);
0158 dom->flavour->domain_release(dom);
0159 spin_unlock(&auth_domain_lock);
0160 }
0161
0162 void auth_domain_put(struct auth_domain *dom)
0163 {
0164 kref_put_lock(&dom->ref, auth_domain_release, &auth_domain_lock);
0165 }
0166 EXPORT_SYMBOL_GPL(auth_domain_put);
0167
0168 struct auth_domain *
0169 auth_domain_lookup(char *name, struct auth_domain *new)
0170 {
0171 struct auth_domain *hp;
0172 struct hlist_head *head;
0173
0174 head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
0175
0176 spin_lock(&auth_domain_lock);
0177
0178 hlist_for_each_entry(hp, head, hash) {
0179 if (strcmp(hp->name, name)==0) {
0180 kref_get(&hp->ref);
0181 spin_unlock(&auth_domain_lock);
0182 return hp;
0183 }
0184 }
0185 if (new)
0186 hlist_add_head_rcu(&new->hash, head);
0187 spin_unlock(&auth_domain_lock);
0188 return new;
0189 }
0190 EXPORT_SYMBOL_GPL(auth_domain_lookup);
0191
0192 struct auth_domain *auth_domain_find(char *name)
0193 {
0194 struct auth_domain *hp;
0195 struct hlist_head *head;
0196
0197 head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
0198
0199 rcu_read_lock();
0200 hlist_for_each_entry_rcu(hp, head, hash) {
0201 if (strcmp(hp->name, name)==0) {
0202 if (!kref_get_unless_zero(&hp->ref))
0203 hp = NULL;
0204 rcu_read_unlock();
0205 return hp;
0206 }
0207 }
0208 rcu_read_unlock();
0209 return NULL;
0210 }
0211 EXPORT_SYMBOL_GPL(auth_domain_find);
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225 void auth_domain_cleanup(void)
0226 {
0227 int h;
0228 struct auth_domain *hp;
0229
0230 for (h = 0; h < DN_HASHMAX; h++)
0231 hlist_for_each_entry(hp, &auth_domain_table[h], hash)
0232 pr_warn("svc: domain %s still present at module unload.\n",
0233 hp->name);
0234 }