2 Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
4 Contributed by Daniel Stenberg.
6 This file is part of GNU Wget.
8 GNU Wget is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 GNU Wget is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Wget. If not, see <http://www.gnu.org/licenses/>.
21 Additional permission under GNU GPL version 3 section 7
23 If you modify this program, or any covered work, by linking or
24 combining it with the OpenSSL project's OpenSSL library (or a
25 modified version of that library), containing parts covered by the
26 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27 grants you additional permission to convey the resulting work.
28 Corresponding Source for a non-source form of such a combination
29 shall include the source code for the parts of OpenSSL used as well
30 as that of the covered work. */
36 http://davenport.sourceforge.net/ntlm.html
37 http://www.innovation.ch/java/ntlm.html
45 #include <openssl/des.h>
46 #include <openssl/md4.h>
47 #include <openssl/opensslv.h>
50 #include "http-ntlm.h"
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
59 /* This is how things were done in the old days */
61 #define DESKEYARG(x) x
64 #define DESKEYARG(x) *x
68 /* Define this to make the type-3 message include the NT response message */
69 #define USE_NTRESPONSES 1
71 /* Flag bits definitions available at on
72 http://davenport.sourceforge.net/ntlm.html */
74 #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
75 #define NTLMFLAG_NEGOTIATE_OEM (1<<1)
76 #define NTLMFLAG_REQUEST_TARGET (1<<2)
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)
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)
103 #define NTLMFLAG_NEGOTIATE_128 (1<<29)
104 #define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
105 #define NTLMFLAG_NEGOTIATE_56 (1<<31)
108 (*) = A "security buffer" is a triplet consisting of two shorts and one
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.
117 /* return true on success, false otherwise */
119 ntlm_input (struct ntlmdata *ntlm, const char *header)
121 if (0 != strncmp (header, "NTLM", 4))
125 while (*header && c_isspace(*header))
130 /* We got a type-2 message here:
132 Index Description Content
133 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
135 8 NTLM Message Type long (0x02000000)
136 12 Target Name security buffer(*)
139 (32) Context (optional) 8 bytes (two consecutive longs)
140 (40) Target Information (optional) security buffer(*)
141 32 (48) start of data block
144 char *buffer = (char *) alloca (strlen (header));
146 DEBUGP (("Received a type-2 NTLM message.\n"));
148 size = base64_decode (header, buffer);
150 return false; /* malformed base64 from server */
152 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
155 /* the nonce of interest is index [24 .. 31], 8 bytes */
156 memcpy (ntlm->nonce, &buffer[24], 8);
158 /* at index decimal 20, there's a 32bit NTLM flag field */
162 if (ntlm->state >= NTLMSTATE_TYPE1)
164 DEBUGP (("Unexpected empty NTLM message.\n"));
165 return false; /* this is an error */
168 DEBUGP (("Empty NTLM message, starting transaction.\n"));
169 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
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.
180 setup_des_key(unsigned char *key_56,
181 DES_key_schedule DESKEYARG(ks))
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;
194 DES_set_odd_parity(&key);
195 DES_set_key(&key, ks);
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.
204 calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
208 setup_des_key(keys, DESKEY(ks));
209 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
210 DESKEY(ks), DES_ENCRYPT);
212 setup_des_key(keys+7, DESKEY(ks));
213 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
214 DESKEY(ks), DES_ENCRYPT);
216 setup_des_key(keys+14, DESKEY(ks));
217 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
218 DESKEY(ks), DES_ENCRYPT);
222 * Set up lanmanager and nt hashed passwords
225 mkhash(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 */
233 unsigned char lmbuffer[21];
234 #ifdef USE_NTRESPONSES
235 unsigned char ntbuffer[21];
238 static const unsigned char magic[] = {
239 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
242 int len = strlen(password);
244 /* make it fit at least 14 bytes */
245 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
250 for (i=0; i<len; i++)
251 pw[i] = c_toupper (password[i]);
257 /* create LanManager hashed password */
260 setup_des_key(pw, DESKEY(ks));
261 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
262 DESKEY(ks), DES_ENCRYPT);
264 setup_des_key(pw+7, DESKEY(ks));
265 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
266 DESKEY(ks), DES_ENCRYPT);
268 memset(lmbuffer+16, 0, 5);
270 /* create LM responses */
271 calc_resp(lmbuffer, nonce, lmresp);
273 #ifdef USE_NTRESPONSES
275 /* create NT hashed password */
278 len = strlen(password);
280 for (i=0; i<len; i++) {
281 pw[2*i] = password[i];
286 MD4_Update(&MD4, pw, 2*len);
287 MD4_Final(ntbuffer, &MD4);
289 memset(ntbuffer+16, 0, 5);
292 calc_resp(ntbuffer, nonce, ntresp);
296 #define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
297 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
298 (((x) >>16)&0xff), ((x)>>24)
300 /* this is for creating ntlm header output */
302 ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
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 */
313 char ntlmbuf[256]; /* enough, unless the host/domain is very long */
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 */
321 /* not set means empty */
328 switch(ntlm->state) {
329 case NTLMSTATE_TYPE1:
330 default: /* for the weird cases we (re)start here */
332 domoff = hostoff + hostlen;
334 DEBUGP (("Creating a type-1 NTLM message.\n"));
336 /* Create and send a type-1 message:
338 Index Description Content
339 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
341 8 NTLM Message Type long (0x01000000)
343 16 Supplied Domain security buffer(*)
344 24 Supplied Workstation security buffer(*)
345 32 start of data block
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 */
361 "%s", /* domain string */
362 0, /* trailing zero */
363 0,0,0, /* part of type-1 long */
366 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
367 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
380 /* initial packet length */
381 size = 32 + hostlen + domlen;
383 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
384 base64_encode (ntlmbuf, size, base64);
386 output = concat_strings ("NTLM ", base64, (char *) 0);
389 case NTLMSTATE_TYPE2:
390 /* We received the type-2 already, create a type-3 message:
392 Index Description Content
393 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
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
411 unsigned char lmresp[0x18]; /* fixed-size */
412 #ifdef USE_NTRESPONSES
413 unsigned char ntresp[0x18]; /* fixed-size */
418 DEBUGP (("Creating a type-3 NTLM message.\n"));
420 usr = strchr(user, '\\');
422 usr = strchr(user, '/');
426 domlen = usr - domain;
431 userlen = strlen(usr);
433 mkhash(passwd, &ntlm->nonce[0], lmresp
434 #ifdef USE_NTRESPONSES
439 domoff = 64; /* always */
440 useroff = domoff + domlen;
441 hostoff = useroff + userlen;
442 lmrespoff = hostoff + hostlen;
443 ntrespoff = lmrespoff + 0x18;
445 /* Create the big type-3 message binary blob */
447 size = snprintf (ntlmbuf, sizeof(ntlmbuf),
449 "\x03%c%c%c" /* type-3, 32 bits */
451 "%c%c%c%c" /* LanManager length + allocated space */
452 "%c%c" /* LanManager offset */
453 "%c%c" /* 2 zeroes */
455 "%c%c" /* NT-response length */
456 "%c%c" /* NT-response allocated space */
457 "%c%c" /* NT-response offset */
458 "%c%c" /* 2 zeroes */
460 "%c%c" /* domain length */
461 "%c%c" /* domain allocated space */
462 "%c%c" /* domain name offset */
463 "%c%c" /* 2 zeroes */
465 "%c%c" /* user length */
466 "%c%c" /* user allocated space */
467 "%c%c" /* user offset */
468 "%c%c" /* 2 zeroes */
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 */
475 "\xff\xff" /* message length */
476 "%c%c" /* 2 zeroes */
478 "\x01\x82" /* flags */
479 "%c%c" /* 2 zeroes */
484 /* LanManager response */
487 0, /* zero termination */
488 0,0,0, /* type-3 long, the 24 upper bits */
490 SHORTPAIR(0x18), /* LanManager response length, twice */
492 SHORTPAIR(lmrespoff),
495 #ifdef USE_NTRESPONSES
496 SHORTPAIR(0x18), /* NT-response length, twice */
502 SHORTPAIR(ntrespoff),
518 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
526 ntlmbuf[62]=ntlmbuf[63]=0;
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))
533 memcpy(&ntlmbuf[size], domain, domlen);
536 memcpy(&ntlmbuf[size], usr, userlen);
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);
545 #ifdef USE_NTRESPONSES
546 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
547 memcpy(&ntlmbuf[size], ntresp, 0x18);
552 ntlmbuf[56] = size & 0xff;
553 ntlmbuf[57] = size >> 8;
555 /* convert the binary blob into base64 */
556 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
557 base64_encode (ntlmbuf, size, base64);
559 output = concat_strings ("NTLM ", base64, (char *) 0);
561 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
566 case NTLMSTATE_TYPE3:
567 /* connection is already authenticated,
568 * don't send a header in future requests */