Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/ceph/auth.c
15109 views
1
#include <linux/ceph/ceph_debug.h>
2
3
#include <linux/module.h>
4
#include <linux/err.h>
5
#include <linux/slab.h>
6
7
#include <linux/ceph/types.h>
8
#include <linux/ceph/decode.h>
9
#include <linux/ceph/libceph.h>
10
#include <linux/ceph/messenger.h>
11
#include "auth_none.h"
12
#include "auth_x.h"
13
14
15
/*
16
* get protocol handler
17
*/
18
static u32 supported_protocols[] = {
19
CEPH_AUTH_NONE,
20
CEPH_AUTH_CEPHX
21
};
22
23
static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol)
24
{
25
switch (protocol) {
26
case CEPH_AUTH_NONE:
27
return ceph_auth_none_init(ac);
28
case CEPH_AUTH_CEPHX:
29
return ceph_x_init(ac);
30
default:
31
return -ENOENT;
32
}
33
}
34
35
/*
36
* setup, teardown.
37
*/
38
struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key)
39
{
40
struct ceph_auth_client *ac;
41
int ret;
42
43
dout("auth_init name '%s'\n", name);
44
45
ret = -ENOMEM;
46
ac = kzalloc(sizeof(*ac), GFP_NOFS);
47
if (!ac)
48
goto out;
49
50
ac->negotiating = true;
51
if (name)
52
ac->name = name;
53
else
54
ac->name = CEPH_AUTH_NAME_DEFAULT;
55
dout("auth_init name %s\n", ac->name);
56
ac->key = key;
57
return ac;
58
59
out:
60
return ERR_PTR(ret);
61
}
62
63
void ceph_auth_destroy(struct ceph_auth_client *ac)
64
{
65
dout("auth_destroy %p\n", ac);
66
if (ac->ops)
67
ac->ops->destroy(ac);
68
kfree(ac);
69
}
70
71
/*
72
* Reset occurs when reconnecting to the monitor.
73
*/
74
void ceph_auth_reset(struct ceph_auth_client *ac)
75
{
76
dout("auth_reset %p\n", ac);
77
if (ac->ops && !ac->negotiating)
78
ac->ops->reset(ac);
79
ac->negotiating = true;
80
}
81
82
int ceph_entity_name_encode(const char *name, void **p, void *end)
83
{
84
int len = strlen(name);
85
86
if (*p + 2*sizeof(u32) + len > end)
87
return -ERANGE;
88
ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT);
89
ceph_encode_32(p, len);
90
ceph_encode_copy(p, name, len);
91
return 0;
92
}
93
94
/*
95
* Initiate protocol negotiation with monitor. Include entity name
96
* and list supported protocols.
97
*/
98
int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len)
99
{
100
struct ceph_mon_request_header *monhdr = buf;
101
void *p = monhdr + 1, *end = buf + len, *lenp;
102
int i, num;
103
int ret;
104
105
dout("auth_build_hello\n");
106
monhdr->have_version = 0;
107
monhdr->session_mon = cpu_to_le16(-1);
108
monhdr->session_mon_tid = 0;
109
110
ceph_encode_32(&p, 0); /* no protocol, yet */
111
112
lenp = p;
113
p += sizeof(u32);
114
115
ceph_decode_need(&p, end, 1 + sizeof(u32), bad);
116
ceph_encode_8(&p, 1);
117
num = ARRAY_SIZE(supported_protocols);
118
ceph_encode_32(&p, num);
119
ceph_decode_need(&p, end, num * sizeof(u32), bad);
120
for (i = 0; i < num; i++)
121
ceph_encode_32(&p, supported_protocols[i]);
122
123
ret = ceph_entity_name_encode(ac->name, &p, end);
124
if (ret < 0)
125
return ret;
126
ceph_decode_need(&p, end, sizeof(u64), bad);
127
ceph_encode_64(&p, ac->global_id);
128
129
ceph_encode_32(&lenp, p - lenp - sizeof(u32));
130
return p - buf;
131
132
bad:
133
return -ERANGE;
134
}
135
136
static int ceph_build_auth_request(struct ceph_auth_client *ac,
137
void *msg_buf, size_t msg_len)
138
{
139
struct ceph_mon_request_header *monhdr = msg_buf;
140
void *p = monhdr + 1;
141
void *end = msg_buf + msg_len;
142
int ret;
143
144
monhdr->have_version = 0;
145
monhdr->session_mon = cpu_to_le16(-1);
146
monhdr->session_mon_tid = 0;
147
148
ceph_encode_32(&p, ac->protocol);
149
150
ret = ac->ops->build_request(ac, p + sizeof(u32), end);
151
if (ret < 0) {
152
pr_err("error %d building auth method %s request\n", ret,
153
ac->ops->name);
154
return ret;
155
}
156
dout(" built request %d bytes\n", ret);
157
ceph_encode_32(&p, ret);
158
return p + ret - msg_buf;
159
}
160
161
/*
162
* Handle auth message from monitor.
163
*/
164
int ceph_handle_auth_reply(struct ceph_auth_client *ac,
165
void *buf, size_t len,
166
void *reply_buf, size_t reply_len)
167
{
168
void *p = buf;
169
void *end = buf + len;
170
int protocol;
171
s32 result;
172
u64 global_id;
173
void *payload, *payload_end;
174
int payload_len;
175
char *result_msg;
176
int result_msg_len;
177
int ret = -EINVAL;
178
179
dout("handle_auth_reply %p %p\n", p, end);
180
ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad);
181
protocol = ceph_decode_32(&p);
182
result = ceph_decode_32(&p);
183
global_id = ceph_decode_64(&p);
184
payload_len = ceph_decode_32(&p);
185
payload = p;
186
p += payload_len;
187
ceph_decode_need(&p, end, sizeof(u32), bad);
188
result_msg_len = ceph_decode_32(&p);
189
result_msg = p;
190
p += result_msg_len;
191
if (p != end)
192
goto bad;
193
194
dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len,
195
result_msg, global_id, payload_len);
196
197
payload_end = payload + payload_len;
198
199
if (global_id && ac->global_id != global_id) {
200
dout(" set global_id %lld -> %lld\n", ac->global_id, global_id);
201
ac->global_id = global_id;
202
}
203
204
if (ac->negotiating) {
205
/* server does not support our protocols? */
206
if (!protocol && result < 0) {
207
ret = result;
208
goto out;
209
}
210
/* set up (new) protocol handler? */
211
if (ac->protocol && ac->protocol != protocol) {
212
ac->ops->destroy(ac);
213
ac->protocol = 0;
214
ac->ops = NULL;
215
}
216
if (ac->protocol != protocol) {
217
ret = ceph_auth_init_protocol(ac, protocol);
218
if (ret) {
219
pr_err("error %d on auth protocol %d init\n",
220
ret, protocol);
221
goto out;
222
}
223
}
224
225
ac->negotiating = false;
226
}
227
228
ret = ac->ops->handle_reply(ac, result, payload, payload_end);
229
if (ret == -EAGAIN) {
230
return ceph_build_auth_request(ac, reply_buf, reply_len);
231
} else if (ret) {
232
pr_err("auth method '%s' error %d\n", ac->ops->name, ret);
233
return ret;
234
}
235
return 0;
236
237
bad:
238
pr_err("failed to decode auth msg\n");
239
out:
240
return ret;
241
}
242
243
int ceph_build_auth(struct ceph_auth_client *ac,
244
void *msg_buf, size_t msg_len)
245
{
246
if (!ac->protocol)
247
return ceph_auth_build_hello(ac, msg_buf, msg_len);
248
BUG_ON(!ac->ops);
249
if (ac->ops->should_authenticate(ac))
250
return ceph_build_auth_request(ac, msg_buf, msg_len);
251
return 0;
252
}
253
254
int ceph_auth_is_authenticated(struct ceph_auth_client *ac)
255
{
256
if (!ac->ops)
257
return 0;
258
return ac->ops->is_authenticated(ac);
259
}
260
261