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