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
);
39 static void set_global_id(struct ceph_auth_client
*ac
, u64 global_id
)
41 dout("%s global_id %llu\n", __func__
, global_id
);
44 pr_err("got zero global_id\n");
46 if (ac
->global_id
&& global_id
!= ac
->global_id
)
47 pr_err("global_id changed from %llu to %llu\n", ac
->global_id
,
50 ac
->global_id
= global_id
;
56 struct ceph_auth_client
*ceph_auth_init(const char *name
,
57 const struct ceph_crypto_key
*key
,
60 struct ceph_auth_client
*ac
;
64 ac
= kzalloc(sizeof(*ac
), GFP_NOFS
);
68 mutex_init(&ac
->mutex
);
69 ac
->negotiating
= true;
73 ac
->name
= CEPH_AUTH_NAME_DEFAULT
;
75 ac
->preferred_mode
= con_modes
[0];
76 ac
->fallback_mode
= con_modes
[1];
78 dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__
,
79 ac
->name
, ac
->preferred_mode
, ac
->fallback_mode
);
86 void ceph_auth_destroy(struct ceph_auth_client
*ac
)
88 dout("auth_destroy %p\n", ac
);
95 * Reset occurs when reconnecting to the monitor.
97 void ceph_auth_reset(struct ceph_auth_client
*ac
)
99 mutex_lock(&ac
->mutex
);
100 dout("auth_reset %p\n", ac
);
101 if (ac
->ops
&& !ac
->negotiating
)
103 ac
->negotiating
= true;
104 mutex_unlock(&ac
->mutex
);
108 * EntityName, not to be confused with entity_name_t
110 int ceph_auth_entity_name_encode(const char *name
, void **p
, void *end
)
112 int len
= strlen(name
);
114 if (*p
+ 2*sizeof(u32
) + len
> end
)
116 ceph_encode_32(p
, CEPH_ENTITY_TYPE_CLIENT
);
117 ceph_encode_32(p
, len
);
118 ceph_encode_copy(p
, name
, len
);
123 * Initiate protocol negotiation with monitor. Include entity name
124 * and list supported protocols.
126 int ceph_auth_build_hello(struct ceph_auth_client
*ac
, void *buf
, size_t len
)
128 struct ceph_mon_request_header
*monhdr
= buf
;
129 void *p
= monhdr
+ 1, *end
= buf
+ len
, *lenp
;
133 mutex_lock(&ac
->mutex
);
134 dout("auth_build_hello\n");
135 monhdr
->have_version
= 0;
136 monhdr
->session_mon
= cpu_to_le16(-1);
137 monhdr
->session_mon_tid
= 0;
139 ceph_encode_32(&p
, CEPH_AUTH_UNKNOWN
); /* no protocol, yet */
144 ceph_decode_need(&p
, end
, 1 + sizeof(u32
), bad
);
145 ceph_encode_8(&p
, 1);
146 num
= ARRAY_SIZE(supported_protocols
);
147 ceph_encode_32(&p
, num
);
148 ceph_decode_need(&p
, end
, num
* sizeof(u32
), bad
);
149 for (i
= 0; i
< num
; i
++)
150 ceph_encode_32(&p
, supported_protocols
[i
]);
152 ret
= ceph_auth_entity_name_encode(ac
->name
, &p
, end
);
155 ceph_decode_need(&p
, end
, sizeof(u64
), bad
);
156 ceph_encode_64(&p
, ac
->global_id
);
158 ceph_encode_32(&lenp
, p
- lenp
- sizeof(u32
));
161 mutex_unlock(&ac
->mutex
);
169 static int build_request(struct ceph_auth_client
*ac
, bool add_header
,
170 void *buf
, int buf_len
)
172 void *end
= buf
+ buf_len
;
178 /* struct ceph_mon_request_header + protocol */
179 ceph_encode_64_safe(&p
, end
, 0, e_range
);
180 ceph_encode_16_safe(&p
, end
, -1, e_range
);
181 ceph_encode_64_safe(&p
, end
, 0, e_range
);
182 ceph_encode_32_safe(&p
, end
, ac
->protocol
, e_range
);
185 ceph_encode_need(&p
, end
, sizeof(u32
), e_range
);
186 ret
= ac
->ops
->build_request(ac
, p
+ sizeof(u32
), end
);
188 pr_err("auth protocol '%s' building request failed: %d\n",
189 ceph_auth_proto_name(ac
->protocol
), ret
);
192 dout(" built request %d bytes\n", ret
);
193 ceph_encode_32(&p
, ret
);
194 return p
+ ret
- buf
;
201 * Handle auth message from monitor.
203 int ceph_handle_auth_reply(struct ceph_auth_client
*ac
,
204 void *buf
, size_t len
,
205 void *reply_buf
, size_t reply_len
)
208 void *end
= buf
+ len
;
212 void *payload
, *payload_end
;
218 mutex_lock(&ac
->mutex
);
219 dout("handle_auth_reply %p %p\n", p
, end
);
220 ceph_decode_need(&p
, end
, sizeof(u32
) * 3 + sizeof(u64
), bad
);
221 protocol
= ceph_decode_32(&p
);
222 result
= ceph_decode_32(&p
);
223 global_id
= ceph_decode_64(&p
);
224 payload_len
= ceph_decode_32(&p
);
227 ceph_decode_need(&p
, end
, sizeof(u32
), bad
);
228 result_msg_len
= ceph_decode_32(&p
);
234 dout(" result %d '%.*s' gid %llu len %d\n", result
, result_msg_len
,
235 result_msg
, global_id
, payload_len
);
237 payload_end
= payload
+ payload_len
;
239 if (ac
->negotiating
) {
240 /* server does not support our protocols? */
241 if (!protocol
&& result
< 0) {
245 /* set up (new) protocol handler? */
246 if (ac
->protocol
&& ac
->protocol
!= protocol
) {
247 ac
->ops
->destroy(ac
);
251 if (ac
->protocol
!= protocol
) {
252 ret
= init_protocol(ac
, protocol
);
254 pr_err("auth protocol '%s' init failed: %d\n",
255 ceph_auth_proto_name(protocol
), ret
);
260 ac
->negotiating
= false;
263 ret
= ac
->ops
->handle_reply(ac
, result
, payload
, payload_end
,
264 NULL
, NULL
, NULL
, NULL
);
265 if (ret
== -EAGAIN
) {
266 ret
= build_request(ac
, true, reply_buf
, reply_len
);
269 pr_err("auth protocol '%s' mauth authentication failed: %d\n",
270 ceph_auth_proto_name(ac
->protocol
), result
);
274 set_global_id(ac
, global_id
);
277 mutex_unlock(&ac
->mutex
);
281 pr_err("failed to decode auth msg\n");
286 int ceph_build_auth(struct ceph_auth_client
*ac
,
287 void *msg_buf
, size_t msg_len
)
291 mutex_lock(&ac
->mutex
);
292 if (ac
->ops
->should_authenticate(ac
))
293 ret
= build_request(ac
, true, msg_buf
, msg_len
);
294 mutex_unlock(&ac
->mutex
);
298 int ceph_auth_is_authenticated(struct ceph_auth_client
*ac
)
302 mutex_lock(&ac
->mutex
);
304 ret
= ac
->ops
->is_authenticated(ac
);
305 mutex_unlock(&ac
->mutex
);
308 EXPORT_SYMBOL(ceph_auth_is_authenticated
);
310 int __ceph_auth_get_authorizer(struct ceph_auth_client
*ac
,
311 struct ceph_auth_handshake
*auth
,
312 int peer_type
, bool force_new
,
313 int *proto
, int *pref_mode
, int *fallb_mode
)
317 mutex_lock(&ac
->mutex
);
318 if (force_new
&& auth
->authorizer
) {
319 ceph_auth_destroy_authorizer(auth
->authorizer
);
320 auth
->authorizer
= NULL
;
322 if (!auth
->authorizer
)
323 ret
= ac
->ops
->create_authorizer(ac
, peer_type
, auth
);
324 else if (ac
->ops
->update_authorizer
)
325 ret
= ac
->ops
->update_authorizer(ac
, peer_type
, auth
);
331 *proto
= ac
->protocol
;
332 if (pref_mode
&& fallb_mode
) {
333 *pref_mode
= ac
->preferred_mode
;
334 *fallb_mode
= ac
->fallback_mode
;
338 mutex_unlock(&ac
->mutex
);
341 EXPORT_SYMBOL(__ceph_auth_get_authorizer
);
343 void ceph_auth_destroy_authorizer(struct ceph_authorizer
*a
)
347 EXPORT_SYMBOL(ceph_auth_destroy_authorizer
);
349 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client
*ac
,
350 struct ceph_authorizer
*a
,
352 int challenge_buf_len
)
356 mutex_lock(&ac
->mutex
);
357 if (ac
->ops
&& ac
->ops
->add_authorizer_challenge
)
358 ret
= ac
->ops
->add_authorizer_challenge(ac
, a
, challenge_buf
,
360 mutex_unlock(&ac
->mutex
);
363 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge
);
365 int ceph_auth_verify_authorizer_reply(struct ceph_auth_client
*ac
,
366 struct ceph_authorizer
*a
,
367 void *reply
, int reply_len
,
368 u8
*session_key
, int *session_key_len
,
369 u8
*con_secret
, int *con_secret_len
)
373 mutex_lock(&ac
->mutex
);
374 if (ac
->ops
&& ac
->ops
->verify_authorizer_reply
)
375 ret
= ac
->ops
->verify_authorizer_reply(ac
, a
,
376 reply
, reply_len
, session_key
, session_key_len
,
377 con_secret
, con_secret_len
);
378 mutex_unlock(&ac
->mutex
);
381 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply
);
383 void ceph_auth_invalidate_authorizer(struct ceph_auth_client
*ac
, int peer_type
)
385 mutex_lock(&ac
->mutex
);
386 if (ac
->ops
&& ac
->ops
->invalidate_authorizer
)
387 ac
->ops
->invalidate_authorizer(ac
, peer_type
);
388 mutex_unlock(&ac
->mutex
);
390 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer
);
393 * msgr2 authentication
396 static bool contains(const int *arr
, int cnt
, int val
)
400 for (i
= 0; i
< cnt
; i
++) {
408 static int encode_con_modes(void **p
, void *end
, int pref_mode
, int fallb_mode
)
410 WARN_ON(pref_mode
== CEPH_CON_MODE_UNKNOWN
);
411 if (fallb_mode
!= CEPH_CON_MODE_UNKNOWN
) {
412 ceph_encode_32_safe(p
, end
, 2, e_range
);
413 ceph_encode_32_safe(p
, end
, pref_mode
, e_range
);
414 ceph_encode_32_safe(p
, end
, fallb_mode
, e_range
);
416 ceph_encode_32_safe(p
, end
, 1, e_range
);
417 ceph_encode_32_safe(p
, end
, pref_mode
, e_range
);
427 * Similar to ceph_auth_build_hello().
429 int ceph_auth_get_request(struct ceph_auth_client
*ac
, void *buf
, int buf_len
)
431 int proto
= ac
->key
? CEPH_AUTH_CEPHX
: CEPH_AUTH_NONE
;
432 void *end
= buf
+ buf_len
;
437 mutex_lock(&ac
->mutex
);
438 if (ac
->protocol
== CEPH_AUTH_UNKNOWN
) {
439 ret
= init_protocol(ac
, proto
);
441 pr_err("auth protocol '%s' init failed: %d\n",
442 ceph_auth_proto_name(proto
), ret
);
446 WARN_ON(ac
->protocol
!= proto
);
451 ceph_encode_32_safe(&p
, end
, ac
->protocol
, e_range
);
452 ret
= encode_con_modes(&p
, end
, ac
->preferred_mode
, ac
->fallback_mode
);
457 p
+= 4; /* space for len */
459 ceph_encode_8_safe(&p
, end
, CEPH_AUTH_MODE_MON
, e_range
);
460 ret
= ceph_auth_entity_name_encode(ac
->name
, &p
, end
);
464 ceph_encode_64_safe(&p
, end
, ac
->global_id
, e_range
);
465 ceph_encode_32(&lenp
, p
- lenp
- 4);
469 mutex_unlock(&ac
->mutex
);
477 int ceph_auth_handle_reply_more(struct ceph_auth_client
*ac
, void *reply
,
478 int reply_len
, void *buf
, int buf_len
)
482 mutex_lock(&ac
->mutex
);
483 ret
= ac
->ops
->handle_reply(ac
, 0, reply
, reply
+ reply_len
,
484 NULL
, NULL
, NULL
, NULL
);
486 ret
= build_request(ac
, false, buf
, buf_len
);
489 mutex_unlock(&ac
->mutex
);
493 int ceph_auth_handle_reply_done(struct ceph_auth_client
*ac
,
494 u64 global_id
, void *reply
, int reply_len
,
495 u8
*session_key
, int *session_key_len
,
496 u8
*con_secret
, int *con_secret_len
)
500 mutex_lock(&ac
->mutex
);
501 ret
= ac
->ops
->handle_reply(ac
, 0, reply
, reply
+ reply_len
,
502 session_key
, session_key_len
,
503 con_secret
, con_secret_len
);
505 set_global_id(ac
, global_id
);
506 mutex_unlock(&ac
->mutex
);
510 bool ceph_auth_handle_bad_method(struct ceph_auth_client
*ac
,
511 int used_proto
, int result
,
512 const int *allowed_protos
, int proto_cnt
,
513 const int *allowed_modes
, int mode_cnt
)
515 mutex_lock(&ac
->mutex
);
516 WARN_ON(used_proto
!= ac
->protocol
);
518 if (result
== -EOPNOTSUPP
) {
519 if (!contains(allowed_protos
, proto_cnt
, ac
->protocol
)) {
520 pr_err("auth protocol '%s' not allowed\n",
521 ceph_auth_proto_name(ac
->protocol
));
524 if (!contains(allowed_modes
, mode_cnt
, ac
->preferred_mode
) &&
525 (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
||
526 !contains(allowed_modes
, mode_cnt
, ac
->fallback_mode
))) {
527 pr_err("preferred mode '%s' not allowed\n",
528 ceph_con_mode_name(ac
->preferred_mode
));
529 if (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
)
530 pr_err("no fallback mode\n");
532 pr_err("fallback mode '%s' not allowed\n",
533 ceph_con_mode_name(ac
->fallback_mode
));
538 WARN_ON(result
== -EOPNOTSUPP
|| result
>= 0);
539 pr_err("auth protocol '%s' msgr authentication failed: %d\n",
540 ceph_auth_proto_name(ac
->protocol
), result
);
542 mutex_unlock(&ac
->mutex
);
546 mutex_unlock(&ac
->mutex
);
550 int ceph_auth_get_authorizer(struct ceph_auth_client
*ac
,
551 struct ceph_auth_handshake
*auth
,
552 int peer_type
, void *buf
, int *buf_len
)
554 void *end
= buf
+ *buf_len
;
555 int pref_mode
, fallb_mode
;
560 ret
= __ceph_auth_get_authorizer(ac
, auth
, peer_type
, true, &proto
,
561 &pref_mode
, &fallb_mode
);
566 ceph_encode_32_safe(&p
, end
, proto
, e_range
);
567 ret
= encode_con_modes(&p
, end
, pref_mode
, fallb_mode
);
571 ceph_encode_32_safe(&p
, end
, auth
->authorizer_buf_len
, e_range
);
578 EXPORT_SYMBOL(ceph_auth_get_authorizer
);
580 int ceph_auth_handle_svc_reply_more(struct ceph_auth_client
*ac
,
581 struct ceph_auth_handshake
*auth
,
582 void *reply
, int reply_len
,
583 void *buf
, int *buf_len
)
585 void *end
= buf
+ *buf_len
;
589 ret
= ceph_auth_add_authorizer_challenge(ac
, auth
->authorizer
,
595 ceph_encode_32_safe(&p
, end
, auth
->authorizer_buf_len
, e_range
);
602 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more
);
604 int ceph_auth_handle_svc_reply_done(struct ceph_auth_client
*ac
,
605 struct ceph_auth_handshake
*auth
,
606 void *reply
, int reply_len
,
607 u8
*session_key
, int *session_key_len
,
608 u8
*con_secret
, int *con_secret_len
)
610 return ceph_auth_verify_authorizer_reply(ac
, auth
->authorizer
,
611 reply
, reply_len
, session_key
, session_key_len
,
612 con_secret
, con_secret_len
);
614 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done
);
616 bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client
*ac
,
617 int peer_type
, int used_proto
, int result
,
618 const int *allowed_protos
, int proto_cnt
,
619 const int *allowed_modes
, int mode_cnt
)
621 mutex_lock(&ac
->mutex
);
622 WARN_ON(used_proto
!= ac
->protocol
);
624 if (result
== -EOPNOTSUPP
) {
625 if (!contains(allowed_protos
, proto_cnt
, ac
->protocol
)) {
626 pr_err("auth protocol '%s' not allowed by %s\n",
627 ceph_auth_proto_name(ac
->protocol
),
628 ceph_entity_type_name(peer_type
));
631 if (!contains(allowed_modes
, mode_cnt
, ac
->preferred_mode
) &&
632 (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
||
633 !contains(allowed_modes
, mode_cnt
, ac
->fallback_mode
))) {
634 pr_err("preferred mode '%s' not allowed by %s\n",
635 ceph_con_mode_name(ac
->preferred_mode
),
636 ceph_entity_type_name(peer_type
));
637 if (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
)
638 pr_err("no fallback mode\n");
640 pr_err("fallback mode '%s' not allowed by %s\n",
641 ceph_con_mode_name(ac
->fallback_mode
),
642 ceph_entity_type_name(peer_type
));
647 WARN_ON(result
== -EOPNOTSUPP
|| result
>= 0);
648 pr_err("auth protocol '%s' authorization to %s failed: %d\n",
649 ceph_auth_proto_name(ac
->protocol
),
650 ceph_entity_type_name(peer_type
), result
);
652 if (ac
->ops
->invalidate_authorizer
)
653 ac
->ops
->invalidate_authorizer(ac
, peer_type
);
655 mutex_unlock(&ac
->mutex
);
659 mutex_unlock(&ac
->mutex
);
662 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer
);