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