1/* NTLM code. 2 Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, 3 Inc. 4 Contributed by Daniel Stenberg. 5 6This file is part of GNU Wget. 7 8GNU Wget is free software; you can redistribute it and/or modify 9it under the terms of the GNU General Public License as published by 10the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13GNU Wget is distributed in the hope that it will be useful, 14but WITHOUT ANY WARRANTY; without even the implied warranty of 15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16GNU General Public License for more details. 17 18You should have received a copy of the GNU General Public License 19along with Wget. If not, see <http://www.gnu.org/licenses/>. 20 21Additional permission under GNU GPL version 3 section 7 22 23If you modify this program, or any covered work, by linking or 24combining it with the OpenSSL project's OpenSSL library (or a 25modified version of that library), containing parts covered by the 26terms of the OpenSSL or SSLeay licenses, the Free Software Foundation 27grants you additional permission to convey the resulting work. 28Corresponding Source for a non-source form of such a combination 29shall include the source code for the parts of OpenSSL used as well 30as that of the covered work. */ 31 32#include "wget.h" 33 34/* NTLM details: 35 36 http://davenport.sourceforge.net/ntlm.html 37 http://www.innovation.ch/java/ntlm.html 38 39*/ 40 41#include <stdio.h> 42#include <string.h> 43#include <stdlib.h> 44 45#include <openssl/des.h> 46#include <openssl/md4.h> 47#include <openssl/opensslv.h> 48 49#include "utils.h" 50#include "http-ntlm.h" 51 52#if OPENSSL_VERSION_NUMBER < 0x00907001L 53#define DES_key_schedule des_key_schedule 54#define DES_cblock des_cblock 55#define DES_set_odd_parity des_set_odd_parity 56#define DES_set_key des_set_key 57#define DES_ecb_encrypt des_ecb_encrypt 58 59/* This is how things were done in the old days */ 60#define DESKEY(x) x 61#define DESKEYARG(x) x 62#else 63/* Modern version */ 64#define DESKEYARG(x) *x 65#define DESKEY(x) &x 66#endif 67 68/* Define this to make the type-3 message include the NT response message */ 69#define USE_NTRESPONSES 1 70 71/* Flag bits definitions available at on 72 http://davenport.sourceforge.net/ntlm.html */ 73 74#define NTLMFLAG_NEGOTIATE_UNICODE (1<<0) 75#define NTLMFLAG_NEGOTIATE_OEM (1<<1) 76#define NTLMFLAG_REQUEST_TARGET (1<<2) 77/* unknown (1<<3) */ 78#define NTLMFLAG_NEGOTIATE_SIGN (1<<4) 79#define NTLMFLAG_NEGOTIATE_SEAL (1<<5) 80#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6) 81#define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7) 82#define NTLMFLAG_NEGOTIATE_NETWARE (1<<8) 83#define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9) 84/* unknown (1<<10) */ 85/* unknown (1<<11) */ 86#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12) 87#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13) 88#define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14) 89#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15) 90#define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16) 91#define NTLMFLAG_TARGET_TYPE_SERVER (1<<17) 92#define NTLMFLAG_TARGET_TYPE_SHARE (1<<18) 93#define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19) 94#define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20) 95#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21) 96#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22) 97#define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23) 98/* unknown (1<24) */ 99/* unknown (1<25) */ 100/* unknown (1<26) */ 101/* unknown (1<27) */ 102/* unknown (1<28) */ 103#define NTLMFLAG_NEGOTIATE_128 (1<<29) 104#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30) 105#define NTLMFLAG_NEGOTIATE_56 (1<<31) 106 107/* 108 (*) = A "security buffer" is a triplet consisting of two shorts and one 109 long: 110 111 1. a 'short' containing the length of the buffer in bytes 112 2. a 'short' containing the allocated space for the buffer in bytes 113 3. a 'long' containing the offset to the start of the buffer from the 114 beginning of the NTLM message, in bytes. 115*/ 116 117/* return true on success, false otherwise */ 118bool 119ntlm_input (struct ntlmdata *ntlm, const char *header) 120{ 121 if (0 != strncmp (header, "NTLM", 4)) 122 return false; 123 124 header += 4; 125 while (*header && c_isspace(*header)) 126 header++; 127 128 if (*header) 129 { 130 /* We got a type-2 message here: 131 132 Index Description Content 133 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 134 (0x4e544c4d53535000) 135 8 NTLM Message Type long (0x02000000) 136 12 Target Name security buffer(*) 137 20 Flags long 138 24 Challenge 8 bytes 139 (32) Context (optional) 8 bytes (two consecutive longs) 140 (40) Target Information (optional) security buffer(*) 141 32 (48) start of data block 142 */ 143 int size; 144 char *buffer = (char *) alloca (strlen (header)); 145 146 DEBUGP (("Received a type-2 NTLM message.\n")); 147 148 size = base64_decode (header, buffer); 149 if (size < 0) 150 return false; /* malformed base64 from server */ 151 152 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */ 153 154 if (size >= 48) 155 /* the nonce of interest is index [24 .. 31], 8 bytes */ 156 memcpy (ntlm->nonce, &buffer[24], 8); 157 158 /* at index decimal 20, there's a 32bit NTLM flag field */ 159 } 160 else 161 { 162 if (ntlm->state >= NTLMSTATE_TYPE1) 163 { 164 DEBUGP (("Unexpected empty NTLM message.\n")); 165 return false; /* this is an error */ 166 } 167 168 DEBUGP (("Empty NTLM message, starting transaction.\n")); 169 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */ 170 } 171 172 return true; 173} 174 175/* 176 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The 177 * key schedule ks is also set. 178 */ 179static void 180setup_des_key(unsigned char *key_56, 181 DES_key_schedule DESKEYARG(ks)) 182{ 183 DES_cblock key; 184 185 key[0] = key_56[0]; 186 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1); 187 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2); 188 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3); 189 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4); 190 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5); 191 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6); 192 key[7] = (key_56[6] << 1) & 0xFF; 193 194 DES_set_odd_parity(&key); 195 DES_set_key(&key, ks); 196} 197 198 /* 199 * takes a 21 byte array and treats it as 3 56-bit DES keys. The 200 * 8 byte plaintext is encrypted with each key and the resulting 24 201 * bytes are stored in the results array. 202 */ 203static void 204calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results) 205{ 206 DES_key_schedule ks; 207 208 setup_des_key(keys, DESKEY(ks)); 209 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results, 210 DESKEY(ks), DES_ENCRYPT); 211 212 setup_des_key(keys+7, DESKEY(ks)); 213 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8), 214 DESKEY(ks), DES_ENCRYPT); 215 216 setup_des_key(keys+14, DESKEY(ks)); 217 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16), 218 DESKEY(ks), DES_ENCRYPT); 219} 220 221/* 222 * Set up lanmanager and nt hashed passwords 223 */ 224static void 225mkhash(const char *password, 226 unsigned char *nonce, /* 8 bytes */ 227 unsigned char *lmresp /* must fit 0x18 bytes */ 228#ifdef USE_NTRESPONSES 229 , unsigned char *ntresp /* must fit 0x18 bytes */ 230#endif 231 ) 232{ 233 unsigned char lmbuffer[21]; 234#ifdef USE_NTRESPONSES 235 unsigned char ntbuffer[21]; 236#endif 237 unsigned char *pw; 238 static const unsigned char magic[] = { 239 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 240 }; 241 int i; 242 int len = strlen(password); 243 244 /* make it fit at least 14 bytes */ 245 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2); 246 247 if (len > 14) 248 len = 14; 249 250 for (i=0; i<len; i++) 251 pw[i] = c_toupper (password[i]); 252 253 for (; i<14; i++) 254 pw[i] = 0; 255 256 { 257 /* create LanManager hashed password */ 258 DES_key_schedule ks; 259 260 setup_des_key(pw, DESKEY(ks)); 261 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer, 262 DESKEY(ks), DES_ENCRYPT); 263 264 setup_des_key(pw+7, DESKEY(ks)); 265 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8), 266 DESKEY(ks), DES_ENCRYPT); 267 268 memset(lmbuffer+16, 0, 5); 269 } 270 /* create LM responses */ 271 calc_resp(lmbuffer, nonce, lmresp); 272 273#ifdef USE_NTRESPONSES 274 { 275 /* create NT hashed password */ 276 MD4_CTX MD4; 277 278 len = strlen(password); 279 280 for (i=0; i<len; i++) { 281 pw[2*i] = password[i]; 282 pw[2*i+1] = 0; 283 } 284 285 MD4_Init(&MD4); 286 MD4_Update(&MD4, pw, 2*len); 287 MD4_Final(ntbuffer, &MD4); 288 289 memset(ntbuffer+16, 0, 5); 290 } 291 292 calc_resp(ntbuffer, nonce, ntresp); 293#endif 294} 295 296#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8) 297#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \ 298 (((x) >>16)&0xff), ((x)>>24) 299 300/* this is for creating ntlm header output */ 301char * 302ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd, 303 bool *ready) 304{ 305 const char *domain=""; /* empty */ 306 const char *host=""; /* empty */ 307 int domlen=strlen(domain); 308 int hostlen = strlen(host); 309 int hostoff; /* host name offset */ 310 int domoff; /* domain name offset */ 311 int size; 312 char *base64; 313 char ntlmbuf[256]; /* enough, unless the host/domain is very long */ 314 315 /* point to the address of the pointer that holds the string to sent to the 316 server, which is for a plain host or for a HTTP proxy */ 317 char *output; 318 319 *ready = false; 320 321 /* not set means empty */ 322 if(!user) 323 user=""; 324 325 if(!passwd) 326 passwd=""; 327 328 switch(ntlm->state) { 329 case NTLMSTATE_TYPE1: 330 default: /* for the weird cases we (re)start here */ 331 hostoff = 32; 332 domoff = hostoff + hostlen; 333 334 DEBUGP (("Creating a type-1 NTLM message.\n")); 335 336 /* Create and send a type-1 message: 337 338 Index Description Content 339 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 340 (0x4e544c4d53535000) 341 8 NTLM Message Type long (0x01000000) 342 12 Flags long 343 16 Supplied Domain security buffer(*) 344 24 Supplied Workstation security buffer(*) 345 32 start of data block 346 347 */ 348 349 snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c" 350 "\x01%c%c%c" /* 32-bit type = 1 */ 351 "%c%c%c%c" /* 32-bit NTLM flag field */ 352 "%c%c" /* domain length */ 353 "%c%c" /* domain allocated space */ 354 "%c%c" /* domain name offset */ 355 "%c%c" /* 2 zeroes */ 356 "%c%c" /* host length */ 357 "%c%c" /* host allocated space */ 358 "%c%c" /* host name offset */ 359 "%c%c" /* 2 zeroes */ 360 "%s" /* host name */ 361 "%s", /* domain string */ 362 0, /* trailing zero */ 363 0,0,0, /* part of type-1 long */ 364 365 LONGQUARTET( 366 NTLMFLAG_NEGOTIATE_OEM| /* 2 */ 367 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */ 368 /* equals 0x0202 */ 369 ), 370 SHORTPAIR(domlen), 371 SHORTPAIR(domlen), 372 SHORTPAIR(domoff), 373 0,0, 374 SHORTPAIR(hostlen), 375 SHORTPAIR(hostlen), 376 SHORTPAIR(hostoff), 377 0,0, 378 host, domain); 379 380 /* initial packet length */ 381 size = 32 + hostlen + domlen; 382 383 base64 = (char *) alloca (BASE64_LENGTH (size) + 1); 384 base64_encode (ntlmbuf, size, base64); 385 386 output = concat_strings ("NTLM ", base64, (char *) 0); 387 break; 388 389 case NTLMSTATE_TYPE2: 390 /* We received the type-2 already, create a type-3 message: 391 392 Index Description Content 393 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP" 394 (0x4e544c4d53535000) 395 8 NTLM Message Type long (0x03000000) 396 12 LM/LMv2 Response security buffer(*) 397 20 NTLM/NTLMv2 Response security buffer(*) 398 28 Domain Name security buffer(*) 399 36 User Name security buffer(*) 400 44 Workstation Name security buffer(*) 401 (52) Session Key (optional) security buffer(*) 402 (60) Flags (optional) long 403 52 (64) start of data block 404 405 */ 406 407 { 408 int lmrespoff; 409 int ntrespoff; 410 int useroff; 411 unsigned char lmresp[0x18]; /* fixed-size */ 412#ifdef USE_NTRESPONSES 413 unsigned char ntresp[0x18]; /* fixed-size */ 414#endif 415 const char *usr; 416 int userlen; 417 418 DEBUGP (("Creating a type-3 NTLM message.\n")); 419 420 usr = strchr(user, '\\'); 421 if(!usr) 422 usr = strchr(user, '/'); 423 424 if (usr) { 425 domain = user; 426 domlen = usr - domain; 427 usr++; 428 } 429 else 430 usr = user; 431 userlen = strlen(usr); 432 433 mkhash(passwd, &ntlm->nonce[0], lmresp 434#ifdef USE_NTRESPONSES 435 , ntresp 436#endif 437 ); 438 439 domoff = 64; /* always */ 440 useroff = domoff + domlen; 441 hostoff = useroff + userlen; 442 lmrespoff = hostoff + hostlen; 443 ntrespoff = lmrespoff + 0x18; 444 445 /* Create the big type-3 message binary blob */ 446 447 size = snprintf (ntlmbuf, sizeof(ntlmbuf), 448 "NTLMSSP%c" 449 "\x03%c%c%c" /* type-3, 32 bits */ 450 451 "%c%c%c%c" /* LanManager length + allocated space */ 452 "%c%c" /* LanManager offset */ 453 "%c%c" /* 2 zeroes */ 454 455 "%c%c" /* NT-response length */ 456 "%c%c" /* NT-response allocated space */ 457 "%c%c" /* NT-response offset */ 458 "%c%c" /* 2 zeroes */ 459 460 "%c%c" /* domain length */ 461 "%c%c" /* domain allocated space */ 462 "%c%c" /* domain name offset */ 463 "%c%c" /* 2 zeroes */ 464 465 "%c%c" /* user length */ 466 "%c%c" /* user allocated space */ 467 "%c%c" /* user offset */ 468 "%c%c" /* 2 zeroes */ 469 470 "%c%c" /* host length */ 471 "%c%c" /* host allocated space */ 472 "%c%c" /* host offset */ 473 "%c%c%c%c%c%c" /* 6 zeroes */ 474 475 "\xff\xff" /* message length */ 476 "%c%c" /* 2 zeroes */ 477 478 "\x01\x82" /* flags */ 479 "%c%c" /* 2 zeroes */ 480 481 /* domain string */ 482 /* user string */ 483 /* host string */ 484 /* LanManager response */ 485 /* NT response */ 486 , 487 0, /* zero termination */ 488 0,0,0, /* type-3 long, the 24 upper bits */ 489 490 SHORTPAIR(0x18), /* LanManager response length, twice */ 491 SHORTPAIR(0x18), 492 SHORTPAIR(lmrespoff), 493 0x0, 0x0, 494 495#ifdef USE_NTRESPONSES 496 SHORTPAIR(0x18), /* NT-response length, twice */ 497 SHORTPAIR(0x18), 498#else 499 0x0, 0x0, 500 0x0, 0x0, 501#endif 502 SHORTPAIR(ntrespoff), 503 0x0, 0x0, 504 505 SHORTPAIR(domlen), 506 SHORTPAIR(domlen), 507 SHORTPAIR(domoff), 508 0x0, 0x0, 509 510 SHORTPAIR(userlen), 511 SHORTPAIR(userlen), 512 SHORTPAIR(useroff), 513 0x0, 0x0, 514 515 SHORTPAIR(hostlen), 516 SHORTPAIR(hostlen), 517 SHORTPAIR(hostoff), 518 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 519 520 0x0, 0x0, 521 522 0x0, 0x0); 523 524 /* size is now 64 */ 525 size=64; 526 ntlmbuf[62]=ntlmbuf[63]=0; 527 528 /* Make sure that the user and domain strings fit in the target buffer 529 before we copy them there. */ 530 if(((size_t) size + userlen + domlen) >= sizeof(ntlmbuf)) 531 return NULL; 532 533 memcpy(&ntlmbuf[size], domain, domlen); 534 size += domlen; 535 536 memcpy(&ntlmbuf[size], usr, userlen); 537 size += userlen; 538 539 /* we append the binary hashes to the end of the blob */ 540 if(size < ((int)sizeof(ntlmbuf) - 0x18)) { 541 memcpy(&ntlmbuf[size], lmresp, 0x18); 542 size += 0x18; 543 } 544 545#ifdef USE_NTRESPONSES 546 if(size < ((int)sizeof(ntlmbuf) - 0x18)) { 547 memcpy(&ntlmbuf[size], ntresp, 0x18); 548 size += 0x18; 549 } 550#endif 551 552 ntlmbuf[56] = size & 0xff; 553 ntlmbuf[57] = size >> 8; 554 555 /* convert the binary blob into base64 */ 556 base64 = (char *) alloca (BASE64_LENGTH (size) + 1); 557 base64_encode (ntlmbuf, size, base64); 558 559 output = concat_strings ("NTLM ", base64, (char *) 0); 560 561 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */ 562 *ready = true; 563 } 564 break; 565 566 case NTLMSTATE_TYPE3: 567 /* connection is already authenticated, 568 * don't send a header in future requests */ 569 *ready = true; 570 output = NULL; 571 break; 572 } 573 574 return output; 575} 576