Changeset 745 for trunk/server/source4/heimdal/lib/ntlm
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/heimdal/lib/ntlm/heimntlm.h
r414 r745 47 47 48 48 #define NTLM_NEG_UNICODE 0x00000001 49 #define NTLM_NEG_OEM 0x00000002 49 50 #define NTLM_NEG_TARGET 0x00000004 51 #define NTLM_MBZ9 0x00000008 52 50 53 #define NTLM_NEG_SIGN 0x00000010 51 54 #define NTLM_NEG_SEAL 0x00000020 55 #define NTLM_NEG_DATAGRAM 0x00000040 56 #define NTLM_NEG_LM_KEY 0x00000080 52 57 #define NTLM_NEG_NTLM 0x00000200 58 #define NTLM_NEG_ANONYMOUS 0x00000800 53 59 54 #define NTLM_SUPPLIED_DOMAIN 0x00001000 55 #define NTLM_SUPPLIED_WORKSTAION 0x00002000 60 #define NTLM_MBZ8 0x00000100 61 #define NTLM_NEG_NTLM 0x00000200 62 #define NTLM_NEG_NT_ONLY 0x00000400 63 #define NTLM_MBZ7 0x00000800 /* anon ? */ 56 64 65 #define NTLM_OEM_SUPPLIED_DOMAIN 0x00001000 66 #define NTLM_OEM_SUPPLIED_WORKSTATION 0x00002000 67 #define NTLM_MBZ6 0x00004000 /* local call ? */ 57 68 #define NTLM_NEG_ALWAYS_SIGN 0x00008000 58 #define NTLM_NEG_NTLM2_SESSION 0x0008000059 69 60 70 #define NTLM_TARGET_DOMAIN 0x00010000 61 71 #define NTLM_TARGET_SERVER 0x00020000 72 73 #define NTLM_TARGET_SHARE 0x00040000 74 #define NTLM_NEG_NTLM2_SESSION 0x00080000 75 #define NTLM_NEG_NTLM2 0x00080000 76 77 #define NTLM_NEG_IDENTIFY 0x00100000 78 #define NTLM_MBZ5 0x00200000 79 #define NTLM_NON_NT_SESSION_KEY 0x00400000 80 #define NTLM_NEG_TARGET_INFO 0x00800000 81 82 #define NTLM_MBZ4 0x01000000 83 #define NTLM_NEG_VERSION 0x02000000 84 #define NTLM_MBZ3 0x04000000 85 #define NTLM_MBZ2 0x08000000 86 87 #define NTLM_MBZ1 0x10000000 62 88 #define NTLM_ENC_128 0x20000000 63 89 #define NTLM_NEG_KEYEX 0x40000000 90 #define NTLM_ENC_56 0x80000000 64 91 65 92 /** … … 68 95 * heim_ntlm_free_targetinfo(). 69 96 */ 97 98 #define NTLM_TI_AV_FLAG_GUEST 0x00000001 99 70 100 struct ntlm_targetinfo { 71 101 char *servername; /**< */ … … 73 103 char *dnsdomainname; /**< */ 74 104 char *dnsservername; /**< */ 105 char *dnstreename; /**< */ 106 uint32_t avflags; /**< */ 75 107 }; 76 108 … … 98 130 char *targetname; /**< */ 99 131 struct ntlm_buf targetinfo; /**< */ 100 unsigned char chall ange[8]; /**< */132 unsigned char challenge[8]; /**< */ 101 133 uint32_t context[2]; /**< */ 102 134 uint32_t os[2]; /**< */ … … 120 152 }; 121 153 154 #include <ntlm_err.h> 122 155 #include <heimntlm-protos.h> 123 156 -
trunk/server/source4/heimdal/lib/ntlm/ntlm.c
r414 r745 3 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 4 * All rights reserved. 5 * 6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved. 5 7 * 6 8 * Redistribution and use in source and binary forms, with or without … … 42 44 #include <limits.h> 43 45 46 #include <roken.h> 47 #include <parse_units.h> 44 48 #include <krb5.h> 45 #include <roken.h>46 49 47 50 #define HC_DEPRECATED_CRYPTO … … 106 109 107 110 #define CHECK(f, e) \ 108 do { ret = f ; if (ret != (e)) { ret = EINVAL; goto out; } } while(0) 111 do { \ 112 ret = f ; if (ret != (e)) { ret = HNTLM_ERR_DECODE; goto out; } } \ 113 while(0) 114 115 static struct units ntlm_flag_units[] = { 116 #define ntlm_flag(x) { #x, NTLM_##x } 117 ntlm_flag(ENC_56), 118 ntlm_flag(NEG_KEYEX), 119 ntlm_flag(ENC_128), 120 ntlm_flag(MBZ1), 121 ntlm_flag(MBZ2), 122 ntlm_flag(MBZ3), 123 ntlm_flag(NEG_VERSION), 124 ntlm_flag(MBZ4), 125 ntlm_flag(NEG_TARGET_INFO), 126 ntlm_flag(NON_NT_SESSION_KEY), 127 ntlm_flag(MBZ5), 128 ntlm_flag(NEG_IDENTIFY), 129 ntlm_flag(NEG_NTLM2), 130 ntlm_flag(TARGET_SHARE), 131 ntlm_flag(TARGET_SERVER), 132 ntlm_flag(TARGET_DOMAIN), 133 ntlm_flag(NEG_ALWAYS_SIGN), 134 ntlm_flag(MBZ6), 135 ntlm_flag(OEM_SUPPLIED_WORKSTATION), 136 ntlm_flag(OEM_SUPPLIED_DOMAIN), 137 ntlm_flag(NEG_ANONYMOUS), 138 ntlm_flag(NEG_NT_ONLY), 139 ntlm_flag(NEG_NTLM), 140 ntlm_flag(MBZ8), 141 ntlm_flag(NEG_LM_KEY), 142 ntlm_flag(NEG_DATAGRAM), 143 ntlm_flag(NEG_SEAL), 144 ntlm_flag(NEG_SIGN), 145 ntlm_flag(MBZ9), 146 ntlm_flag(NEG_TARGET), 147 ntlm_flag(NEG_OEM), 148 ntlm_flag(NEG_UNICODE), 149 #undef ntlm_flag 150 {NULL, 0} 151 }; 152 153 size_t 154 heim_ntlm_unparse_flags(uint32_t flags, char *s, size_t len) 155 { 156 return unparse_flags(flags, ntlm_flag_units, s, len); 157 } 158 109 159 110 160 /** … … 198 248 } 199 249 250 /* 251 * 252 */ 253 200 254 static krb5_error_code 201 ret_string(krb5_storage *sp, int ucs2, s truct sec_buffer *desc, char **s)255 ret_string(krb5_storage *sp, int ucs2, size_t len, char **s) 202 256 { 203 257 krb5_error_code ret; 204 258 205 *s = malloc(desc->length + 1); 206 CHECK(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset); 207 CHECK(krb5_storage_read(sp, *s, desc->length), desc->length); 208 (*s)[desc->length] = '\0'; 259 *s = malloc(len + 1); 260 if (*s == NULL) 261 return ENOMEM; 262 CHECK(krb5_storage_read(sp, *s, len), len); 263 264 (*s)[len] = '\0'; 209 265 210 266 if (ucs2) { 211 267 size_t i; 212 for (i = 0; i < desc->length/ 2; i++) {268 for (i = 0; i < len / 2; i++) { 213 269 (*s)[i] = (*s)[i * 2]; 214 270 if ((*s)[i * 2 + 1]) { … … 221 277 } 222 278 ret = 0; 223 out: 224 return ret; 225 226 return 0; 279 out: 280 return ret; 281 } 282 283 284 285 static krb5_error_code 286 ret_sec_string(krb5_storage *sp, int ucs2, struct sec_buffer *desc, char **s) 287 { 288 krb5_error_code ret = 0; 289 CHECK(krb5_storage_seek(sp, desc->offset, SEEK_SET), desc->offset); 290 CHECK(ret_string(sp, ucs2, desc->length, s), 0); 291 out: 292 return ret; 227 293 } 228 294 … … 293 359 free(ti->dnsdomainname); 294 360 free(ti->dnsservername); 361 free(ti->dnstreename); 295 362 memset(ti, 0, sizeof(*ti)); 296 363 } 297 364 298 365 static int 299 encode_ti_ blob(krb5_storage *out, uint16_t type, int ucs2, char *s)366 encode_ti_string(krb5_storage *out, uint16_t type, int ucs2, char *s) 300 367 { 301 368 krb5_error_code ret; … … 311 378 * 312 379 * @param ti the ntlm_targetinfo message to encode. 313 * @param ucs2 i f the strings should be encoded with ucs2 (selected by flag in message).380 * @param ucs2 ignored 314 381 * @param data is the return buffer with the encoded message, should be 315 382 * freed with heim_ntlm_free_buf(). … … 336 403 return ENOMEM; 337 404 405 krb5_storage_set_byteorder(out, KRB5_STORAGE_BYTEORDER_LE); 406 338 407 if (ti->servername) 339 CHECK(encode_ti_ blob(out, 1, ucs2, ti->servername), 0);408 CHECK(encode_ti_string(out, 1, ucs2, ti->servername), 0); 340 409 if (ti->domainname) 341 CHECK(encode_ti_ blob(out, 2, ucs2, ti->domainname), 0);410 CHECK(encode_ti_string(out, 2, ucs2, ti->domainname), 0); 342 411 if (ti->dnsservername) 343 CHECK(encode_ti_ blob(out, 3, ucs2, ti->dnsservername), 0);412 CHECK(encode_ti_string(out, 3, ucs2, ti->dnsservername), 0); 344 413 if (ti->dnsdomainname) 345 CHECK(encode_ti_blob(out, 4, ucs2, ti->dnsdomainname), 0); 414 CHECK(encode_ti_string(out, 4, ucs2, ti->dnsdomainname), 0); 415 if (ti->dnstreename) 416 CHECK(encode_ti_string(out, 5, ucs2, ti->dnstreename), 0); 417 if (ti->avflags) { 418 CHECK(krb5_store_uint16(out, 6), 0); 419 CHECK(krb5_store_uint16(out, 4), 0); 420 CHECK(krb5_store_uint32(out, ti->avflags), 0); 421 } 346 422 347 423 /* end tag */ … … 378 454 struct ntlm_targetinfo *ti) 379 455 { 456 uint16_t type, len; 457 krb5_storage *in; 458 int ret = 0, done = 0; 459 380 460 memset(ti, 0, sizeof(*ti)); 381 return 0; 461 462 if (data->length == 0) 463 return 0; 464 465 in = krb5_storage_from_readonly_mem(data->data, data->length); 466 if (in == NULL) 467 return ENOMEM; 468 krb5_storage_set_byteorder(in, KRB5_STORAGE_BYTEORDER_LE); 469 470 while (!done) { 471 CHECK(krb5_ret_uint16(in, &type), 0); 472 CHECK(krb5_ret_uint16(in, &len), 0); 473 474 switch (type) { 475 case 0: 476 done = 1; 477 break; 478 case 1: 479 CHECK(ret_string(in, ucs2, len, &ti->servername), 0); 480 break; 481 case 2: 482 CHECK(ret_string(in, ucs2, len, &ti->domainname), 0); 483 break; 484 case 3: 485 CHECK(ret_string(in, ucs2, len, &ti->dnsservername), 0); 486 break; 487 case 4: 488 CHECK(ret_string(in, ucs2, len, &ti->dnsdomainname), 0); 489 break; 490 case 5: 491 CHECK(ret_string(in, ucs2, len, &ti->dnstreename), 0); 492 break; 493 case 6: 494 CHECK(krb5_ret_uint32(in, &ti->avflags), 0); 495 break; 496 default: 497 krb5_storage_seek(in, len, SEEK_CUR); 498 break; 499 } 500 } 501 out: 502 if (in) 503 krb5_storage_free(in); 504 return ret; 382 505 } 383 506 … … 413 536 in = krb5_storage_from_readonly_mem(buf->data, buf->length); 414 537 if (in == NULL) { 415 ret = E INVAL;538 ret = ENOMEM; 416 539 goto out; 417 540 } … … 423 546 CHECK(type, 1); 424 547 CHECK(krb5_ret_uint32(in, &data->flags), 0); 425 if (data->flags & NTLM_ SUPPLIED_DOMAIN)548 if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN) 426 549 CHECK(ret_sec_buffer(in, &domain), 0); 427 if (data->flags & NTLM_ SUPPLIED_WORKSTAION)550 if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION) 428 551 CHECK(ret_sec_buffer(in, &hostname), 0); 429 552 #if 0 … … 433 556 } 434 557 #endif 435 if (data->flags & NTLM_ SUPPLIED_DOMAIN)436 CHECK(ret_s tring(in, 0, &domain, &data->domain), 0);437 if (data->flags & NTLM_ SUPPLIED_WORKSTAION)438 CHECK(ret_s tring(in, 0, &hostname, &data->hostname), 0);558 if (data->flags & NTLM_OEM_SUPPLIED_DOMAIN) 559 CHECK(ret_sec_string(in, 0, &domain, &data->domain), 0); 560 if (data->flags & NTLM_OEM_SUPPLIED_WORKSTATION) 561 CHECK(ret_sec_string(in, 0, &hostname, &data->hostname), 0); 439 562 440 563 out: … … 473 596 if (type1->domain) { 474 597 base += 8; 475 flags |= NTLM_ SUPPLIED_DOMAIN;598 flags |= NTLM_OEM_SUPPLIED_DOMAIN; 476 599 } 477 600 if (type1->hostname) { 478 601 base += 8; 479 flags |= NTLM_ SUPPLIED_WORKSTAION;602 flags |= NTLM_OEM_SUPPLIED_WORKSTATION; 480 603 } 481 604 if (type1->os[0]) 482 605 base += 8; 483 606 607 domain.offset = base; 484 608 if (type1->domain) { 485 domain.offset = base;486 609 domain.length = len_string(0, type1->domain); 487 610 domain.allocated = domain.length; 488 } 611 } else { 612 domain.length = 0; 613 domain.allocated = 0; 614 } 615 616 hostname.offset = domain.allocated + domain.offset; 489 617 if (type1->hostname) { 490 hostname.offset = domain.allocated + domain.offset;491 618 hostname.length = len_string(0, type1->hostname); 492 619 hostname.allocated = hostname.length; 620 } else { 621 hostname.length = 0; 622 hostname.allocated = 0; 493 623 } 494 624 … … 503 633 CHECK(krb5_store_uint32(out, flags), 0); 504 634 505 if (type1->domain) 506 CHECK(store_sec_buffer(out, &domain), 0); 507 if (type1->hostname) 508 CHECK(store_sec_buffer(out, &hostname), 0); 509 if (type1->os[0]) { 635 CHECK(store_sec_buffer(out, &domain), 0); 636 CHECK(store_sec_buffer(out, &hostname), 0); 637 #if 0 510 638 CHECK(krb5_store_uint32(out, type1->os[0]), 0); 511 639 CHECK(krb5_store_uint32(out, type1->os[1]), 0); 512 } 640 #endif 513 641 if (type1->domain) 514 642 CHECK(put_string(out, 0, type1->domain), 0); … … 559 687 in = krb5_storage_from_readonly_mem(buf->data, buf->length); 560 688 if (in == NULL) { 561 ret = E INVAL;689 ret = ENOMEM; 562 690 goto out; 563 691 } … … 573 701 if (type2->flags & NTLM_NEG_UNICODE) 574 702 ucs2 = 1; 575 CHECK(krb5_storage_read(in, type2->chall ange, sizeof(type2->challange)),576 sizeof(type2->chall ange));703 CHECK(krb5_storage_read(in, type2->challenge, sizeof(type2->challenge)), 704 sizeof(type2->challenge)); 577 705 CHECK(krb5_ret_uint32(in, &ctx[0]), 0); /* context */ 578 706 CHECK(krb5_ret_uint32(in, &ctx[1]), 0); 579 707 CHECK(ret_sec_buffer(in, &targetinfo), 0); 580 708 /* os version */ 581 #if 0 582 583 584 #endif 585 586 CHECK(ret_s tring(in, ucs2, &targetname, &type2->targetname), 0);709 if (type2->flags & NTLM_NEG_VERSION) { 710 CHECK(krb5_ret_uint32(in, &type2->os[0]), 0); 711 CHECK(krb5_ret_uint32(in, &type2->os[1]), 0); 712 } 713 714 CHECK(ret_sec_string(in, ucs2, &targetname, &type2->targetname), 0); 587 715 CHECK(ret_buf(in, &targetinfo, &type2->targetinfo), 0); 588 716 ret = 0; … … 619 747 int ucs2 = 0; 620 748 621 if (type2->os[0])622 base = 56; 623 else624 base = 48;749 base = 48; 750 751 if (type2->flags & NTLM_NEG_VERSION) 752 base += 8; 625 753 626 754 if (type2->flags & NTLM_NEG_UNICODE) … … 645 773 CHECK(store_sec_buffer(out, &targetname), 0); 646 774 CHECK(krb5_store_uint32(out, type2->flags), 0); 647 CHECK(krb5_storage_write(out, type2->chall ange, sizeof(type2->challange)),648 sizeof(type2->chall ange));775 CHECK(krb5_storage_write(out, type2->challenge, sizeof(type2->challenge)), 776 sizeof(type2->challenge)); 649 777 CHECK(krb5_store_uint32(out, 0), 0); /* context */ 650 778 CHECK(krb5_store_uint32(out, 0), 0); 651 779 CHECK(store_sec_buffer(out, &targetinfo), 0); 652 780 /* os version */ 653 if (type2-> os[0]) {781 if (type2->flags & NTLM_NEG_VERSION) { 654 782 CHECK(krb5_store_uint32(out, type2->os[0]), 0); 655 783 CHECK(krb5_store_uint32(out, type2->os[1]), 0); … … 710 838 krb5_storage *in; 711 839 struct sec_buffer lm, ntlm, target, username, sessionkey, ws; 840 uint32_t min_offset = 72; 712 841 713 842 memset(type3, 0, sizeof(*type3)); … … 716 845 in = krb5_storage_from_readonly_mem(buf->data, buf->length); 717 846 if (in == NULL) { 718 ret = E INVAL;847 ret = ENOMEM; 719 848 goto out; 720 849 } … … 726 855 CHECK(type, 3); 727 856 CHECK(ret_sec_buffer(in, &lm), 0); 857 if (lm.allocated) 858 min_offset = min(min_offset, lm.offset); 728 859 CHECK(ret_sec_buffer(in, &ntlm), 0); 860 if (ntlm.allocated) 861 min_offset = min(min_offset, ntlm.offset); 729 862 CHECK(ret_sec_buffer(in, &target), 0); 863 if (target.allocated) 864 min_offset = min(min_offset, target.offset); 730 865 CHECK(ret_sec_buffer(in, &username), 0); 866 if (username.allocated) 867 min_offset = min(min_offset, username.offset); 731 868 CHECK(ret_sec_buffer(in, &ws), 0); 732 if (lm.offset >= 60) { 869 if (ws.allocated) 870 min_offset = min(min_offset, ws.offset); 871 872 if (min_offset > 52) { 733 873 CHECK(ret_sec_buffer(in, &sessionkey), 0); 734 } 735 if (lm.offset >= 64) { 874 min_offset = max(min_offset, sessionkey.offset); 736 875 CHECK(krb5_ret_uint32(in, &type3->flags), 0); 737 876 } 738 if ( lm.offset >= 72) {877 if (min_offset > 52 + 8 + 4 + 8) { 739 878 CHECK(krb5_ret_uint32(in, &type3->os[0]), 0); 740 879 CHECK(krb5_ret_uint32(in, &type3->os[1]), 0); … … 742 881 CHECK(ret_buf(in, &lm, &type3->lm), 0); 743 882 CHECK(ret_buf(in, &ntlm, &type3->ntlm), 0); 744 CHECK(ret_s tring(in, ucs2, &target, &type3->targetname), 0);745 CHECK(ret_s tring(in, ucs2, &username, &type3->username), 0);746 CHECK(ret_s tring(in, ucs2, &ws, &type3->ws), 0);883 CHECK(ret_sec_string(in, ucs2, &target, &type3->targetname), 0); 884 CHECK(ret_sec_string(in, ucs2, &username, &type3->username), 0); 885 CHECK(ret_sec_string(in, ucs2, &ws, &type3->ws), 0); 747 886 if (sessionkey.offset) 748 887 CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0); … … 787 926 788 927 base = 52; 789 if (type3->sessionkey.length) { 790 791 792 } 928 929 base += 8; /* sessionkey sec buf */ 930 base += 4; /* flags */ 931 793 932 if (type3->os[0]) { 794 933 base += 8; … … 798 937 ucs2 = 1; 799 938 800 lm.offset = base; 939 target.offset = base; 940 target.length = len_string(ucs2, type3->targetname); 941 target.allocated = target.length; 942 943 username.offset = target.offset + target.allocated; 944 username.length = len_string(ucs2, type3->username); 945 username.allocated = username.length; 946 947 ws.offset = username.offset + username.allocated; 948 ws.length = len_string(ucs2, type3->ws); 949 ws.allocated = ws.length; 950 951 lm.offset = ws.offset + ws.allocated; 801 952 lm.length = type3->lm.length; 802 953 lm.allocated = type3->lm.length; … … 806 957 ntlm.allocated = ntlm.length; 807 958 808 target.offset = ntlm.offset + ntlm.allocated; 809 target.length = len_string(ucs2, type3->targetname); 810 target.allocated = target.length; 811 812 username.offset = target.offset + target.allocated; 813 username.length = len_string(ucs2, type3->username); 814 username.allocated = username.length; 815 816 ws.offset = username.offset + username.allocated; 817 ws.length = len_string(ucs2, type3->ws); 818 ws.allocated = ws.length; 819 820 sessionkey.offset = ws.offset + ws.allocated; 959 sessionkey.offset = ntlm.offset + ntlm.allocated; 821 960 sessionkey.length = type3->sessionkey.length; 822 961 sessionkey.allocated = type3->sessionkey.length; … … 836 975 CHECK(store_sec_buffer(out, &username), 0); 837 976 CHECK(store_sec_buffer(out, &ws), 0); 838 /* optional */ 839 if (type3->sessionkey.length) { 840 CHECK(store_sec_buffer(out, &sessionkey), 0); 841 CHECK(krb5_store_uint32(out, type3->flags), 0); 842 } 977 CHECK(store_sec_buffer(out, &sessionkey), 0); 978 CHECK(krb5_store_uint32(out, type3->flags), 0); 979 843 980 #if 0 844 981 CHECK(krb5_store_uint32(out, 0), 0); /* os0 */ … … 846 983 #endif 847 984 848 CHECK(put_buf(out, &type3->lm), 0);849 CHECK(put_buf(out, &type3->ntlm), 0);850 985 CHECK(put_string(out, ucs2, type3->targetname), 0); 851 986 CHECK(put_string(out, ucs2, type3->username), 0); 852 987 CHECK(put_string(out, ucs2, type3->ws), 0); 988 CHECK(put_buf(out, &type3->lm), 0); 989 CHECK(put_buf(out, &type3->ntlm), 0); 853 990 CHECK(put_buf(out, &type3->sessionkey), 0); 854 991 … … 873 1010 static void 874 1011 splitandenc(unsigned char *hash, 875 unsigned char *chall ange,1012 unsigned char *challenge, 876 1013 unsigned char *answer) 877 1014 { 878 DES_cblock key; 879 DES_key_schedule sched; 880 881 ((unsigned char*)key)[0] = hash[0]; 882 ((unsigned char*)key)[1] = (hash[0] << 7) | (hash[1] >> 1); 883 ((unsigned char*)key)[2] = (hash[1] << 6) | (hash[2] >> 2); 884 ((unsigned char*)key)[3] = (hash[2] << 5) | (hash[3] >> 3); 885 ((unsigned char*)key)[4] = (hash[3] << 4) | (hash[4] >> 4); 886 ((unsigned char*)key)[5] = (hash[4] << 3) | (hash[5] >> 5); 887 ((unsigned char*)key)[6] = (hash[5] << 2) | (hash[6] >> 6); 888 ((unsigned char*)key)[7] = (hash[6] << 1); 889 890 DES_set_odd_parity(&key); 891 DES_set_key_unchecked(&key, &sched); 892 DES_ecb_encrypt((DES_cblock *)challange, (DES_cblock *)answer, &sched, 1); 893 memset(&sched, 0, sizeof(sched)); 1015 EVP_CIPHER_CTX ctx; 1016 unsigned char key[8]; 1017 1018 key[0] = hash[0]; 1019 key[1] = (hash[0] << 7) | (hash[1] >> 1); 1020 key[2] = (hash[1] << 6) | (hash[2] >> 2); 1021 key[3] = (hash[2] << 5) | (hash[3] >> 3); 1022 key[4] = (hash[3] << 4) | (hash[4] >> 4); 1023 key[5] = (hash[4] << 3) | (hash[5] >> 5); 1024 key[6] = (hash[5] << 2) | (hash[6] >> 6); 1025 key[7] = (hash[6] << 1); 1026 1027 EVP_CIPHER_CTX_init(&ctx); 1028 1029 EVP_CipherInit_ex(&ctx, EVP_des_cbc(), NULL, key, NULL, 1); 1030 EVP_Cipher(&ctx, answer, challenge, 8); 1031 EVP_CIPHER_CTX_cleanup(&ctx); 894 1032 memset(key, 0, sizeof(key)); 895 1033 } … … 911 1049 { 912 1050 struct ntlm_buf buf; 913 MD4_CTX ctx;1051 EVP_MD_CTX *m; 914 1052 int ret; 915 1053 … … 924 1062 return ret; 925 1063 } 926 MD4_Init(&ctx); 927 MD4_Update(&ctx, buf.data, buf.length); 928 MD4_Final(key->data, &ctx); 1064 1065 m = EVP_MD_CTX_create(); 1066 if (m == NULL) { 1067 heim_ntlm_free_buf(key); 1068 heim_ntlm_free_buf(&buf); 1069 return ENOMEM; 1070 } 1071 1072 EVP_DigestInit_ex(m, EVP_md4(), NULL); 1073 EVP_DigestUpdate(m, buf.data, buf.length); 1074 EVP_DigestFinal_ex(m, key->data, NULL); 1075 EVP_MD_CTX_destroy(m); 1076 929 1077 heim_ntlm_free_buf(&buf); 930 1078 return 0; … … 936 1084 * @param key the ntlm v1 key 937 1085 * @param len length of key 938 * @param chall ange sent by the server1086 * @param challenge sent by the server 939 1087 * @param answer calculated answer, should be freed with heim_ntlm_free_buf(). 940 1088 * … … 947 1095 int 948 1096 heim_ntlm_calculate_ntlm1(void *key, size_t len, 949 unsigned char chall ange[8],1097 unsigned char challenge[8], 950 1098 struct ntlm_buf *answer) 951 1099 { … … 953 1101 954 1102 if (len != MD4_DIGEST_LENGTH) 955 return EINVAL;1103 return HNTLM_ERR_INVALID_LENGTH; 956 1104 957 1105 memcpy(res, key, len); … … 963 1111 answer->length = 24; 964 1112 965 splitandenc(&res[0], chall ange, ((unsigned char *)answer->data) + 0);966 splitandenc(&res[7], chall ange, ((unsigned char *)answer->data) + 8);967 splitandenc(&res[14], chall ange, ((unsigned char *)answer->data) + 16);1113 splitandenc(&res[0], challenge, ((unsigned char *)answer->data) + 0); 1114 splitandenc(&res[7], challenge, ((unsigned char *)answer->data) + 8); 1115 splitandenc(&res[14], challenge, ((unsigned char *)answer->data) + 16); 968 1116 969 1117 return 0; 970 1118 } 1119 1120 int 1121 heim_ntlm_v1_base_session(void *key, size_t len, 1122 struct ntlm_buf *session) 1123 { 1124 EVP_MD_CTX *m; 1125 1126 session->length = MD4_DIGEST_LENGTH; 1127 session->data = malloc(session->length); 1128 if (session->data == NULL) { 1129 session->length = 0; 1130 return ENOMEM; 1131 } 1132 1133 m = EVP_MD_CTX_create(); 1134 if (m == NULL) { 1135 heim_ntlm_free_buf(session); 1136 return ENOMEM; 1137 } 1138 EVP_DigestInit_ex(m, EVP_md4(), NULL); 1139 EVP_DigestUpdate(m, key, len); 1140 EVP_DigestFinal_ex(m, session->data, NULL); 1141 EVP_MD_CTX_destroy(m); 1142 1143 return 0; 1144 } 1145 1146 int 1147 heim_ntlm_v2_base_session(void *key, size_t len, 1148 struct ntlm_buf *ntlmResponse, 1149 struct ntlm_buf *session) 1150 { 1151 unsigned int hmaclen; 1152 HMAC_CTX c; 1153 1154 if (ntlmResponse->length <= 16) 1155 return HNTLM_ERR_INVALID_LENGTH; 1156 1157 session->data = malloc(16); 1158 if (session->data == NULL) 1159 return ENOMEM; 1160 session->length = 16; 1161 1162 /* Note: key is the NTLMv2 key */ 1163 HMAC_CTX_init(&c); 1164 HMAC_Init_ex(&c, key, len, EVP_md5(), NULL); 1165 HMAC_Update(&c, ntlmResponse->data, 16); 1166 HMAC_Final(&c, session->data, &hmaclen); 1167 HMAC_CTX_cleanup(&c); 1168 1169 return 0; 1170 } 1171 1172 1173 int 1174 heim_ntlm_keyex_wrap(struct ntlm_buf *base_session, 1175 struct ntlm_buf *session, 1176 struct ntlm_buf *encryptedSession) 1177 { 1178 EVP_CIPHER_CTX c; 1179 int ret; 1180 1181 session->length = MD4_DIGEST_LENGTH; 1182 session->data = malloc(session->length); 1183 if (session->data == NULL) { 1184 session->length = 0; 1185 return ENOMEM; 1186 } 1187 encryptedSession->length = MD4_DIGEST_LENGTH; 1188 encryptedSession->data = malloc(encryptedSession->length); 1189 if (encryptedSession->data == NULL) { 1190 heim_ntlm_free_buf(session); 1191 encryptedSession->length = 0; 1192 return ENOMEM; 1193 } 1194 1195 EVP_CIPHER_CTX_init(&c); 1196 1197 ret = EVP_CipherInit_ex(&c, EVP_rc4(), NULL, base_session->data, NULL, 1); 1198 if (ret != 1) { 1199 EVP_CIPHER_CTX_cleanup(&c); 1200 heim_ntlm_free_buf(encryptedSession); 1201 heim_ntlm_free_buf(session); 1202 return HNTLM_ERR_CRYPTO; 1203 } 1204 1205 if (RAND_bytes(session->data, session->length) != 1) { 1206 EVP_CIPHER_CTX_cleanup(&c); 1207 heim_ntlm_free_buf(encryptedSession); 1208 heim_ntlm_free_buf(session); 1209 return HNTLM_ERR_RAND; 1210 } 1211 1212 EVP_Cipher(&c, encryptedSession->data, session->data, encryptedSession->length); 1213 EVP_CIPHER_CTX_cleanup(&c); 1214 1215 return 0; 1216 1217 1218 1219 } 1220 1221 971 1222 972 1223 /** … … 989 1240 struct ntlm_buf *master) 990 1241 { 991 RC4_KEY rc4; 992 993 memset(master, 0, sizeof(*master)); 1242 struct ntlm_buf sess; 1243 int ret; 1244 1245 ret = heim_ntlm_v1_base_session(key, len, &sess); 1246 if (ret) 1247 return ret; 1248 1249 ret = heim_ntlm_keyex_wrap(&sess, session, master); 1250 heim_ntlm_free_buf(&sess); 1251 1252 return ret; 1253 } 1254 1255 /** 1256 * Generates an NTLMv2 session random with associated session master key. 1257 * 1258 * @param key the NTLMv2 key 1259 * @param len length of key 1260 * @param blob the NTLMv2 "blob" 1261 * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). 1262 * @param master calculated session master key, should be freed with heim_ntlm_free_buf(). 1263 * 1264 * @return In case of success 0 is return, an errors, a errno in what 1265 * went wrong. 1266 * 1267 * @ingroup ntlm_core 1268 */ 1269 1270 1271 int 1272 heim_ntlm_build_ntlm2_master(void *key, size_t len, 1273 struct ntlm_buf *blob, 1274 struct ntlm_buf *session, 1275 struct ntlm_buf *master) 1276 { 1277 struct ntlm_buf sess; 1278 int ret; 1279 1280 ret = heim_ntlm_v2_base_session(key, len, blob, &sess); 1281 if (ret) 1282 return ret; 1283 1284 ret = heim_ntlm_keyex_wrap(&sess, session, master); 1285 heim_ntlm_free_buf(&sess); 1286 1287 return ret; 1288 } 1289 1290 /** 1291 * Given a key and encrypted session, unwrap the session key 1292 * 1293 * @param baseKey the sessionBaseKey 1294 * @param encryptedSession encrypted session, type3.session field. 1295 * @param session generated session nonce, should be freed with heim_ntlm_free_buf(). 1296 * 1297 * @return In case of success 0 is return, an errors, a errno in what 1298 * went wrong. 1299 * 1300 * @ingroup ntlm_core 1301 */ 1302 1303 int 1304 heim_ntlm_keyex_unwrap(struct ntlm_buf *baseKey, 1305 struct ntlm_buf *encryptedSession, 1306 struct ntlm_buf *session) 1307 { 1308 EVP_CIPHER_CTX c; 1309 994 1310 memset(session, 0, sizeof(*session)); 995 1311 996 if ( len!= MD4_DIGEST_LENGTH)997 return EINVAL;1312 if (baseKey->length != MD4_DIGEST_LENGTH) 1313 return HNTLM_ERR_INVALID_LENGTH; 998 1314 999 1315 session->length = MD4_DIGEST_LENGTH; … … 1001 1317 if (session->data == NULL) { 1002 1318 session->length = 0; 1003 return E INVAL;1004 } 1005 master->length = MD4_DIGEST_LENGTH;1006 master->data = malloc(master->length); 1007 if ( master->data == NULL) {1008 heim_ntlm_free_buf(master);1319 return ENOMEM; 1320 } 1321 EVP_CIPHER_CTX_init(&c); 1322 1323 if (EVP_CipherInit_ex(&c, EVP_rc4(), NULL, baseKey->data, NULL, 0) != 1) { 1324 EVP_CIPHER_CTX_cleanup(&c); 1009 1325 heim_ntlm_free_buf(session); 1010 return EINVAL; 1011 } 1012 1013 { 1014 unsigned char sessionkey[MD4_DIGEST_LENGTH]; 1015 MD4_CTX ctx; 1016 1017 MD4_Init(&ctx); 1018 MD4_Update(&ctx, key, len); 1019 MD4_Final(sessionkey, &ctx); 1020 1021 RC4_set_key(&rc4, sizeof(sessionkey), sessionkey); 1022 } 1023 1024 if (RAND_bytes(session->data, session->length) != 1) { 1025 heim_ntlm_free_buf(master); 1026 heim_ntlm_free_buf(session); 1027 return EINVAL; 1028 } 1029 1030 RC4(&rc4, master->length, session->data, master->data); 1031 memset(&rc4, 0, sizeof(rc4)); 1326 return HNTLM_ERR_CRYPTO; 1327 } 1328 1329 EVP_Cipher(&c, session->data, encryptedSession->data, session->length); 1330 EVP_CIPHER_CTX_cleanup(&c); 1032 1331 1033 1332 return 0; 1034 1333 } 1334 1035 1335 1036 1336 /** … … 1105 1405 } 1106 1406 1107 1108 /** 1109 * Calculate NTLMv2 response 1407 /** 1408 * Calculate LMv2 response 1110 1409 * 1111 1410 * @param key the ntlm key … … 1113 1412 * @param username name of the user, as sent in the message, assumed to be in UTF8. 1114 1413 * @param target the name of the target, assumed to be in UTF8. 1115 * @param serverchallange challange as sent by the server in the type2 message. 1414 * @param serverchallenge challenge as sent by the server in the type2 message. 1415 * @param ntlmv2 calculated session key 1416 * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). 1417 * 1418 * @return In case of success 0 is return, an errors, a errno in what 1419 * went wrong. 1420 * 1421 * @ingroup ntlm_core 1422 */ 1423 1424 int 1425 heim_ntlm_calculate_lm2(const void *key, size_t len, 1426 const char *username, 1427 const char *target, 1428 const unsigned char serverchallenge[8], 1429 unsigned char ntlmv2[16], 1430 struct ntlm_buf *answer) 1431 { 1432 unsigned char clientchallenge[8]; 1433 1434 if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) 1435 return HNTLM_ERR_RAND; 1436 1437 /* calculate ntlmv2 key */ 1438 1439 heim_ntlm_ntlmv2_key(key, len, username, target, ntlmv2); 1440 1441 answer->data = malloc(24); 1442 if (answer->data == NULL) 1443 return ENOMEM; 1444 answer->length = 24; 1445 1446 heim_ntlm_derive_ntlm2_sess(ntlmv2, clientchallenge, 8, 1447 serverchallenge, answer->data); 1448 1449 memcpy(((uint8_t *)answer->data) + 16, clientchallenge, 8); 1450 1451 return 0; 1452 } 1453 1454 1455 /** 1456 * Calculate NTLMv2 response 1457 * 1458 * @param key the ntlm key 1459 * @param len length of key 1460 * @param username name of the user, as sent in the message, assumed to be in UTF8. 1461 * @param target the name of the target, assumed to be in UTF8. 1462 * @param serverchallenge challenge as sent by the server in the type2 message. 1116 1463 * @param infotarget infotarget as sent by the server in the type2 message. 1117 1464 * @param ntlmv2 calculated session key … … 1128 1475 const char *username, 1129 1476 const char *target, 1130 const unsigned char serverchall ange[8],1477 const unsigned char serverchallenge[8], 1131 1478 const struct ntlm_buf *infotarget, 1132 1479 unsigned char ntlmv2[16], … … 1135 1482 krb5_error_code ret; 1136 1483 krb5_data data; 1137 unsigned int hmaclen;1138 1484 unsigned char ntlmv2answer[16]; 1139 1485 krb5_storage *sp; 1140 unsigned char clientchallange[8]; 1141 HMAC_CTX c; 1486 unsigned char clientchallenge[8]; 1142 1487 uint64_t t; 1143 1488 1144 1489 t = unix2nttime(time(NULL)); 1145 1490 1146 if (RAND_bytes(clientchall ange, sizeof(clientchallange)) != 1)1147 return EINVAL;1491 if (RAND_bytes(clientchallenge, sizeof(clientchallenge)) != 1) 1492 return HNTLM_ERR_RAND; 1148 1493 1149 1494 /* calculate ntlmv2 key */ … … 1164 1509 CHECK(krb5_store_uint32(sp, t >> 32), 0); 1165 1510 1166 CHECK(krb5_storage_write(sp, clientchall ange, 8), 8);1511 CHECK(krb5_storage_write(sp, clientchallenge, 8), 8); 1167 1512 1168 1513 CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */ … … 1175 1520 sp = NULL; 1176 1521 1177 HMAC_CTX_init(&c); 1178 HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL); 1179 HMAC_Update(&c, serverchallange, 8); 1180 HMAC_Update(&c, data.data, data.length); 1181 HMAC_Final(&c, ntlmv2answer, &hmaclen); 1182 HMAC_CTX_cleanup(&c); 1522 heim_ntlm_derive_ntlm2_sess(ntlmv2, data.data, data.length, serverchallenge, ntlmv2answer); 1183 1523 1184 1524 sp = krb5_storage_emem(); … … 1216 1556 * @param target the name of the target, assumed to be in UTF8. 1217 1557 * @param now the time now (0 if the library should pick it up itself) 1218 * @param serverchall ange challange as sent by the server in the type2 message.1558 * @param serverchallenge challenge as sent by the server in the type2 message. 1219 1559 * @param answer ntlm response answer, should be freed with heim_ntlm_free_buf(). 1220 1560 * @param infotarget infotarget as sent by the server in the type2 message. … … 1232 1572 const char *target, 1233 1573 time_t now, 1234 const unsigned char serverchall ange[8],1574 const unsigned char serverchallenge[8], 1235 1575 const struct ntlm_buf *answer, 1236 1576 struct ntlm_buf *infotarget, … … 1238 1578 { 1239 1579 krb5_error_code ret; 1240 unsigned int hmaclen;1241 1580 unsigned char clientanswer[16]; 1242 1581 unsigned char clientnonce[8]; 1243 1582 unsigned char serveranswer[16]; 1244 1583 krb5_storage *sp; 1245 HMAC_CTX c;1246 uint64_t t;1247 1584 time_t authtime; 1248 1585 uint32_t temp; 1586 uint64_t t; 1249 1587 1250 1588 infotarget->length = 0; … … 1252 1590 1253 1591 if (answer->length < 16) 1254 return EINVAL;1592 return HNTLM_ERR_INVALID_LENGTH; 1255 1593 1256 1594 if (now == 0) … … 1283 1621 1284 1622 if (abs((int)(authtime - now)) > authtimediff) { 1285 ret = EINVAL;1623 ret = HNTLM_ERR_TIME_SKEW; 1286 1624 goto out; 1287 1625 } 1288 1626 1289 /* client chall ange */1627 /* client challenge */ 1290 1628 CHECK(krb5_storage_read(sp, clientnonce, 8), 8); 1291 1629 … … 1305 1643 sp = NULL; 1306 1644 1307 HMAC_CTX_init(&c); 1308 HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL); 1309 HMAC_Update(&c, serverchallange, 8); 1310 HMAC_Update(&c, ((unsigned char *)answer->data) + 16, answer->length - 16); 1311 HMAC_Final(&c, serveranswer, &hmaclen); 1312 HMAC_CTX_cleanup(&c); 1645 if (answer->length < 16) { 1646 ret = HNTLM_ERR_INVALID_LENGTH; 1647 goto out; 1648 } 1649 1650 heim_ntlm_derive_ntlm2_sess(ntlmv2, 1651 ((unsigned char *)answer->data) + 16, answer->length - 16, 1652 serverchallenge, 1653 serveranswer); 1313 1654 1314 1655 if (memcmp(serveranswer, clientanswer, 16) != 0) { 1315 1656 heim_ntlm_free_buf(infotarget); 1316 return EINVAL;1657 return HNTLM_ERR_AUTH; 1317 1658 } 1318 1659 … … 1348 1689 struct ntlm_buf *ntlm) 1349 1690 { 1350 unsigned char ntlm2_sess_hash[ MD5_DIGEST_LENGTH];1691 unsigned char ntlm2_sess_hash[8]; 1351 1692 unsigned char res[21], *resp; 1352 MD5_CTX md5; 1693 int code; 1694 1695 code = heim_ntlm_calculate_ntlm2_sess_hash(clnt_nonce, svr_chal, 1696 ntlm2_sess_hash); 1697 if (code) { 1698 return code; 1699 } 1353 1700 1354 1701 lm->data = malloc(24); 1355 if (lm->data == NULL) 1356 return ENOMEM; 1702 if (lm->data == NULL) { 1703 return ENOMEM; 1704 } 1357 1705 lm->length = 24; 1358 1706 … … 1369 1717 memcpy(lm->data, clnt_nonce, 8); 1370 1718 1371 MD5_Init(&md5);1372 MD5_Update(&md5, svr_chal, 8); /* session nonce part 1 */1373 MD5_Update(&md5, clnt_nonce, 8); /* session nonce part 2 */1374 MD5_Final(ntlm2_sess_hash, &md5); /* will only use first 8 bytes */1375 1376 1719 memset(res, 0, sizeof(res)); 1377 1720 memcpy(res, ntlm_hash, 16); … … 1384 1727 return 0; 1385 1728 } 1729 1730 1731 /* 1732 * Calculate the NTLM2 Session "Verifier" 1733 * 1734 * @param clnt_nonce client nonce 1735 * @param svr_chal server challage 1736 * @param hash The NTLM session verifier 1737 * 1738 * @return In case of success 0 is return, an errors, a errno in what 1739 * went wrong. 1740 * 1741 * @ingroup ntlm_core 1742 */ 1743 1744 int 1745 heim_ntlm_calculate_ntlm2_sess_hash(const unsigned char clnt_nonce[8], 1746 const unsigned char svr_chal[8], 1747 unsigned char verifier[8]) 1748 { 1749 unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH]; 1750 EVP_MD_CTX *m; 1751 1752 m = EVP_MD_CTX_create(); 1753 if (m == NULL) 1754 return ENOMEM; 1755 1756 EVP_DigestInit_ex(m, EVP_md5(), NULL); 1757 EVP_DigestUpdate(m, svr_chal, 8); /* session nonce part 1 */ 1758 EVP_DigestUpdate(m, clnt_nonce, 8); /* session nonce part 2 */ 1759 EVP_DigestFinal_ex(m, ntlm2_sess_hash, NULL); /* will only use first 8 bytes */ 1760 EVP_MD_CTX_destroy(m); 1761 1762 memcpy(verifier, ntlm2_sess_hash, 8); 1763 1764 return 0; 1765 } 1766 1767 1768 /* 1769 * Derive a NTLM2 session key 1770 * 1771 * @param sessionkey session key from domain controller 1772 * @param clnt_nonce client nonce 1773 * @param svr_chal server challenge 1774 * @param derivedkey salted session key 1775 * 1776 * @return In case of success 0 is return, an errors, a errno in what 1777 * went wrong. 1778 * 1779 * @ingroup ntlm_core 1780 */ 1781 1782 void 1783 heim_ntlm_derive_ntlm2_sess(const unsigned char sessionkey[16], 1784 const unsigned char *clnt_nonce, size_t clnt_nonce_length, 1785 const unsigned char svr_chal[8], 1786 unsigned char derivedkey[16]) 1787 { 1788 unsigned int hmaclen; 1789 HMAC_CTX c; 1790 1791 /* HMAC(Ksession, serverchallenge || clientchallenge) */ 1792 HMAC_CTX_init(&c); 1793 HMAC_Init_ex(&c, sessionkey, 16, EVP_md5(), NULL); 1794 HMAC_Update(&c, svr_chal, 8); 1795 HMAC_Update(&c, clnt_nonce, clnt_nonce_length); 1796 HMAC_Final(&c, derivedkey, &hmaclen); 1797 HMAC_CTX_cleanup(&c); 1798 } 1799
Note:
See TracChangeset
for help on using the changeset viewer.