1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/ceph/ceph_debug.h>
4 #include <linux/module.h>
6 #include <linux/slab.h>
8 #include <linux/ceph/types.h>
9 #include <linux/ceph/decode.h>
10 #include <linux/ceph/libceph.h>
11 #include <linux/ceph/messenger.h>
12 #include "auth_none.h"
17 * get protocol handler
19 static u32 supported_protocols
[] = {
24 static int init_protocol(struct ceph_auth_client
*ac
, int proto
)
26 dout("%s proto %d\n", __func__
, proto
);
30 return ceph_auth_none_init(ac
);
32 return ceph_x_init(ac
);
34 pr_err("bad auth protocol %d\n", proto
);
42 struct ceph_auth_client
*ceph_auth_init(const char *name
,
43 const struct ceph_crypto_key
*key
,
46 struct ceph_auth_client
*ac
;
50 ac
= kzalloc(sizeof(*ac
), GFP_NOFS
);
54 mutex_init(&ac
->mutex
);
55 ac
->negotiating
= true;
59 ac
->name
= CEPH_AUTH_NAME_DEFAULT
;
61 ac
->preferred_mode
= con_modes
[0];
62 ac
->fallback_mode
= con_modes
[1];
64 dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__
,
65 ac
->name
, ac
->preferred_mode
, ac
->fallback_mode
);
72 void ceph_auth_destroy(struct ceph_auth_client
*ac
)
74 dout("auth_destroy %p\n", ac
);
81 * Reset occurs when reconnecting to the monitor.
83 void ceph_auth_reset(struct ceph_auth_client
*ac
)
85 mutex_lock(&ac
->mutex
);
86 dout("auth_reset %p\n", ac
);
87 if (ac
->ops
&& !ac
->negotiating
)
89 ac
->negotiating
= true;
90 mutex_unlock(&ac
->mutex
);
94 * EntityName, not to be confused with entity_name_t
96 int ceph_auth_entity_name_encode(const char *name
, void **p
, void *end
)
98 int len
= strlen(name
);
100 if (*p
+ 2*sizeof(u32
) + len
> end
)
102 ceph_encode_32(p
, CEPH_ENTITY_TYPE_CLIENT
);
103 ceph_encode_32(p
, len
);
104 ceph_encode_copy(p
, name
, len
);
109 * Initiate protocol negotiation with monitor. Include entity name
110 * and list supported protocols.
112 int ceph_auth_build_hello(struct ceph_auth_client
*ac
, void *buf
, size_t len
)
114 struct ceph_mon_request_header
*monhdr
= buf
;
115 void *p
= monhdr
+ 1, *end
= buf
+ len
, *lenp
;
119 mutex_lock(&ac
->mutex
);
120 dout("auth_build_hello\n");
121 monhdr
->have_version
= 0;
122 monhdr
->session_mon
= cpu_to_le16(-1);
123 monhdr
->session_mon_tid
= 0;
125 ceph_encode_32(&p
, CEPH_AUTH_UNKNOWN
); /* no protocol, yet */
130 ceph_decode_need(&p
, end
, 1 + sizeof(u32
), bad
);
131 ceph_encode_8(&p
, 1);
132 num
= ARRAY_SIZE(supported_protocols
);
133 ceph_encode_32(&p
, num
);
134 ceph_decode_need(&p
, end
, num
* sizeof(u32
), bad
);
135 for (i
= 0; i
< num
; i
++)
136 ceph_encode_32(&p
, supported_protocols
[i
]);
138 ret
= ceph_auth_entity_name_encode(ac
->name
, &p
, end
);
141 ceph_decode_need(&p
, end
, sizeof(u64
), bad
);
142 ceph_encode_64(&p
, ac
->global_id
);
144 ceph_encode_32(&lenp
, p
- lenp
- sizeof(u32
));
147 mutex_unlock(&ac
->mutex
);
155 static int build_request(struct ceph_auth_client
*ac
, bool add_header
,
156 void *buf
, int buf_len
)
158 void *end
= buf
+ buf_len
;
164 /* struct ceph_mon_request_header + protocol */
165 ceph_encode_64_safe(&p
, end
, 0, e_range
);
166 ceph_encode_16_safe(&p
, end
, -1, e_range
);
167 ceph_encode_64_safe(&p
, end
, 0, e_range
);
168 ceph_encode_32_safe(&p
, end
, ac
->protocol
, e_range
);
171 ceph_encode_need(&p
, end
, sizeof(u32
), e_range
);
172 ret
= ac
->ops
->build_request(ac
, p
+ sizeof(u32
), end
);
174 pr_err("auth protocol '%s' building request failed: %d\n",
175 ceph_auth_proto_name(ac
->protocol
), ret
);
178 dout(" built request %d bytes\n", ret
);
179 ceph_encode_32(&p
, ret
);
180 return p
+ ret
- buf
;
187 * Handle auth message from monitor.
189 int ceph_handle_auth_reply(struct ceph_auth_client
*ac
,
190 void *buf
, size_t len
,
191 void *reply_buf
, size_t reply_len
)
194 void *end
= buf
+ len
;
198 void *payload
, *payload_end
;
204 mutex_lock(&ac
->mutex
);
205 dout("handle_auth_reply %p %p\n", p
, end
);
206 ceph_decode_need(&p
, end
, sizeof(u32
) * 3 + sizeof(u64
), bad
);
207 protocol
= ceph_decode_32(&p
);
208 result
= ceph_decode_32(&p
);
209 global_id
= ceph_decode_64(&p
);
210 payload_len
= ceph_decode_32(&p
);
213 ceph_decode_need(&p
, end
, sizeof(u32
), bad
);
214 result_msg_len
= ceph_decode_32(&p
);
220 dout(" result %d '%.*s' gid %llu len %d\n", result
, result_msg_len
,
221 result_msg
, global_id
, payload_len
);
223 payload_end
= payload
+ payload_len
;
225 if (global_id
&& ac
->global_id
!= global_id
) {
226 dout(" set global_id %lld -> %lld\n", ac
->global_id
, global_id
);
227 ac
->global_id
= global_id
;
230 if (ac
->negotiating
) {
231 /* server does not support our protocols? */
232 if (!protocol
&& result
< 0) {
236 /* set up (new) protocol handler? */
237 if (ac
->protocol
&& ac
->protocol
!= protocol
) {
238 ac
->ops
->destroy(ac
);
242 if (ac
->protocol
!= protocol
) {
243 ret
= init_protocol(ac
, protocol
);
245 pr_err("auth protocol '%s' init failed: %d\n",
246 ceph_auth_proto_name(protocol
), ret
);
251 ac
->negotiating
= false;
254 ret
= ac
->ops
->handle_reply(ac
, result
, payload
, payload_end
,
255 NULL
, NULL
, NULL
, NULL
);
257 ret
= build_request(ac
, true, reply_buf
, reply_len
);
259 pr_err("auth protocol '%s' mauth authentication failed: %d\n",
260 ceph_auth_proto_name(ac
->protocol
), result
);
263 mutex_unlock(&ac
->mutex
);
267 pr_err("failed to decode auth msg\n");
272 int ceph_build_auth(struct ceph_auth_client
*ac
,
273 void *msg_buf
, size_t msg_len
)
277 mutex_lock(&ac
->mutex
);
278 if (ac
->ops
->should_authenticate(ac
))
279 ret
= build_request(ac
, true, msg_buf
, msg_len
);
280 mutex_unlock(&ac
->mutex
);
284 int ceph_auth_is_authenticated(struct ceph_auth_client
*ac
)
288 mutex_lock(&ac
->mutex
);
290 ret
= ac
->ops
->is_authenticated(ac
);
291 mutex_unlock(&ac
->mutex
);
294 EXPORT_SYMBOL(ceph_auth_is_authenticated
);
296 int __ceph_auth_get_authorizer(struct ceph_auth_client
*ac
,
297 struct ceph_auth_handshake
*auth
,
298 int peer_type
, bool force_new
,
299 int *proto
, int *pref_mode
, int *fallb_mode
)
303 mutex_lock(&ac
->mutex
);
304 if (force_new
&& auth
->authorizer
) {
305 ceph_auth_destroy_authorizer(auth
->authorizer
);
306 auth
->authorizer
= NULL
;
308 if (!auth
->authorizer
)
309 ret
= ac
->ops
->create_authorizer(ac
, peer_type
, auth
);
310 else if (ac
->ops
->update_authorizer
)
311 ret
= ac
->ops
->update_authorizer(ac
, peer_type
, auth
);
317 *proto
= ac
->protocol
;
318 if (pref_mode
&& fallb_mode
) {
319 *pref_mode
= ac
->preferred_mode
;
320 *fallb_mode
= ac
->fallback_mode
;
324 mutex_unlock(&ac
->mutex
);
327 EXPORT_SYMBOL(__ceph_auth_get_authorizer
);
329 void ceph_auth_destroy_authorizer(struct ceph_authorizer
*a
)
333 EXPORT_SYMBOL(ceph_auth_destroy_authorizer
);
335 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client
*ac
,
336 struct ceph_authorizer
*a
,
338 int challenge_buf_len
)
342 mutex_lock(&ac
->mutex
);
343 if (ac
->ops
&& ac
->ops
->add_authorizer_challenge
)
344 ret
= ac
->ops
->add_authorizer_challenge(ac
, a
, challenge_buf
,
346 mutex_unlock(&ac
->mutex
);
349 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge
);
351 int ceph_auth_verify_authorizer_reply(struct ceph_auth_client
*ac
,
352 struct ceph_authorizer
*a
,
353 void *reply
, int reply_len
,
354 u8
*session_key
, int *session_key_len
,
355 u8
*con_secret
, int *con_secret_len
)
359 mutex_lock(&ac
->mutex
);
360 if (ac
->ops
&& ac
->ops
->verify_authorizer_reply
)
361 ret
= ac
->ops
->verify_authorizer_reply(ac
, a
,
362 reply
, reply_len
, session_key
, session_key_len
,
363 con_secret
, con_secret_len
);
364 mutex_unlock(&ac
->mutex
);
367 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply
);
369 void ceph_auth_invalidate_authorizer(struct ceph_auth_client
*ac
, int peer_type
)
371 mutex_lock(&ac
->mutex
);
372 if (ac
->ops
&& ac
->ops
->invalidate_authorizer
)
373 ac
->ops
->invalidate_authorizer(ac
, peer_type
);
374 mutex_unlock(&ac
->mutex
);
376 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer
);
379 * msgr2 authentication
382 static bool contains(const int *arr
, int cnt
, int val
)
386 for (i
= 0; i
< cnt
; i
++) {
394 static int encode_con_modes(void **p
, void *end
, int pref_mode
, int fallb_mode
)
396 WARN_ON(pref_mode
== CEPH_CON_MODE_UNKNOWN
);
397 if (fallb_mode
!= CEPH_CON_MODE_UNKNOWN
) {
398 ceph_encode_32_safe(p
, end
, 2, e_range
);
399 ceph_encode_32_safe(p
, end
, pref_mode
, e_range
);
400 ceph_encode_32_safe(p
, end
, fallb_mode
, e_range
);
402 ceph_encode_32_safe(p
, end
, 1, e_range
);
403 ceph_encode_32_safe(p
, end
, pref_mode
, e_range
);
413 * Similar to ceph_auth_build_hello().
415 int ceph_auth_get_request(struct ceph_auth_client
*ac
, void *buf
, int buf_len
)
417 int proto
= ac
->key
? CEPH_AUTH_CEPHX
: CEPH_AUTH_NONE
;
418 void *end
= buf
+ buf_len
;
423 mutex_lock(&ac
->mutex
);
424 if (ac
->protocol
== CEPH_AUTH_UNKNOWN
) {
425 ret
= init_protocol(ac
, proto
);
427 pr_err("auth protocol '%s' init failed: %d\n",
428 ceph_auth_proto_name(proto
), ret
);
432 WARN_ON(ac
->protocol
!= proto
);
437 ceph_encode_32_safe(&p
, end
, ac
->protocol
, e_range
);
438 ret
= encode_con_modes(&p
, end
, ac
->preferred_mode
, ac
->fallback_mode
);
443 p
+= 4; /* space for len */
445 ceph_encode_8_safe(&p
, end
, CEPH_AUTH_MODE_MON
, e_range
);
446 ret
= ceph_auth_entity_name_encode(ac
->name
, &p
, end
);
450 ceph_encode_64_safe(&p
, end
, ac
->global_id
, e_range
);
451 ceph_encode_32(&lenp
, p
- lenp
- 4);
455 mutex_unlock(&ac
->mutex
);
463 int ceph_auth_handle_reply_more(struct ceph_auth_client
*ac
, void *reply
,
464 int reply_len
, void *buf
, int buf_len
)
468 mutex_lock(&ac
->mutex
);
469 ret
= ac
->ops
->handle_reply(ac
, 0, reply
, reply
+ reply_len
,
470 NULL
, NULL
, NULL
, NULL
);
472 ret
= build_request(ac
, false, buf
, buf_len
);
475 mutex_unlock(&ac
->mutex
);
479 int ceph_auth_handle_reply_done(struct ceph_auth_client
*ac
,
480 u64 global_id
, void *reply
, int reply_len
,
481 u8
*session_key
, int *session_key_len
,
482 u8
*con_secret
, int *con_secret_len
)
486 mutex_lock(&ac
->mutex
);
487 if (global_id
&& ac
->global_id
!= global_id
) {
488 dout("%s global_id %llu -> %llu\n", __func__
, ac
->global_id
,
490 ac
->global_id
= global_id
;
493 ret
= ac
->ops
->handle_reply(ac
, 0, reply
, reply
+ reply_len
,
494 session_key
, session_key_len
,
495 con_secret
, con_secret_len
);
496 mutex_unlock(&ac
->mutex
);
500 bool ceph_auth_handle_bad_method(struct ceph_auth_client
*ac
,
501 int used_proto
, int result
,
502 const int *allowed_protos
, int proto_cnt
,
503 const int *allowed_modes
, int mode_cnt
)
505 mutex_lock(&ac
->mutex
);
506 WARN_ON(used_proto
!= ac
->protocol
);
508 if (result
== -EOPNOTSUPP
) {
509 if (!contains(allowed_protos
, proto_cnt
, ac
->protocol
)) {
510 pr_err("auth protocol '%s' not allowed\n",
511 ceph_auth_proto_name(ac
->protocol
));
514 if (!contains(allowed_modes
, mode_cnt
, ac
->preferred_mode
) &&
515 (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
||
516 !contains(allowed_modes
, mode_cnt
, ac
->fallback_mode
))) {
517 pr_err("preferred mode '%s' not allowed\n",
518 ceph_con_mode_name(ac
->preferred_mode
));
519 if (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
)
520 pr_err("no fallback mode\n");
522 pr_err("fallback mode '%s' not allowed\n",
523 ceph_con_mode_name(ac
->fallback_mode
));
528 WARN_ON(result
== -EOPNOTSUPP
|| result
>= 0);
529 pr_err("auth protocol '%s' msgr authentication failed: %d\n",
530 ceph_auth_proto_name(ac
->protocol
), result
);
532 mutex_unlock(&ac
->mutex
);
536 mutex_unlock(&ac
->mutex
);
540 int ceph_auth_get_authorizer(struct ceph_auth_client
*ac
,
541 struct ceph_auth_handshake
*auth
,
542 int peer_type
, void *buf
, int *buf_len
)
544 void *end
= buf
+ *buf_len
;
545 int pref_mode
, fallb_mode
;
550 ret
= __ceph_auth_get_authorizer(ac
, auth
, peer_type
, true, &proto
,
551 &pref_mode
, &fallb_mode
);
556 ceph_encode_32_safe(&p
, end
, proto
, e_range
);
557 ret
= encode_con_modes(&p
, end
, pref_mode
, fallb_mode
);
561 ceph_encode_32_safe(&p
, end
, auth
->authorizer_buf_len
, e_range
);
568 EXPORT_SYMBOL(ceph_auth_get_authorizer
);
570 int ceph_auth_handle_svc_reply_more(struct ceph_auth_client
*ac
,
571 struct ceph_auth_handshake
*auth
,
572 void *reply
, int reply_len
,
573 void *buf
, int *buf_len
)
575 void *end
= buf
+ *buf_len
;
579 ret
= ceph_auth_add_authorizer_challenge(ac
, auth
->authorizer
,
585 ceph_encode_32_safe(&p
, end
, auth
->authorizer_buf_len
, e_range
);
592 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more
);
594 int ceph_auth_handle_svc_reply_done(struct ceph_auth_client
*ac
,
595 struct ceph_auth_handshake
*auth
,
596 void *reply
, int reply_len
,
597 u8
*session_key
, int *session_key_len
,
598 u8
*con_secret
, int *con_secret_len
)
600 return ceph_auth_verify_authorizer_reply(ac
, auth
->authorizer
,
601 reply
, reply_len
, session_key
, session_key_len
,
602 con_secret
, con_secret_len
);
604 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done
);
606 bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client
*ac
,
607 int peer_type
, int used_proto
, int result
,
608 const int *allowed_protos
, int proto_cnt
,
609 const int *allowed_modes
, int mode_cnt
)
611 mutex_lock(&ac
->mutex
);
612 WARN_ON(used_proto
!= ac
->protocol
);
614 if (result
== -EOPNOTSUPP
) {
615 if (!contains(allowed_protos
, proto_cnt
, ac
->protocol
)) {
616 pr_err("auth protocol '%s' not allowed by %s\n",
617 ceph_auth_proto_name(ac
->protocol
),
618 ceph_entity_type_name(peer_type
));
621 if (!contains(allowed_modes
, mode_cnt
, ac
->preferred_mode
) &&
622 (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
||
623 !contains(allowed_modes
, mode_cnt
, ac
->fallback_mode
))) {
624 pr_err("preferred mode '%s' not allowed by %s\n",
625 ceph_con_mode_name(ac
->preferred_mode
),
626 ceph_entity_type_name(peer_type
));
627 if (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
)
628 pr_err("no fallback mode\n");
630 pr_err("fallback mode '%s' not allowed by %s\n",
631 ceph_con_mode_name(ac
->fallback_mode
),
632 ceph_entity_type_name(peer_type
));
637 WARN_ON(result
== -EOPNOTSUPP
|| result
>= 0);
638 pr_err("auth protocol '%s' authorization to %s failed: %d\n",
639 ceph_auth_proto_name(ac
->protocol
),
640 ceph_entity_type_name(peer_type
), result
);
642 if (ac
->ops
->invalidate_authorizer
)
643 ac
->ops
->invalidate_authorizer(ac
, peer_type
);
645 mutex_unlock(&ac
->mutex
);
649 mutex_unlock(&ac
->mutex
);
652 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer
);