]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
3d14c5d2 | 2 | #include <linux/ceph/ceph_debug.h> |
4e7a5dcd SW |
3 | |
4 | #include <linux/module.h> | |
5 | #include <linux/err.h> | |
d45d0d97 | 6 | #include <linux/slab.h> |
4e7a5dcd | 7 | |
3d14c5d2 YS |
8 | #include <linux/ceph/types.h> |
9 | #include <linux/ceph/decode.h> | |
10 | #include <linux/ceph/libceph.h> | |
11 | #include <linux/ceph/messenger.h> | |
4e7a5dcd | 12 | #include "auth_none.h" |
ec0994e4 | 13 | #include "auth_x.h" |
4e7a5dcd | 14 | |
4e7a5dcd SW |
15 | |
16 | /* | |
17 | * get protocol handler | |
18 | */ | |
19 | static u32 supported_protocols[] = { | |
ec0994e4 SW |
20 | CEPH_AUTH_NONE, |
21 | CEPH_AUTH_CEPHX | |
4e7a5dcd SW |
22 | }; |
23 | ||
cd84db6e | 24 | static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol) |
4e7a5dcd SW |
25 | { |
26 | switch (protocol) { | |
27 | case CEPH_AUTH_NONE: | |
28 | return ceph_auth_none_init(ac); | |
ec0994e4 SW |
29 | case CEPH_AUTH_CEPHX: |
30 | return ceph_x_init(ac); | |
4e7a5dcd SW |
31 | default: |
32 | return -ENOENT; | |
33 | } | |
34 | } | |
35 | ||
36 | /* | |
37 | * setup, teardown. | |
38 | */ | |
8323c3aa | 39 | struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key) |
4e7a5dcd SW |
40 | { |
41 | struct ceph_auth_client *ac; | |
42 | int ret; | |
43 | ||
8323c3aa | 44 | dout("auth_init name '%s'\n", name); |
4e7a5dcd SW |
45 | |
46 | ret = -ENOMEM; | |
47 | ac = kzalloc(sizeof(*ac), GFP_NOFS); | |
48 | if (!ac) | |
49 | goto out; | |
50 | ||
e9966076 | 51 | mutex_init(&ac->mutex); |
4e7a5dcd SW |
52 | ac->negotiating = true; |
53 | if (name) | |
54 | ac->name = name; | |
55 | else | |
56 | ac->name = CEPH_AUTH_NAME_DEFAULT; | |
8323c3aa TV |
57 | dout("auth_init name %s\n", ac->name); |
58 | ac->key = key; | |
4e7a5dcd SW |
59 | return ac; |
60 | ||
61 | out: | |
62 | return ERR_PTR(ret); | |
63 | } | |
64 | ||
65 | void ceph_auth_destroy(struct ceph_auth_client *ac) | |
66 | { | |
67 | dout("auth_destroy %p\n", ac); | |
68 | if (ac->ops) | |
69 | ac->ops->destroy(ac); | |
70 | kfree(ac); | |
71 | } | |
72 | ||
73 | /* | |
74 | * Reset occurs when reconnecting to the monitor. | |
75 | */ | |
76 | void ceph_auth_reset(struct ceph_auth_client *ac) | |
77 | { | |
e9966076 | 78 | mutex_lock(&ac->mutex); |
4e7a5dcd SW |
79 | dout("auth_reset %p\n", ac); |
80 | if (ac->ops && !ac->negotiating) | |
81 | ac->ops->reset(ac); | |
82 | ac->negotiating = true; | |
e9966076 | 83 | mutex_unlock(&ac->mutex); |
4e7a5dcd SW |
84 | } |
85 | ||
f01d5cb2 ID |
86 | /* |
87 | * EntityName, not to be confused with entity_name_t | |
88 | */ | |
89 | int ceph_auth_entity_name_encode(const char *name, void **p, void *end) | |
4e7a5dcd SW |
90 | { |
91 | int len = strlen(name); | |
92 | ||
93 | if (*p + 2*sizeof(u32) + len > end) | |
94 | return -ERANGE; | |
95 | ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT); | |
96 | ceph_encode_32(p, len); | |
97 | ceph_encode_copy(p, name, len); | |
98 | return 0; | |
99 | } | |
100 | ||
101 | /* | |
102 | * Initiate protocol negotiation with monitor. Include entity name | |
103 | * and list supported protocols. | |
104 | */ | |
105 | int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) | |
106 | { | |
107 | struct ceph_mon_request_header *monhdr = buf; | |
108 | void *p = monhdr + 1, *end = buf + len, *lenp; | |
109 | int i, num; | |
110 | int ret; | |
111 | ||
e9966076 | 112 | mutex_lock(&ac->mutex); |
4e7a5dcd SW |
113 | dout("auth_build_hello\n"); |
114 | monhdr->have_version = 0; | |
115 | monhdr->session_mon = cpu_to_le16(-1); | |
116 | monhdr->session_mon_tid = 0; | |
117 | ||
fdc723e7 | 118 | ceph_encode_32(&p, CEPH_AUTH_UNKNOWN); /* no protocol, yet */ |
4e7a5dcd SW |
119 | |
120 | lenp = p; | |
121 | p += sizeof(u32); | |
122 | ||
07c8739c SW |
123 | ceph_decode_need(&p, end, 1 + sizeof(u32), bad); |
124 | ceph_encode_8(&p, 1); | |
4e7a5dcd SW |
125 | num = ARRAY_SIZE(supported_protocols); |
126 | ceph_encode_32(&p, num); | |
07c8739c | 127 | ceph_decode_need(&p, end, num * sizeof(u32), bad); |
4e7a5dcd SW |
128 | for (i = 0; i < num; i++) |
129 | ceph_encode_32(&p, supported_protocols[i]); | |
130 | ||
f01d5cb2 | 131 | ret = ceph_auth_entity_name_encode(ac->name, &p, end); |
4e7a5dcd | 132 | if (ret < 0) |
e9966076 | 133 | goto out; |
4e7a5dcd SW |
134 | ceph_decode_need(&p, end, sizeof(u64), bad); |
135 | ceph_encode_64(&p, ac->global_id); | |
136 | ||
137 | ceph_encode_32(&lenp, p - lenp - sizeof(u32)); | |
e9966076 SW |
138 | ret = p - buf; |
139 | out: | |
140 | mutex_unlock(&ac->mutex); | |
141 | return ret; | |
4e7a5dcd SW |
142 | |
143 | bad: | |
e9966076 SW |
144 | ret = -ERANGE; |
145 | goto out; | |
4e7a5dcd SW |
146 | } |
147 | ||
cd84db6e YS |
148 | static int ceph_build_auth_request(struct ceph_auth_client *ac, |
149 | void *msg_buf, size_t msg_len) | |
9bd2e6f8 SW |
150 | { |
151 | struct ceph_mon_request_header *monhdr = msg_buf; | |
152 | void *p = monhdr + 1; | |
153 | void *end = msg_buf + msg_len; | |
154 | int ret; | |
155 | ||
156 | monhdr->have_version = 0; | |
157 | monhdr->session_mon = cpu_to_le16(-1); | |
158 | monhdr->session_mon_tid = 0; | |
159 | ||
160 | ceph_encode_32(&p, ac->protocol); | |
161 | ||
162 | ret = ac->ops->build_request(ac, p + sizeof(u32), end); | |
163 | if (ret < 0) { | |
559c1e00 SW |
164 | pr_err("error %d building auth method %s request\n", ret, |
165 | ac->ops->name); | |
e9966076 | 166 | goto out; |
9bd2e6f8 SW |
167 | } |
168 | dout(" built request %d bytes\n", ret); | |
169 | ceph_encode_32(&p, ret); | |
e9966076 SW |
170 | ret = p + ret - msg_buf; |
171 | out: | |
172 | return ret; | |
9bd2e6f8 SW |
173 | } |
174 | ||
4e7a5dcd SW |
175 | /* |
176 | * Handle auth message from monitor. | |
177 | */ | |
178 | int ceph_handle_auth_reply(struct ceph_auth_client *ac, | |
179 | void *buf, size_t len, | |
180 | void *reply_buf, size_t reply_len) | |
181 | { | |
182 | void *p = buf; | |
183 | void *end = buf + len; | |
184 | int protocol; | |
185 | s32 result; | |
186 | u64 global_id; | |
187 | void *payload, *payload_end; | |
188 | int payload_len; | |
189 | char *result_msg; | |
190 | int result_msg_len; | |
191 | int ret = -EINVAL; | |
192 | ||
e9966076 | 193 | mutex_lock(&ac->mutex); |
4e7a5dcd SW |
194 | dout("handle_auth_reply %p %p\n", p, end); |
195 | ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad); | |
196 | protocol = ceph_decode_32(&p); | |
197 | result = ceph_decode_32(&p); | |
198 | global_id = ceph_decode_64(&p); | |
199 | payload_len = ceph_decode_32(&p); | |
200 | payload = p; | |
201 | p += payload_len; | |
202 | ceph_decode_need(&p, end, sizeof(u32), bad); | |
203 | result_msg_len = ceph_decode_32(&p); | |
204 | result_msg = p; | |
205 | p += result_msg_len; | |
206 | if (p != end) | |
207 | goto bad; | |
208 | ||
209 | dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len, | |
210 | result_msg, global_id, payload_len); | |
211 | ||
212 | payload_end = payload + payload_len; | |
213 | ||
214 | if (global_id && ac->global_id != global_id) { | |
215 | dout(" set global_id %lld -> %lld\n", ac->global_id, global_id); | |
216 | ac->global_id = global_id; | |
217 | } | |
218 | ||
219 | if (ac->negotiating) { | |
dc14657c YS |
220 | /* server does not support our protocols? */ |
221 | if (!protocol && result < 0) { | |
222 | ret = result; | |
223 | goto out; | |
224 | } | |
4e7a5dcd SW |
225 | /* set up (new) protocol handler? */ |
226 | if (ac->protocol && ac->protocol != protocol) { | |
227 | ac->ops->destroy(ac); | |
228 | ac->protocol = 0; | |
229 | ac->ops = NULL; | |
230 | } | |
231 | if (ac->protocol != protocol) { | |
232 | ret = ceph_auth_init_protocol(ac, protocol); | |
233 | if (ret) { | |
e95e9a7a SW |
234 | pr_err("error %d on auth protocol %d init\n", |
235 | ret, protocol); | |
4e7a5dcd SW |
236 | goto out; |
237 | } | |
238 | } | |
9bd2e6f8 SW |
239 | |
240 | ac->negotiating = false; | |
4e7a5dcd SW |
241 | } |
242 | ||
243 | ret = ac->ops->handle_reply(ac, result, payload, payload_end); | |
244 | if (ret == -EAGAIN) { | |
e9966076 | 245 | ret = ceph_build_auth_request(ac, reply_buf, reply_len); |
4e7a5dcd | 246 | } else if (ret) { |
559c1e00 | 247 | pr_err("auth method '%s' error %d\n", ac->ops->name, ret); |
4e7a5dcd | 248 | } |
4e7a5dcd | 249 | |
4e7a5dcd | 250 | out: |
e9966076 | 251 | mutex_unlock(&ac->mutex); |
4e7a5dcd | 252 | return ret; |
e9966076 SW |
253 | |
254 | bad: | |
255 | pr_err("failed to decode auth msg\n"); | |
256 | ret = -EINVAL; | |
257 | goto out; | |
4e7a5dcd SW |
258 | } |
259 | ||
9bd2e6f8 SW |
260 | int ceph_build_auth(struct ceph_auth_client *ac, |
261 | void *msg_buf, size_t msg_len) | |
262 | { | |
e9966076 SW |
263 | int ret = 0; |
264 | ||
265 | mutex_lock(&ac->mutex); | |
464691bd | 266 | if (ac->ops->should_authenticate(ac)) |
e9966076 SW |
267 | ret = ceph_build_auth_request(ac, msg_buf, msg_len); |
268 | mutex_unlock(&ac->mutex); | |
269 | return ret; | |
9bd2e6f8 | 270 | } |
4e7a5dcd | 271 | |
9bd2e6f8 SW |
272 | int ceph_auth_is_authenticated(struct ceph_auth_client *ac) |
273 | { | |
e9966076 SW |
274 | int ret = 0; |
275 | ||
276 | mutex_lock(&ac->mutex); | |
277 | if (ac->ops) | |
278 | ret = ac->ops->is_authenticated(ac); | |
279 | mutex_unlock(&ac->mutex); | |
280 | return ret; | |
9bd2e6f8 | 281 | } |
27859f97 SW |
282 | EXPORT_SYMBOL(ceph_auth_is_authenticated); |
283 | ||
284 | int ceph_auth_create_authorizer(struct ceph_auth_client *ac, | |
285 | int peer_type, | |
286 | struct ceph_auth_handshake *auth) | |
287 | { | |
e9966076 SW |
288 | int ret = 0; |
289 | ||
290 | mutex_lock(&ac->mutex); | |
27859f97 | 291 | if (ac->ops && ac->ops->create_authorizer) |
e9966076 SW |
292 | ret = ac->ops->create_authorizer(ac, peer_type, auth); |
293 | mutex_unlock(&ac->mutex); | |
294 | return ret; | |
27859f97 SW |
295 | } |
296 | EXPORT_SYMBOL(ceph_auth_create_authorizer); | |
297 | ||
6c1ea260 | 298 | void ceph_auth_destroy_authorizer(struct ceph_authorizer *a) |
27859f97 | 299 | { |
6c1ea260 | 300 | a->destroy(a); |
27859f97 SW |
301 | } |
302 | EXPORT_SYMBOL(ceph_auth_destroy_authorizer); | |
303 | ||
304 | int ceph_auth_update_authorizer(struct ceph_auth_client *ac, | |
305 | int peer_type, | |
306 | struct ceph_auth_handshake *a) | |
307 | { | |
308 | int ret = 0; | |
309 | ||
e9966076 | 310 | mutex_lock(&ac->mutex); |
27859f97 SW |
311 | if (ac->ops && ac->ops->update_authorizer) |
312 | ret = ac->ops->update_authorizer(ac, peer_type, a); | |
e9966076 | 313 | mutex_unlock(&ac->mutex); |
27859f97 SW |
314 | return ret; |
315 | } | |
316 | EXPORT_SYMBOL(ceph_auth_update_authorizer); | |
317 | ||
6daca13d ID |
318 | int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac, |
319 | struct ceph_authorizer *a, | |
320 | void *challenge_buf, | |
321 | int challenge_buf_len) | |
322 | { | |
323 | int ret = 0; | |
324 | ||
325 | mutex_lock(&ac->mutex); | |
326 | if (ac->ops && ac->ops->add_authorizer_challenge) | |
327 | ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf, | |
328 | challenge_buf_len); | |
329 | mutex_unlock(&ac->mutex); | |
330 | return ret; | |
331 | } | |
332 | EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge); | |
333 | ||
27859f97 | 334 | int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac, |
0dde5848 | 335 | struct ceph_authorizer *a) |
27859f97 | 336 | { |
e9966076 SW |
337 | int ret = 0; |
338 | ||
339 | mutex_lock(&ac->mutex); | |
27859f97 | 340 | if (ac->ops && ac->ops->verify_authorizer_reply) |
0dde5848 | 341 | ret = ac->ops->verify_authorizer_reply(ac, a); |
e9966076 SW |
342 | mutex_unlock(&ac->mutex); |
343 | return ret; | |
27859f97 SW |
344 | } |
345 | EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply); | |
346 | ||
347 | void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type) | |
348 | { | |
e9966076 | 349 | mutex_lock(&ac->mutex); |
27859f97 SW |
350 | if (ac->ops && ac->ops->invalidate_authorizer) |
351 | ac->ops->invalidate_authorizer(ac, peer_type); | |
e9966076 | 352 | mutex_unlock(&ac->mutex); |
27859f97 SW |
353 | } |
354 | EXPORT_SYMBOL(ceph_auth_invalidate_authorizer); |