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 /* 40 * setup, teardown. 41 */ 42 struct ceph_auth_client *ceph_auth_init(const char *name, 43 const struct ceph_crypto_key *key, 44 const int *con_modes) 45 { 46 struct ceph_auth_client *ac; 47 int ret; 48 49 ret = -ENOMEM; 50 ac = kzalloc(sizeof(*ac), GFP_NOFS); 51 if (!ac) 52 goto out; 53 54 mutex_init(&ac->mutex); 55 ac->negotiating = true; 56 if (name) 57 ac->name = name; 58 else 59 ac->name = CEPH_AUTH_NAME_DEFAULT; 60 ac->key = key; 61 ac->preferred_mode = con_modes[0]; 62 ac->fallback_mode = con_modes[1]; 63 64 dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__, 65 ac->name, ac->preferred_mode, ac->fallback_mode); 66 return ac; 67 68 out: 69 return ERR_PTR(ret); 70 } 71 72 void ceph_auth_destroy(struct ceph_auth_client *ac) 73 { 74 dout("auth_destroy %p\n", ac); 75 if (ac->ops) 76 ac->ops->destroy(ac); 77 kfree(ac); 78 } 79 80 /* 81 * Reset occurs when reconnecting to the monitor. 82 */ 83 void ceph_auth_reset(struct ceph_auth_client *ac) 84 { 85 mutex_lock(&ac->mutex); 86 dout("auth_reset %p\n", ac); 87 if (ac->ops && !ac->negotiating) 88 ac->ops->reset(ac); 89 ac->negotiating = true; 90 mutex_unlock(&ac->mutex); 91 } 92 93 /* 94 * EntityName, not to be confused with entity_name_t 95 */ 96 int ceph_auth_entity_name_encode(const char *name, void **p, void *end) 97 { 98 int len = strlen(name); 99 100 if (*p + 2*sizeof(u32) + len > end) 101 return -ERANGE; 102 ceph_encode_32(p, CEPH_ENTITY_TYPE_CLIENT); 103 ceph_encode_32(p, len); 104 ceph_encode_copy(p, name, len); 105 return 0; 106 } 107 108 /* 109 * Initiate protocol negotiation with monitor. Include entity name 110 * and list supported protocols. 111 */ 112 int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) 113 { 114 struct ceph_mon_request_header *monhdr = buf; 115 void *p = monhdr + 1, *end = buf + len, *lenp; 116 int i, num; 117 int ret; 118 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; 124 125 ceph_encode_32(&p, CEPH_AUTH_UNKNOWN); /* no protocol, yet */ 126 127 lenp = p; 128 p += sizeof(u32); 129 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]); 137 138 ret = ceph_auth_entity_name_encode(ac->name, &p, end); 139 if (ret < 0) 140 goto out; 141 ceph_decode_need(&p, end, sizeof(u64), bad); 142 ceph_encode_64(&p, ac->global_id); 143 144 ceph_encode_32(&lenp, p - lenp - sizeof(u32)); 145 ret = p - buf; 146 out: 147 mutex_unlock(&ac->mutex); 148 return ret; 149 150 bad: 151 ret = -ERANGE; 152 goto out; 153 } 154 155 static int build_request(struct ceph_auth_client *ac, bool add_header, 156 void *buf, int buf_len) 157 { 158 void *end = buf + buf_len; 159 void *p; 160 int ret; 161 162 p = buf; 163 if (add_header) { 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); 169 } 170 171 ceph_encode_need(&p, end, sizeof(u32), e_range); 172 ret = ac->ops->build_request(ac, p + sizeof(u32), end); 173 if (ret < 0) { 174 pr_err("auth protocol '%s' building request failed: %d\n", 175 ceph_auth_proto_name(ac->protocol), ret); 176 return ret; 177 } 178 dout(" built request %d bytes\n", ret); 179 ceph_encode_32(&p, ret); 180 return p + ret - buf; 181 182 e_range: 183 return -ERANGE; 184 } 185 186 /* 187 * Handle auth message from monitor. 188 */ 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) 192 { 193 void *p = buf; 194 void *end = buf + len; 195 int protocol; 196 s32 result; 197 u64 global_id; 198 void *payload, *payload_end; 199 int payload_len; 200 char *result_msg; 201 int result_msg_len; 202 int ret = -EINVAL; 203 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); 211 payload = p; 212 p += payload_len; 213 ceph_decode_need(&p, end, sizeof(u32), bad); 214 result_msg_len = ceph_decode_32(&p); 215 result_msg = p; 216 p += result_msg_len; 217 if (p != end) 218 goto bad; 219 220 dout(" result %d '%.*s' gid %llu len %d\n", result, result_msg_len, 221 result_msg, global_id, payload_len); 222 223 payload_end = payload + payload_len; 224 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; 228 } 229 230 if (ac->negotiating) { 231 /* server does not support our protocols? */ 232 if (!protocol && result < 0) { 233 ret = result; 234 goto out; 235 } 236 /* set up (new) protocol handler? */ 237 if (ac->protocol && ac->protocol != protocol) { 238 ac->ops->destroy(ac); 239 ac->protocol = 0; 240 ac->ops = NULL; 241 } 242 if (ac->protocol != protocol) { 243 ret = init_protocol(ac, protocol); 244 if (ret) { 245 pr_err("auth protocol '%s' init failed: %d\n", 246 ceph_auth_proto_name(protocol), ret); 247 goto out; 248 } 249 } 250 251 ac->negotiating = false; 252 } 253 254 ret = ac->ops->handle_reply(ac, result, payload, payload_end, 255 NULL, NULL, NULL, NULL); 256 if (ret == -EAGAIN) 257 ret = build_request(ac, true, reply_buf, reply_len); 258 else if (ret) 259 pr_err("auth protocol '%s' mauth authentication failed: %d\n", 260 ceph_auth_proto_name(ac->protocol), result); 261 262 out: 263 mutex_unlock(&ac->mutex); 264 return ret; 265 266 bad: 267 pr_err("failed to decode auth msg\n"); 268 ret = -EINVAL; 269 goto out; 270 } 271 272 int ceph_build_auth(struct ceph_auth_client *ac, 273 void *msg_buf, size_t msg_len) 274 { 275 int ret = 0; 276 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); 281 return ret; 282 } 283 284 int ceph_auth_is_authenticated(struct ceph_auth_client *ac) 285 { 286 int ret = 0; 287 288 mutex_lock(&ac->mutex); 289 if (ac->ops) 290 ret = ac->ops->is_authenticated(ac); 291 mutex_unlock(&ac->mutex); 292 return ret; 293 } 294 EXPORT_SYMBOL(ceph_auth_is_authenticated); 295 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) 300 { 301 int ret; 302 303 mutex_lock(&ac->mutex); 304 if (force_new && auth->authorizer) { 305 ceph_auth_destroy_authorizer(auth->authorizer); 306 auth->authorizer = NULL; 307 } 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); 312 else 313 ret = 0; 314 if (ret) 315 goto out; 316 317 *proto = ac->protocol; 318 if (pref_mode && fallb_mode) { 319 *pref_mode = ac->preferred_mode; 320 *fallb_mode = ac->fallback_mode; 321 } 322 323 out: 324 mutex_unlock(&ac->mutex); 325 return ret; 326 } 327 EXPORT_SYMBOL(__ceph_auth_get_authorizer); 328 329 void ceph_auth_destroy_authorizer(struct ceph_authorizer *a) 330 { 331 a->destroy(a); 332 } 333 EXPORT_SYMBOL(ceph_auth_destroy_authorizer); 334 335 int ceph_auth_add_authorizer_challenge(struct ceph_auth_client *ac, 336 struct ceph_authorizer *a, 337 void *challenge_buf, 338 int challenge_buf_len) 339 { 340 int ret = 0; 341 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, 345 challenge_buf_len); 346 mutex_unlock(&ac->mutex); 347 return ret; 348 } 349 EXPORT_SYMBOL(ceph_auth_add_authorizer_challenge); 350 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) 356 { 357 int ret = 0; 358 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); 365 return ret; 366 } 367 EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply); 368 369 void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type) 370 { 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); 375 } 376 EXPORT_SYMBOL(ceph_auth_invalidate_authorizer); 377 378 /* 379 * msgr2 authentication 380 */ 381 382 static bool contains(const int *arr, int cnt, int val) 383 { 384 int i; 385 386 for (i = 0; i < cnt; i++) { 387 if (arr[i] == val) 388 return true; 389 } 390 391 return false; 392 } 393 394 static int encode_con_modes(void **p, void *end, int pref_mode, int fallb_mode) 395 { 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); 401 } else { 402 ceph_encode_32_safe(p, end, 1, e_range); 403 ceph_encode_32_safe(p, end, pref_mode, e_range); 404 } 405 406 return 0; 407 408 e_range: 409 return -ERANGE; 410 } 411 412 /* 413 * Similar to ceph_auth_build_hello(). 414 */ 415 int ceph_auth_get_request(struct ceph_auth_client *ac, void *buf, int buf_len) 416 { 417 int proto = ac->key ? CEPH_AUTH_CEPHX : CEPH_AUTH_NONE; 418 void *end = buf + buf_len; 419 void *lenp; 420 void *p; 421 int ret; 422 423 mutex_lock(&ac->mutex); 424 if (ac->protocol == CEPH_AUTH_UNKNOWN) { 425 ret = init_protocol(ac, proto); 426 if (ret) { 427 pr_err("auth protocol '%s' init failed: %d\n", 428 ceph_auth_proto_name(proto), ret); 429 goto out; 430 } 431 } else { 432 WARN_ON(ac->protocol != proto); 433 ac->ops->reset(ac); 434 } 435 436 p = buf; 437 ceph_encode_32_safe(&p, end, ac->protocol, e_range); 438 ret = encode_con_modes(&p, end, ac->preferred_mode, ac->fallback_mode); 439 if (ret) 440 goto out; 441 442 lenp = p; 443 p += 4; /* space for len */ 444 445 ceph_encode_8_safe(&p, end, CEPH_AUTH_MODE_MON, e_range); 446 ret = ceph_auth_entity_name_encode(ac->name, &p, end); 447 if (ret) 448 goto out; 449 450 ceph_encode_64_safe(&p, end, ac->global_id, e_range); 451 ceph_encode_32(&lenp, p - lenp - 4); 452 ret = p - buf; 453 454 out: 455 mutex_unlock(&ac->mutex); 456 return ret; 457 458 e_range: 459 ret = -ERANGE; 460 goto out; 461 } 462 463 int ceph_auth_handle_reply_more(struct ceph_auth_client *ac, void *reply, 464 int reply_len, void *buf, int buf_len) 465 { 466 int ret; 467 468 mutex_lock(&ac->mutex); 469 ret = ac->ops->handle_reply(ac, 0, reply, reply + reply_len, 470 NULL, NULL, NULL, NULL); 471 if (ret == -EAGAIN) 472 ret = build_request(ac, false, buf, buf_len); 473 else 474 WARN_ON(ret >= 0); 475 mutex_unlock(&ac->mutex); 476 return ret; 477 } 478 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) 483 { 484 int ret; 485 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, 489 global_id); 490 ac->global_id = global_id; 491 } 492 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); 497 return ret; 498 } 499 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) 504 { 505 mutex_lock(&ac->mutex); 506 WARN_ON(used_proto != ac->protocol); 507 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)); 512 goto not_allowed; 513 } 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"); 521 else 522 pr_err("fallback mode '%s' not allowed\n", 523 ceph_con_mode_name(ac->fallback_mode)); 524 goto not_allowed; 525 } 526 } 527 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); 531 532 mutex_unlock(&ac->mutex); 533 return true; 534 535 not_allowed: 536 mutex_unlock(&ac->mutex); 537 return false; 538 } 539 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) 543 { 544 void *end = buf + *buf_len; 545 int pref_mode, fallb_mode; 546 int proto; 547 void *p; 548 int ret; 549 550 ret = __ceph_auth_get_authorizer(ac, auth, peer_type, true, &proto, 551 &pref_mode, &fallb_mode); 552 if (ret) 553 return ret; 554 555 p = buf; 556 ceph_encode_32_safe(&p, end, proto, e_range); 557 ret = encode_con_modes(&p, end, pref_mode, fallb_mode); 558 if (ret) 559 return ret; 560 561 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 562 *buf_len = p - buf; 563 return 0; 564 565 e_range: 566 return -ERANGE; 567 } 568 EXPORT_SYMBOL(ceph_auth_get_authorizer); 569 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) 574 { 575 void *end = buf + *buf_len; 576 void *p; 577 int ret; 578 579 ret = ceph_auth_add_authorizer_challenge(ac, auth->authorizer, 580 reply, reply_len); 581 if (ret) 582 return ret; 583 584 p = buf; 585 ceph_encode_32_safe(&p, end, auth->authorizer_buf_len, e_range); 586 *buf_len = p - buf; 587 return 0; 588 589 e_range: 590 return -ERANGE; 591 } 592 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_more); 593 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) 599 { 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); 603 } 604 EXPORT_SYMBOL(ceph_auth_handle_svc_reply_done); 605 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) 610 { 611 mutex_lock(&ac->mutex); 612 WARN_ON(used_proto != ac->protocol); 613 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)); 619 goto not_allowed; 620 } 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"); 629 else 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)); 633 goto not_allowed; 634 } 635 } 636 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); 641 642 if (ac->ops->invalidate_authorizer) 643 ac->ops->invalidate_authorizer(ac, peer_type); 644 645 mutex_unlock(&ac->mutex); 646 return true; 647 648 not_allowed: 649 mutex_unlock(&ac->mutex); 650 return false; 651 } 652 EXPORT_SYMBOL(ceph_auth_handle_bad_authorizer); 653