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