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 void ceph_auth_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 if (result) { 264 pr_err("auth protocol '%s' mauth authentication failed: %d\n", 265 ceph_auth_proto_name(ac->protocol), result); 266 ret = result; 267 goto out; 268 } 269 270 ret = ac->ops->handle_reply(ac, global_id, payload, payload_end, 271 NULL, NULL, NULL, NULL); 272 if (ret == -EAGAIN) { 273 ret = build_request(ac, true, reply_buf, reply_len); 274 goto out; 275 } else if (ret) { 276 goto out; 277 } 278 279 out: 280 mutex_unlock(&ac->mutex); 281 return ret; 282 283 bad: 284 pr_err("failed to decode auth msg\n"); 285 ret = -EINVAL; 286 goto out; 287 } 288 289 int ceph_build_auth(struct ceph_auth_client *ac, 290 void *msg_buf, size_t msg_len) 291 { 292 int ret = 0; 293 294 mutex_lock(&ac->mutex); 295 if (ac->ops->should_authenticate(ac)) 296 ret = build_request(ac, true, msg_buf, msg_len); 297 mutex_unlock(&ac->mutex); 298 return ret; 299 } 300 301 int ceph_auth_is_authenticated(struct ceph_auth_client *ac) 302 { 303 int ret = 0; 304 305 mutex_lock(&ac->mutex); 306 if (ac->ops) 307 ret = ac->ops->is_authenticated(ac); 308 mutex_unlock(&ac->mutex); 309 return ret; 310 } 311 EXPORT_SYMBOL(ceph_auth_is_authenticated); 312 313 int __ceph_auth_get_authorizer(struct ceph_auth_client *ac, 314 struct ceph_auth_handshake *auth, 315 int peer_type, bool force_new, 316 int *proto, int *pref_mode, int *fallb_mode) 317 { 318 int ret; 319 320 mutex_lock(&ac->mutex); 321 if (force_new && auth->authorizer) { 322 ceph_auth_destroy_authorizer(auth->authorizer); 323 auth->authorizer = NULL; 324 } 325 if (!auth->authorizer) 326 ret = ac->ops->create_authorizer(ac, peer_type, auth); 327 else if (ac->ops->update_authorizer) 328 ret = ac->ops->update_authorizer(ac, peer_type, auth); 329 else 330 ret = 0; 331 if (ret) 332 goto out; 333 334 *proto = ac->protocol; 335 if (pref_mode && fallb_mode) { 336 *pref_mode = ac->preferred_mode; 337 *fallb_mode = ac->fallback_mode; 338 } 339 340 out: 341 mutex_unlock(&ac->mutex); 342 return ret; 343 } 344 EXPORT_SYMBOL(__ceph_auth_get_authorizer); 345 346 void ceph_auth_destroy_authorizer(struct ceph_authorizer *a) 347 { 348 a->destroy(a); 349 } 350 EXPORT_SYMBOL(ceph_auth_destroy_authorizer); 351 352 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac, 353 struct ceph_authorizer *a, 354 void *challenge_buf, 355 int challenge_buf_len) 356 { 357 int ret = 0; 358 359 mutex_lock(&ac->mutex); 360 if (ac->ops && ac->ops->add_authorizer_challenge) 361 ret = ac->ops->add_authorizer_challenge(ac, a, challenge_buf, 362 challenge_buf_len); 363 mutex_unlock(&ac->mutex); 364 return ret; 365 } 366 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge); 367 368 int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac, 369 struct ceph_authorizer *a, 370 void *reply, int reply_len, 371 u8 *session_key, int *session_key_len, 372 u8 *con_secret, int *con_secret_len) 373 { 374 int ret = 0; 375 376 mutex_lock(&ac->mutex); 377 if (ac->ops && ac->ops->verify_authorizer_reply) 378 ret = ac->ops->verify_authorizer_reply(ac, a, 379 reply, reply_len, session_key, session_key_len, 380 con_secret, con_secret_len); 381 mutex_unlock(&ac->mutex); 382 return ret; 383 } 384 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply); 385 386 void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type) 387 { 388 mutex_lock(&ac->mutex); 389 if (ac->ops && ac->ops->invalidate_authorizer) 390 ac->ops->invalidate_authorizer(ac, peer_type); 391 mutex_unlock(&ac->mutex); 392 } 393 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer); 394 395 /* 396 * msgr2 authentication 397 */ 398 399 static bool contains(const int *arr, int cnt, int val) 400 { 401 int i; 402 403 for (i = 0; i < cnt; i++) { 404 if (arr[i] == val) 405 return true; 406 } 407 408 return false; 409 } 410 411 static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode) 412 { 413 WARN_ON(pref_mode == CEPH_CON_MODE_UNKNOWN); 414 if (fallb_mode != CEPH_CON_MODE_UNKNOWN) { 415 ceph_encode_32_safe(p, end, 2, e_range); 416 ceph_encode_32_safe(p, end, pref_mode, e_range); 417 ceph_encode_32_safe(p, end, fallb_mode, e_range); 418 } else { 419 ceph_encode_32_safe(p, end, 1, e_range); 420 ceph_encode_32_safe(p, end, pref_mode, e_range); 421 } 422 423 return 0; 424 425 e_range: 426 return -ERANGE; 427 } 428 429 /* 430 * Similar to ceph_auth_build_hello(). 431 */ 432 int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len) 433 { 434 int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE; 435 void *end = buf + buf_len; 436 void *lenp; 437 void *p; 438 int ret; 439 440 mutex_lock(&ac->mutex); 441 if (ac->protocol == CEPH_AUTH_UNKNOWN) { 442 ret = init_protocol(ac, proto); 443 if (ret) { 444 pr_err("auth protocol '%s' init failed: %d\n", 445 ceph_auth_proto_name(proto), ret); 446 goto out; 447 } 448 } else { 449 WARN_ON(ac->protocol != proto); 450 ac->ops->reset(ac); 451 } 452 453 p = buf; 454 ceph_encode_32_safe(&p, end, ac->protocol, e_range); 455 ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode); 456 if (ret) 457 goto out; 458 459 lenp = p; 460 p += 4; /* space for len */ 461 462 ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range); 463 ret = ceph_auth_entity_name_encode(ac->name, &p, end); 464 if (ret) 465 goto out; 466 467 ceph_encode_64_safe(&p, end, ac->global_id, e_range); 468 ceph_encode_32(&lenp, p - lenp - 4); 469 ret = p - buf; 470 471 out: 472 mutex_unlock(&ac->mutex); 473 return ret; 474 475 e_range: 476 ret = -ERANGE; 477 goto out; 478 } 479 480 int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply, 481 int reply_len, void *buf, int buf_len) 482 { 483 int ret; 484 485 mutex_lock(&ac->mutex); 486 ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len, 487 NULL, NULL, NULL, NULL); 488 if (ret == -EAGAIN) 489 ret = build_request(ac, false, buf, buf_len); 490 else 491 WARN_ON(ret >= 0); 492 mutex_unlock(&ac->mutex); 493 return ret; 494 } 495 496 int ceph_auth_handle_reply_done(struct ceph_auth_client *ac, 497 u64 global_id, void *reply, int reply_len, 498 u8 *session_key, int *session_key_len, 499 u8 *con_secret, int *con_secret_len) 500 { 501 int ret; 502 503 mutex_lock(&ac->mutex); 504 ret = ac->ops->handle_reply(ac, global_id, reply, reply + reply_len, 505 session_key, session_key_len, 506 con_secret, con_secret_len); 507 WARN_ON(ret == -EAGAIN || ret > 0); 508 mutex_unlock(&ac->mutex); 509 return ret; 510 } 511 512 bool ceph_auth_handle_bad_method(struct ceph_auth_client *ac, 513 int used_proto, int result, 514 const int *allowed_protos, int proto_cnt, 515 const int *allowed_modes, int mode_cnt) 516 { 517 mutex_lock(&ac->mutex); 518 WARN_ON(used_proto != ac->protocol); 519 520 if (result == -EOPNOTSUPP) { 521 if (!contains(allowed_protos, proto_cnt, ac->protocol)) { 522 pr_err("auth protocol '%s' not allowed\n", 523 ceph_auth_proto_name(ac->protocol)); 524 goto not_allowed; 525 } 526 if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) && 527 (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN || 528 !contains(allowed_modes, mode_cnt, ac->fallback_mode))) { 529 pr_err("preferred mode '%s' not allowed\n", 530 ceph_con_mode_name(ac->preferred_mode)); 531 if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN) 532 pr_err("no fallback mode\n"); 533 else 534 pr_err("fallback mode '%s' not allowed\n", 535 ceph_con_mode_name(ac->fallback_mode)); 536 goto not_allowed; 537 } 538 } 539 540 WARN_ON(result == -EOPNOTSUPP || result >= 0); 541 pr_err("auth protocol '%s' msgr authentication failed: %d\n", 542 ceph_auth_proto_name(ac->protocol), result); 543 544 mutex_unlock(&ac->mutex); 545 return true; 546 547 not_allowed: 548 mutex_unlock(&ac->mutex); 549 return false; 550 } 551 552 int ceph_auth_get_authorizer(struct ceph_auth_client *ac, 553 struct ceph_auth_handshake *auth, 554 int peer_type, void *buf, int *buf_len) 555 { 556 void *end = buf + *buf_len; 557 int pref_mode, fallb_mode; 558 int proto; 559 void *p; 560 int ret; 561 562 ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto, 563 &pref_mode, &fallb_mode); 564 if (ret) 565 return ret; 566 567 p = buf; 568 ceph_encode_32_safe(&p, end, proto, e_range); 569 ret = encode_con_modes(&p, end, pref_mode, fallb_mode); 570 if (ret) 571 return ret; 572 573 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 574 *buf_len = p - buf; 575 return 0; 576 577 e_range: 578 return -ERANGE; 579 } 580 EXPORT_SYMBOL(ceph_auth_get_authorizer); 581 582 int ceph_auth_handle_svc_reply_more(struct ceph_auth_client *ac, 583 struct ceph_auth_handshake *auth, 584 void *reply, int reply_len, 585 void *buf, int *buf_len) 586 { 587 void *end = buf + *buf_len; 588 void *p; 589 int ret; 590 591 ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer, 592 reply, reply_len); 593 if (ret) 594 return ret; 595 596 p = buf; 597 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 598 *buf_len = p - buf; 599 return 0; 600 601 e_range: 602 return -ERANGE; 603 } 604 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more); 605 606 int ceph_auth_handle_svc_reply_done(struct ceph_auth_client *ac, 607 struct ceph_auth_handshake *auth, 608 void *reply, int reply_len, 609 u8 *session_key, int *session_key_len, 610 u8 *con_secret, int *con_secret_len) 611 { 612 return ceph_auth_verify_authorizer_reply(ac, auth->authorizer, 613 reply, reply_len, session_key, session_key_len, 614 con_secret, con_secret_len); 615 } 616 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done); 617 618 bool ceph_auth_handle_bad_authorizer(struct ceph_auth_client *ac, 619 int peer_type, int used_proto, int result, 620 const int *allowed_protos, int proto_cnt, 621 const int *allowed_modes, int mode_cnt) 622 { 623 mutex_lock(&ac->mutex); 624 WARN_ON(used_proto != ac->protocol); 625 626 if (result == -EOPNOTSUPP) { 627 if (!contains(allowed_protos, proto_cnt, ac->protocol)) { 628 pr_err("auth protocol '%s' not allowed by %s\n", 629 ceph_auth_proto_name(ac->protocol), 630 ceph_entity_type_name(peer_type)); 631 goto not_allowed; 632 } 633 if (!contains(allowed_modes, mode_cnt, ac->preferred_mode) && 634 (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN || 635 !contains(allowed_modes, mode_cnt, ac->fallback_mode))) { 636 pr_err("preferred mode '%s' not allowed by %s\n", 637 ceph_con_mode_name(ac->preferred_mode), 638 ceph_entity_type_name(peer_type)); 639 if (ac->fallback_mode == CEPH_CON_MODE_UNKNOWN) 640 pr_err("no fallback mode\n"); 641 else 642 pr_err("fallback mode '%s' not allowed by %s\n", 643 ceph_con_mode_name(ac->fallback_mode), 644 ceph_entity_type_name(peer_type)); 645 goto not_allowed; 646 } 647 } 648 649 WARN_ON(result == -EOPNOTSUPP || result >= 0); 650 pr_err("auth protocol '%s' authorization to %s failed: %d\n", 651 ceph_auth_proto_name(ac->protocol), 652 ceph_entity_type_name(peer_type), result); 653 654 if (ac->ops->invalidate_authorizer) 655 ac->ops->invalidate_authorizer(ac, peer_type); 656 657 mutex_unlock(&ac->mutex); 658 return true; 659 660 not_allowed: 661 mutex_unlock(&ac->mutex); 662 return false; 663 } 664 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer); 665