Changeset 988 for vendor/current/libcli/auth/credentials.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/libcli/auth/credentials.c
r746 r988 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 6 6 Copyright (C) Andrew Tridgell 1997-2003 7 7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004 8 8 9 9 This program is free software; you can redistribute it and/or modify 10 10 it under the terms of the GNU General Public License as published by 11 11 the Free Software Foundation; either version 3 of the License, or 12 12 (at your option) any later version. 13 13 14 14 This program is distributed in the hope that it will be useful, 15 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 17 GNU General Public License for more details. 18 18 19 19 You should have received a copy of the GNU General Public License 20 20 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 31 31 struct netr_Credential *out) 32 32 { 33 des_crypt112(out->data, in->data, creds->session_key, 1); 33 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 34 AES_KEY key; 35 uint8_t iv[AES_BLOCK_SIZE]; 36 37 AES_set_encrypt_key(creds->session_key, 128, &key); 38 ZERO_STRUCT(iv); 39 40 aes_cfb8_encrypt(in->data, out->data, 8, &key, iv, AES_ENCRYPT); 41 } else { 42 des_crypt112(out->data, in->data, creds->session_key, 1); 43 } 34 44 } 35 45 … … 76 86 memset(zero, 0, sizeof(zero)); 77 87 78 hmac_md5_init_rfc2104(machine_password->hash, sizeof(machine_password->hash), &ctx); 88 hmac_md5_init_rfc2104(machine_password->hash, sizeof(machine_password->hash), &ctx); 79 89 MD5Init(&md5); 80 90 MD5Update(&md5, zero, sizeof(zero)); … … 86 96 } 87 97 98 /* 99 initialise the credentials state for AES/HMAC-SHA256-style 128 bit session keys 100 101 this call is made after the netr_ServerReqChallenge call 102 */ 103 static void netlogon_creds_init_hmac_sha256(struct netlogon_creds_CredentialState *creds, 104 const struct netr_Credential *client_challenge, 105 const struct netr_Credential *server_challenge, 106 const struct samr_Password *machine_password) 107 { 108 struct HMACSHA256Context ctx; 109 uint8_t digest[SHA256_DIGEST_LENGTH]; 110 111 ZERO_STRUCT(creds->session_key); 112 113 hmac_sha256_init(machine_password->hash, 114 sizeof(machine_password->hash), 115 &ctx); 116 hmac_sha256_update(client_challenge->data, 8, &ctx); 117 hmac_sha256_update(server_challenge->data, 8, &ctx); 118 hmac_sha256_final(digest, &ctx); 119 120 memcpy(creds->session_key, digest, sizeof(creds->session_key)); 121 122 ZERO_STRUCT(digest); 123 ZERO_STRUCT(ctx); 124 } 125 88 126 static void netlogon_creds_first_step(struct netlogon_creds_CredentialState *creds, 89 127 const struct netr_Credential *client_challenge, … … 105 143 struct netr_Credential time_cred; 106 144 107 DEBUG(5,("\tseed %08x:%08x\n", 145 DEBUG(5,("\tseed %08x:%08x\n", 108 146 IVAL(creds->seed.data, 0), IVAL(creds->seed.data, 4))); 109 147 … … 115 153 netlogon_creds_step_crypt(creds, &time_cred, &creds->client); 116 154 117 DEBUG(5,("\tCLIENT %08x:%08x\n", 155 DEBUG(5,("\tCLIENT %08x:%08x\n", 118 156 IVAL(creds->client.data, 0), IVAL(creds->client.data, 4))); 119 157 … … 121 159 SIVAL(time_cred.data, 4, IVAL(creds->seed.data, 4)); 122 160 123 DEBUG(5,("\tseed+time+1 %08x:%08x\n", 161 DEBUG(5,("\tseed+time+1 %08x:%08x\n", 124 162 IVAL(time_cred.data, 0), IVAL(time_cred.data, 4))); 125 163 126 164 netlogon_creds_step_crypt(creds, &time_cred, &creds->server); 127 165 128 DEBUG(5,("\tSERVER %08x:%08x\n", 166 DEBUG(5,("\tSERVER %08x:%08x\n", 129 167 IVAL(creds->server.data, 0), IVAL(creds->server.data, 4))); 130 168 … … 183 221 184 222 data_blob_free(&session_key); 223 } 224 225 /* 226 AES encrypt a password buffer using the session key 227 */ 228 void netlogon_creds_aes_encrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len) 229 { 230 AES_KEY key; 231 uint8_t iv[AES_BLOCK_SIZE]; 232 233 AES_set_encrypt_key(creds->session_key, 128, &key); 234 ZERO_STRUCT(iv); 235 236 aes_cfb8_encrypt(data, data, len, &key, iv, AES_ENCRYPT); 237 } 238 239 /* 240 AES decrypt a password buffer using the session key 241 */ 242 void netlogon_creds_aes_decrypt(struct netlogon_creds_CredentialState *creds, uint8_t *data, size_t len) 243 { 244 AES_KEY key; 245 uint8_t iv[AES_BLOCK_SIZE]; 246 247 AES_set_encrypt_key(creds->session_key, 128, &key); 248 ZERO_STRUCT(iv); 249 250 aes_cfb8_encrypt(data, data, len, &key, iv, AES_DECRYPT); 185 251 } 186 252 … … 194 260 credentials 195 261 */ 196 197 struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx, 262 263 struct netlogon_creds_CredentialState *netlogon_creds_client_init(TALLOC_CTX *mem_ctx, 198 264 const char *client_account, 199 const char *client_computer_name, 265 const char *client_computer_name, 266 uint16_t secure_channel_type, 200 267 const struct netr_Credential *client_challenge, 201 268 const struct netr_Credential *server_challenge, … … 205 272 { 206 273 struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); 207 274 208 275 if (!creds) { 209 276 return NULL; 210 277 } 211 278 212 279 creds->sequence = time(NULL); 213 280 creds->negotiate_flags = negotiate_flags; 281 creds->secure_channel_type = secure_channel_type; 214 282 215 283 creds->computer_name = talloc_strdup(creds, client_computer_name); … … 228 296 dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash)); 229 297 230 if (negotiate_flags & NETLOGON_NEG_128BIT) { 298 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 299 netlogon_creds_init_hmac_sha256(creds, 300 client_challenge, 301 server_challenge, 302 machine_password); 303 } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { 231 304 netlogon_creds_init_128bit(creds, client_challenge, server_challenge, machine_password); 232 305 } else { … … 247 320 */ 248 321 249 struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx, 322 struct netlogon_creds_CredentialState *netlogon_creds_client_init_session_key(TALLOC_CTX *mem_ctx, 250 323 const uint8_t session_key[16]) 251 324 { … … 256 329 return NULL; 257 330 } 258 331 259 332 memcpy(creds->session_key, session_key, 16); 260 333 … … 266 339 current client and server credentials and the seed 267 340 268 produce the next authenticator in the sequence ready to send to 341 produce the next authenticator in the sequence ready to send to 269 342 the server 270 343 */ 271 344 void netlogon_creds_client_authenticator(struct netlogon_creds_CredentialState *creds, 272 345 struct netr_Authenticator *next) 273 { 346 { 347 uint32_t t32n = (uint32_t)time(NULL); 348 349 /* 350 * we always increment and ignore an overflow here 351 */ 274 352 creds->sequence += 2; 353 354 if (t32n > creds->sequence) { 355 /* 356 * we may increment more 357 */ 358 creds->sequence = t32n; 359 } else { 360 uint32_t d = creds->sequence - t32n; 361 362 if (d >= INT32_MAX) { 363 /* 364 * got an overflow of time_t vs. uint32_t 365 */ 366 creds->sequence = t32n; 367 } 368 } 369 275 370 netlogon_creds_step(creds); 276 371 … … 285 380 const struct netr_Credential *received_credentials) 286 381 { 287 if (!received_credentials || 382 if (!received_credentials || 288 383 memcmp(received_credentials->data, creds->server.data, 8) != 0) { 289 384 DEBUG(2,("credentials check failed\n")); … … 318 413 credentials 319 414 */ 320 struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *mem_ctx, 415 struct netlogon_creds_CredentialState *netlogon_creds_server_init(TALLOC_CTX *mem_ctx, 321 416 const char *client_account, 322 const char *client_computer_name, 417 const char *client_computer_name, 323 418 uint16_t secure_channel_type, 324 419 const struct netr_Credential *client_challenge, 325 420 const struct netr_Credential *server_challenge, 326 421 const struct samr_Password *machine_password, 327 struct netr_Credential *credentials_in,422 const struct netr_Credential *credentials_in, 328 423 struct netr_Credential *credentials_out, 329 424 uint32_t negotiate_flags) 330 425 { 331 426 332 427 struct netlogon_creds_CredentialState *creds = talloc_zero(mem_ctx, struct netlogon_creds_CredentialState); 333 428 334 429 if (!creds) { 335 430 return NULL; 336 431 } 337 432 338 433 creds->negotiate_flags = negotiate_flags; 339 434 creds->secure_channel_type = secure_channel_type; 435 436 dump_data_pw("Client chall", client_challenge->data, sizeof(client_challenge->data)); 437 dump_data_pw("Server chall", server_challenge->data, sizeof(server_challenge->data)); 438 dump_data_pw("Machine Pass", machine_password->hash, sizeof(machine_password->hash)); 340 439 341 440 creds->computer_name = talloc_strdup(creds, client_computer_name); … … 350 449 } 351 450 352 if (negotiate_flags & NETLOGON_NEG_128BIT) { 353 netlogon_creds_init_128bit(creds, client_challenge, server_challenge, 451 if (negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 452 netlogon_creds_init_hmac_sha256(creds, 453 client_challenge, 454 server_challenge, 455 machine_password); 456 } else if (negotiate_flags & NETLOGON_NEG_STRONG_KEYS) { 457 netlogon_creds_init_128bit(creds, client_challenge, server_challenge, 354 458 machine_password); 355 459 } else { 356 netlogon_creds_init_64bit(creds, client_challenge, server_challenge, 460 netlogon_creds_init_64bit(creds, client_challenge, server_challenge, 357 461 machine_password); 358 462 } 359 463 360 464 netlogon_creds_first_step(creds, client_challenge, server_challenge); 465 466 dump_data_pw("Session key", creds->session_key, 16); 467 dump_data_pw("Client Credential ", creds->client.data, 8); 468 dump_data_pw("Server Credential ", creds->server.data, 8); 469 470 dump_data_pw("Credentials in", credentials_in->data, sizeof(credentials_in->data)); 361 471 362 472 /* And before we leak information about the machine account … … 369 479 *credentials_out = creds->server; 370 480 481 dump_data_pw("Credentials out", credentials_out->data, sizeof(credentials_out->data)); 482 371 483 return creds; 372 484 } 373 485 374 486 NTSTATUS netlogon_creds_server_step_check(struct netlogon_creds_CredentialState *creds, 375 struct netr_Authenticator *received_authenticator,376 struct netr_Authenticator *return_authenticator) 487 const struct netr_Authenticator *received_authenticator, 488 struct netr_Authenticator *return_authenticator) 377 489 { 378 490 if (!received_authenticator || !return_authenticator) { … … 384 496 } 385 497 386 /* TODO: this may allow the a replay attack on a non-signed387 connection. Should we check that this is increasing? */388 498 creds->sequence = received_authenticator->timestamp; 389 499 netlogon_creds_step(creds); 390 500 if (netlogon_creds_server_check_internal(creds, &received_authenticator->cred)) { 391 501 return_authenticator->cred = creds->server; 392 return_authenticator->timestamp = creds->sequence;502 return_authenticator->timestamp = 0; 393 503 return NT_STATUS_OK; 394 504 } else { … … 398 508 } 399 509 400 void netlogon_creds_decrypt_samlogon(struct netlogon_creds_CredentialState *creds, 401 uint16_t validation_level, 402 union netr_Validation *validation) 510 static void netlogon_creds_crypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, 511 uint16_t validation_level, 512 union netr_Validation *validation, 513 bool do_encrypt) 403 514 { 404 515 static const char zeros[16]; 405 406 516 struct netr_SamBaseInfo *base = NULL; 517 518 if (validation == NULL) { 519 return; 520 } 521 407 522 switch (validation_level) { 408 523 case 2: … … 433 548 if (validation_level == 6) { 434 549 /* they aren't encrypted! */ 550 } else if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 551 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ 552 if (memcmp(base->key.key, zeros, 553 sizeof(base->key.key)) != 0) { 554 if (do_encrypt) { 555 netlogon_creds_aes_encrypt(creds, 556 base->key.key, 557 sizeof(base->key.key)); 558 } else { 559 netlogon_creds_aes_decrypt(creds, 560 base->key.key, 561 sizeof(base->key.key)); 562 } 563 } 564 565 if (memcmp(base->LMSessKey.key, zeros, 566 sizeof(base->LMSessKey.key)) != 0) { 567 if (do_encrypt) { 568 netlogon_creds_aes_encrypt(creds, 569 base->LMSessKey.key, 570 sizeof(base->LMSessKey.key)); 571 572 } else { 573 netlogon_creds_aes_decrypt(creds, 574 base->LMSessKey.key, 575 sizeof(base->LMSessKey.key)); 576 } 577 } 435 578 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { 436 if (memcmp(base->key.key, zeros, 579 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ 580 if (memcmp(base->key.key, zeros, 437 581 sizeof(base->key.key)) != 0) { 438 netlogon_creds_arcfour_crypt(creds, 439 base->key.key, 582 netlogon_creds_arcfour_crypt(creds, 583 base->key.key, 440 584 sizeof(base->key.key)); 441 585 } 442 443 if (memcmp(base->LMSessKey.key, zeros, 586 587 if (memcmp(base->LMSessKey.key, zeros, 444 588 sizeof(base->LMSessKey.key)) != 0) { 445 netlogon_creds_arcfour_crypt(creds, 446 base->LMSessKey.key, 589 netlogon_creds_arcfour_crypt(creds, 590 base->LMSessKey.key, 447 591 sizeof(base->LMSessKey.key)); 448 592 } 449 593 } else { 450 if (memcmp(base->LMSessKey.key, zeros, 594 /* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */ 595 if (memcmp(base->LMSessKey.key, zeros, 451 596 sizeof(base->LMSessKey.key)) != 0) { 452 netlogon_creds_des_decrypt_LMKey(creds, 597 if (do_encrypt) { 598 netlogon_creds_des_encrypt_LMKey(creds, 453 599 &base->LMSessKey); 454 } 455 } 456 } 600 } else { 601 netlogon_creds_des_decrypt_LMKey(creds, 602 &base->LMSessKey); 603 } 604 } 605 } 606 } 607 608 void netlogon_creds_decrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, 609 uint16_t validation_level, 610 union netr_Validation *validation) 611 { 612 netlogon_creds_crypt_samlogon_validation(creds, validation_level, 613 validation, false); 614 } 615 616 void netlogon_creds_encrypt_samlogon_validation(struct netlogon_creds_CredentialState *creds, 617 uint16_t validation_level, 618 union netr_Validation *validation) 619 { 620 netlogon_creds_crypt_samlogon_validation(creds, validation_level, 621 validation, true); 622 } 623 624 static void netlogon_creds_crypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, 625 enum netr_LogonInfoClass level, 626 union netr_LogonLevel *logon, 627 bool do_encrypt) 628 { 629 static const char zeros[16]; 630 631 if (logon == NULL) { 632 return; 633 } 634 635 switch (level) { 636 case NetlogonInteractiveInformation: 637 case NetlogonInteractiveTransitiveInformation: 638 case NetlogonServiceInformation: 639 case NetlogonServiceTransitiveInformation: 640 if (logon->password == NULL) { 641 return; 642 } 643 644 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 645 uint8_t *h; 646 647 h = logon->password->lmpassword.hash; 648 if (memcmp(h, zeros, 16) != 0) { 649 if (do_encrypt) { 650 netlogon_creds_aes_encrypt(creds, h, 16); 651 } else { 652 netlogon_creds_aes_decrypt(creds, h, 16); 653 } 654 } 655 656 h = logon->password->ntpassword.hash; 657 if (memcmp(h, zeros, 16) != 0) { 658 if (do_encrypt) { 659 netlogon_creds_aes_encrypt(creds, h, 16); 660 } else { 661 netlogon_creds_aes_decrypt(creds, h, 16); 662 } 663 } 664 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { 665 uint8_t *h; 666 667 h = logon->password->lmpassword.hash; 668 if (memcmp(h, zeros, 16) != 0) { 669 netlogon_creds_arcfour_crypt(creds, h, 16); 670 } 671 672 h = logon->password->ntpassword.hash; 673 if (memcmp(h, zeros, 16) != 0) { 674 netlogon_creds_arcfour_crypt(creds, h, 16); 675 } 676 } else { 677 struct samr_Password *p; 678 679 p = &logon->password->lmpassword; 680 if (memcmp(p->hash, zeros, 16) != 0) { 681 if (do_encrypt) { 682 netlogon_creds_des_encrypt(creds, p); 683 } else { 684 netlogon_creds_des_decrypt(creds, p); 685 } 686 } 687 p = &logon->password->ntpassword; 688 if (memcmp(p->hash, zeros, 16) != 0) { 689 if (do_encrypt) { 690 netlogon_creds_des_encrypt(creds, p); 691 } else { 692 netlogon_creds_des_decrypt(creds, p); 693 } 694 } 695 } 696 break; 697 698 case NetlogonNetworkInformation: 699 case NetlogonNetworkTransitiveInformation: 700 break; 701 702 case NetlogonGenericInformation: 703 if (logon->generic == NULL) { 704 return; 705 } 706 707 if (creds->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) { 708 if (do_encrypt) { 709 netlogon_creds_aes_encrypt(creds, 710 logon->generic->data, 711 logon->generic->length); 712 } else { 713 netlogon_creds_aes_decrypt(creds, 714 logon->generic->data, 715 logon->generic->length); 716 } 717 } else if (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR) { 718 netlogon_creds_arcfour_crypt(creds, 719 logon->generic->data, 720 logon->generic->length); 721 } else { 722 /* Using DES to verify kerberos tickets makes no sense */ 723 } 724 break; 725 } 726 } 727 728 void netlogon_creds_decrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, 729 enum netr_LogonInfoClass level, 730 union netr_LogonLevel *logon) 731 { 732 netlogon_creds_crypt_samlogon_logon(creds, level, logon, false); 733 } 734 735 void netlogon_creds_encrypt_samlogon_logon(struct netlogon_creds_CredentialState *creds, 736 enum netr_LogonInfoClass level, 737 union netr_LogonLevel *logon) 738 { 739 netlogon_creds_crypt_samlogon_logon(creds, level, logon, true); 740 } 741 742 union netr_LogonLevel *netlogon_creds_shallow_copy_logon(TALLOC_CTX *mem_ctx, 743 enum netr_LogonInfoClass level, 744 const union netr_LogonLevel *in) 745 { 746 union netr_LogonLevel *out; 747 748 if (in == NULL) { 749 return NULL; 750 } 751 752 out = talloc(mem_ctx, union netr_LogonLevel); 753 if (out == NULL) { 754 return NULL; 755 } 756 757 *out = *in; 758 759 switch (level) { 760 case NetlogonInteractiveInformation: 761 case NetlogonInteractiveTransitiveInformation: 762 case NetlogonServiceInformation: 763 case NetlogonServiceTransitiveInformation: 764 if (in->password == NULL) { 765 return out; 766 } 767 768 out->password = talloc(out, struct netr_PasswordInfo); 769 if (out->password == NULL) { 770 talloc_free(out); 771 return NULL; 772 } 773 *out->password = *in->password; 774 775 return out; 776 777 case NetlogonNetworkInformation: 778 case NetlogonNetworkTransitiveInformation: 779 break; 780 781 case NetlogonGenericInformation: 782 if (in->generic == NULL) { 783 return out; 784 } 785 786 out->generic = talloc(out, struct netr_GenericInfo); 787 if (out->generic == NULL) { 788 talloc_free(out); 789 return NULL; 790 } 791 *out->generic = *in->generic; 792 793 if (in->generic->data == NULL) { 794 return out; 795 } 796 797 if (in->generic->length == 0) { 798 return out; 799 } 800 801 out->generic->data = talloc_memdup(out->generic, 802 in->generic->data, 803 in->generic->length); 804 if (out->generic->data == NULL) { 805 talloc_free(out); 806 return NULL; 807 } 808 809 return out; 810 } 811 812 return out; 813 } 457 814 458 815 /*
Note:
See TracChangeset
for help on using the changeset viewer.