1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 http://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 ***************************************************************************/ 22 23#include "setup.h" 24 25#ifdef USE_NTLM 26 27/* 28 * NTLM details: 29 * 30 * http://davenport.sourceforge.net/ntlm.html 31 * http://www.innovation.ch/java/ntlm.html 32 */ 33 34#define DEBUG_ME 0 35 36#ifdef USE_SSLEAY 37 38# ifdef USE_OPENSSL 39# include <openssl/des.h> 40# ifndef OPENSSL_NO_MD4 41# include <openssl/md4.h> 42# endif 43# include <openssl/md5.h> 44# include <openssl/ssl.h> 45# include <openssl/rand.h> 46# else 47# include <des.h> 48# ifndef OPENSSL_NO_MD4 49# include <md4.h> 50# endif 51# include <md5.h> 52# include <ssl.h> 53# include <rand.h> 54# endif 55# include "ssluse.h" 56 57#elif defined(USE_GNUTLS) 58 59# include <gcrypt.h> 60# include "gtls.h" 61# define MD5_DIGEST_LENGTH 16 62# define MD4_DIGEST_LENGTH 16 63 64#elif defined(USE_NSS) 65 66# include <nss.h> 67# include <pk11pub.h> 68# include <hasht.h> 69# include "nssg.h" 70# include "curl_md4.h" 71# define MD5_DIGEST_LENGTH MD5_LENGTH 72 73#elif defined(USE_WINDOWS_SSPI) 74# include "curl_sspi.h" 75#else 76# error "Can't compile NTLM support without a crypto library." 77#endif 78 79#include "urldata.h" 80#include "non-ascii.h" 81#include "sendf.h" 82#include "curl_base64.h" 83#include "curl_ntlm_core.h" 84#include "curl_gethostname.h" 85#include "curl_memory.h" 86 87#define BUILDING_CURL_NTLM_MSGS_C 88#include "curl_ntlm_msgs.h" 89 90#define _MPRINTF_REPLACE /* use our functions only */ 91#include <curl/mprintf.h> 92 93/* The last #include file should be: */ 94#include "memdebug.h" 95 96/* "NTLMSSP" signature is always in ASCII regardless of the platform */ 97#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" 98 99#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff) 100#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \ 101 (((x) >> 16) & 0xff), (((x) >> 24) & 0xff) 102 103#if DEBUG_ME 104# define DEBUG_OUT(x) x 105static void ntlm_print_flags(FILE *handle, unsigned long flags) 106{ 107 if(flags & NTLMFLAG_NEGOTIATE_UNICODE) 108 fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); 109 if(flags & NTLMFLAG_NEGOTIATE_OEM) 110 fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); 111 if(flags & NTLMFLAG_REQUEST_TARGET) 112 fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); 113 if(flags & (1<<3)) 114 fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); 115 if(flags & NTLMFLAG_NEGOTIATE_SIGN) 116 fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); 117 if(flags & NTLMFLAG_NEGOTIATE_SEAL) 118 fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); 119 if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) 120 fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); 121 if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) 122 fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); 123 if(flags & NTLMFLAG_NEGOTIATE_NETWARE) 124 fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); 125 if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) 126 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); 127 if(flags & (1<<10)) 128 fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); 129 if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) 130 fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); 131 if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) 132 fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); 133 if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) 134 fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); 135 if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) 136 fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); 137 if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) 138 fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); 139 if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) 140 fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); 141 if(flags & NTLMFLAG_TARGET_TYPE_SERVER) 142 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); 143 if(flags & NTLMFLAG_TARGET_TYPE_SHARE) 144 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); 145 if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) 146 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); 147 if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) 148 fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); 149 if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) 150 fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); 151 if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) 152 fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); 153 if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) 154 fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); 155 if(flags & (1<<24)) 156 fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); 157 if(flags & (1<<25)) 158 fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); 159 if(flags & (1<<26)) 160 fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); 161 if(flags & (1<<27)) 162 fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); 163 if(flags & (1<<28)) 164 fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); 165 if(flags & NTLMFLAG_NEGOTIATE_128) 166 fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); 167 if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) 168 fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); 169 if(flags & NTLMFLAG_NEGOTIATE_56) 170 fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); 171} 172 173static void ntlm_print_hex(FILE *handle, const char *buf, size_t len) 174{ 175 const char *p = buf; 176 (void)handle; 177 fprintf(stderr, "0x"); 178 while(len-- > 0) 179 fprintf(stderr, "%02.2x", (unsigned int)*p++); 180} 181#else 182# define DEBUG_OUT(x) Curl_nop_stmt 183#endif 184 185#ifndef USE_WINDOWS_SSPI 186/* 187 * This function converts from the little endian format used in the 188 * incoming package to whatever endian format we're using natively. 189 * Argument is a pointer to a 4 byte buffer. 190 */ 191static unsigned int readint_le(unsigned char *buf) 192{ 193 return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | 194 ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); 195} 196#endif 197 198/* 199 NTLM message structure notes: 200 201 A 'short' is a 'network short', a little-endian 16-bit unsigned value. 202 203 A 'long' is a 'network long', a little-endian, 32-bit unsigned value. 204 205 A 'security buffer' represents a triplet used to point to a buffer, 206 consisting of two shorts and one long: 207 208 1. A 'short' containing the length of the buffer content in bytes. 209 2. A 'short' containing the allocated space for the buffer in bytes. 210 3. A 'long' containing the offset to the start of the buffer in bytes, 211 from the beginning of the NTLM message. 212*/ 213 214/* 215 * Curl_ntlm_decode_type2_message() 216 * 217 * This is used to decode a ntlm type-2 message received from a: HTTP, SMTP 218 * or POP3 server. The message is first decoded from a base64 string into a 219 * raw ntlm message and checked for validity before the appropriate data for 220 * creating a type-3 message is written to the given ntlm data structure. 221 * 222 * Parameters: 223 * 224 * data [in] - Pointer to session handle. 225 * header [in] - Pointer to the input buffer. 226 * ntlm [in] - Pointer to ntlm data struct being used and modified. 227 * 228 * Returns CURLE_OK on success. 229 */ 230CURLcode Curl_ntlm_decode_type2_message(struct SessionHandle *data, 231 const char* header, 232 struct ntlmdata* ntlm) 233{ 234#ifndef USE_WINDOWS_SSPI 235 static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; 236#endif 237 238 /* NTLM type-2 message structure: 239 240 Index Description Content 241 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 242 (0x4e544c4d53535000) 243 8 NTLM Message Type long (0x02000000) 244 12 Target Name security buffer 245 20 Flags long 246 24 Challenge 8 bytes 247 (32) Context 8 bytes (two consecutive longs) (*) 248 (40) Target Information security buffer (*) 249 (48) OS Version Structure 8 bytes (*) 250 32 (48) (56) Start of data block (*) 251 (*) -> Optional 252 */ 253 254 size_t size = 0; 255 unsigned char *buffer = NULL; 256 CURLcode error; 257 258#if defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_WINDOWS_SSPI) 259 (void)data; 260#endif 261 262 error = Curl_base64_decode(header, &buffer, &size); 263 if(error) 264 return error; 265 266 if(!buffer) { 267 infof(data, "NTLM handshake failure (unhandled condition)\n"); 268 return CURLE_REMOTE_ACCESS_DENIED; 269 } 270 271#ifdef USE_WINDOWS_SSPI 272 ntlm->type_2 = malloc(size + 1); 273 if(ntlm->type_2 == NULL) { 274 free(buffer); 275 return CURLE_OUT_OF_MEMORY; 276 } 277 ntlm->n_type_2 = (unsigned long)size; 278 memcpy(ntlm->type_2, buffer, size); 279#else 280 ntlm->flags = 0; 281 282 if((size < 32) || 283 (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) || 284 (memcmp(buffer + 8, type2_marker, sizeof(type2_marker)) != 0)) { 285 /* This was not a good enough type-2 message */ 286 free(buffer); 287 infof(data, "NTLM handshake failure (bad type-2 message)\n"); 288 return CURLE_REMOTE_ACCESS_DENIED; 289 } 290 291 ntlm->flags = readint_le(&buffer[20]); 292 memcpy(ntlm->nonce, &buffer[24], 8); 293 294 DEBUG_OUT({ 295 fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); 296 ntlm_print_flags(stderr, ntlm->flags); 297 fprintf(stderr, "\n nonce="); 298 ntlm_print_hex(stderr, (char *)ntlm->nonce, 8); 299 fprintf(stderr, "\n****\n"); 300 fprintf(stderr, "**** Header %s\n ", header); 301 }); 302#endif 303 free(buffer); 304 305 return CURLE_OK; 306} 307 308#ifdef USE_WINDOWS_SSPI 309void Curl_ntlm_sspi_cleanup(struct ntlmdata *ntlm) 310{ 311 if(ntlm->type_2) { 312 free(ntlm->type_2); 313 ntlm->type_2 = NULL; 314 } 315 if(ntlm->has_handles) { 316 s_pSecFn->DeleteSecurityContext(&ntlm->c_handle); 317 s_pSecFn->FreeCredentialsHandle(&ntlm->handle); 318 ntlm->has_handles = 0; 319 } 320 if(ntlm->p_identity) { 321 if(ntlm->identity.User) free(ntlm->identity.User); 322 if(ntlm->identity.Password) free(ntlm->identity.Password); 323 if(ntlm->identity.Domain) free(ntlm->identity.Domain); 324 ntlm->p_identity = NULL; 325 } 326} 327#endif 328 329#ifndef USE_WINDOWS_SSPI 330/* copy the source to the destination and fill in zeroes in every 331 other destination byte! */ 332static void unicodecpy(unsigned char *dest, 333 const char *src, size_t length) 334{ 335 size_t i; 336 for(i = 0; i < length; i++) { 337 dest[2 * i] = (unsigned char)src[i]; 338 dest[2 * i + 1] = '\0'; 339 } 340} 341#endif 342 343/* 344 * Curl_ntlm_create_type1_message() 345 * 346 * This is used to generate an already encoded NTLM type-1 message ready 347 * for sending to the recipient, be it a: HTTP, SMTP or POP3 server, 348 * using the appropriate compile time crypo API. 349 * 350 * Parameters: 351 * 352 * userp [in] - The user name in the format User or Domain\User. 353 * passdwp [in] - The user's password. 354 * ntlm [in/out] - The ntlm data struct being used and modified. 355 * outptr [in/out] - The adress where a pointer to newly allocated memory 356 * holding the result will be stored upon completion. 357 * outlen [out] - The length of the output message. 358 * 359 * Returns CURLE_OK on success. 360 */ 361CURLcode Curl_ntlm_create_type1_message(const char *userp, 362 const char *passwdp, 363 struct ntlmdata *ntlm, 364 char **outptr, 365 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 unsigned char ntlmbuf[NTLM_BUFSIZE]; 382 size_t size; 383 384#ifdef USE_WINDOWS_SSPI 385 386 SecBuffer buf; 387 SecBufferDesc desc; 388 SECURITY_STATUS status; 389 ULONG attrs; 390 const char *dest = ""; 391 const char *user; 392 const char *domain = ""; 393 size_t userlen = 0; 394 size_t domlen = 0; 395 size_t passwdlen = 0; 396 TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */ 397 398 Curl_ntlm_sspi_cleanup(ntlm); 399 400 user = strchr(userp, '\\'); 401 if(!user) 402 user = strchr(userp, '/'); 403 404 if(user) { 405 domain = userp; 406 domlen = user - userp; 407 user++; 408 } 409 else { 410 user = userp; 411 domain = ""; 412 domlen = 0; 413 } 414 415 if(user) 416 userlen = strlen(user); 417 418 if(passwdp) 419 passwdlen = strlen(passwdp); 420 421 if(userlen > 0) { 422 /* note: initialize all of this before doing the mallocs so that 423 * it can be cleaned up later without leaking memory. 424 */ 425 ntlm->p_identity = &ntlm->identity; 426 memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity)); 427 if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL) 428 return CURLE_OUT_OF_MEMORY; 429 430 ntlm->identity.UserLength = (unsigned long)userlen; 431 if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL) 432 return CURLE_OUT_OF_MEMORY; 433 434 ntlm->identity.PasswordLength = (unsigned long)strlen(passwdp); 435 if((ntlm->identity.Domain = malloc(domlen + 1)) == NULL) 436 return CURLE_OUT_OF_MEMORY; 437 438 strncpy((char *)ntlm->identity.Domain, domain, domlen); 439 ntlm->identity.Domain[domlen] = '\0'; 440 ntlm->identity.DomainLength = (unsigned long)domlen; 441 ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; 442 } 443 else 444 ntlm->p_identity = NULL; 445 446 status = s_pSecFn->AcquireCredentialsHandleA(NULL, (void *)"NTLM", 447 SECPKG_CRED_OUTBOUND, NULL, 448 ntlm->p_identity, NULL, NULL, 449 &ntlm->handle, &tsDummy); 450 if(status != SEC_E_OK) 451 return CURLE_OUT_OF_MEMORY; 452 453 desc.ulVersion = SECBUFFER_VERSION; 454 desc.cBuffers = 1; 455 desc.pBuffers = &buf; 456 buf.cbBuffer = NTLM_BUFSIZE; 457 buf.BufferType = SECBUFFER_TOKEN; 458 buf.pvBuffer = ntlmbuf; 459 460 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL, 461 (void *)dest, 462 ISC_REQ_CONFIDENTIALITY | 463 ISC_REQ_REPLAY_DETECT | 464 ISC_REQ_CONNECTION, 465 0, SECURITY_NETWORK_DREP, 466 NULL, 0, 467 &ntlm->c_handle, &desc, 468 &attrs, &tsDummy); 469 470 if(status == SEC_I_COMPLETE_AND_CONTINUE || 471 status == SEC_I_CONTINUE_NEEDED) 472 s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc); 473 else if(status != SEC_E_OK) { 474 s_pSecFn->FreeCredentialsHandle(&ntlm->handle); 475 return CURLE_RECV_ERROR; 476 } 477 478 ntlm->has_handles = 1; 479 size = buf.cbBuffer; 480 481#else 482 483 const char *host = ""; /* empty */ 484 const char *domain = ""; /* empty */ 485 size_t hostlen = 0; 486 size_t domlen = 0; 487 size_t hostoff = 0; 488 size_t domoff = hostoff + hostlen; /* This is 0: remember that host and 489 domain are empty */ 490 (void)userp; 491 (void)passwdp; 492 (void)ntlm; 493 494#if USE_NTLM2SESSION 495#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY 496#else 497#define NTLM2FLAG 0 498#endif 499 snprintf((char *)ntlmbuf, NTLM_BUFSIZE, 500 NTLMSSP_SIGNATURE "%c" 501 "\x01%c%c%c" /* 32-bit type = 1 */ 502 "%c%c%c%c" /* 32-bit NTLM flag field */ 503 "%c%c" /* domain length */ 504 "%c%c" /* domain allocated space */ 505 "%c%c" /* domain name offset */ 506 "%c%c" /* 2 zeroes */ 507 "%c%c" /* host length */ 508 "%c%c" /* host allocated space */ 509 "%c%c" /* host name offset */ 510 "%c%c" /* 2 zeroes */ 511 "%s" /* host name */ 512 "%s", /* domain string */ 513 0, /* trailing zero */ 514 0, 0, 0, /* part of type-1 long */ 515 516 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | 517 NTLMFLAG_REQUEST_TARGET | 518 NTLMFLAG_NEGOTIATE_NTLM_KEY | 519 NTLM2FLAG | 520 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), 521 SHORTPAIR(domlen), 522 SHORTPAIR(domlen), 523 SHORTPAIR(domoff), 524 0, 0, 525 SHORTPAIR(hostlen), 526 SHORTPAIR(hostlen), 527 SHORTPAIR(hostoff), 528 0, 0, 529 host, /* this is empty */ 530 domain /* this is empty */); 531 532 /* Initial packet length */ 533 size = 32 + hostlen + domlen; 534 535#endif 536 537 DEBUG_OUT({ 538 fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x " 539 "0x%08.8x ", 540 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM | 541 NTLMFLAG_REQUEST_TARGET | 542 NTLMFLAG_NEGOTIATE_NTLM_KEY | 543 NTLM2FLAG | 544 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), 545 NTLMFLAG_NEGOTIATE_OEM | 546 NTLMFLAG_REQUEST_TARGET | 547 NTLMFLAG_NEGOTIATE_NTLM_KEY | 548 NTLM2FLAG | 549 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); 550 ntlm_print_flags(stderr, 551 NTLMFLAG_NEGOTIATE_OEM | 552 NTLMFLAG_REQUEST_TARGET | 553 NTLMFLAG_NEGOTIATE_NTLM_KEY | 554 NTLM2FLAG | 555 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); 556 fprintf(stderr, "\n****\n"); 557 }); 558 559 /* Return with binary blob encoded into base64 */ 560 return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen); 561} 562 563/* 564 * Curl_ntlm_create_type3_message() 565 * 566 * This is used to generate an already encoded NTLM type-3 message ready 567 * for sending to the recipient, be it a: HTTP, SMTP or POP3 server, 568 * using the appropriate compile time crypo API. 569 * 570 * Parameters: 571 * 572 * data [in] - The session handle. 573 * userp [in] - The user name in the format User or Domain\User. 574 * passdwp [in] - The user's password. 575 * ntlm [in/out] - The ntlm data struct being used and modified. 576 * outptr [in/out] - The adress where a pointer to newly allocated memory 577 * holding the result will be stored upon completion. 578 * outlen [out] - The length of the output message. 579 * 580 * Returns CURLE_OK on success. 581 */ 582CURLcode Curl_ntlm_create_type3_message(struct SessionHandle *data, 583 const char *userp, 584 const char *passwdp, 585 struct ntlmdata *ntlm, 586 char **outptr, 587 size_t *outlen) 588{ 589 /* NTLM type-3 message structure: 590 591 Index Description Content 592 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 593 (0x4e544c4d53535000) 594 8 NTLM Message Type long (0x03000000) 595 12 LM/LMv2 Response security buffer 596 20 NTLM/NTLMv2 Response security buffer 597 28 Target Name security buffer 598 36 User Name security buffer 599 44 Workstation Name security buffer 600 (52) Session Key security buffer (*) 601 (60) Flags long (*) 602 (64) OS Version Structure 8 bytes (*) 603 52 (64) (72) Start of data block 604 (*) -> Optional 605 */ 606 607 unsigned char ntlmbuf[NTLM_BUFSIZE]; 608 size_t size; 609 610#ifdef USE_WINDOWS_SSPI 611 const char *dest = ""; 612 SecBuffer type_2; 613 SecBuffer type_3; 614 SecBufferDesc type_2_desc; 615 SecBufferDesc type_3_desc; 616 SECURITY_STATUS status; 617 ULONG attrs; 618 TimeStamp tsDummy; /* For Windows 9x compatibility of SSPI calls */ 619 620 (void)passwdp; 621 (void)userp; 622 (void)data; 623 624 type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION; 625 type_2_desc.cBuffers = type_3_desc.cBuffers = 1; 626 type_2_desc.pBuffers = &type_2; 627 type_3_desc.pBuffers = &type_3; 628 629 type_2.BufferType = SECBUFFER_TOKEN; 630 type_2.pvBuffer = ntlm->type_2; 631 type_2.cbBuffer = ntlm->n_type_2; 632 type_3.BufferType = SECBUFFER_TOKEN; 633 type_3.pvBuffer = ntlmbuf; 634 type_3.cbBuffer = NTLM_BUFSIZE; 635 636 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, 637 &ntlm->c_handle, 638 (void *)dest, 639 ISC_REQ_CONFIDENTIALITY | 640 ISC_REQ_REPLAY_DETECT | 641 ISC_REQ_CONNECTION, 642 0, SECURITY_NETWORK_DREP, 643 &type_2_desc, 644 0, &ntlm->c_handle, 645 &type_3_desc, 646 &attrs, &tsDummy); 647 if(status != SEC_E_OK) 648 return CURLE_RECV_ERROR; 649 650 size = type_3.cbBuffer; 651 652 Curl_ntlm_sspi_cleanup(ntlm); 653 654#else 655 int lmrespoff; 656 unsigned char lmresp[24]; /* fixed-size */ 657#if USE_NTRESPONSES 658 int ntrespoff; 659 unsigned char ntresp[24]; /* fixed-size */ 660#endif 661 bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE; 662 char host[HOSTNAME_MAX + 1] = ""; 663 const char *user; 664 const char *domain = ""; 665 size_t hostoff = 0; 666 size_t useroff = 0; 667 size_t domoff = 0; 668 size_t hostlen = 0; 669 size_t userlen = 0; 670 size_t domlen = 0; 671 CURLcode res; 672 673 user = strchr(userp, '\\'); 674 if(!user) 675 user = strchr(userp, '/'); 676 677 if(user) { 678 domain = userp; 679 domlen = (user - domain); 680 user++; 681 } 682 else 683 user = userp; 684 685 if(user) 686 userlen = strlen(user); 687 688 /* Get the machine's un-qualified host name as NTLM doesn't like the fully 689 qualified domain name */ 690 if(Curl_gethostname(host, sizeof(host))) { 691 infof(data, "gethostname() failed, continuing without!"); 692 hostlen = 0; 693 } 694 else { 695 hostlen = strlen(host); 696 } 697 698 if(unicode) { 699 domlen = domlen * 2; 700 userlen = userlen * 2; 701 hostlen = hostlen * 2; 702 } 703 704#if USE_NTLM2SESSION 705 /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ 706 if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { 707 unsigned char ntbuffer[0x18]; 708 unsigned char tmp[0x18]; 709 unsigned char md5sum[MD5_DIGEST_LENGTH]; 710 unsigned char entropy[8]; 711 712 /* Need to create 8 bytes random data */ 713#ifdef USE_SSLEAY 714 MD5_CTX MD5pw; 715 Curl_ossl_seed(data); /* Initiate the seed if not already done */ 716 RAND_bytes(entropy, 8); 717#elif defined(USE_GNUTLS) 718 gcry_md_hd_t MD5pw; 719 Curl_gtls_seed(data); /* Initiate the seed if not already done */ 720 gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM); 721#elif defined(USE_NSS) 722 PK11Context *MD5pw; 723 unsigned int MD5len; 724 Curl_nss_seed(data); /* Initiate the seed if not already done */ 725 PK11_GenerateRandom(entropy, 8); 726#endif 727 728 /* 8 bytes random data as challenge in lmresp */ 729 memcpy(lmresp, entropy, 8); 730 731 /* Pad with zeros */ 732 memset(lmresp + 8, 0, 0x10); 733 734 /* Fill tmp with challenge(nonce?) + entropy */ 735 memcpy(tmp, &ntlm->nonce[0], 8); 736 memcpy(tmp + 8, entropy, 8); 737 738#ifdef USE_SSLEAY 739 MD5_Init(&MD5pw); 740 MD5_Update(&MD5pw, tmp, 16); 741 MD5_Final(md5sum, &MD5pw); 742#elif defined(USE_GNUTLS) 743 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); 744 gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH); 745 memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH); 746 gcry_md_close(MD5pw); 747#elif defined(USE_NSS) 748 MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); 749 PK11_DigestOp(MD5pw, tmp, 16); 750 PK11_DigestFinal(MD5pw, md5sum, &MD5len, MD5_DIGEST_LENGTH); 751 PK11_DestroyContext(MD5pw, PR_TRUE); 752#endif 753 754 /* We shall only use the first 8 bytes of md5sum, but the des 755 code in Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */ 756 if(CURLE_OUT_OF_MEMORY == 757 Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer)) 758 return CURLE_OUT_OF_MEMORY; 759 Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp); 760 761 /* End of NTLM2 Session code */ 762 } 763 else 764#endif 765 { 766 767#if USE_NTRESPONSES 768 unsigned char ntbuffer[0x18]; 769#endif 770 unsigned char lmbuffer[0x18]; 771 772#if USE_NTRESPONSES 773 if(CURLE_OUT_OF_MEMORY == 774 Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer)) 775 return CURLE_OUT_OF_MEMORY; 776 Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); 777#endif 778 779 Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer); 780 Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); 781 /* A safer but less compatible alternative is: 782 * Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); 783 * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ 784 } 785 786 lmrespoff = 64; /* size of the message header */ 787#if USE_NTRESPONSES 788 ntrespoff = lmrespoff + 0x18; 789 domoff = ntrespoff + 0x18; 790#else 791 domoff = lmrespoff + 0x18; 792#endif 793 useroff = domoff + domlen; 794 hostoff = useroff + userlen; 795 796 /* Create the big type-3 message binary blob */ 797 size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE, 798 NTLMSSP_SIGNATURE "%c" 799 "\x03%c%c%c" /* 32-bit type = 3 */ 800 801 "%c%c" /* LanManager length */ 802 "%c%c" /* LanManager allocated space */ 803 "%c%c" /* LanManager offset */ 804 "%c%c" /* 2 zeroes */ 805 806 "%c%c" /* NT-response length */ 807 "%c%c" /* NT-response allocated space */ 808 "%c%c" /* NT-response offset */ 809 "%c%c" /* 2 zeroes */ 810 811 "%c%c" /* domain length */ 812 "%c%c" /* domain allocated space */ 813 "%c%c" /* domain name offset */ 814 "%c%c" /* 2 zeroes */ 815 816 "%c%c" /* user length */ 817 "%c%c" /* user allocated space */ 818 "%c%c" /* user offset */ 819 "%c%c" /* 2 zeroes */ 820 821 "%c%c" /* host length */ 822 "%c%c" /* host allocated space */ 823 "%c%c" /* host offset */ 824 "%c%c" /* 2 zeroes */ 825 826 "%c%c" /* session key length (unknown purpose) */ 827 "%c%c" /* session key allocated space (unknown purpose) */ 828 "%c%c" /* session key offset (unknown purpose) */ 829 "%c%c" /* 2 zeroes */ 830 831 "%c%c%c%c", /* flags */ 832 833 /* domain string */ 834 /* user string */ 835 /* host string */ 836 /* LanManager response */ 837 /* NT response */ 838 839 0, /* zero termination */ 840 0, 0, 0, /* type-3 long, the 24 upper bits */ 841 842 SHORTPAIR(0x18), /* LanManager response length, twice */ 843 SHORTPAIR(0x18), 844 SHORTPAIR(lmrespoff), 845 0x0, 0x0, 846 847#if USE_NTRESPONSES 848 SHORTPAIR(0x18), /* NT-response length, twice */ 849 SHORTPAIR(0x18), 850 SHORTPAIR(ntrespoff), 851 0x0, 0x0, 852#else 853 0x0, 0x0, 854 0x0, 0x0, 855 0x0, 0x0, 856 0x0, 0x0, 857#endif 858 SHORTPAIR(domlen), 859 SHORTPAIR(domlen), 860 SHORTPAIR(domoff), 861 0x0, 0x0, 862 863 SHORTPAIR(userlen), 864 SHORTPAIR(userlen), 865 SHORTPAIR(useroff), 866 0x0, 0x0, 867 868 SHORTPAIR(hostlen), 869 SHORTPAIR(hostlen), 870 SHORTPAIR(hostoff), 871 0x0, 0x0, 872 873 0x0, 0x0, 874 0x0, 0x0, 875 0x0, 0x0, 876 0x0, 0x0, 877 878 LONGQUARTET(ntlm->flags)); 879 880 DEBUGASSERT(size == 64); 881 DEBUGASSERT(size == (size_t)lmrespoff); 882 883 /* We append the binary hashes */ 884 if(size < (NTLM_BUFSIZE - 0x18)) { 885 memcpy(&ntlmbuf[size], lmresp, 0x18); 886 size += 0x18; 887 } 888 889 DEBUG_OUT({ 890 fprintf(stderr, "**** TYPE3 header lmresp="); 891 ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); 892 }); 893 894#if USE_NTRESPONSES 895 if(size < (NTLM_BUFSIZE - 0x18)) { 896 DEBUGASSERT(size == (size_t)ntrespoff); 897 memcpy(&ntlmbuf[size], ntresp, 0x18); 898 size += 0x18; 899 } 900 901 DEBUG_OUT({ 902 fprintf(stderr, "\n ntresp="); 903 ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18); 904 }); 905 906#endif 907 908 DEBUG_OUT({ 909 fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", 910 LONGQUARTET(ntlm->flags), ntlm->flags); 911 ntlm_print_flags(stderr, ntlm->flags); 912 fprintf(stderr, "\n****\n"); 913 }); 914 915 /* Make sure that the domain, user and host strings fit in the 916 buffer before we copy them there. */ 917 if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) { 918 failf(data, "user + domain + host name too big"); 919 return CURLE_OUT_OF_MEMORY; 920 } 921 922 DEBUGASSERT(size == domoff); 923 if(unicode) 924 unicodecpy(&ntlmbuf[size], domain, domlen / 2); 925 else 926 memcpy(&ntlmbuf[size], domain, domlen); 927 928 size += domlen; 929 930 DEBUGASSERT(size == useroff); 931 if(unicode) 932 unicodecpy(&ntlmbuf[size], user, userlen / 2); 933 else 934 memcpy(&ntlmbuf[size], user, userlen); 935 936 size += userlen; 937 938 DEBUGASSERT(size == hostoff); 939 if(unicode) 940 unicodecpy(&ntlmbuf[size], host, hostlen / 2); 941 else 942 memcpy(&ntlmbuf[size], host, hostlen); 943 944 size += hostlen; 945 946 /* Convert domain, user, and host to ASCII but leave the rest as-is */ 947 res = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff], 948 size - domoff); 949 if(res) 950 return CURLE_CONV_FAILED; 951 952#endif 953 954 /* Return with binary blob encoded into base64 */ 955 return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen); 956} 957 958#endif /* USE_NTLM */ 959