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#include "setup.h" 23 24/* NTLM details: 25 26 http://davenport.sourceforge.net/ntlm.html 27 http://www.innovation.ch/java/ntlm.html 28*/ 29 30#ifndef CURL_DISABLE_HTTP 31#ifdef USE_NTLM 32 33#define DEBUG_ME 0 34 35/* -- WIN32 approved -- */ 36#include <stdio.h> 37#include <string.h> 38#include <stdarg.h> 39#include <stdlib.h> 40#include <ctype.h> 41 42#ifdef HAVE_UNISTD_H 43#include <unistd.h> 44#endif 45 46#if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) 47#include <netdb.h> 48#endif 49 50#include "urldata.h" 51#include "non-ascii.h" /* for Curl_convert_... prototypes */ 52#include "sendf.h" 53#include "rawstr.h" 54#include "curl_base64.h" 55#include "http_ntlm.h" 56#include "url.h" 57#include "curl_gethostname.h" 58#include "curl_memory.h" 59 60#define _MPRINTF_REPLACE /* use our functions only */ 61#include <curl/mprintf.h> 62 63/* "NTLMSSP" signature is always in ASCII regardless of the platform */ 64#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50" 65 66#ifdef USE_SSLEAY 67#include "ssluse.h" 68# ifdef USE_OPENSSL 69# include <openssl/des.h> 70# ifndef OPENSSL_NO_MD4 71# include <openssl/md4.h> 72# endif 73# include <openssl/md5.h> 74# include <openssl/ssl.h> 75# include <openssl/rand.h> 76# else 77# include <des.h> 78# ifndef OPENSSL_NO_MD4 79# include <md4.h> 80# endif 81# include <md5.h> 82# include <ssl.h> 83# include <rand.h> 84# endif 85 86#ifndef OPENSSL_VERSION_NUMBER 87#error "OPENSSL_VERSION_NUMBER not defined" 88#endif 89 90#if OPENSSL_VERSION_NUMBER < 0x00907001L 91#define DES_key_schedule des_key_schedule 92#define DES_cblock des_cblock 93#define DES_set_odd_parity des_set_odd_parity 94#define DES_set_key des_set_key 95#define DES_ecb_encrypt des_ecb_encrypt 96 97/* This is how things were done in the old days */ 98#define DESKEY(x) x 99#define DESKEYARG(x) x 100#else 101/* Modern version */ 102#define DESKEYARG(x) *x 103#define DESKEY(x) &x 104#endif 105 106#ifdef OPENSSL_NO_MD4 107/* This requires MD4, but OpenSSL was compiled without it */ 108#define USE_NTRESPONSES 0 109#define USE_NTLM2SESSION 0 110#endif 111 112#elif defined(USE_GNUTLS) 113 114#include "gtls.h" 115#include <gcrypt.h> 116 117#define MD5_DIGEST_LENGTH 16 118#define MD4_DIGEST_LENGTH 16 119 120#elif defined(USE_NSS) 121 122#include "curl_md4.h" 123#include "nssg.h" 124#include <nss.h> 125#include <pk11pub.h> 126#include <hasht.h> 127#define MD5_DIGEST_LENGTH MD5_LENGTH 128 129#elif defined(USE_WINDOWS_SSPI) 130 131#include "curl_sspi.h" 132 133#else 134# error "Can't compile NTLM support without a crypto library." 135#endif 136 137/* The last #include file should be: */ 138#include "memdebug.h" 139 140#ifndef USE_NTRESPONSES 141/* Define this to make the type-3 message include the NT response message */ 142#define USE_NTRESPONSES 1 143 144/* Define this to make the type-3 message include the NTLM2Session response 145 message, requires USE_NTRESPONSES. */ 146#define USE_NTLM2SESSION 1 147#endif 148 149#ifndef USE_WINDOWS_SSPI 150/* this function converts from the little endian format used in the incoming 151 package to whatever endian format we're using natively */ 152static unsigned int readint_le(unsigned char *buf) /* must point to a 153 4 bytes buffer*/ 154{ 155 return ((unsigned int)buf[0]) | ((unsigned int)buf[1] << 8) | 156 ((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24); 157} 158#endif 159 160#if DEBUG_ME 161# define DEBUG_OUT(x) x 162static void print_flags(FILE *handle, unsigned long flags) 163{ 164 if(flags & NTLMFLAG_NEGOTIATE_UNICODE) 165 fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE "); 166 if(flags & NTLMFLAG_NEGOTIATE_OEM) 167 fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM "); 168 if(flags & NTLMFLAG_REQUEST_TARGET) 169 fprintf(handle, "NTLMFLAG_REQUEST_TARGET "); 170 if(flags & (1<<3)) 171 fprintf(handle, "NTLMFLAG_UNKNOWN_3 "); 172 if(flags & NTLMFLAG_NEGOTIATE_SIGN) 173 fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN "); 174 if(flags & NTLMFLAG_NEGOTIATE_SEAL) 175 fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL "); 176 if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) 177 fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE "); 178 if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) 179 fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY "); 180 if(flags & NTLMFLAG_NEGOTIATE_NETWARE) 181 fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE "); 182 if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) 183 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY "); 184 if(flags & (1<<10)) 185 fprintf(handle, "NTLMFLAG_UNKNOWN_10 "); 186 if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS) 187 fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS "); 188 if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) 189 fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED "); 190 if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) 191 fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED "); 192 if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) 193 fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL "); 194 if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) 195 fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN "); 196 if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) 197 fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN "); 198 if(flags & NTLMFLAG_TARGET_TYPE_SERVER) 199 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER "); 200 if(flags & NTLMFLAG_TARGET_TYPE_SHARE) 201 fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE "); 202 if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) 203 fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY "); 204 if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) 205 fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE "); 206 if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) 207 fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE "); 208 if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) 209 fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY "); 210 if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) 211 fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO "); 212 if(flags & (1<<24)) 213 fprintf(handle, "NTLMFLAG_UNKNOWN_24 "); 214 if(flags & (1<<25)) 215 fprintf(handle, "NTLMFLAG_UNKNOWN_25 "); 216 if(flags & (1<<26)) 217 fprintf(handle, "NTLMFLAG_UNKNOWN_26 "); 218 if(flags & (1<<27)) 219 fprintf(handle, "NTLMFLAG_UNKNOWN_27 "); 220 if(flags & (1<<28)) 221 fprintf(handle, "NTLMFLAG_UNKNOWN_28 "); 222 if(flags & NTLMFLAG_NEGOTIATE_128) 223 fprintf(handle, "NTLMFLAG_NEGOTIATE_128 "); 224 if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) 225 fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE "); 226 if(flags & NTLMFLAG_NEGOTIATE_56) 227 fprintf(handle, "NTLMFLAG_NEGOTIATE_56 "); 228} 229 230static void print_hex(FILE *handle, const char *buf, size_t len) 231{ 232 const char *p = buf; 233 fprintf(stderr, "0x"); 234 while(len-- > 0) 235 fprintf(stderr, "%02.2x", (unsigned int)*p++); 236} 237#else 238# define DEBUG_OUT(x) 239#endif 240 241/* 242 (*) = A "security buffer" is a triplet consisting of two shorts and one 243 long: 244 245 1. a 'short' containing the length of the buffer in bytes 246 2. a 'short' containing the allocated space for the buffer in bytes 247 3. a 'long' containing the offset to the start of the buffer from the 248 beginning of the NTLM message, in bytes. 249*/ 250 251 252CURLntlm Curl_input_ntlm(struct connectdata *conn, 253 bool proxy, /* if proxy or not */ 254 const char *header) /* rest of the www-authenticate: 255 header */ 256{ 257 /* point to the correct struct with this */ 258 struct ntlmdata *ntlm; 259#ifndef USE_WINDOWS_SSPI 260 static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 }; 261#endif 262 263#ifdef USE_NSS 264 if(CURLE_OK != Curl_nss_force_init(conn->data)) 265 return CURLNTLM_BAD; 266#endif 267 268 ntlm = proxy?&conn->proxyntlm:&conn->ntlm; 269 270 /* skip initial whitespaces */ 271 while(*header && ISSPACE(*header)) 272 header++; 273 274 if(checkprefix("NTLM", header)) { 275 header += strlen("NTLM"); 276 277 while(*header && ISSPACE(*header)) 278 header++; 279 280 if(*header) { 281 /* We got a type-2 message here: 282 283 Index Description Content 284 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 285 (0x4e544c4d53535000) 286 8 NTLM Message Type long (0x02000000) 287 12 Target Name security buffer(*) 288 20 Flags long 289 24 Challenge 8 bytes 290 (32) Context (optional) 8 bytes (two consecutive longs) 291 (40) Target Information (optional) security buffer(*) 292 32 (48) start of data block 293 */ 294 size_t size; 295 unsigned char *buffer; 296 size = Curl_base64_decode(header, &buffer); 297 if(!buffer) 298 return CURLNTLM_BAD; 299 300 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */ 301 302#ifdef USE_WINDOWS_SSPI 303 ntlm->type_2 = malloc(size+1); 304 if(ntlm->type_2 == NULL) { 305 free(buffer); 306 return CURLE_OUT_OF_MEMORY; 307 } 308 ntlm->n_type_2 = size; 309 memcpy(ntlm->type_2, buffer, size); 310#else 311 ntlm->flags = 0; 312 313 if((size < 32) || 314 (memcmp(buffer, NTLMSSP_SIGNATURE, 8) != 0) || 315 (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0)) { 316 /* This was not a good enough type-2 message */ 317 free(buffer); 318 return CURLNTLM_BAD; 319 } 320 321 ntlm->flags = readint_le(&buffer[20]); 322 memcpy(ntlm->nonce, &buffer[24], 8); 323 324 DEBUG_OUT({ 325 fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags); 326 print_flags(stderr, ntlm->flags); 327 fprintf(stderr, "\n nonce="); 328 print_hex(stderr, (char *)ntlm->nonce, 8); 329 fprintf(stderr, "\n****\n"); 330 fprintf(stderr, "**** Header %s\n ", header); 331 }); 332#endif 333 free(buffer); 334 } 335 else { 336 if(ntlm->state >= NTLMSTATE_TYPE1) 337 return CURLNTLM_BAD; 338 339 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */ 340 } 341 } 342 return CURLNTLM_FINE; 343} 344 345#ifndef USE_WINDOWS_SSPI 346 347#ifdef USE_SSLEAY 348/* 349 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The 350 * key schedule ks is also set. 351 */ 352static void setup_des_key(const unsigned char *key_56, 353 DES_key_schedule DESKEYARG(ks)) 354{ 355 DES_cblock key; 356 357 key[0] = key_56[0]; 358 key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); 359 key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); 360 key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); 361 key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); 362 key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); 363 key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); 364 key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); 365 366 DES_set_odd_parity(&key); 367 DES_set_key(&key, ks); 368} 369 370#else /* defined(USE_SSLEAY) */ 371 372/* 373 * Turns a 56 bit key into the 64 bit, odd parity key. Used by GnuTLS and NSS. 374 */ 375static void extend_key_56_to_64(const unsigned char *key_56, char *key) 376{ 377 key[0] = key_56[0]; 378 key[1] = (unsigned char)(((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1)); 379 key[2] = (unsigned char)(((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2)); 380 key[3] = (unsigned char)(((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3)); 381 key[4] = (unsigned char)(((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4)); 382 key[5] = (unsigned char)(((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5)); 383 key[6] = (unsigned char)(((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6)); 384 key[7] = (unsigned char) ((key_56[6] << 1) & 0xFF); 385} 386 387#if defined(USE_GNUTLS) 388 389/* 390 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. 391 */ 392static void setup_des_key(const unsigned char *key_56, 393 gcry_cipher_hd_t *des) 394{ 395 char key[8]; 396 extend_key_56_to_64(key_56, key); 397 gcry_cipher_setkey(*des, key, 8); 398} 399 400#elif defined(USE_NSS) 401 402/* 403 * Expands a 56 bit key KEY_56 to 64 bit and encrypts 64 bit of data, using 404 * the expanded key. The caller is responsible for giving 64 bit of valid 405 * data is IN and (at least) 64 bit large buffer as OUT. 406 */ 407static bool encrypt_des(const unsigned char *in, unsigned char *out, 408 const unsigned char *key_56) 409{ 410 const CK_MECHANISM_TYPE mech = CKM_DES_ECB; /* DES cipher in ECB mode */ 411 PK11SlotInfo *slot = NULL; 412 char key[8]; /* expanded 64 bit key */ 413 SECItem key_item; 414 PK11SymKey *symkey = NULL; 415 SECItem *param = NULL; 416 PK11Context *ctx = NULL; 417 int out_len; /* not used, required by NSS */ 418 bool rv = FALSE; 419 420 /* use internal slot for DES encryption (requires NSS to be initialized) */ 421 slot = PK11_GetInternalKeySlot(); 422 if(!slot) 423 return FALSE; 424 425 /* expand the 56 bit key to 64 bit and wrap by NSS */ 426 extend_key_56_to_64(key_56, key); 427 key_item.data = (unsigned char *)key; 428 key_item.len = /* hard-wired */ 8; 429 symkey = PK11_ImportSymKey(slot, mech, PK11_OriginUnwrap, CKA_ENCRYPT, 430 &key_item, NULL); 431 if(!symkey) 432 goto fail; 433 434 /* create DES encryption context */ 435 param = PK11_ParamFromIV(mech, /* no IV in ECB mode */ NULL); 436 if(!param) 437 goto fail; 438 ctx = PK11_CreateContextBySymKey(mech, CKA_ENCRYPT, symkey, param); 439 if(!ctx) 440 goto fail; 441 442 /* perform the encryption */ 443 if(SECSuccess == PK11_CipherOp(ctx, out, &out_len, /* outbuflen */ 8, 444 (unsigned char *)in, /* inbuflen */ 8) 445 && SECSuccess == PK11_Finalize(ctx)) 446 rv = /* all OK */ TRUE; 447 448fail: 449 /* cleanup */ 450 if(ctx) 451 PK11_DestroyContext(ctx, PR_TRUE); 452 if(symkey) 453 PK11_FreeSymKey(symkey); 454 if(param) 455 SECITEM_FreeItem(param, PR_TRUE); 456 PK11_FreeSlot(slot); 457 return rv; 458} 459 460#endif /* defined(USE_NSS) */ 461 462#endif /* defined(USE_SSLEAY) */ 463 464 /* 465 * takes a 21 byte array and treats it as 3 56-bit DES keys. The 466 * 8 byte plaintext is encrypted with each key and the resulting 24 467 * bytes are stored in the results array. 468 */ 469static void lm_resp(const unsigned char *keys, 470 const unsigned char *plaintext, 471 unsigned char *results) 472{ 473#ifdef USE_SSLEAY 474 DES_key_schedule ks; 475 476 setup_des_key(keys, DESKEY(ks)); 477 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, 478 DESKEY(ks), DES_ENCRYPT); 479 480 setup_des_key(keys+7, DESKEY(ks)); 481 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8), 482 DESKEY(ks), DES_ENCRYPT); 483 484 setup_des_key(keys+14, DESKEY(ks)); 485 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), 486 DESKEY(ks), DES_ENCRYPT); 487#elif defined(USE_GNUTLS) 488 gcry_cipher_hd_t des; 489 490 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 491 setup_des_key(keys, &des); 492 gcry_cipher_encrypt(des, results, 8, plaintext, 8); 493 gcry_cipher_close(des); 494 495 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 496 setup_des_key(keys+7, &des); 497 gcry_cipher_encrypt(des, results+8, 8, plaintext, 8); 498 gcry_cipher_close(des); 499 500 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 501 setup_des_key(keys+14, &des); 502 gcry_cipher_encrypt(des, results+16, 8, plaintext, 8); 503 gcry_cipher_close(des); 504#elif defined(USE_NSS) 505 encrypt_des(plaintext, results, keys); 506 encrypt_des(plaintext, results+8, keys+7); 507 encrypt_des(plaintext, results+16, keys+14); 508#endif 509} 510 511 512/* 513 * Set up lanmanager hashed password 514 */ 515static void mk_lm_hash(struct SessionHandle *data, 516 const char *password, 517 unsigned char *lmbuffer /* 21 bytes */) 518{ 519 CURLcode res; 520 unsigned char pw[14]; 521 static const unsigned char magic[] = { 522 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 /* i.e. KGS!@#$% */ 523 }; 524 size_t len = CURLMIN(strlen(password), 14); 525 526 Curl_strntoupper((char *)pw, password, len); 527 memset(&pw[len], 0, 14-len); 528 529 /* 530 * The LanManager hashed password needs to be created using the 531 * password in the network encoding not the host encoding. 532 */ 533 res = Curl_convert_to_network(data, (char *)pw, 14); 534 if(res) 535 return; 536 537 { 538 /* Create LanManager hashed password. */ 539 540#ifdef USE_SSLEAY 541 DES_key_schedule ks; 542 543 setup_des_key(pw, DESKEY(ks)); 544 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, 545 DESKEY(ks), DES_ENCRYPT); 546 547 setup_des_key(pw+7, DESKEY(ks)); 548 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8), 549 DESKEY(ks), DES_ENCRYPT); 550#elif defined(USE_GNUTLS) 551 gcry_cipher_hd_t des; 552 553 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 554 setup_des_key(pw, &des); 555 gcry_cipher_encrypt(des, lmbuffer, 8, magic, 8); 556 gcry_cipher_close(des); 557 558 gcry_cipher_open(&des, GCRY_CIPHER_DES, GCRY_CIPHER_MODE_ECB, 0); 559 setup_des_key(pw+7, &des); 560 gcry_cipher_encrypt(des, lmbuffer+8, 8, magic, 8); 561 gcry_cipher_close(des); 562#elif defined(USE_NSS) 563 encrypt_des(magic, lmbuffer, pw); 564 encrypt_des(magic, lmbuffer+8, pw+7); 565#endif 566 567 memset(lmbuffer + 16, 0, 21 - 16); 568 } 569} 570 571#if USE_NTRESPONSES 572static void ascii_to_unicode_le(unsigned char *dest, const char *src, 573 size_t srclen) 574{ 575 size_t i; 576 for(i=0; i<srclen; i++) { 577 dest[2*i] = (unsigned char)src[i]; 578 dest[2*i+1] = '\0'; 579 } 580} 581 582/* 583 * Set up nt hashed passwords 584 */ 585static CURLcode mk_nt_hash(struct SessionHandle *data, 586 const char *password, 587 unsigned char *ntbuffer /* 21 bytes */) 588{ 589 size_t len = strlen(password); 590 unsigned char *pw = malloc(len*2); 591 CURLcode result; 592 if(!pw) 593 return CURLE_OUT_OF_MEMORY; 594 595 ascii_to_unicode_le(pw, password, len); 596 597 /* 598 * The NT hashed password needs to be created using the password in the 599 * network encoding not the host encoding. 600 */ 601 result = Curl_convert_to_network(data, (char *)pw, len*2); 602 if(result) 603 return result; 604 605 { 606 /* Create NT hashed password. */ 607#ifdef USE_SSLEAY 608 MD4_CTX MD4pw; 609 MD4_Init(&MD4pw); 610 MD4_Update(&MD4pw, pw, 2*len); 611 MD4_Final(ntbuffer, &MD4pw); 612#elif defined(USE_GNUTLS) 613 gcry_md_hd_t MD4pw; 614 gcry_md_open(&MD4pw, GCRY_MD_MD4, 0); 615 gcry_md_write(MD4pw, pw, 2*len); 616 memcpy (ntbuffer, gcry_md_read (MD4pw, 0), MD4_DIGEST_LENGTH); 617 gcry_md_close(MD4pw); 618#elif defined(USE_NSS) 619 Curl_md4it(ntbuffer, pw, 2*len); 620#endif 621 622 memset(ntbuffer + 16, 0, 21 - 16); 623 } 624 625 free(pw); 626 return CURLE_OK; 627} 628#endif 629 630 631#endif 632 633#ifdef USE_WINDOWS_SSPI 634 635static void 636ntlm_sspi_cleanup(struct ntlmdata *ntlm) 637{ 638 if(ntlm->type_2) { 639 free(ntlm->type_2); 640 ntlm->type_2 = NULL; 641 } 642 if(ntlm->has_handles) { 643 s_pSecFn->DeleteSecurityContext(&ntlm->c_handle); 644 s_pSecFn->FreeCredentialsHandle(&ntlm->handle); 645 ntlm->has_handles = 0; 646 } 647 if(ntlm->p_identity) { 648 if(ntlm->identity.User) free(ntlm->identity.User); 649 if(ntlm->identity.Password) free(ntlm->identity.Password); 650 if(ntlm->identity.Domain) free(ntlm->identity.Domain); 651 ntlm->p_identity = NULL; 652 } 653} 654 655#endif 656 657#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff) 658#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \ 659 (((x) >>16)&0xff), (((x)>>24) & 0xff) 660 661#define HOSTNAME_MAX 1024 662 663#ifndef USE_WINDOWS_SSPI 664/* copy the source to the destination and fill in zeroes in every 665 other destination byte! */ 666static void unicodecpy(unsigned char *dest, 667 const char *src, size_t length) 668{ 669 size_t i; 670 for(i=0; i<length; i++) { 671 dest[2*i] = (unsigned char)src[i]; 672 dest[2*i+1] = '\0'; 673 } 674} 675#endif 676 677/* this is for creating ntlm header output */ 678CURLcode Curl_output_ntlm(struct connectdata *conn, 679 bool proxy) 680{ 681 const char *domain=""; /* empty */ 682 char host [HOSTNAME_MAX+ 1] = ""; /* empty */ 683#ifndef USE_WINDOWS_SSPI 684 size_t domlen = strlen(domain); 685 size_t hostlen = strlen(host); 686 size_t hostoff; /* host name offset */ 687 size_t domoff; /* domain name offset */ 688#endif 689 size_t size; 690 char *base64=NULL; 691 unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very 692 long */ 693 694 /* point to the address of the pointer that holds the string to sent to the 695 server, which is for a plain host or for a HTTP proxy */ 696 char **allocuserpwd; 697 698 /* point to the name and password for this */ 699 const char *userp; 700 const char *passwdp; 701 /* point to the correct struct with this */ 702 struct ntlmdata *ntlm; 703 struct auth *authp; 704 705 DEBUGASSERT(conn); 706 DEBUGASSERT(conn->data); 707 708#ifdef USE_NSS 709 if(CURLE_OK != Curl_nss_force_init(conn->data)) 710 return CURLE_OUT_OF_MEMORY; 711#endif 712 713 if(proxy) { 714 allocuserpwd = &conn->allocptr.proxyuserpwd; 715 userp = conn->proxyuser; 716 passwdp = conn->proxypasswd; 717 ntlm = &conn->proxyntlm; 718 authp = &conn->data->state.authproxy; 719 } 720 else { 721 allocuserpwd = &conn->allocptr.userpwd; 722 userp = conn->user; 723 passwdp = conn->passwd; 724 ntlm = &conn->ntlm; 725 authp = &conn->data->state.authhost; 726 } 727 authp->done = FALSE; 728 729 /* not set means empty */ 730 if(!userp) 731 userp=""; 732 733 if(!passwdp) 734 passwdp=""; 735 736#ifdef USE_WINDOWS_SSPI 737 if(s_hSecDll == NULL) { 738 /* not thread safe and leaks - use curl_global_init() to avoid */ 739 CURLcode err = Curl_sspi_global_init(); 740 if(s_hSecDll == NULL) 741 return err; 742 } 743#endif 744 745 switch(ntlm->state) { 746 case NTLMSTATE_TYPE1: 747 default: /* for the weird cases we (re)start here */ 748#ifdef USE_WINDOWS_SSPI 749 { 750 SecBuffer buf; 751 SecBufferDesc desc; 752 SECURITY_STATUS status; 753 ULONG attrs; 754 const char *user; 755 int domlen; 756 TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */ 757 758 ntlm_sspi_cleanup(ntlm); 759 760 user = strchr(userp, '\\'); 761 if(!user) 762 user = strchr(userp, '/'); 763 764 if(user) { 765 domain = userp; 766 domlen = user - userp; 767 user++; 768 } 769 else { 770 user = userp; 771 domain = ""; 772 domlen = 0; 773 } 774 775 if(user && *user) { 776 /* note: initialize all of this before doing the mallocs so that 777 * it can be cleaned up later without leaking memory. 778 */ 779 ntlm->p_identity = &ntlm->identity; 780 memset(ntlm->p_identity, 0, sizeof(*ntlm->p_identity)); 781 if((ntlm->identity.User = (unsigned char *)strdup(user)) == NULL) 782 return CURLE_OUT_OF_MEMORY; 783 ntlm->identity.UserLength = strlen(user); 784 if((ntlm->identity.Password = (unsigned char *)strdup(passwdp)) == NULL) 785 return CURLE_OUT_OF_MEMORY; 786 ntlm->identity.PasswordLength = strlen(passwdp); 787 if((ntlm->identity.Domain = malloc(domlen+1)) == NULL) 788 return CURLE_OUT_OF_MEMORY; 789 strncpy((char *)ntlm->identity.Domain, domain, domlen); 790 ntlm->identity.Domain[domlen] = '\0'; 791 ntlm->identity.DomainLength = domlen; 792 ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; 793 } 794 else { 795 ntlm->p_identity = NULL; 796 } 797 798 if(s_pSecFn->AcquireCredentialsHandleA( 799 NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity, 800 NULL, NULL, &ntlm->handle, &tsDummy 801 ) != SEC_E_OK) { 802 return CURLE_OUT_OF_MEMORY; 803 } 804 805 desc.ulVersion = SECBUFFER_VERSION; 806 desc.cBuffers = 1; 807 desc.pBuffers = &buf; 808 buf.cbBuffer = sizeof(ntlmbuf); 809 buf.BufferType = SECBUFFER_TOKEN; 810 buf.pvBuffer = ntlmbuf; 811 812 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, NULL, 813 (char *) host, 814 ISC_REQ_CONFIDENTIALITY | 815 ISC_REQ_REPLAY_DETECT | 816 ISC_REQ_CONNECTION, 817 0, SECURITY_NETWORK_DREP, 818 NULL, 0, 819 &ntlm->c_handle, &desc, 820 &attrs, &tsDummy); 821 822 if(status == SEC_I_COMPLETE_AND_CONTINUE || 823 status == SEC_I_CONTINUE_NEEDED) { 824 s_pSecFn->CompleteAuthToken(&ntlm->c_handle, &desc); 825 } 826 else if(status != SEC_E_OK) { 827 s_pSecFn->FreeCredentialsHandle(&ntlm->handle); 828 return CURLE_RECV_ERROR; 829 } 830 831 ntlm->has_handles = 1; 832 size = buf.cbBuffer; 833 } 834#else 835 hostoff = 0; 836 domoff = hostoff + hostlen; /* This is 0: remember that host and domain 837 are empty */ 838 839 /* Create and send a type-1 message: 840 841 Index Description Content 842 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 843 (0x4e544c4d53535000) 844 8 NTLM Message Type long (0x01000000) 845 12 Flags long 846 16 Supplied Domain security buffer(*) 847 24 Supplied Workstation security buffer(*) 848 32 start of data block 849 850 */ 851#if USE_NTLM2SESSION 852#define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY 853#else 854#define NTLM2FLAG 0 855#endif 856 snprintf((char *)ntlmbuf, sizeof(ntlmbuf), NTLMSSP_SIGNATURE "%c" 857 "\x01%c%c%c" /* 32-bit type = 1 */ 858 "%c%c%c%c" /* 32-bit NTLM flag field */ 859 "%c%c" /* domain length */ 860 "%c%c" /* domain allocated space */ 861 "%c%c" /* domain name offset */ 862 "%c%c" /* 2 zeroes */ 863 "%c%c" /* host length */ 864 "%c%c" /* host allocated space */ 865 "%c%c" /* host name offset */ 866 "%c%c" /* 2 zeroes */ 867 "%s" /* host name */ 868 "%s", /* domain string */ 869 0, /* trailing zero */ 870 0,0,0, /* part of type-1 long */ 871 872 LONGQUARTET( 873 NTLMFLAG_NEGOTIATE_OEM| 874 NTLMFLAG_REQUEST_TARGET| 875 NTLMFLAG_NEGOTIATE_NTLM_KEY| 876 NTLM2FLAG| 877 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN 878 ), 879 SHORTPAIR(domlen), 880 SHORTPAIR(domlen), 881 SHORTPAIR(domoff), 882 0,0, 883 SHORTPAIR(hostlen), 884 SHORTPAIR(hostlen), 885 SHORTPAIR(hostoff), 886 0,0, 887 host /* this is empty */, domain /* this is empty */); 888 889 /* initial packet length */ 890 size = 32 + hostlen + domlen; 891#endif 892 893 DEBUG_OUT({ 894 fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x " 895 "0x%08.8x ", 896 LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM| 897 NTLMFLAG_REQUEST_TARGET| 898 NTLMFLAG_NEGOTIATE_NTLM_KEY| 899 NTLM2FLAG| 900 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN), 901 NTLMFLAG_NEGOTIATE_OEM| 902 NTLMFLAG_REQUEST_TARGET| 903 NTLMFLAG_NEGOTIATE_NTLM_KEY| 904 NTLM2FLAG| 905 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); 906 print_flags(stderr, 907 NTLMFLAG_NEGOTIATE_OEM| 908 NTLMFLAG_REQUEST_TARGET| 909 NTLMFLAG_NEGOTIATE_NTLM_KEY| 910 NTLM2FLAG| 911 NTLMFLAG_NEGOTIATE_ALWAYS_SIGN); 912 fprintf(stderr, "\n****\n"); 913 }); 914 915 /* now size is the size of the base64 encoded package size */ 916 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64); 917 918 if(size >0 ) { 919 Curl_safefree(*allocuserpwd); 920 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", 921 proxy?"Proxy-":"", 922 base64); 923 DEBUG_OUT(fprintf(stderr, "**** Header %s\n ", *allocuserpwd)); 924 free(base64); 925 } 926 else 927 return CURLE_OUT_OF_MEMORY; /* FIX TODO */ 928 929 break; 930 931 case NTLMSTATE_TYPE2: 932 /* We received the type-2 message already, create a type-3 message: 933 934 Index Description Content 935 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 936 (0x4e544c4d53535000) 937 8 NTLM Message Type long (0x03000000) 938 12 LM/LMv2 Response security buffer(*) 939 20 NTLM/NTLMv2 Response security buffer(*) 940 28 Domain Name security buffer(*) 941 36 User Name security buffer(*) 942 44 Workstation Name security buffer(*) 943 (52) Session Key (optional) security buffer(*) 944 (60) Flags (optional) long 945 52 (64) start of data block 946 947 */ 948 949 { 950#ifdef USE_WINDOWS_SSPI 951 SecBuffer type_2, type_3; 952 SecBufferDesc type_2_desc, type_3_desc; 953 SECURITY_STATUS status; 954 ULONG attrs; 955 TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */ 956 957 type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION; 958 type_2_desc.cBuffers = type_3_desc.cBuffers = 1; 959 type_2_desc.pBuffers = &type_2; 960 type_3_desc.pBuffers = &type_3; 961 962 type_2.BufferType = SECBUFFER_TOKEN; 963 type_2.pvBuffer = ntlm->type_2; 964 type_2.cbBuffer = ntlm->n_type_2; 965 type_3.BufferType = SECBUFFER_TOKEN; 966 type_3.pvBuffer = ntlmbuf; 967 type_3.cbBuffer = sizeof(ntlmbuf); 968 969 status = s_pSecFn->InitializeSecurityContextA(&ntlm->handle, 970 &ntlm->c_handle, 971 (char *) host, 972 ISC_REQ_CONFIDENTIALITY | 973 ISC_REQ_REPLAY_DETECT | 974 ISC_REQ_CONNECTION, 975 0, SECURITY_NETWORK_DREP, 976 &type_2_desc, 977 0, &ntlm->c_handle, 978 &type_3_desc, 979 &attrs, &tsDummy); 980 981 if(status != SEC_E_OK) 982 return CURLE_RECV_ERROR; 983 984 size = type_3.cbBuffer; 985 986 ntlm_sspi_cleanup(ntlm); 987 988#else 989 int lmrespoff; 990 unsigned char lmresp[24]; /* fixed-size */ 991#if USE_NTRESPONSES 992 int ntrespoff; 993 unsigned char ntresp[24]; /* fixed-size */ 994#endif 995 bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE)?TRUE:FALSE; 996 size_t useroff; 997 const char *user; 998 size_t userlen; 999 CURLcode res; 1000 1001 user = strchr(userp, '\\'); 1002 if(!user) 1003 user = strchr(userp, '/'); 1004 1005 if(user) { 1006 domain = userp; 1007 domlen = (user - domain); 1008 user++; 1009 } 1010 else 1011 user = userp; 1012 userlen = strlen(user); 1013 1014 if(Curl_gethostname(host, HOSTNAME_MAX)) { 1015 infof(conn->data, "gethostname() failed, continuing without!"); 1016 hostlen = 0; 1017 } 1018 else { 1019 /* If the workstation if configured with a full DNS name (i.e. 1020 * workstation.somewhere.net) gethostname() returns the fully qualified 1021 * name, which NTLM doesn't like. 1022 */ 1023 char *dot = strchr(host, '.'); 1024 if(dot) 1025 *dot = '\0'; 1026 hostlen = strlen(host); 1027 } 1028 1029 if(unicode) { 1030 domlen = domlen * 2; 1031 userlen = userlen * 2; 1032 hostlen = hostlen * 2; 1033 } 1034 1035#if USE_NTLM2SESSION 1036 /* We don't support NTLM2 if we don't have USE_NTRESPONSES */ 1037 if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) { 1038 unsigned char ntbuffer[0x18]; 1039 unsigned char tmp[0x18]; 1040 unsigned char md5sum[MD5_DIGEST_LENGTH]; 1041 unsigned char entropy[8]; 1042 1043 /* Need to create 8 bytes random data */ 1044#ifdef USE_SSLEAY 1045 MD5_CTX MD5pw; 1046 Curl_ossl_seed(conn->data); /* Initiate the seed if not already done */ 1047 RAND_bytes(entropy,8); 1048#elif defined(USE_GNUTLS) 1049 gcry_md_hd_t MD5pw; 1050 Curl_gtls_seed(conn->data); /* Initiate the seed if not already done */ 1051 gcry_randomize(entropy, 8, GCRY_STRONG_RANDOM); 1052#elif defined(USE_NSS) 1053 PK11Context *MD5pw; 1054 unsigned int outlen; 1055 Curl_nss_seed(conn->data); /* Initiate the seed if not already done */ 1056 PK11_GenerateRandom(entropy, 8); 1057#endif 1058 1059 /* 8 bytes random data as challenge in lmresp */ 1060 memcpy(lmresp,entropy,8); 1061 /* Pad with zeros */ 1062 memset(lmresp+8,0,0x10); 1063 1064 /* Fill tmp with challenge(nonce?) + entropy */ 1065 memcpy(tmp,&ntlm->nonce[0],8); 1066 memcpy(tmp+8,entropy,8); 1067 1068#ifdef USE_SSLEAY 1069 MD5_Init(&MD5pw); 1070 MD5_Update(&MD5pw, tmp, 16); 1071 MD5_Final(md5sum, &MD5pw); 1072#elif defined(USE_GNUTLS) 1073 gcry_md_open(&MD5pw, GCRY_MD_MD5, 0); 1074 gcry_md_write(MD5pw, tmp, MD5_DIGEST_LENGTH); 1075 memcpy(md5sum, gcry_md_read (MD5pw, 0), MD5_DIGEST_LENGTH); 1076 gcry_md_close(MD5pw); 1077#elif defined(USE_NSS) 1078 MD5pw = PK11_CreateDigestContext(SEC_OID_MD5); 1079 PK11_DigestOp(MD5pw, tmp, 16); 1080 PK11_DigestFinal(MD5pw, md5sum, &outlen, MD5_DIGEST_LENGTH); 1081 PK11_DestroyContext(MD5pw, PR_TRUE); 1082#endif 1083 1084 /* We shall only use the first 8 bytes of md5sum, 1085 but the des code in lm_resp only encrypt the first 8 bytes */ 1086 if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY) 1087 return CURLE_OUT_OF_MEMORY; 1088 lm_resp(ntbuffer, md5sum, ntresp); 1089 1090 /* End of NTLM2 Session code */ 1091 } 1092 else 1093#endif 1094 { 1095 1096#if USE_NTRESPONSES 1097 unsigned char ntbuffer[0x18]; 1098#endif 1099 unsigned char lmbuffer[0x18]; 1100 1101#if USE_NTRESPONSES 1102 if(mk_nt_hash(conn->data, passwdp, ntbuffer) == CURLE_OUT_OF_MEMORY) 1103 return CURLE_OUT_OF_MEMORY; 1104 lm_resp(ntbuffer, &ntlm->nonce[0], ntresp); 1105#endif 1106 1107 mk_lm_hash(conn->data, passwdp, lmbuffer); 1108 lm_resp(lmbuffer, &ntlm->nonce[0], lmresp); 1109 /* A safer but less compatible alternative is: 1110 * lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); 1111 * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */ 1112 } 1113 1114 lmrespoff = 64; /* size of the message header */ 1115#if USE_NTRESPONSES 1116 ntrespoff = lmrespoff + 0x18; 1117 domoff = ntrespoff + 0x18; 1118#else 1119 domoff = lmrespoff + 0x18; 1120#endif 1121 useroff = domoff + domlen; 1122 hostoff = useroff + userlen; 1123 1124 /* Create the big type-3 message binary blob */ 1125 size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf), 1126 NTLMSSP_SIGNATURE "%c" 1127 "\x03%c%c%c" /* type-3, 32 bits */ 1128 1129 "%c%c" /* LanManager length */ 1130 "%c%c" /* LanManager allocated space */ 1131 "%c%c" /* LanManager offset */ 1132 "%c%c" /* 2 zeroes */ 1133 1134 "%c%c" /* NT-response length */ 1135 "%c%c" /* NT-response allocated space */ 1136 "%c%c" /* NT-response offset */ 1137 "%c%c" /* 2 zeroes */ 1138 1139 "%c%c" /* domain length */ 1140 "%c%c" /* domain allocated space */ 1141 "%c%c" /* domain name offset */ 1142 "%c%c" /* 2 zeroes */ 1143 1144 "%c%c" /* user length */ 1145 "%c%c" /* user allocated space */ 1146 "%c%c" /* user offset */ 1147 "%c%c" /* 2 zeroes */ 1148 1149 "%c%c" /* host length */ 1150 "%c%c" /* host allocated space */ 1151 "%c%c" /* host offset */ 1152 "%c%c" /* 2 zeroes */ 1153 1154 "%c%c" /* session key length (unknown purpose) */ 1155 "%c%c" /* session key allocated space (unknown purpose) */ 1156 "%c%c" /* session key offset (unknown purpose) */ 1157 "%c%c" /* 2 zeroes */ 1158 1159 "%c%c%c%c" /* flags */ 1160 1161 /* domain string */ 1162 /* user string */ 1163 /* host string */ 1164 /* LanManager response */ 1165 /* NT response */ 1166 , 1167 0, /* zero termination */ 1168 0,0,0, /* type-3 long, the 24 upper bits */ 1169 1170 SHORTPAIR(0x18), /* LanManager response length, twice */ 1171 SHORTPAIR(0x18), 1172 SHORTPAIR(lmrespoff), 1173 0x0, 0x0, 1174 1175#if USE_NTRESPONSES 1176 SHORTPAIR(0x18), /* NT-response length, twice */ 1177 SHORTPAIR(0x18), 1178 SHORTPAIR(ntrespoff), 1179 0x0, 0x0, 1180#else 1181 0x0, 0x0, 1182 0x0, 0x0, 1183 0x0, 0x0, 1184 0x0, 0x0, 1185#endif 1186 SHORTPAIR(domlen), 1187 SHORTPAIR(domlen), 1188 SHORTPAIR(domoff), 1189 0x0, 0x0, 1190 1191 SHORTPAIR(userlen), 1192 SHORTPAIR(userlen), 1193 SHORTPAIR(useroff), 1194 0x0, 0x0, 1195 1196 SHORTPAIR(hostlen), 1197 SHORTPAIR(hostlen), 1198 SHORTPAIR(hostoff), 1199 0x0, 0x0, 1200 1201 0x0, 0x0, 1202 0x0, 0x0, 1203 0x0, 0x0, 1204 0x0, 0x0, 1205 1206 LONGQUARTET(ntlm->flags)); 1207 DEBUGASSERT(size==64); 1208 1209 DEBUGASSERT(size == (size_t)lmrespoff); 1210 /* We append the binary hashes */ 1211 if(size < (sizeof(ntlmbuf) - 0x18)) { 1212 memcpy(&ntlmbuf[size], lmresp, 0x18); 1213 size += 0x18; 1214 } 1215 1216 DEBUG_OUT({ 1217 fprintf(stderr, "**** TYPE3 header lmresp="); 1218 print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18); 1219 }); 1220 1221#if USE_NTRESPONSES 1222 if(size < (sizeof(ntlmbuf) - 0x18)) { 1223 DEBUGASSERT(size == (size_t)ntrespoff); 1224 memcpy(&ntlmbuf[size], ntresp, 0x18); 1225 size += 0x18; 1226 } 1227 1228 DEBUG_OUT({ 1229 fprintf(stderr, "\n ntresp="); 1230 print_hex(stderr, (char *)&ntlmbuf[ntrespoff], 0x18); 1231 }); 1232 1233#endif 1234 1235 DEBUG_OUT({ 1236 fprintf(stderr, "\n flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ", 1237 LONGQUARTET(ntlm->flags), ntlm->flags); 1238 print_flags(stderr, ntlm->flags); 1239 fprintf(stderr, "\n****\n"); 1240 }); 1241 1242 1243 /* Make sure that the domain, user and host strings fit in the target 1244 buffer before we copy them there. */ 1245 if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) { 1246 failf(conn->data, "user + domain + host name too big"); 1247 return CURLE_OUT_OF_MEMORY; 1248 } 1249 1250 DEBUGASSERT(size == domoff); 1251 if(unicode) 1252 unicodecpy(&ntlmbuf[size], domain, domlen/2); 1253 else 1254 memcpy(&ntlmbuf[size], domain, domlen); 1255 1256 size += domlen; 1257 1258 DEBUGASSERT(size == useroff); 1259 if(unicode) 1260 unicodecpy(&ntlmbuf[size], user, userlen/2); 1261 else 1262 memcpy(&ntlmbuf[size], user, userlen); 1263 1264 size += userlen; 1265 1266 DEBUGASSERT(size == hostoff); 1267 if(unicode) 1268 unicodecpy(&ntlmbuf[size], host, hostlen/2); 1269 else 1270 memcpy(&ntlmbuf[size], host, hostlen); 1271 1272 size += hostlen; 1273 1274 /* convert domain, user, and host to ASCII but leave the rest as-is */ 1275 res = Curl_convert_to_network(conn->data, (char *)&ntlmbuf[domoff], 1276 size-domoff); 1277 if(res) 1278 return CURLE_CONV_FAILED; 1279 1280#endif 1281 1282 /* convert the binary blob into base64 */ 1283 size = Curl_base64_encode(NULL, (char *)ntlmbuf, size, &base64); 1284 1285 if(size >0 ) { 1286 Curl_safefree(*allocuserpwd); 1287 *allocuserpwd = aprintf("%sAuthorization: NTLM %s\r\n", 1288 proxy?"Proxy-":"", 1289 base64); 1290 DEBUG_OUT(fprintf(stderr, "**** %s\n ", *allocuserpwd)); 1291 free(base64); 1292 } 1293 else 1294 return CURLE_OUT_OF_MEMORY; /* FIX TODO */ 1295 1296 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ 1297 authp->done = TRUE; 1298 } 1299 break; 1300 1301 case NTLMSTATE_TYPE3: 1302 /* connection is already authenticated, 1303 * don't send a header in future requests */ 1304 if(*allocuserpwd) { 1305 free(*allocuserpwd); 1306 *allocuserpwd=NULL; 1307 } 1308 authp->done = TRUE; 1309 break; 1310 } 1311 1312 return CURLE_OK; 1313} 1314 1315 1316void 1317Curl_ntlm_cleanup(struct connectdata *conn) 1318{ 1319#ifdef USE_WINDOWS_SSPI 1320 ntlm_sspi_cleanup(&conn->ntlm); 1321 ntlm_sspi_cleanup(&conn->proxyntlm); 1322#else 1323 (void)conn; 1324#endif 1325} 1326 1327 1328#endif /* USE_NTLM */ 1329#endif /* !CURL_DISABLE_HTTP */ 1330