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