Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/sunrpc/svcauth.c
15109 views
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 <[email protected]>
7
*
8
* CHANGES
9
* 19-Apr-2000 Chris Evans - Security fix
10
*/
11
12
#include <linux/types.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
21
#define RPCDBG_FACILITY RPCDBG_AUTH
22
23
24
/*
25
* Table of authenticators
26
*/
27
extern struct auth_ops svcauth_null;
28
extern struct auth_ops svcauth_unix;
29
30
static DEFINE_SPINLOCK(authtab_lock);
31
static struct auth_ops *authtab[RPC_AUTH_MAXFLAVOR] = {
32
[0] = &svcauth_null,
33
[1] = &svcauth_unix,
34
};
35
36
int
37
svc_authenticate(struct svc_rqst *rqstp, __be32 *authp)
38
{
39
rpc_authflavor_t flavor;
40
struct auth_ops *aops;
41
42
*authp = rpc_auth_ok;
43
44
flavor = svc_getnl(&rqstp->rq_arg.head[0]);
45
46
dprintk("svc: svc_authenticate (%d)\n", flavor);
47
48
spin_lock(&authtab_lock);
49
if (flavor >= RPC_AUTH_MAXFLAVOR || !(aops = authtab[flavor]) ||
50
!try_module_get(aops->owner)) {
51
spin_unlock(&authtab_lock);
52
*authp = rpc_autherr_badcred;
53
return SVC_DENIED;
54
}
55
spin_unlock(&authtab_lock);
56
57
rqstp->rq_authop = aops;
58
return aops->accept(rqstp, authp);
59
}
60
EXPORT_SYMBOL_GPL(svc_authenticate);
61
62
int svc_set_client(struct svc_rqst *rqstp)
63
{
64
return rqstp->rq_authop->set_client(rqstp);
65
}
66
EXPORT_SYMBOL_GPL(svc_set_client);
67
68
/* A request, which was authenticated, has now executed.
69
* Time to finalise the credentials and verifier
70
* and release and resources
71
*/
72
int svc_authorise(struct svc_rqst *rqstp)
73
{
74
struct auth_ops *aops = rqstp->rq_authop;
75
int rv = 0;
76
77
rqstp->rq_authop = NULL;
78
79
if (aops) {
80
rv = aops->release(rqstp);
81
module_put(aops->owner);
82
}
83
return rv;
84
}
85
86
int
87
svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops)
88
{
89
int rv = -EINVAL;
90
spin_lock(&authtab_lock);
91
if (flavor < RPC_AUTH_MAXFLAVOR && authtab[flavor] == NULL) {
92
authtab[flavor] = aops;
93
rv = 0;
94
}
95
spin_unlock(&authtab_lock);
96
return rv;
97
}
98
EXPORT_SYMBOL_GPL(svc_auth_register);
99
100
void
101
svc_auth_unregister(rpc_authflavor_t flavor)
102
{
103
spin_lock(&authtab_lock);
104
if (flavor < RPC_AUTH_MAXFLAVOR)
105
authtab[flavor] = NULL;
106
spin_unlock(&authtab_lock);
107
}
108
EXPORT_SYMBOL_GPL(svc_auth_unregister);
109
110
/**************************************************
111
* 'auth_domains' are stored in a hash table indexed by name.
112
* When the last reference to an 'auth_domain' is dropped,
113
* the object is unhashed and freed.
114
* If auth_domain_lookup fails to find an entry, it will return
115
* it's second argument 'new'. If this is non-null, it will
116
* have been atomically linked into the table.
117
*/
118
119
#define DN_HASHBITS 6
120
#define DN_HASHMAX (1<<DN_HASHBITS)
121
122
static struct hlist_head auth_domain_table[DN_HASHMAX];
123
static spinlock_t auth_domain_lock =
124
__SPIN_LOCK_UNLOCKED(auth_domain_lock);
125
126
void auth_domain_put(struct auth_domain *dom)
127
{
128
if (atomic_dec_and_lock(&dom->ref.refcount, &auth_domain_lock)) {
129
hlist_del(&dom->hash);
130
dom->flavour->domain_release(dom);
131
spin_unlock(&auth_domain_lock);
132
}
133
}
134
EXPORT_SYMBOL_GPL(auth_domain_put);
135
136
struct auth_domain *
137
auth_domain_lookup(char *name, struct auth_domain *new)
138
{
139
struct auth_domain *hp;
140
struct hlist_head *head;
141
struct hlist_node *np;
142
143
head = &auth_domain_table[hash_str(name, DN_HASHBITS)];
144
145
spin_lock(&auth_domain_lock);
146
147
hlist_for_each_entry(hp, np, head, hash) {
148
if (strcmp(hp->name, name)==0) {
149
kref_get(&hp->ref);
150
spin_unlock(&auth_domain_lock);
151
return hp;
152
}
153
}
154
if (new)
155
hlist_add_head(&new->hash, head);
156
spin_unlock(&auth_domain_lock);
157
return new;
158
}
159
EXPORT_SYMBOL_GPL(auth_domain_lookup);
160
161
struct auth_domain *auth_domain_find(char *name)
162
{
163
return auth_domain_lookup(name, NULL);
164
}
165
EXPORT_SYMBOL_GPL(auth_domain_find);
166
167