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 void ceph_auth_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
;
62 ac
= kzalloc(sizeof(*ac
), GFP_NOFS
);
64 return ERR_PTR(-ENOMEM
);
66 mutex_init(&ac
->mutex
);
67 ac
->negotiating
= true;
71 ac
->name
= CEPH_AUTH_NAME_DEFAULT
;
73 ac
->preferred_mode
= con_modes
[0];
74 ac
->fallback_mode
= con_modes
[1];
76 dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__
,
77 ac
->name
, ac
->preferred_mode
, ac
->fallback_mode
);
81 void ceph_auth_destroy(struct ceph_auth_client
*ac
)
83 dout("auth_destroy %p\n", ac
);
90 * Reset occurs when reconnecting to the monitor.
92 void ceph_auth_reset(struct ceph_auth_client
*ac
)
94 mutex_lock(&ac
->mutex
);
95 dout("auth_reset %p\n", ac
);
96 if (ac
->ops
&& !ac
->negotiating
)
98 ac
->negotiating
= true;
99 mutex_unlock(&ac
->mutex
);
103 * EntityName, not to be confused with entity_name_t
105 int ceph_auth_entity_name_encode(const char *name
, void **p
, void *end
)
107 int len
= strlen(name
);
109 if (*p
+ 2*sizeof(u32
) + len
> end
)
111 ceph_encode_32(p
, CEPH_ENTITY_TYPE_CLIENT
);
112 ceph_encode_32(p
, len
);
113 ceph_encode_copy(p
, name
, len
);
118 * Initiate protocol negotiation with monitor. Include entity name
119 * and list supported protocols.
121 int ceph_auth_build_hello(struct ceph_auth_client
*ac
, void *buf
, size_t len
)
123 struct ceph_mon_request_header
*monhdr
= buf
;
124 void *p
= monhdr
+ 1, *end
= buf
+ len
, *lenp
;
128 mutex_lock(&ac
->mutex
);
129 dout("auth_build_hello\n");
130 monhdr
->have_version
= 0;
131 monhdr
->session_mon
= cpu_to_le16(-1);
132 monhdr
->session_mon_tid
= 0;
134 ceph_encode_32(&p
, CEPH_AUTH_UNKNOWN
); /* no protocol, yet */
139 ceph_decode_need(&p
, end
, 1 + sizeof(u32
), bad
);
140 ceph_encode_8(&p
, 1);
141 num
= ARRAY_SIZE(supported_protocols
);
142 ceph_encode_32(&p
, num
);
143 ceph_decode_need(&p
, end
, num
* sizeof(u32
), bad
);
144 for (i
= 0; i
< num
; i
++)
145 ceph_encode_32(&p
, supported_protocols
[i
]);
147 ret
= ceph_auth_entity_name_encode(ac
->name
, &p
, end
);
150 ceph_decode_need(&p
, end
, sizeof(u64
), bad
);
151 ceph_encode_64(&p
, ac
->global_id
);
153 ceph_encode_32(&lenp
, p
- lenp
- sizeof(u32
));
156 mutex_unlock(&ac
->mutex
);
164 static int build_request(struct ceph_auth_client
*ac
, bool add_header
,
165 void *buf
, int buf_len
)
167 void *end
= buf
+ buf_len
;
173 /* struct ceph_mon_request_header + protocol */
174 ceph_encode_64_safe(&p
, end
, 0, e_range
);
175 ceph_encode_16_safe(&p
, end
, -1, e_range
);
176 ceph_encode_64_safe(&p
, end
, 0, e_range
);
177 ceph_encode_32_safe(&p
, end
, ac
->protocol
, e_range
);
180 ceph_encode_need(&p
, end
, sizeof(u32
), e_range
);
181 ret
= ac
->ops
->build_request(ac
, p
+ sizeof(u32
), end
);
183 pr_err("auth protocol '%s' building request failed: %d\n",
184 ceph_auth_proto_name(ac
->protocol
), ret
);
187 dout(" built request %d bytes\n", ret
);
188 ceph_encode_32(&p
, ret
);
189 return p
+ ret
- buf
;
196 * Handle auth message from monitor.
198 int ceph_handle_auth_reply(struct ceph_auth_client
*ac
,
199 void *buf
, size_t len
,
200 void *reply_buf
, size_t reply_len
)
203 void *end
= buf
+ len
;
207 void *payload
, *payload_end
;
213 mutex_lock(&ac
->mutex
);
214 dout("handle_auth_reply %p %p\n", p
, end
);
215 ceph_decode_need(&p
, end
, sizeof(u32
) * 3 + sizeof(u64
), bad
);
216 protocol
= ceph_decode_32(&p
);
217 result
= ceph_decode_32(&p
);
218 global_id
= ceph_decode_64(&p
);
219 payload_len
= ceph_decode_32(&p
);
222 ceph_decode_need(&p
, end
, sizeof(u32
), bad
);
223 result_msg_len
= ceph_decode_32(&p
);
229 dout(" result %d '%.*s' gid %llu len %d\n", result
, result_msg_len
,
230 result_msg
, global_id
, payload_len
);
232 payload_end
= payload
+ payload_len
;
234 if (ac
->negotiating
) {
235 /* server does not support our protocols? */
236 if (!protocol
&& result
< 0) {
240 /* set up (new) protocol handler? */
241 if (ac
->protocol
&& ac
->protocol
!= protocol
) {
242 ac
->ops
->destroy(ac
);
246 if (ac
->protocol
!= protocol
) {
247 ret
= init_protocol(ac
, protocol
);
249 pr_err("auth protocol '%s' init failed: %d\n",
250 ceph_auth_proto_name(protocol
), ret
);
255 ac
->negotiating
= false;
259 pr_err("auth protocol '%s' mauth authentication failed: %d\n",
260 ceph_auth_proto_name(ac
->protocol
), result
);
265 ret
= ac
->ops
->handle_reply(ac
, global_id
, payload
, payload_end
,
266 NULL
, NULL
, NULL
, NULL
);
267 if (ret
== -EAGAIN
) {
268 ret
= build_request(ac
, true, reply_buf
, reply_len
);
275 mutex_unlock(&ac
->mutex
);
279 pr_err("failed to decode auth msg\n");
284 int ceph_build_auth(struct ceph_auth_client
*ac
,
285 void *msg_buf
, size_t msg_len
)
289 mutex_lock(&ac
->mutex
);
290 if (ac
->ops
->should_authenticate(ac
))
291 ret
= build_request(ac
, true, msg_buf
, msg_len
);
292 mutex_unlock(&ac
->mutex
);
296 int ceph_auth_is_authenticated(struct ceph_auth_client
*ac
)
300 mutex_lock(&ac
->mutex
);
302 ret
= ac
->ops
->is_authenticated(ac
);
303 mutex_unlock(&ac
->mutex
);
306 EXPORT_SYMBOL(ceph_auth_is_authenticated
);
308 int __ceph_auth_get_authorizer(struct ceph_auth_client
*ac
,
309 struct ceph_auth_handshake
*auth
,
310 int peer_type
, bool force_new
,
311 int *proto
, int *pref_mode
, int *fallb_mode
)
315 mutex_lock(&ac
->mutex
);
316 if (force_new
&& auth
->authorizer
) {
317 ceph_auth_destroy_authorizer(auth
->authorizer
);
318 auth
->authorizer
= NULL
;
320 if (!auth
->authorizer
)
321 ret
= ac
->ops
->create_authorizer(ac
, peer_type
, auth
);
322 else if (ac
->ops
->update_authorizer
)
323 ret
= ac
->ops
->update_authorizer(ac
, peer_type
, auth
);
329 *proto
= ac
->protocol
;
330 if (pref_mode
&& fallb_mode
) {
331 *pref_mode
= ac
->preferred_mode
;
332 *fallb_mode
= ac
->fallback_mode
;
336 mutex_unlock(&ac
->mutex
);
339 EXPORT_SYMBOL(__ceph_auth_get_authorizer
);
341 void ceph_auth_destroy_authorizer(struct ceph_authorizer
*a
)
345 EXPORT_SYMBOL(ceph_auth_destroy_authorizer
);
347 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client
*ac
,
348 struct ceph_authorizer
*a
,
350 int challenge_buf_len
)
354 mutex_lock(&ac
->mutex
);
355 if (ac
->ops
&& ac
->ops
->add_authorizer_challenge
)
356 ret
= ac
->ops
->add_authorizer_challenge(ac
, a
, challenge_buf
,
358 mutex_unlock(&ac
->mutex
);
361 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge
);
363 int ceph_auth_verify_authorizer_reply(struct ceph_auth_client
*ac
,
364 struct ceph_authorizer
*a
,
365 void *reply
, int reply_len
,
366 u8
*session_key
, int *session_key_len
,
367 u8
*con_secret
, int *con_secret_len
)
371 mutex_lock(&ac
->mutex
);
372 if (ac
->ops
&& ac
->ops
->verify_authorizer_reply
)
373 ret
= ac
->ops
->verify_authorizer_reply(ac
, a
,
374 reply
, reply_len
, session_key
, session_key_len
,
375 con_secret
, con_secret_len
);
376 mutex_unlock(&ac
->mutex
);
379 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply
);
381 void ceph_auth_invalidate_authorizer(struct ceph_auth_client
*ac
, int peer_type
)
383 mutex_lock(&ac
->mutex
);
384 if (ac
->ops
&& ac
->ops
->invalidate_authorizer
)
385 ac
->ops
->invalidate_authorizer(ac
, peer_type
);
386 mutex_unlock(&ac
->mutex
);
388 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer
);
391 * msgr2 authentication
394 static bool contains(const int *arr
, int cnt
, int val
)
398 for (i
= 0; i
< cnt
; i
++) {
406 static int encode_con_modes(void **p
, void *end
, int pref_mode
, int fallb_mode
)
408 WARN_ON(pref_mode
== CEPH_CON_MODE_UNKNOWN
);
409 if (fallb_mode
!= CEPH_CON_MODE_UNKNOWN
) {
410 ceph_encode_32_safe(p
, end
, 2, e_range
);
411 ceph_encode_32_safe(p
, end
, pref_mode
, e_range
);
412 ceph_encode_32_safe(p
, end
, fallb_mode
, e_range
);
414 ceph_encode_32_safe(p
, end
, 1, e_range
);
415 ceph_encode_32_safe(p
, end
, pref_mode
, e_range
);
425 * Similar to ceph_auth_build_hello().
427 int ceph_auth_get_request(struct ceph_auth_client
*ac
, void *buf
, int buf_len
)
429 int proto
= ac
->key
? CEPH_AUTH_CEPHX
: CEPH_AUTH_NONE
;
430 void *end
= buf
+ buf_len
;
435 mutex_lock(&ac
->mutex
);
436 if (ac
->protocol
== CEPH_AUTH_UNKNOWN
) {
437 ret
= init_protocol(ac
, proto
);
439 pr_err("auth protocol '%s' init failed: %d\n",
440 ceph_auth_proto_name(proto
), ret
);
444 WARN_ON(ac
->protocol
!= proto
);
449 ceph_encode_32_safe(&p
, end
, ac
->protocol
, e_range
);
450 ret
= encode_con_modes(&p
, end
, ac
->preferred_mode
, ac
->fallback_mode
);
455 p
+= 4; /* space for len */
457 ceph_encode_8_safe(&p
, end
, CEPH_AUTH_MODE_MON
, e_range
);
458 ret
= ceph_auth_entity_name_encode(ac
->name
, &p
, end
);
462 ceph_encode_64_safe(&p
, end
, ac
->global_id
, e_range
);
463 ceph_encode_32(&lenp
, p
- lenp
- 4);
467 mutex_unlock(&ac
->mutex
);
475 int ceph_auth_handle_reply_more(struct ceph_auth_client
*ac
, void *reply
,
476 int reply_len
, void *buf
, int buf_len
)
480 mutex_lock(&ac
->mutex
);
481 ret
= ac
->ops
->handle_reply(ac
, 0, reply
, reply
+ reply_len
,
482 NULL
, NULL
, NULL
, NULL
);
484 ret
= build_request(ac
, false, buf
, buf_len
);
487 mutex_unlock(&ac
->mutex
);
491 int ceph_auth_handle_reply_done(struct ceph_auth_client
*ac
,
492 u64 global_id
, void *reply
, int reply_len
,
493 u8
*session_key
, int *session_key_len
,
494 u8
*con_secret
, int *con_secret_len
)
498 mutex_lock(&ac
->mutex
);
499 ret
= ac
->ops
->handle_reply(ac
, global_id
, reply
, reply
+ reply_len
,
500 session_key
, session_key_len
,
501 con_secret
, con_secret_len
);
502 WARN_ON(ret
== -EAGAIN
|| ret
> 0);
503 mutex_unlock(&ac
->mutex
);
507 bool ceph_auth_handle_bad_method(struct ceph_auth_client
*ac
,
508 int used_proto
, int result
,
509 const int *allowed_protos
, int proto_cnt
,
510 const int *allowed_modes
, int mode_cnt
)
512 mutex_lock(&ac
->mutex
);
513 WARN_ON(used_proto
!= ac
->protocol
);
515 if (result
== -EOPNOTSUPP
) {
516 if (!contains(allowed_protos
, proto_cnt
, ac
->protocol
)) {
517 pr_err("auth protocol '%s' not allowed\n",
518 ceph_auth_proto_name(ac
->protocol
));
521 if (!contains(allowed_modes
, mode_cnt
, ac
->preferred_mode
) &&
522 (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
||
523 !contains(allowed_modes
, mode_cnt
, ac
->fallback_mode
))) {
524 pr_err("preferred mode '%s' not allowed\n",
525 ceph_con_mode_name(ac
->preferred_mode
));
526 if (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
)
527 pr_err("no fallback mode\n");
529 pr_err("fallback mode '%s' not allowed\n",
530 ceph_con_mode_name(ac
->fallback_mode
));
535 WARN_ON(result
== -EOPNOTSUPP
|| result
>= 0);
536 pr_err("auth protocol '%s' msgr authentication failed: %d\n",
537 ceph_auth_proto_name(ac
->protocol
), result
);
539 mutex_unlock(&ac
->mutex
);
543 mutex_unlock(&ac
->mutex
);
547 int ceph_auth_get_authorizer(struct ceph_auth_client
*ac
,
548 struct ceph_auth_handshake
*auth
,
549 int peer_type
, void *buf
, int *buf_len
)
551 void *end
= buf
+ *buf_len
;
552 int pref_mode
, fallb_mode
;
557 ret
= __ceph_auth_get_authorizer(ac
, auth
, peer_type
, true, &proto
,
558 &pref_mode
, &fallb_mode
);
563 ceph_encode_32_safe(&p
, end
, proto
, e_range
);
564 ret
= encode_con_modes(&p
, end
, pref_mode
, fallb_mode
);
568 ceph_encode_32_safe(&p
, end
, auth
->authorizer_buf_len
, e_range
);
575 EXPORT_SYMBOL(ceph_auth_get_authorizer
);
577 int ceph_auth_handle_svc_reply_more(struct ceph_auth_client
*ac
,
578 struct ceph_auth_handshake
*auth
,
579 void *reply
, int reply_len
,
580 void *buf
, int *buf_len
)
582 void *end
= buf
+ *buf_len
;
586 ret
= ceph_auth_add_authorizer_challenge(ac
, auth
->authorizer
,
592 ceph_encode_32_safe(&p
, end
, auth
->authorizer_buf_len
, e_range
);
599 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more
);
601 int ceph_auth_handle_svc_reply_done(struct ceph_auth_client
*ac
,
602 struct ceph_auth_handshake
*auth
,
603 void *reply
, int reply_len
,
604 u8
*session_key
, int *session_key_len
,
605 u8
*con_secret
, int *con_secret_len
)
607 return ceph_auth_verify_authorizer_reply(ac
, auth
->authorizer
,
608 reply
, reply_len
, session_key
, session_key_len
,
609 con_secret
, con_secret_len
);
611 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done
);
613 bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client
*ac
,
614 int peer_type
, int used_proto
, int result
,
615 const int *allowed_protos
, int proto_cnt
,
616 const int *allowed_modes
, int mode_cnt
)
618 mutex_lock(&ac
->mutex
);
619 WARN_ON(used_proto
!= ac
->protocol
);
621 if (result
== -EOPNOTSUPP
) {
622 if (!contains(allowed_protos
, proto_cnt
, ac
->protocol
)) {
623 pr_err("auth protocol '%s' not allowed by %s\n",
624 ceph_auth_proto_name(ac
->protocol
),
625 ceph_entity_type_name(peer_type
));
628 if (!contains(allowed_modes
, mode_cnt
, ac
->preferred_mode
) &&
629 (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
||
630 !contains(allowed_modes
, mode_cnt
, ac
->fallback_mode
))) {
631 pr_err("preferred mode '%s' not allowed by %s\n",
632 ceph_con_mode_name(ac
->preferred_mode
),
633 ceph_entity_type_name(peer_type
));
634 if (ac
->fallback_mode
== CEPH_CON_MODE_UNKNOWN
)
635 pr_err("no fallback mode\n");
637 pr_err("fallback mode '%s' not allowed by %s\n",
638 ceph_con_mode_name(ac
->fallback_mode
),
639 ceph_entity_type_name(peer_type
));
644 WARN_ON(result
== -EOPNOTSUPP
|| result
>= 0);
645 pr_err("auth protocol '%s' authorization to %s failed: %d\n",
646 ceph_auth_proto_name(ac
->protocol
),
647 ceph_entity_type_name(peer_type
), result
);
649 if (ac
->ops
->invalidate_authorizer
)
650 ac
->ops
->invalidate_authorizer(ac
, peer_type
);
652 mutex_unlock(&ac
->mutex
);
656 mutex_unlock(&ac
->mutex
);
659 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer
);