1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/ceph/ceph_debug.h> 4 5 #include <linux/err.h> 6 #include <linux/module.h> 7 #include <linux/random.h> 8 #include <linux/slab.h> 9 10 #include <linux/ceph/decode.h> 11 #include <linux/ceph/auth.h> 12 #include <linux/ceph/ceph_features.h> 13 #include <linux/ceph/libceph.h> 14 #include <linux/ceph/messenger.h> 15 16 #include "crypto.h" 17 #include "auth_x.h" 18 #include "auth_x_protocol.h" 19 20 static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); 21 22 static int ceph_x_is_authenticated(struct ceph_auth_client *ac) 23 { 24 struct ceph_x_info *xi = ac->private; 25 int missing; 26 int need; /* missing + need renewal */ 27 28 ceph_x_validate_tickets(ac, &need); 29 missing = ac->want_keys & ~xi->have_keys; 30 WARN_ON((need & missing) != missing); 31 dout("%s want 0x%x have 0x%x missing 0x%x -> %d\n", __func__, 32 ac->want_keys, xi->have_keys, missing, !missing); 33 return !missing; 34 } 35 36 static int ceph_x_should_authenticate(struct ceph_auth_client *ac) 37 { 38 struct ceph_x_info *xi = ac->private; 39 int need; 40 41 ceph_x_validate_tickets(ac, &need); 42 dout("%s want 0x%x have 0x%x need 0x%x -> %d\n", __func__, 43 ac->want_keys, xi->have_keys, need, !!need); 44 return !!need; 45 } 46 47 static int ceph_x_encrypt_offset(void) 48 { 49 return sizeof(u32) + sizeof(struct ceph_x_encrypt_header); 50 } 51 52 static int ceph_x_encrypt_buflen(int ilen) 53 { 54 return ceph_x_encrypt_offset() + ilen + 16; 55 } 56 57 static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf, 58 int buf_len, int plaintext_len) 59 { 60 struct ceph_x_encrypt_header *hdr = buf + sizeof(u32); 61 int ciphertext_len; 62 int ret; 63 64 hdr->struct_v = 1; 65 hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC); 66 67 ret = ceph_crypt(secret, true, buf + sizeof(u32), buf_len - sizeof(u32), 68 plaintext_len + sizeof(struct ceph_x_encrypt_header), 69 &ciphertext_len); 70 if (ret) 71 return ret; 72 73 ceph_encode_32(&buf, ciphertext_len); 74 return sizeof(u32) + ciphertext_len; 75 } 76 77 static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p, 78 int ciphertext_len) 79 { 80 struct ceph_x_encrypt_header *hdr = p; 81 int plaintext_len; 82 int ret; 83 84 ret = ceph_crypt(secret, false, p, ciphertext_len, ciphertext_len, 85 &plaintext_len); 86 if (ret) 87 return ret; 88 89 if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) { 90 pr_err("%s bad magic\n", __func__); 91 return -EINVAL; 92 } 93 94 return plaintext_len - sizeof(*hdr); 95 } 96 97 static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end) 98 { 99 int ciphertext_len; 100 int ret; 101 102 ceph_decode_32_safe(p, end, ciphertext_len, e_inval); 103 ceph_decode_need(p, end, ciphertext_len, e_inval); 104 105 ret = __ceph_x_decrypt(secret, *p, ciphertext_len); 106 if (ret < 0) 107 return ret; 108 109 *p += ciphertext_len; 110 return ret; 111 112 e_inval: 113 return -EINVAL; 114 } 115 116 /* 117 * get existing (or insert new) ticket handler 118 */ 119 static struct ceph_x_ticket_handler * 120 get_ticket_handler(struct ceph_auth_client *ac, int service) 121 { 122 struct ceph_x_ticket_handler *th; 123 struct ceph_x_info *xi = ac->private; 124 struct rb_node *parent = NULL, **p = &xi->ticket_handlers.rb_node; 125 126 while (*p) { 127 parent = *p; 128 th = rb_entry(parent, struct ceph_x_ticket_handler, node); 129 if (service < th->service) 130 p = &(*p)->rb_left; 131 else if (service > th->service) 132 p = &(*p)->rb_right; 133 else 134 return th; 135 } 136 137 /* add it */ 138 th = kzalloc(sizeof(*th), GFP_NOFS); 139 if (!th) 140 return ERR_PTR(-ENOMEM); 141 th->service = service; 142 rb_link_node(&th->node, parent, p); 143 rb_insert_color(&th->node, &xi->ticket_handlers); 144 return th; 145 } 146 147 static void remove_ticket_handler(struct ceph_auth_client *ac, 148 struct ceph_x_ticket_handler *th) 149 { 150 struct ceph_x_info *xi = ac->private; 151 152 dout("remove_ticket_handler %p %d\n", th, th->service); 153 rb_erase(&th->node, &xi->ticket_handlers); 154 ceph_crypto_key_destroy(&th->session_key); 155 if (th->ticket_blob) 156 ceph_buffer_put(th->ticket_blob); 157 kfree(th); 158 } 159 160 static int process_one_ticket(struct ceph_auth_client *ac, 161 struct ceph_crypto_key *secret, 162 void **p, void *end) 163 { 164 struct ceph_x_info *xi = ac->private; 165 int type; 166 u8 tkt_struct_v, blob_struct_v; 167 struct ceph_x_ticket_handler *th; 168 void *dp, *dend; 169 int dlen; 170 char is_enc; 171 struct timespec64 validity; 172 void *tp, *tpend; 173 void **ptp; 174 struct ceph_crypto_key new_session_key = { 0 }; 175 struct ceph_buffer *new_ticket_blob; 176 time64_t new_expires, new_renew_after; 177 u64 new_secret_id; 178 int ret; 179 180 ceph_decode_need(p, end, sizeof(u32) + 1, bad); 181 182 type = ceph_decode_32(p); 183 dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); 184 185 tkt_struct_v = ceph_decode_8(p); 186 if (tkt_struct_v != 1) 187 goto bad; 188 189 th = get_ticket_handler(ac, type); 190 if (IS_ERR(th)) { 191 ret = PTR_ERR(th); 192 goto out; 193 } 194 195 /* blob for me */ 196 dp = *p + ceph_x_encrypt_offset(); 197 ret = ceph_x_decrypt(secret, p, end); 198 if (ret < 0) 199 goto out; 200 dout(" decrypted %d bytes\n", ret); 201 dend = dp + ret; 202 203 ceph_decode_8_safe(&dp, dend, tkt_struct_v, bad); 204 if (tkt_struct_v != 1) 205 goto bad; 206 207 ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); 208 if (ret) 209 goto out; 210 211 ceph_decode_need(&dp, dend, sizeof(struct ceph_timespec), bad); 212 ceph_decode_timespec64(&validity, dp); 213 dp += sizeof(struct ceph_timespec); 214 new_expires = ktime_get_real_seconds() + validity.tv_sec; 215 new_renew_after = new_expires - (validity.tv_sec / 4); 216 dout(" expires=%llu renew_after=%llu\n", new_expires, 217 new_renew_after); 218 219 /* ticket blob for service */ 220 ceph_decode_8_safe(p, end, is_enc, bad); 221 if (is_enc) { 222 /* encrypted */ 223 tp = *p + ceph_x_encrypt_offset(); 224 ret = ceph_x_decrypt(&th->session_key, p, end); 225 if (ret < 0) 226 goto out; 227 dout(" encrypted ticket, decrypted %d bytes\n", ret); 228 ptp = &tp; 229 tpend = tp + ret; 230 } else { 231 /* unencrypted */ 232 ptp = p; 233 tpend = end; 234 } 235 ceph_decode_32_safe(ptp, tpend, dlen, bad); 236 dout(" ticket blob is %d bytes\n", dlen); 237 ceph_decode_need(ptp, tpend, 1 + sizeof(u64), bad); 238 blob_struct_v = ceph_decode_8(ptp); 239 if (blob_struct_v != 1) 240 goto bad; 241 242 new_secret_id = ceph_decode_64(ptp); 243 ret = ceph_decode_buffer(&new_ticket_blob, ptp, tpend); 244 if (ret) 245 goto out; 246 247 /* all is well, update our ticket */ 248 ceph_crypto_key_destroy(&th->session_key); 249 if (th->ticket_blob) 250 ceph_buffer_put(th->ticket_blob); 251 th->session_key = new_session_key; 252 th->ticket_blob = new_ticket_blob; 253 th->secret_id = new_secret_id; 254 th->expires = new_expires; 255 th->renew_after = new_renew_after; 256 th->have_key = true; 257 dout(" got ticket service %d (%s) secret_id %lld len %d\n", 258 type, ceph_entity_type_name(type), th->secret_id, 259 (int)th->ticket_blob->vec.iov_len); 260 xi->have_keys |= th->service; 261 return 0; 262 263 bad: 264 ret = -EINVAL; 265 out: 266 ceph_crypto_key_destroy(&new_session_key); 267 return ret; 268 } 269 270 static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, 271 struct ceph_crypto_key *secret, 272 void **p, void *end) 273 { 274 u8 reply_struct_v; 275 u32 num; 276 int ret; 277 278 ceph_decode_8_safe(p, end, reply_struct_v, bad); 279 if (reply_struct_v != 1) 280 return -EINVAL; 281 282 ceph_decode_32_safe(p, end, num, bad); 283 dout("%d tickets\n", num); 284 285 while (num--) { 286 ret = process_one_ticket(ac, secret, p, end); 287 if (ret) 288 return ret; 289 } 290 291 return 0; 292 293 bad: 294 return -EINVAL; 295 } 296 297 /* 298 * Encode and encrypt the second part (ceph_x_authorize_b) of the 299 * authorizer. The first part (ceph_x_authorize_a) should already be 300 * encoded. 301 */ 302 static int encrypt_authorizer(struct ceph_x_authorizer *au, 303 u64 *server_challenge) 304 { 305 struct ceph_x_authorize_a *msg_a; 306 struct ceph_x_authorize_b *msg_b; 307 void *p, *end; 308 int ret; 309 310 msg_a = au->buf->vec.iov_base; 311 WARN_ON(msg_a->ticket_blob.secret_id != cpu_to_le64(au->secret_id)); 312 p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len); 313 end = au->buf->vec.iov_base + au->buf->vec.iov_len; 314 315 msg_b = p + ceph_x_encrypt_offset(); 316 msg_b->struct_v = 2; 317 msg_b->nonce = cpu_to_le64(au->nonce); 318 if (server_challenge) { 319 msg_b->have_challenge = 1; 320 msg_b->server_challenge_plus_one = 321 cpu_to_le64(*server_challenge + 1); 322 } else { 323 msg_b->have_challenge = 0; 324 msg_b->server_challenge_plus_one = 0; 325 } 326 327 ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b)); 328 if (ret < 0) 329 return ret; 330 331 p += ret; 332 if (server_challenge) { 333 WARN_ON(p != end); 334 } else { 335 WARN_ON(p > end); 336 au->buf->vec.iov_len = p - au->buf->vec.iov_base; 337 } 338 339 return 0; 340 } 341 342 static void ceph_x_authorizer_cleanup(struct ceph_x_authorizer *au) 343 { 344 ceph_crypto_key_destroy(&au->session_key); 345 if (au->buf) { 346 ceph_buffer_put(au->buf); 347 au->buf = NULL; 348 } 349 } 350 351 static int ceph_x_build_authorizer(struct ceph_auth_client *ac, 352 struct ceph_x_ticket_handler *th, 353 struct ceph_x_authorizer *au) 354 { 355 int maxlen; 356 struct ceph_x_authorize_a *msg_a; 357 struct ceph_x_authorize_b *msg_b; 358 int ret; 359 int ticket_blob_len = 360 (th->ticket_blob ? th->ticket_blob->vec.iov_len : 0); 361 362 dout("build_authorizer for %s %p\n", 363 ceph_entity_type_name(th->service), au); 364 365 ceph_crypto_key_destroy(&au->session_key); 366 ret = ceph_crypto_key_clone(&au->session_key, &th->session_key); 367 if (ret) 368 goto out_au; 369 370 maxlen = sizeof(*msg_a) + ticket_blob_len + 371 ceph_x_encrypt_buflen(sizeof(*msg_b)); 372 dout(" need len %d\n", maxlen); 373 if (au->buf && au->buf->alloc_len < maxlen) { 374 ceph_buffer_put(au->buf); 375 au->buf = NULL; 376 } 377 if (!au->buf) { 378 au->buf = ceph_buffer_new(maxlen, GFP_NOFS); 379 if (!au->buf) { 380 ret = -ENOMEM; 381 goto out_au; 382 } 383 } 384 au->service = th->service; 385 WARN_ON(!th->secret_id); 386 au->secret_id = th->secret_id; 387 388 msg_a = au->buf->vec.iov_base; 389 msg_a->struct_v = 1; 390 msg_a->global_id = cpu_to_le64(ac->global_id); 391 msg_a->service_id = cpu_to_le32(th->service); 392 msg_a->ticket_blob.struct_v = 1; 393 msg_a->ticket_blob.secret_id = cpu_to_le64(th->secret_id); 394 msg_a->ticket_blob.blob_len = cpu_to_le32(ticket_blob_len); 395 if (ticket_blob_len) { 396 memcpy(msg_a->ticket_blob.blob, th->ticket_blob->vec.iov_base, 397 th->ticket_blob->vec.iov_len); 398 } 399 dout(" th %p secret_id %lld %lld\n", th, th->secret_id, 400 le64_to_cpu(msg_a->ticket_blob.secret_id)); 401 402 get_random_bytes(&au->nonce, sizeof(au->nonce)); 403 ret = encrypt_authorizer(au, NULL); 404 if (ret) { 405 pr_err("failed to encrypt authorizer: %d", ret); 406 goto out_au; 407 } 408 409 dout(" built authorizer nonce %llx len %d\n", au->nonce, 410 (int)au->buf->vec.iov_len); 411 return 0; 412 413 out_au: 414 ceph_x_authorizer_cleanup(au); 415 return ret; 416 } 417 418 static int ceph_x_encode_ticket(struct ceph_x_ticket_handler *th, 419 void **p, void *end) 420 { 421 ceph_decode_need(p, end, 1 + sizeof(u64), bad); 422 ceph_encode_8(p, 1); 423 ceph_encode_64(p, th->secret_id); 424 if (th->ticket_blob) { 425 const char *buf = th->ticket_blob->vec.iov_base; 426 u32 len = th->ticket_blob->vec.iov_len; 427 428 ceph_encode_32_safe(p, end, len, bad); 429 ceph_encode_copy_safe(p, end, buf, len, bad); 430 } else { 431 ceph_encode_32_safe(p, end, 0, bad); 432 } 433 434 return 0; 435 bad: 436 return -ERANGE; 437 } 438 439 static bool need_key(struct ceph_x_ticket_handler *th) 440 { 441 if (!th->have_key) 442 return true; 443 444 return ktime_get_real_seconds() >= th->renew_after; 445 } 446 447 static bool have_key(struct ceph_x_ticket_handler *th) 448 { 449 if (th->have_key && ktime_get_real_seconds() >= th->expires) { 450 dout("ticket %d (%s) secret_id %llu expired\n", th->service, 451 ceph_entity_type_name(th->service), th->secret_id); 452 th->have_key = false; 453 } 454 455 return th->have_key; 456 } 457 458 static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed) 459 { 460 int want = ac->want_keys; 461 struct ceph_x_info *xi = ac->private; 462 int service; 463 464 *pneed = ac->want_keys & ~(xi->have_keys); 465 466 for (service = 1; service <= want; service <<= 1) { 467 struct ceph_x_ticket_handler *th; 468 469 if (!(ac->want_keys & service)) 470 continue; 471 472 if (*pneed & service) 473 continue; 474 475 th = get_ticket_handler(ac, service); 476 if (IS_ERR(th)) { 477 *pneed |= service; 478 continue; 479 } 480 481 if (need_key(th)) 482 *pneed |= service; 483 if (!have_key(th)) 484 xi->have_keys &= ~service; 485 } 486 } 487 488 static int ceph_x_build_request(struct ceph_auth_client *ac, 489 void *buf, void *end) 490 { 491 struct ceph_x_info *xi = ac->private; 492 int need; 493 struct ceph_x_request_header *head = buf; 494 void *p; 495 int ret; 496 struct ceph_x_ticket_handler *th = 497 get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH); 498 499 if (IS_ERR(th)) 500 return PTR_ERR(th); 501 502 ceph_x_validate_tickets(ac, &need); 503 dout("%s want 0x%x have 0x%x need 0x%x\n", __func__, ac->want_keys, 504 xi->have_keys, need); 505 506 if (need & CEPH_ENTITY_TYPE_AUTH) { 507 struct ceph_x_authenticate *auth = (void *)(head + 1); 508 void *enc_buf = xi->auth_authorizer.enc_buf; 509 struct ceph_x_challenge_blob *blob = enc_buf + 510 ceph_x_encrypt_offset(); 511 u64 *u; 512 513 p = auth + 1; 514 if (p > end) 515 return -ERANGE; 516 517 dout(" get_auth_session_key\n"); 518 head->op = cpu_to_le16(CEPHX_GET_AUTH_SESSION_KEY); 519 520 /* encrypt and hash */ 521 get_random_bytes(&auth->client_challenge, sizeof(u64)); 522 blob->client_challenge = auth->client_challenge; 523 blob->server_challenge = cpu_to_le64(xi->server_challenge); 524 ret = ceph_x_encrypt(&xi->secret, enc_buf, CEPHX_AU_ENC_BUF_LEN, 525 sizeof(*blob)); 526 if (ret < 0) 527 return ret; 528 529 auth->struct_v = 2; /* nautilus+ */ 530 auth->key = 0; 531 for (u = (u64 *)enc_buf; u + 1 <= (u64 *)(enc_buf + ret); u++) 532 auth->key ^= *(__le64 *)u; 533 dout(" server_challenge %llx client_challenge %llx key %llx\n", 534 xi->server_challenge, le64_to_cpu(auth->client_challenge), 535 le64_to_cpu(auth->key)); 536 537 /* now encode the old ticket if exists */ 538 ret = ceph_x_encode_ticket(th, &p, end); 539 if (ret < 0) 540 return ret; 541 542 /* nautilus+: request service tickets at the same time */ 543 need = ac->want_keys & ~CEPH_ENTITY_TYPE_AUTH; 544 WARN_ON(!need); 545 ceph_encode_32_safe(&p, end, need, e_range); 546 return p - buf; 547 } 548 549 if (need) { 550 dout(" get_principal_session_key\n"); 551 ret = ceph_x_build_authorizer(ac, th, &xi->auth_authorizer); 552 if (ret) 553 return ret; 554 555 p = buf; 556 ceph_encode_16_safe(&p, end, CEPHX_GET_PRINCIPAL_SESSION_KEY, 557 e_range); 558 ceph_encode_copy_safe(&p, end, 559 xi->auth_authorizer.buf->vec.iov_base, 560 xi->auth_authorizer.buf->vec.iov_len, e_range); 561 ceph_encode_8_safe(&p, end, 1, e_range); 562 ceph_encode_32_safe(&p, end, need, e_range); 563 return p - buf; 564 } 565 566 return 0; 567 568 e_range: 569 return -ERANGE; 570 } 571 572 static int decode_con_secret(void **p, void *end, u8 *con_secret, 573 int *con_secret_len) 574 { 575 int len; 576 577 ceph_decode_32_safe(p, end, len, bad); 578 ceph_decode_need(p, end, len, bad); 579 580 dout("%s len %d\n", __func__, len); 581 if (con_secret) { 582 if (len > CEPH_MAX_CON_SECRET_LEN) { 583 pr_err("connection secret too big %d\n", len); 584 goto bad_memzero; 585 } 586 memcpy(con_secret, *p, len); 587 *con_secret_len = len; 588 } 589 memzero_explicit(*p, len); 590 *p += len; 591 return 0; 592 593 bad_memzero: 594 memzero_explicit(*p, len); 595 bad: 596 pr_err("failed to decode connection secret\n"); 597 return -EINVAL; 598 } 599 600 static int handle_auth_session_key(struct ceph_auth_client *ac, 601 void **p, void *end, 602 u8 *session_key, int *session_key_len, 603 u8 *con_secret, int *con_secret_len) 604 { 605 struct ceph_x_info *xi = ac->private; 606 struct ceph_x_ticket_handler *th; 607 void *dp, *dend; 608 int len; 609 int ret; 610 611 /* AUTH ticket */ 612 ret = ceph_x_proc_ticket_reply(ac, &xi->secret, p, end); 613 if (ret) 614 return ret; 615 616 if (*p == end) { 617 /* pre-nautilus (or didn't request service tickets!) */ 618 WARN_ON(session_key || con_secret); 619 return 0; 620 } 621 622 th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH); 623 if (IS_ERR(th)) 624 return PTR_ERR(th); 625 626 if (session_key) { 627 memcpy(session_key, th->session_key.key, th->session_key.len); 628 *session_key_len = th->session_key.len; 629 } 630 631 /* connection secret */ 632 ceph_decode_32_safe(p, end, len, e_inval); 633 dout("%s connection secret blob len %d\n", __func__, len); 634 if (len > 0) { 635 dp = *p + ceph_x_encrypt_offset(); 636 ret = ceph_x_decrypt(&th->session_key, p, *p + len); 637 if (ret < 0) 638 return ret; 639 640 dout("%s decrypted %d bytes\n", __func__, ret); 641 dend = dp + ret; 642 643 ret = decode_con_secret(&dp, dend, con_secret, con_secret_len); 644 if (ret) 645 return ret; 646 } 647 648 /* service tickets */ 649 ceph_decode_32_safe(p, end, len, e_inval); 650 dout("%s service tickets blob len %d\n", __func__, len); 651 if (len > 0) { 652 ret = ceph_x_proc_ticket_reply(ac, &th->session_key, 653 p, *p + len); 654 if (ret) 655 return ret; 656 } 657 658 return 0; 659 660 e_inval: 661 return -EINVAL; 662 } 663 664 static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result, 665 void *buf, void *end, 666 u8 *session_key, int *session_key_len, 667 u8 *con_secret, int *con_secret_len) 668 { 669 struct ceph_x_info *xi = ac->private; 670 struct ceph_x_ticket_handler *th; 671 int len = end - buf; 672 void *p; 673 int op; 674 int ret; 675 676 if (result) 677 return result; /* XXX hmm? */ 678 679 if (xi->starting) { 680 /* it's a hello */ 681 struct ceph_x_server_challenge *sc = buf; 682 683 if (len != sizeof(*sc)) 684 return -EINVAL; 685 xi->server_challenge = le64_to_cpu(sc->server_challenge); 686 dout("handle_reply got server challenge %llx\n", 687 xi->server_challenge); 688 xi->starting = false; 689 xi->have_keys &= ~CEPH_ENTITY_TYPE_AUTH; 690 return -EAGAIN; 691 } 692 693 p = buf; 694 ceph_decode_16_safe(&p, end, op, e_inval); 695 ceph_decode_32_safe(&p, end, result, e_inval); 696 dout("handle_reply op %d result %d\n", op, result); 697 switch (op) { 698 case CEPHX_GET_AUTH_SESSION_KEY: 699 /* AUTH ticket + [connection secret] + service tickets */ 700 ret = handle_auth_session_key(ac, &p, end, session_key, 701 session_key_len, con_secret, 702 con_secret_len); 703 break; 704 705 case CEPHX_GET_PRINCIPAL_SESSION_KEY: 706 th = get_ticket_handler(ac, CEPH_ENTITY_TYPE_AUTH); 707 if (IS_ERR(th)) 708 return PTR_ERR(th); 709 710 /* service tickets */ 711 ret = ceph_x_proc_ticket_reply(ac, &th->session_key, &p, end); 712 break; 713 714 default: 715 return -EINVAL; 716 } 717 if (ret) 718 return ret; 719 if (ac->want_keys == xi->have_keys) 720 return 0; 721 return -EAGAIN; 722 723 e_inval: 724 return -EINVAL; 725 } 726 727 static void ceph_x_destroy_authorizer(struct ceph_authorizer *a) 728 { 729 struct ceph_x_authorizer *au = (void *)a; 730 731 ceph_x_authorizer_cleanup(au); 732 kfree(au); 733 } 734 735 static int ceph_x_create_authorizer( 736 struct ceph_auth_client *ac, int peer_type, 737 struct ceph_auth_handshake *auth) 738 { 739 struct ceph_x_authorizer *au; 740 struct ceph_x_ticket_handler *th; 741 int ret; 742 743 th = get_ticket_handler(ac, peer_type); 744 if (IS_ERR(th)) 745 return PTR_ERR(th); 746 747 au = kzalloc(sizeof(*au), GFP_NOFS); 748 if (!au) 749 return -ENOMEM; 750 751 au->base.destroy = ceph_x_destroy_authorizer; 752 753 ret = ceph_x_build_authorizer(ac, th, au); 754 if (ret) { 755 kfree(au); 756 return ret; 757 } 758 759 auth->authorizer = (struct ceph_authorizer *) au; 760 auth->authorizer_buf = au->buf->vec.iov_base; 761 auth->authorizer_buf_len = au->buf->vec.iov_len; 762 auth->authorizer_reply_buf = au->enc_buf; 763 auth->authorizer_reply_buf_len = CEPHX_AU_ENC_BUF_LEN; 764 auth->sign_message = ac->ops->sign_message; 765 auth->check_message_signature = ac->ops->check_message_signature; 766 767 return 0; 768 } 769 770 static int ceph_x_update_authorizer( 771 struct ceph_auth_client *ac, int peer_type, 772 struct ceph_auth_handshake *auth) 773 { 774 struct ceph_x_authorizer *au; 775 struct ceph_x_ticket_handler *th; 776 777 th = get_ticket_handler(ac, peer_type); 778 if (IS_ERR(th)) 779 return PTR_ERR(th); 780 781 au = (struct ceph_x_authorizer *)auth->authorizer; 782 if (au->secret_id < th->secret_id) { 783 dout("ceph_x_update_authorizer service %u secret %llu < %llu\n", 784 au->service, au->secret_id, th->secret_id); 785 return ceph_x_build_authorizer(ac, th, au); 786 } 787 return 0; 788 } 789 790 /* 791 * CephXAuthorizeChallenge 792 */ 793 static int decrypt_authorizer_challenge(struct ceph_crypto_key *secret, 794 void *challenge, int challenge_len, 795 u64 *server_challenge) 796 { 797 void *dp, *dend; 798 int ret; 799 800 /* no leading len */ 801 ret = __ceph_x_decrypt(secret, challenge, challenge_len); 802 if (ret < 0) 803 return ret; 804 805 dout("%s decrypted %d bytes\n", __func__, ret); 806 dp = challenge + sizeof(struct ceph_x_encrypt_header); 807 dend = dp + ret; 808 809 ceph_decode_skip_8(&dp, dend, e_inval); /* struct_v */ 810 ceph_decode_64_safe(&dp, dend, *server_challenge, e_inval); 811 dout("%s server_challenge %llu\n", __func__, *server_challenge); 812 return 0; 813 814 e_inval: 815 return -EINVAL; 816 } 817 818 static int ceph_x_add_authorizer_challenge(struct ceph_auth_client *ac, 819 struct ceph_authorizer *a, 820 void *challenge, int challenge_len) 821 { 822 struct ceph_x_authorizer *au = (void *)a; 823 u64 server_challenge; 824 int ret; 825 826 ret = decrypt_authorizer_challenge(&au->session_key, challenge, 827 challenge_len, &server_challenge); 828 if (ret) { 829 pr_err("failed to decrypt authorize challenge: %d", ret); 830 return ret; 831 } 832 833 ret = encrypt_authorizer(au, &server_challenge); 834 if (ret) { 835 pr_err("failed to encrypt authorizer w/ challenge: %d", ret); 836 return ret; 837 } 838 839 return 0; 840 } 841 842 /* 843 * CephXAuthorizeReply 844 */ 845 static int decrypt_authorizer_reply(struct ceph_crypto_key *secret, 846 void **p, void *end, u64 *nonce_plus_one, 847 u8 *con_secret, int *con_secret_len) 848 { 849 void *dp, *dend; 850 u8 struct_v; 851 int ret; 852 853 dp = *p + ceph_x_encrypt_offset(); 854 ret = ceph_x_decrypt(secret, p, end); 855 if (ret < 0) 856 return ret; 857 858 dout("%s decrypted %d bytes\n", __func__, ret); 859 dend = dp + ret; 860 861 ceph_decode_8_safe(&dp, dend, struct_v, e_inval); 862 ceph_decode_64_safe(&dp, dend, *nonce_plus_one, e_inval); 863 dout("%s nonce_plus_one %llu\n", __func__, *nonce_plus_one); 864 if (struct_v >= 2) { 865 ret = decode_con_secret(&dp, dend, con_secret, con_secret_len); 866 if (ret) 867 return ret; 868 } 869 870 return 0; 871 872 e_inval: 873 return -EINVAL; 874 } 875 876 static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, 877 struct ceph_authorizer *a, 878 void *reply, int reply_len, 879 u8 *session_key, int *session_key_len, 880 u8 *con_secret, int *con_secret_len) 881 { 882 struct ceph_x_authorizer *au = (void *)a; 883 u64 nonce_plus_one; 884 int ret; 885 886 if (session_key) { 887 memcpy(session_key, au->session_key.key, au->session_key.len); 888 *session_key_len = au->session_key.len; 889 } 890 891 ret = decrypt_authorizer_reply(&au->session_key, &reply, 892 reply + reply_len, &nonce_plus_one, 893 con_secret, con_secret_len); 894 if (ret) 895 return ret; 896 897 if (nonce_plus_one != au->nonce + 1) { 898 pr_err("failed to authenticate server\n"); 899 return -EPERM; 900 } 901 902 return 0; 903 } 904 905 static void ceph_x_reset(struct ceph_auth_client *ac) 906 { 907 struct ceph_x_info *xi = ac->private; 908 909 dout("reset\n"); 910 xi->starting = true; 911 xi->server_challenge = 0; 912 } 913 914 static void ceph_x_destroy(struct ceph_auth_client *ac) 915 { 916 struct ceph_x_info *xi = ac->private; 917 struct rb_node *p; 918 919 dout("ceph_x_destroy %p\n", ac); 920 ceph_crypto_key_destroy(&xi->secret); 921 922 while ((p = rb_first(&xi->ticket_handlers)) != NULL) { 923 struct ceph_x_ticket_handler *th = 924 rb_entry(p, struct ceph_x_ticket_handler, node); 925 remove_ticket_handler(ac, th); 926 } 927 928 ceph_x_authorizer_cleanup(&xi->auth_authorizer); 929 930 kfree(ac->private); 931 ac->private = NULL; 932 } 933 934 static void invalidate_ticket(struct ceph_auth_client *ac, int peer_type) 935 { 936 struct ceph_x_ticket_handler *th; 937 938 th = get_ticket_handler(ac, peer_type); 939 if (IS_ERR(th)) 940 return; 941 942 if (th->have_key) { 943 dout("ticket %d (%s) secret_id %llu invalidated\n", 944 th->service, ceph_entity_type_name(th->service), 945 th->secret_id); 946 th->have_key = false; 947 } 948 } 949 950 static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac, 951 int peer_type) 952 { 953 /* 954 * We are to invalidate a service ticket in the hopes of 955 * getting a new, hopefully more valid, one. But, we won't get 956 * it unless our AUTH ticket is good, so invalidate AUTH ticket 957 * as well, just in case. 958 */ 959 invalidate_ticket(ac, peer_type); 960 invalidate_ticket(ac, CEPH_ENTITY_TYPE_AUTH); 961 } 962 963 static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg, 964 __le64 *psig) 965 { 966 void *enc_buf = au->enc_buf; 967 int ret; 968 969 if (!CEPH_HAVE_FEATURE(msg->con->peer_features, CEPHX_V2)) { 970 struct { 971 __le32 len; 972 __le32 header_crc; 973 __le32 front_crc; 974 __le32 middle_crc; 975 __le32 data_crc; 976 } __packed *sigblock = enc_buf + ceph_x_encrypt_offset(); 977 978 sigblock->len = cpu_to_le32(4*sizeof(u32)); 979 sigblock->header_crc = msg->hdr.crc; 980 sigblock->front_crc = msg->footer.front_crc; 981 sigblock->middle_crc = msg->footer.middle_crc; 982 sigblock->data_crc = msg->footer.data_crc; 983 984 ret = ceph_x_encrypt(&au->session_key, enc_buf, 985 CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock)); 986 if (ret < 0) 987 return ret; 988 989 *psig = *(__le64 *)(enc_buf + sizeof(u32)); 990 } else { 991 struct { 992 __le32 header_crc; 993 __le32 front_crc; 994 __le32 front_len; 995 __le32 middle_crc; 996 __le32 middle_len; 997 __le32 data_crc; 998 __le32 data_len; 999 __le32 seq_lower_word; 1000 } __packed *sigblock = enc_buf; 1001 struct { 1002 __le64 a, b, c, d; 1003 } __packed *penc = enc_buf; 1004 int ciphertext_len; 1005 1006 sigblock->header_crc = msg->hdr.crc; 1007 sigblock->front_crc = msg->footer.front_crc; 1008 sigblock->front_len = msg->hdr.front_len; 1009 sigblock->middle_crc = msg->footer.middle_crc; 1010 sigblock->middle_len = msg->hdr.middle_len; 1011 sigblock->data_crc = msg->footer.data_crc; 1012 sigblock->data_len = msg->hdr.data_len; 1013 sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq; 1014 1015 /* no leading len, no ceph_x_encrypt_header */ 1016 ret = ceph_crypt(&au->session_key, true, enc_buf, 1017 CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock), 1018 &ciphertext_len); 1019 if (ret) 1020 return ret; 1021 1022 *psig = penc->a ^ penc->b ^ penc->c ^ penc->d; 1023 } 1024 1025 return 0; 1026 } 1027 1028 static int ceph_x_sign_message(struct ceph_auth_handshake *auth, 1029 struct ceph_msg *msg) 1030 { 1031 __le64 sig; 1032 int ret; 1033 1034 if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN)) 1035 return 0; 1036 1037 ret = calc_signature((struct ceph_x_authorizer *)auth->authorizer, 1038 msg, &sig); 1039 if (ret) 1040 return ret; 1041 1042 msg->footer.sig = sig; 1043 msg->footer.flags |= CEPH_MSG_FOOTER_SIGNED; 1044 return 0; 1045 } 1046 1047 static int ceph_x_check_message_signature(struct ceph_auth_handshake *auth, 1048 struct ceph_msg *msg) 1049 { 1050 __le64 sig_check; 1051 int ret; 1052 1053 if (ceph_test_opt(from_msgr(msg->con->msgr), NOMSGSIGN)) 1054 return 0; 1055 1056 ret = calc_signature((struct ceph_x_authorizer *)auth->authorizer, 1057 msg, &sig_check); 1058 if (ret) 1059 return ret; 1060 if (sig_check == msg->footer.sig) 1061 return 0; 1062 if (msg->footer.flags & CEPH_MSG_FOOTER_SIGNED) 1063 dout("ceph_x_check_message_signature %p has signature %llx " 1064 "expect %llx\n", msg, msg->footer.sig, sig_check); 1065 else 1066 dout("ceph_x_check_message_signature %p sender did not set " 1067 "CEPH_MSG_FOOTER_SIGNED\n", msg); 1068 return -EBADMSG; 1069 } 1070 1071 static const struct ceph_auth_client_ops ceph_x_ops = { 1072 .is_authenticated = ceph_x_is_authenticated, 1073 .should_authenticate = ceph_x_should_authenticate, 1074 .build_request = ceph_x_build_request, 1075 .handle_reply = ceph_x_handle_reply, 1076 .create_authorizer = ceph_x_create_authorizer, 1077 .update_authorizer = ceph_x_update_authorizer, 1078 .add_authorizer_challenge = ceph_x_add_authorizer_challenge, 1079 .verify_authorizer_reply = ceph_x_verify_authorizer_reply, 1080 .invalidate_authorizer = ceph_x_invalidate_authorizer, 1081 .reset = ceph_x_reset, 1082 .destroy = ceph_x_destroy, 1083 .sign_message = ceph_x_sign_message, 1084 .check_message_signature = ceph_x_check_message_signature, 1085 }; 1086 1087 1088 int ceph_x_init(struct ceph_auth_client *ac) 1089 { 1090 struct ceph_x_info *xi; 1091 int ret; 1092 1093 dout("ceph_x_init %p\n", ac); 1094 ret = -ENOMEM; 1095 xi = kzalloc(sizeof(*xi), GFP_NOFS); 1096 if (!xi) 1097 goto out; 1098 1099 ret = -EINVAL; 1100 if (!ac->key) { 1101 pr_err("no secret set (for auth_x protocol)\n"); 1102 goto out_nomem; 1103 } 1104 1105 ret = ceph_crypto_key_clone(&xi->secret, ac->key); 1106 if (ret < 0) { 1107 pr_err("cannot clone key: %d\n", ret); 1108 goto out_nomem; 1109 } 1110 1111 xi->starting = true; 1112 xi->ticket_handlers = RB_ROOT; 1113 1114 ac->protocol = CEPH_AUTH_CEPHX; 1115 ac->private = xi; 1116 ac->ops = &ceph_x_ops; 1117 return 0; 1118 1119 out_nomem: 1120 kfree(xi); 1121 out: 1122 return ret; 1123 } 1124