1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/ceph/ceph_debug.h> 3 4 #include <linux/module.h> 5 #include <linux/err.h> 6 #include <linux/slab.h> 7 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" 13 #include "auth_x.h" 14 15 16 /* 17 * get protocol handler 18 */ 19 static u32 supported_protocols[] = { 20 CEPH_AUTH_NONE, 21 CEPH_AUTH_CEPHX 22 }; 23 24 static int init_protocol(struct ceph_auth_client *ac, int proto) 25 { 26 dout("%s proto %d\n", __func__, proto); 27 28 switch (proto) { 29 case CEPH_AUTH_NONE: 30 return ceph_auth_none_init(ac); 31 case CEPH_AUTH_CEPHX: 32 return ceph_x_init(ac); 33 default: 34 pr_err("bad auth protocol %d\n", proto); 35 return -EINVAL; 36 } 37 } 38 39 static void set_global_id(struct ceph_auth_client *ac, u64 global_id) 40 { 41 dout("%s global_id %llu\n", __func__, global_id); 42 43 if (!global_id) 44 pr_err("got zero global_id\n"); 45 46 if (ac->global_id && global_id != ac->global_id) 47 pr_err("global_id changed from %llu to %llu\n", ac->global_id, 48 global_id); 49 50 ac->global_id = global_id; 51 } 52 53 /* 54 * setup, teardown. 55 */ 56 struct ceph_auth_client *ceph_auth_init(const char *name, 57 const struct ceph_crypto_key *key, 58 const int *con_modes) 59 { 60 struct ceph_auth_client *ac; 61 int ret; 62 63 ret = -ENOMEM; 64 ac = kzalloc(sizeof(*ac), GFP_NOFS); 65 if (!ac) 66 goto out; 67 68 mutex_init(&ac->mutex); 69 ac->negotiating = true; 70 if (name) 71 ac->name = name; 72 else 73 ac->name = CEPH_AUTH_NAME_DEFAULT; 74 ac->key = key; 75 ac->preferred_mode = con_modes[0]; 76 ac->fallback_mode = con_modes[1]; 77 78 dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__, 79 ac->name, ac->preferred_mode, ac->fallback_mode); 80 return ac; 81 82 out: 83 return ERR_PTR(ret); 84 } 85 86 void ceph_auth_destroy(struct ceph_auth_client *ac) 87 { 88 dout("auth_destroy %p\n", ac); 89 if (ac->ops) 90 ac->ops->destroy(ac); 91 kfree(ac); 92 } 93 94 /* 95 * Reset occurs when reconnecting to the monitor. 96 */ 97 void ceph_auth_reset(struct ceph_auth_client *ac) 98 { 99 mutex_lock(&ac->mutex); 100 dout("auth_reset %p\n", ac); 101 if (ac->ops && !ac->negotiating) 102 ac->ops->reset(ac); 103 ac->negotiating = true; 104 mutex_unlock(&ac->mutex); 105 } 106 107 /* 108 * EntityName, not to be confused with entity_name_t 109 */ 110 int ceph_auth_entity_name_encode(const char *name, void **p, void *end) 111 { 112 int len = strlen(name); 113 114 if (*p + 2*sizeof(u32) + len > end) 115 return -ERANGE; 116 ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT); 117 ceph_encode_32(p, len); 118 ceph_encode_copy(p, name, len); 119 return 0; 120 } 121 122 /* 123 * Initiate protocol negotiation with monitor. Include entity name 124 * and list supported protocols. 125 */ 126 int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) 127 { 128 struct ceph_mon_request_header *monhdr = buf; 129 void *p = monhdr + 1, *end = buf + len, *lenp; 130 int i, num; 131 int ret; 132 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; 138 139 ceph_encode_32(&p, CEPH_AUTH_UNKNOWN); /* no protocol, yet */ 140 141 lenp = p; 142 p += sizeof(u32); 143 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]); 151 152 ret = ceph_auth_entity_name_encode(ac->name, &p, end); 153 if (ret < 0) 154 goto out; 155 ceph_decode_need(&p, end, sizeof(u64), bad); 156 ceph_encode_64(&p, ac->global_id); 157 158 ceph_encode_32(&lenp, p - lenp - sizeof(u32)); 159 ret = p - buf; 160 out: 161 mutex_unlock(&ac->mutex); 162 return ret; 163 164 bad: 165 ret = -ERANGE; 166 goto out; 167 } 168 169 static int build_request(struct ceph_auth_client *ac, bool add_header, 170 void *buf, int buf_len) 171 { 172 void *end = buf + buf_len; 173 void *p; 174 int ret; 175 176 p = buf; 177 if (add_header) { 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); 183 } 184 185 ceph_encode_need(&p, end, sizeof(u32), e_range); 186 ret = ac->ops->build_request(ac, p + sizeof(u32), end); 187 if (ret < 0) { 188 pr_err("auth protocol '%s' building request failed: %d\n", 189 ceph_auth_proto_name(ac->protocol), ret); 190 return ret; 191 } 192 dout(" built request %d bytes\n", ret); 193 ceph_encode_32(&p, ret); 194 return p + ret - buf; 195 196 e_range: 197 return -ERANGE; 198 } 199 200 /* 201 * Handle auth message from monitor. 202 */ 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) 206 { 207 void *p = buf; 208 void *end = buf + len; 209 int protocol; 210 s32 result; 211 u64 global_id; 212 void *payload, *payload_end; 213 int payload_len; 214 char *result_msg; 215 int result_msg_len; 216 int ret = -EINVAL; 217 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); 225 payload = p; 226 p += payload_len; 227 ceph_decode_need(&p, end, sizeof(u32), bad); 228 result_msg_len = ceph_decode_32(&p); 229 result_msg = p; 230 p += result_msg_len; 231 if (p != end) 232 goto bad; 233 234 dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len, 235 result_msg, global_id, payload_len); 236 237 payload_end = payload + payload_len; 238 239 if (ac->negotiating) { 240 /* server does not support our protocols? */ 241 if (!protocol && result < 0) { 242 ret = result; 243 goto out; 244 } 245 /* set up (new) protocol handler? */ 246 if (ac->protocol && ac->protocol != protocol) { 247 ac->ops->destroy(ac); 248 ac->protocol = 0; 249 ac->ops = NULL; 250 } 251 if (ac->protocol != protocol) { 252 ret = init_protocol(ac, protocol); 253 if (ret) { 254 pr_err("auth protocol '%s' init failed: %d\n", 255 ceph_auth_proto_name(protocol), ret); 256 goto out; 257 } 258 } 259 260 ac->negotiating = false; 261 } 262 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); 267 goto out; 268 } else if (ret) { 269 pr_err("auth protocol '%s' mauth authentication failed: %d\n", 270 ceph_auth_proto_name(ac->protocol), result); 271 goto out; 272 } 273 274 set_global_id(ac, global_id); 275 276 out: 277 mutex_unlock(&ac->mutex); 278 return ret; 279 280 bad: 281 pr_err("failed to decode auth msg\n"); 282 ret = -EINVAL; 283 goto out; 284 } 285 286 int ceph_build_auth(struct ceph_auth_client *ac, 287 void *msg_buf, size_t msg_len) 288 { 289 int ret = 0; 290 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); 295 return ret; 296 } 297 298 int ceph_auth_is_authenticated(struct ceph_auth_client *ac) 299 { 300 int ret = 0; 301 302 mutex_lock(&ac->mutex); 303 if (ac->ops) 304 ret = ac->ops->is_authenticated(ac); 305 mutex_unlock(&ac->mutex); 306 return ret; 307 } 308 EXPORT_SYMBOL(ceph_auth_is_authenticated); 309 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) 314 { 315 int ret; 316 317 mutex_lock(&ac->mutex); 318 if (force_new && auth->authorizer) { 319 ceph_auth_destroy_authorizer(auth->authorizer); 320 auth->authorizer = NULL; 321 } 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); 326 else 327 ret = 0; 328 if (ret) 329 goto out; 330 331 *proto = ac->protocol; 332 if (pref_mode && fallb_mode) { 333 *pref_mode = ac->preferred_mode; 334 *fallb_mode = ac->fallback_mode; 335 } 336 337 out: 338 mutex_unlock(&ac->mutex); 339 return ret; 340 } 341 EXPORT_SYMBOL(__ceph_auth_get_authorizer); 342 343 void ceph_auth_destroy_authorizer(struct ceph_authorizer *a) 344 { 345 a->destroy(a); 346 } 347 EXPORT_SYMBOL(ceph_auth_destroy_authorizer); 348 349 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac, 350 struct ceph_authorizer *a, 351 void *challenge_buf, 352 int challenge_buf_len) 353 { 354 int ret = 0; 355 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, 359 challenge_buf_len); 360 mutex_unlock(&ac->mutex); 361 return ret; 362 } 363 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge); 364 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) 370 { 371 int ret = 0; 372 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); 379 return ret; 380 } 381 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply); 382 383 void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type) 384 { 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); 389 } 390 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer); 391 392 /* 393 * msgr2 authentication 394 */ 395 396 static bool contains(const int *arr, int cnt, int val) 397 { 398 int i; 399 400 for (i = 0; i < cnt; i++) { 401 if (arr[i] == val) 402 return true; 403 } 404 405 return false; 406 } 407 408 static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode) 409 { 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); 415 } else { 416 ceph_encode_32_safe(p, end, 1, e_range); 417 ceph_encode_32_safe(p, end, pref_mode, e_range); 418 } 419 420 return 0; 421 422 e_range: 423 return -ERANGE; 424 } 425 426 /* 427 * Similar to ceph_auth_build_hello(). 428 */ 429 int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len) 430 { 431 int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE; 432 void *end = buf + buf_len; 433 void *lenp; 434 void *p; 435 int ret; 436 437 mutex_lock(&ac->mutex); 438 if (ac->protocol == CEPH_AUTH_UNKNOWN) { 439 ret = init_protocol(ac, proto); 440 if (ret) { 441 pr_err("auth protocol '%s' init failed: %d\n", 442 ceph_auth_proto_name(proto), ret); 443 goto out; 444 } 445 } else { 446 WARN_ON(ac->protocol != proto); 447 ac->ops->reset(ac); 448 } 449 450 p = buf; 451 ceph_encode_32_safe(&p, end, ac->protocol, e_range); 452 ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode); 453 if (ret) 454 goto out; 455 456 lenp = p; 457 p += 4; /* space for len */ 458 459 ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range); 460 ret = ceph_auth_entity_name_encode(ac->name, &p, end); 461 if (ret) 462 goto out; 463 464 ceph_encode_64_safe(&p, end, ac->global_id, e_range); 465 ceph_encode_32(&lenp, p - lenp - 4); 466 ret = p - buf; 467 468 out: 469 mutex_unlock(&ac->mutex); 470 return ret; 471 472 e_range: 473 ret = -ERANGE; 474 goto out; 475 } 476 477 int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply, 478 int reply_len, void *buf, int buf_len) 479 { 480 int ret; 481 482 mutex_lock(&ac->mutex); 483 ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len, 484 NULL, NULL, NULL, NULL); 485 if (ret == -EAGAIN) 486 ret = build_request(ac, false, buf, buf_len); 487 else 488 WARN_ON(ret >= 0); 489 mutex_unlock(&ac->mutex); 490 return ret; 491 } 492 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) 497 { 498 int ret; 499 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); 504 if (!ret) 505 set_global_id(ac, global_id); 506 mutex_unlock(&ac->mutex); 507 return ret; 508 } 509 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) 514 { 515 mutex_lock(&ac->mutex); 516 WARN_ON(used_proto != ac->protocol); 517 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)); 522 goto not_allowed; 523 } 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"); 531 else 532 pr_err("fallback mode '%s' not allowed\n", 533 ceph_con_mode_name(ac->fallback_mode)); 534 goto not_allowed; 535 } 536 } 537 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); 541 542 mutex_unlock(&ac->mutex); 543 return true; 544 545 not_allowed: 546 mutex_unlock(&ac->mutex); 547 return false; 548 } 549 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) 553 { 554 void *end = buf + *buf_len; 555 int pref_mode, fallb_mode; 556 int proto; 557 void *p; 558 int ret; 559 560 ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto, 561 &pref_mode, &fallb_mode); 562 if (ret) 563 return ret; 564 565 p = buf; 566 ceph_encode_32_safe(&p, end, proto, e_range); 567 ret = encode_con_modes(&p, end, pref_mode, fallb_mode); 568 if (ret) 569 return ret; 570 571 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 572 *buf_len = p - buf; 573 return 0; 574 575 e_range: 576 return -ERANGE; 577 } 578 EXPORT_SYMBOL(ceph_auth_get_authorizer); 579 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) 584 { 585 void *end = buf + *buf_len; 586 void *p; 587 int ret; 588 589 ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer, 590 reply, reply_len); 591 if (ret) 592 return ret; 593 594 p = buf; 595 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 596 *buf_len = p - buf; 597 return 0; 598 599 e_range: 600 return -ERANGE; 601 } 602 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more); 603 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) 609 { 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); 613 } 614 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done); 615 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) 620 { 621 mutex_lock(&ac->mutex); 622 WARN_ON(used_proto != ac->protocol); 623 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)); 629 goto not_allowed; 630 } 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"); 639 else 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)); 643 goto not_allowed; 644 } 645 } 646 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); 651 652 if (ac->ops->invalidate_authorizer) 653 ac->ops->invalidate_authorizer(ac, peer_type); 654 655 mutex_unlock(&ac->mutex); 656 return true; 657 658 not_allowed: 659 mutex_unlock(&ac->mutex); 660 return false; 661 } 662 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer); 663