1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23 #include "curl_setup.h" 24 25 #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI) 26 27 /* 28 * NTLM details: 29 * 30 * http://davenport.sourceforge.net/ntlm.html 31 * http://www.innovation.ch/java/ntlm.html 32 */ 33 34 #define DEBUG_ME 0 35 36 #include "urldata.h" 37 #include "non-ascii.h" 38 #include "sendf.h" 39 #include "curl_base64.h" 40 #include "curl_ntlm_core.h" 41 #include "curl_gethostname.h" 42 #include "curl_multibyte.h" 43 #include "warnless.h" 44 45 #include "vtls/vtls.h" 46 47 #ifdef USE_NSS 48 #include "vtls/nssg.h" /* for Curl_nss_force_init() */ 49 #endif 50 51 #define BUILDING_CURL_NTLM_MSGS_C 52 #include "curl_ntlm_msgs.h" 53 #include "curl_sasl.h" 54 #include "curl_endian.h" 55 #include "curl_printf.h" 56 57 /* The last #include files should be: */ 58 #include "curl_memory.h" 59 #include "memdebug.h" 60 61 /* "NTLMSSP" signature is always in ASCII regardless of the platform */ 62 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" 63 64 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff) 65 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \ 66 (((x) >> 16) & 0xff), (((x) >> 24) & 0xff) 67 68 #if DEBUG_ME 69 # define DEBUG_OUT(x) x 70 static void ntlm_print_flags(FILE *handle, unsigned long flags) 71 { 72 if(flags & NTLMFLAG_NEGOTIATE_UNICODE) 73 fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); 74 if(flags & NTLMFLAG_NEGOTIATE_OEM) 75 fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); 76 if(flags & NTLMFLAG_REQUEST_TARGET) 77 fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); 78 if(flags & (1<<3)) 79 fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); 80 if(flags & NTLMFLAG_NEGOTIATE_SIGN) 81 fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); 82 if(flags & NTLMFLAG_NEGOTIATE_SEAL) 83 fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); 84 if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) 85 fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); 86 if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) 87 fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); 88 if(flags & NTLMFLAG_NEGOTIATE_NETWARE) 89 fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); 90 if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) 91 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); 92 if(flags & (1<<10)) 93 fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); 94 if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) 95 fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); 96 if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) 97 fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); 98 if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) 99 fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); 100 if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) 101 fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); 102 if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) 103 fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); 104 if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) 105 fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); 106 if(flags & NTLMFLAG_TARGET_TYPE_SERVER) 107 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); 108 if(flags & NTLMFLAG_TARGET_TYPE_SHARE) 109 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); 110 if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) 111 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); 112 if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) 113 fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); 114 if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) 115 fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); 116 if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) 117 fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); 118 if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) 119 fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); 120 if(flags & (1<<24)) 121 fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); 122 if(flags & (1<<25)) 123 fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); 124 if(flags & (1<<26)) 125 fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); 126 if(flags & (1<<27)) 127 fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); 128 if(flags & (1<<28)) 129 fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); 130 if(flags & NTLMFLAG_NEGOTIATE_128) 131 fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); 132 if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) 133 fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); 134 if(flags & NTLMFLAG_NEGOTIATE_56) 135 fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); 136 } 137 138 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) 139 { 140 const char *p = buf; 141 (void)handle; 142 fprintf(stderr, "0x"); 143 while(len-- > 0) 144 fprintf(stderr, "%02.2x", (unsigned int)*p++); 145 } 146 #else 147 # define DEBUG_OUT(x) Curl_nop_stmt 148 #endif 149 150 /* 151 * ntlm_decode_type2_target() 152 * 153 * This is used to decode the "target info" in the ntlm type-2 message 154 * received. 155 * 156 * Parameters: 157 * 158 * data [in] - The session handle. 159 * buffer [in] - The decoded type-2 message. 160 * size [in] - The input buffer size, at least 32 bytes. 161 * ntlm [in/out] - The ntlm data struct being used and modified. 162 * 163 * Returns CURLE_OK on success. 164 */ 165 static CURLcode ntlm_decode_type2_target(struct SessionHandle *data, 166 unsigned char *buffer, 167 size_t size, 168 struct ntlmdata *ntlm) 169 { 170 unsigned short target_info_len = 0; 171 unsigned int target_info_offset = 0; 172 173 if(size >= 48) { 174 target_info_len = Curl_read16_le(&buffer[40]); 175 target_info_offset = Curl_read32_le(&buffer[44]); 176 if(target_info_len > 0) { 177 if(((target_info_offset + target_info_len) > size) || 178 (target_info_offset < 48)) { 179 infof(data, "NTLM handshake failure (bad type-2 message). " 180 "Target Info Offset Len is set incorrect by the peer\n"); 181 return CURLE_BAD_CONTENT_ENCODING; 182 } 183 184 ntlm->target_info = malloc(target_info_len); 185 if(!ntlm->target_info) 186 return CURLE_OUT_OF_MEMORY; 187 188 memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len); 189 } 190 } 191 192 ntlm->target_info_len = target_info_len; 193 194 return CURLE_OK; 195 } 196 197 /* 198 NTLM message structure notes: 199 200 A 'short' is a 'network short', a little-endian 16-bit unsigned value. 201 202 A 'long' is a 'network long', a little-endian, 32-bit unsigned value. 203 204 A 'security buffer' represents a triplet used to point to a buffer, 205 consisting of two shorts and one long: 206 207 1. A 'short' containing the length of the buffer content in bytes. 208 2. A 'short' containing the allocated space for the buffer in bytes. 209 3. A 'long' containing the offset to the start of the buffer in bytes, 210 from the beginning of the NTLM message. 211 */ 212 213 /* 214 * Curl_sasl_decode_ntlm_type2_message() 215 * 216 * This is used to decode an already encoded NTLM type-2 message. The message 217 * is first decoded from a base64 string into a raw NTLM message and checked 218 * for validity before the appropriate data for creating a type-3 message is 219 * written to the given NTLM data structure. 220 * 221 * Parameters: 222 * 223 * data [in] - The session handle. 224 * type2msg [in] - The base64 encoded type-2 message. 225 * ntlm [in/out] - The ntlm data struct being used and modified. 226 * 227 * Returns CURLE_OK on success. 228 */ 229 CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data, 230 const char *type2msg, 231 struct ntlmdata *ntlm) 232 { 233 static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; 234 235 /* NTLM type-2 message structure: 236 237 Index Description Content 238 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 239 (0x4e544c4d53535000) 240 8 NTLM Message Type long (0x02000000) 241 12 Target Name security buffer 242 20 Flags long 243 24 Challenge 8 bytes 244 (32) Context 8 bytes (two consecutive longs) (*) 245 (40) Target Information security buffer (*) 246 (48) OS Version Structure 8 bytes (*) 247 32 (48) (56) Start of data block (*) 248 (*) -> Optional 249 */ 250 251 CURLcode result = CURLE_OK; 252 unsigned char *type2 = NULL; 253 size_t type2_len = 0; 254 255 #if defined(USE_NSS) 256 /* Make sure the crypto backend is initialized */ 257 result = Curl_nss_force_init(data); 258 if(result) 259 return result; 260 #elif defined(CURL_DISABLE_VERBOSE_STRINGS) 261 (void)data; 262 #endif 263 264 /* Decode the base-64 encoded type-2 message */ 265 if(strlen(type2msg) && *type2msg != '=') { 266 result = Curl_base64_decode(type2msg, &type2, &type2_len); 267 if(result) 268 return result; 269 } 270 271 /* Ensure we have a valid type-2 message */ 272 if(!type2) { 273 infof(data, "NTLM handshake failure (empty type-2 message)\n"); 274 return CURLE_BAD_CONTENT_ENCODING; 275 } 276 277 ntlm->flags = 0; 278 279 if((type2_len < 32) || 280 (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) || 281 (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) { 282 /* This was not a good enough type-2 message */ 283 free(type2); 284 infof(data, "NTLM handshake failure (bad type-2 message)\n"); 285 return CURLE_BAD_CONTENT_ENCODING; 286 } 287 288 ntlm->flags = Curl_read32_le(&type2[20]); 289 memcpy(ntlm->nonce, &type2[24], 8); 290 291 if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) { 292 result = ntlm_decode_type2_target(data, type2, type2_len, ntlm); 293 if(result) { 294 free(type2); 295 infof(data, "NTLM handshake failure (bad type-2 message)\n"); 296 return result; 297 } 298 } 299 300 DEBUG_OUT({ 301 fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); 302 ntlm_print_flags(stderr, ntlm->flags); 303 fprintf(stderr, "\n nonce="); 304 ntlm_print_hex(stderr, (char *)ntlm->nonce, 8); 305 fprintf(stderr, "\n****\n"); 306 fprintf(stderr, "**** Header %s\n ", header); 307 }); 308 309 free(type2); 310 311 return result; 312 } 313 314 /* copy the source to the destination and fill in zeroes in every 315 other destination byte! */ 316 static void unicodecpy(unsigned char *dest, const char *src, size_t length) 317 { 318 size_t i; 319 for(i = 0; i < length; i++) { 320 dest[2 * i] = (unsigned char)src[i]; 321 dest[2 * i + 1] = '\0'; 322 } 323 } 324 325 /* 326 * Curl_sasl_create_ntlm_type1_message() 327 * 328 * This is used to generate an already encoded NTLM type-1 message ready for 329 * sending to the recipient using the appropriate compile time crypto API. 330 * 331 * Parameters: 332 * 333 * userp [in] - The user name in the format User or Domain\User. 334 * passdwp [in] - The user's password. 335 * ntlm [in/out] - The ntlm data struct being used and modified. 336 * outptr [in/out] - The address where a pointer to newly allocated memory 337 * holding the result will be stored upon completion. 338 * outlen [out] - The length of the output message. 339 * 340 * Returns CURLE_OK on success. 341 */ 342 CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp, 343 const char *passwdp, 344 struct ntlmdata *ntlm, 345 char **outptr, size_t *outlen) 346 { 347 /* NTLM type-1 message structure: 348 349 Index Description Content 350 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 351 (0x4e544c4d53535000) 352 8 NTLM Message Type long (0x01000000) 353 12 Flags long 354 (16) Supplied Domain security buffer (*) 355 (24) Supplied Workstation security buffer (*) 356 (32) OS Version Structure 8 bytes (*) 357 (32) (40) Start of data block (*) 358 (*) -> Optional 359 */ 360 361 size_t size; 362 363 unsigned char ntlmbuf[NTLM_BUFSIZE]; 364 const char *host = ""; /* empty */ 365 const char *domain = ""; /* empty */ 366 size_t hostlen = 0; 367 size_t domlen = 0; 368 size_t hostoff = 0; 369 size_t domoff = hostoff + hostlen; /* This is 0: remember that host and 370 domain are empty */ 371 (void)userp; 372 (void)passwdp; 373 374 /* Clean up any former leftovers and initialise to defaults */ 375 Curl_sasl_ntlm_cleanup(ntlm); 376 377 #if USE_NTRESPONSES && USE_NTLM2SESSION 378 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY 379 #else 380 #define NTLM2FLAG 0 381 #endif 382 snprintf((char *)ntlmbuf, NTLM_BUFSIZE, 383 NTLMSSP_SIGNATURE "%c" 384 "\x01%c%c%c" /* 32-bit type = 1 */ 385 "%c%c%c%c" /* 32-bit NTLM flag field */ 386 "%c%c" /* domain length */ 387 "%c%c" /* domain allocated space */ 388 "%c%c" /* domain name offset */ 389 "%c%c" /* 2 zeroes */ 390 "%c%c" /* host length */ 391 "%c%c" /* host allocated space */ 392 "%c%c" /* host name offset */ 393 "%c%c" /* 2 zeroes */ 394 "%s" /* host name */ 395 "%s", /* domain string */ 396 0, /* trailing zero */ 397 0, 0, 0, /* part of type-1 long */ 398 399 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | 400 NTLMFLAG_REQUEST_TARGET | 401 NTLMFLAG_NEGOTIATE_NTLM_KEY | 402 NTLM2FLAG | 403 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), 404 SHORTPAIR(domlen), 405 SHORTPAIR(domlen), 406 SHORTPAIR(domoff), 407 0, 0, 408 SHORTPAIR(hostlen), 409 SHORTPAIR(hostlen), 410 SHORTPAIR(hostoff), 411 0, 0, 412 host, /* this is empty */ 413 domain /* this is empty */); 414 415 /* Initial packet length */ 416 size = 32 + hostlen + domlen; 417 418 DEBUG_OUT({ 419 fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x " 420 "0x%08.8x ", 421 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | 422 NTLMFLAG_REQUEST_TARGET | 423 NTLMFLAG_NEGOTIATE_NTLM_KEY | 424 NTLM2FLAG | 425 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), 426 NTLMFLAG_NEGOTIATE_OEM | 427 NTLMFLAG_REQUEST_TARGET | 428 NTLMFLAG_NEGOTIATE_NTLM_KEY | 429 NTLM2FLAG | 430 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); 431 ntlm_print_flags(stderr, 432 NTLMFLAG_NEGOTIATE_OEM | 433 NTLMFLAG_REQUEST_TARGET | 434 NTLMFLAG_NEGOTIATE_NTLM_KEY | 435 NTLM2FLAG | 436 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); 437 fprintf(stderr, "\n****\n"); 438 }); 439 440 /* Return with binary blob encoded into base64 */ 441 return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen); 442 } 443 444 /* 445 * Curl_sasl_create_ntlm_type3_message() 446 * 447 * This is used to generate an already encoded NTLM type-3 message ready for 448 * sending to the recipient using the appropriate compile time crypto API. 449 * 450 * Parameters: 451 * 452 * data [in] - The session handle. 453 * userp [in] - The user name in the format User or Domain\User. 454 * passdwp [in] - The user's password. 455 * ntlm [in/out] - The ntlm data struct being used and modified. 456 * outptr [in/out] - The address where a pointer to newly allocated memory 457 * holding the result will be stored upon completion. 458 * outlen [out] - The length of the output message. 459 * 460 * Returns CURLE_OK on success. 461 */ 462 CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data, 463 const char *userp, 464 const char *passwdp, 465 struct ntlmdata *ntlm, 466 char **outptr, size_t *outlen) 467 468 { 469 /* NTLM type-3 message structure: 470 471 Index Description Content 472 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 473 (0x4e544c4d53535000) 474 8 NTLM Message Type long (0x03000000) 475 12 LM/LMv2 Response security buffer 476 20 NTLM/NTLMv2 Response security buffer 477 28 Target Name security buffer 478 36 User Name security buffer 479 44 Workstation Name security buffer 480 (52) Session Key security buffer (*) 481 (60) Flags long (*) 482 (64) OS Version Structure 8 bytes (*) 483 52 (64) (72) Start of data block 484 (*) -> Optional 485 */ 486 487 CURLcode result = CURLE_OK; 488 size_t size; 489 unsigned char ntlmbuf[NTLM_BUFSIZE]; 490 int lmrespoff; 491 unsigned char lmresp[24]; /* fixed-size */ 492 #if USE_NTRESPONSES 493 int ntrespoff; 494 unsigned int ntresplen = 24; 495 unsigned char ntresp[24]; /* fixed-size */ 496 unsigned char *ptr_ntresp = &ntresp[0]; 497 unsigned char *ntlmv2resp = NULL; 498 #endif 499 bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; 500 char host[HOSTNAME_MAX + 1] = ""; 501 const char *user; 502 const char *domain = ""; 503 size_t hostoff = 0; 504 size_t useroff = 0; 505 size_t domoff = 0; 506 size_t hostlen = 0; 507 size_t userlen = 0; 508 size_t domlen = 0; 509 510 user = strchr(userp, '\\'); 511 if(!user) 512 user = strchr(userp, '/'); 513 514 if(user) { 515 domain = userp; 516 domlen = (user - domain); 517 user++; 518 } 519 else 520 user = userp; 521 522 if(user) 523 userlen = strlen(user); 524 525 /* Get the machine's un-qualified host name as NTLM doesn't like the fully 526 qualified domain name */ 527 if(Curl_gethostname(host, sizeof(host))) { 528 infof(data, "gethostname() failed, continuing without!\n"); 529 hostlen = 0; 530 } 531 else { 532 hostlen = strlen(host); 533 } 534 535 #if USE_NTRESPONSES && USE_NTLM_V2 536 if(ntlm->target_info_len) { 537 unsigned char ntbuffer[0x18]; 538 unsigned int entropy[2]; 539 unsigned char ntlmv2hash[0x18]; 540 541 entropy[0] = Curl_rand(data); 542 entropy[1] = Curl_rand(data); 543 544 result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); 545 if(result) 546 return result; 547 548 result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen, 549 ntbuffer, ntlmv2hash); 550 if(result) 551 return result; 552 553 /* LMv2 response */ 554 result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, 555 (unsigned char *)&entropy[0], 556 &ntlm->nonce[0], lmresp); 557 if(result) 558 return result; 559 560 /* NTLMv2 response */ 561 result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, 562 (unsigned char *)&entropy[0], 563 ntlm, &ntlmv2resp, &ntresplen); 564 if(result) 565 return result; 566 567 ptr_ntresp = ntlmv2resp; 568 } 569 else 570 #endif 571 572 #if USE_NTRESPONSES && USE_NTLM2SESSION 573 /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ 574 if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { 575 unsigned char ntbuffer[0x18]; 576 unsigned char tmp[0x18]; 577 unsigned char md5sum[MD5_DIGEST_LENGTH]; 578 unsigned int entropy[2]; 579 580 /* Need to create 8 bytes random data */ 581 entropy[0] = Curl_rand(data); 582 entropy[1] = Curl_rand(data); 583 584 /* 8 bytes random data as challenge in lmresp */ 585 memcpy(lmresp, entropy, 8); 586 587 /* Pad with zeros */ 588 memset(lmresp + 8, 0, 0x10); 589 590 /* Fill tmp with challenge(nonce?) + entropy */ 591 memcpy(tmp, &ntlm->nonce[0], 8); 592 memcpy(tmp + 8, entropy, 8); 593 594 result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH); 595 if(!result) 596 /* We shall only use the first 8 bytes of md5sum, but the des code in 597 Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ 598 result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); 599 if(result) 600 return result; 601 602 Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); 603 604 /* End of NTLM2 Session code */ 605 606 } 607 else 608 #endif 609 { 610 611 #if USE_NTRESPONSES 612 unsigned char ntbuffer[0x18]; 613 #endif 614 unsigned char lmbuffer[0x18]; 615 616 #if USE_NTRESPONSES 617 result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer); 618 if(result) 619 return result; 620 621 Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); 622 #endif 623 624 result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer); 625 if(result) 626 return result; 627 628 Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); 629 630 /* A safer but less compatible alternative is: 631 * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); 632 * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ 633 } 634 635 if(unicode) { 636 domlen = domlen * 2; 637 userlen = userlen * 2; 638 hostlen = hostlen * 2; 639 } 640 641 lmrespoff = 64; /* size of the message header */ 642 #if USE_NTRESPONSES 643 ntrespoff = lmrespoff + 0x18; 644 domoff = ntrespoff + ntresplen; 645 #else 646 domoff = lmrespoff + 0x18; 647 #endif 648 useroff = domoff + domlen; 649 hostoff = useroff + userlen; 650 651 /* Create the big type-3 message binary blob */ 652 size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE, 653 NTLMSSP_SIGNATURE "%c" 654 "\x03%c%c%c" /* 32-bit type = 3 */ 655 656 "%c%c" /* LanManager length */ 657 "%c%c" /* LanManager allocated space */ 658 "%c%c" /* LanManager offset */ 659 "%c%c" /* 2 zeroes */ 660 661 "%c%c" /* NT-response length */ 662 "%c%c" /* NT-response allocated space */ 663 "%c%c" /* NT-response offset */ 664 "%c%c" /* 2 zeroes */ 665 666 "%c%c" /* domain length */ 667 "%c%c" /* domain allocated space */ 668 "%c%c" /* domain name offset */ 669 "%c%c" /* 2 zeroes */ 670 671 "%c%c" /* user length */ 672 "%c%c" /* user allocated space */ 673 "%c%c" /* user offset */ 674 "%c%c" /* 2 zeroes */ 675 676 "%c%c" /* host length */ 677 "%c%c" /* host allocated space */ 678 "%c%c" /* host offset */ 679 "%c%c" /* 2 zeroes */ 680 681 "%c%c" /* session key length (unknown purpose) */ 682 "%c%c" /* session key allocated space (unknown purpose) */ 683 "%c%c" /* session key offset (unknown purpose) */ 684 "%c%c" /* 2 zeroes */ 685 686 "%c%c%c%c", /* flags */ 687 688 /* domain string */ 689 /* user string */ 690 /* host string */ 691 /* LanManager response */ 692 /* NT response */ 693 694 0, /* zero termination */ 695 0, 0, 0, /* type-3 long, the 24 upper bits */ 696 697 SHORTPAIR(0x18), /* LanManager response length, twice */ 698 SHORTPAIR(0x18), 699 SHORTPAIR(lmrespoff), 700 0x0, 0x0, 701 702 #if USE_NTRESPONSES 703 SHORTPAIR(ntresplen), /* NT-response length, twice */ 704 SHORTPAIR(ntresplen), 705 SHORTPAIR(ntrespoff), 706 0x0, 0x0, 707 #else 708 0x0, 0x0, 709 0x0, 0x0, 710 0x0, 0x0, 711 0x0, 0x0, 712 #endif 713 SHORTPAIR(domlen), 714 SHORTPAIR(domlen), 715 SHORTPAIR(domoff), 716 0x0, 0x0, 717 718 SHORTPAIR(userlen), 719 SHORTPAIR(userlen), 720 SHORTPAIR(useroff), 721 0x0, 0x0, 722 723 SHORTPAIR(hostlen), 724 SHORTPAIR(hostlen), 725 SHORTPAIR(hostoff), 726 0x0, 0x0, 727 728 0x0, 0x0, 729 0x0, 0x0, 730 0x0, 0x0, 731 0x0, 0x0, 732 733 LONGQUARTET(ntlm->flags)); 734 735 DEBUGASSERT(size == 64); 736 DEBUGASSERT(size == (size_t)lmrespoff); 737 738 /* We append the binary hashes */ 739 if(size < (NTLM_BUFSIZE - 0x18)) { 740 memcpy(&ntlmbuf[size], lmresp, 0x18); 741 size += 0x18; 742 } 743 744 DEBUG_OUT({ 745 fprintf(stderr, "**** TYPE3 header lmresp="); 746 ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); 747 }); 748 749 #if USE_NTRESPONSES 750 if(size < (NTLM_BUFSIZE - ntresplen)) { 751 DEBUGASSERT(size == (size_t)ntrespoff); 752 memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen); 753 size += ntresplen; 754 } 755 756 DEBUG_OUT({ 757 fprintf(stderr, "\n ntresp="); 758 ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen); 759 }); 760 761 free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */ 762 763 #endif 764 765 DEBUG_OUT({ 766 fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", 767 LONGQUARTET(ntlm->flags), ntlm->flags); 768 ntlm_print_flags(stderr, ntlm->flags); 769 fprintf(stderr, "\n****\n"); 770 }); 771 772 /* Make sure that the domain, user and host strings fit in the 773 buffer before we copy them there. */ 774 if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) { 775 failf(data, "user + domain + host name too big"); 776 return CURLE_OUT_OF_MEMORY; 777 } 778 779 DEBUGASSERT(size == domoff); 780 if(unicode) 781 unicodecpy(&ntlmbuf[size], domain, domlen / 2); 782 else 783 memcpy(&ntlmbuf[size], domain, domlen); 784 785 size += domlen; 786 787 DEBUGASSERT(size == useroff); 788 if(unicode) 789 unicodecpy(&ntlmbuf[size], user, userlen / 2); 790 else 791 memcpy(&ntlmbuf[size], user, userlen); 792 793 size += userlen; 794 795 DEBUGASSERT(size == hostoff); 796 if(unicode) 797 unicodecpy(&ntlmbuf[size], host, hostlen / 2); 798 else 799 memcpy(&ntlmbuf[size], host, hostlen); 800 801 size += hostlen; 802 803 /* Convert domain, user, and host to ASCII but leave the rest as-is */ 804 result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff], 805 size - domoff); 806 if(result) 807 return CURLE_CONV_FAILED; 808 809 /* Return with binary blob encoded into base64 */ 810 result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen); 811 812 Curl_sasl_ntlm_cleanup(ntlm); 813 814 return result; 815 } 816 817 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */ 818