2 Copyright (C) 2005-2006 Free Software Foundation, Inc.
3 Contributed by Daniel Stenberg.
5 This file is part of GNU Wget.
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Wget. If not, see <http://www.gnu.org/licenses/>.
20 In addition, as a special exception, the Free Software Foundation
21 gives permission to link the code of its release of Wget with the
22 OpenSSL project's "OpenSSL" library (or with modified versions of it
23 that use the same license as the "OpenSSL" library), and distribute
24 the linked executables. You must obey the GNU General Public License
25 in all respects for all of the code used other than "OpenSSL". If you
26 modify this file, you may extend this exception to your version of the
27 file, but you are not obligated to do so. If you do not wish to do
28 so, delete this exception statement from your version. */
34 http://davenport.sourceforge.net/ntlm.html
35 http://www.innovation.ch/java/ntlm.html
43 #include <openssl/des.h>
44 #include <openssl/md4.h>
48 #include "http-ntlm.h"
50 #if OPENSSL_VERSION_NUMBER < 0x00907001L
51 #define DES_key_schedule des_key_schedule
52 #define DES_cblock des_cblock
53 #define DES_set_odd_parity des_set_odd_parity
54 #define DES_set_key des_set_key
55 #define DES_ecb_encrypt des_ecb_encrypt
57 /* This is how things were done in the old days */
59 #define DESKEYARG(x) x
62 #define DESKEYARG(x) *x
66 /* Define this to make the type-3 message include the NT response message */
67 #define USE_NTRESPONSES 1
69 /* Flag bits definitions available at on
70 http://davenport.sourceforge.net/ntlm.html */
72 #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
73 #define NTLMFLAG_NEGOTIATE_OEM (1<<1)
74 #define NTLMFLAG_REQUEST_TARGET (1<<2)
76 #define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
77 #define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
78 #define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
79 #define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
80 #define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
81 #define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
84 #define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
85 #define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
86 #define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
87 #define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
88 #define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
89 #define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
90 #define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
91 #define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
92 #define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
93 #define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
94 #define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
95 #define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
101 #define NTLMFLAG_NEGOTIATE_128 (1<<29)
102 #define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
103 #define NTLMFLAG_NEGOTIATE_56 (1<<31)
106 (*) = A "security buffer" is a triplet consisting of two shorts and one
109 1. a 'short' containing the length of the buffer in bytes
110 2. a 'short' containing the allocated space for the buffer in bytes
111 3. a 'long' containing the offset to the start of the buffer from the
112 beginning of the NTLM message, in bytes.
115 /* return true on success, false otherwise */
117 ntlm_input (struct ntlmdata *ntlm, const char *header)
119 if (0 != strncmp (header, "NTLM", 4))
123 while (*header && ISSPACE(*header))
128 /* We got a type-2 message here:
130 Index Description Content
131 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
133 8 NTLM Message Type long (0x02000000)
134 12 Target Name security buffer(*)
137 (32) Context (optional) 8 bytes (two consecutive longs)
138 (40) Target Information (optional) security buffer(*)
139 32 (48) start of data block
142 char *buffer = (char *) alloca (strlen (header));
144 DEBUGP (("Received a type-2 NTLM message.\n"));
146 size = base64_decode (header, buffer);
148 return false; /* malformed base64 from server */
150 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
153 /* the nonce of interest is index [24 .. 31], 8 bytes */
154 memcpy (ntlm->nonce, &buffer[24], 8);
156 /* at index decimal 20, there's a 32bit NTLM flag field */
160 if (ntlm->state >= NTLMSTATE_TYPE1)
162 DEBUGP (("Unexpected empty NTLM message.\n"));
163 return false; /* this is an error */
166 DEBUGP (("Empty NTLM message, starting transaction.\n"));
167 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
174 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
175 * key schedule ks is also set.
178 setup_des_key(unsigned char *key_56,
179 DES_key_schedule DESKEYARG(ks))
184 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
185 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
186 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
187 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
188 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
189 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
190 key[7] = (key_56[6] << 1) & 0xFF;
192 DES_set_odd_parity(&key);
193 DES_set_key(&key, ks);
197 * takes a 21 byte array and treats it as 3 56-bit DES keys. The
198 * 8 byte plaintext is encrypted with each key and the resulting 24
199 * bytes are stored in the results array.
202 calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
206 setup_des_key(keys, DESKEY(ks));
207 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
208 DESKEY(ks), DES_ENCRYPT);
210 setup_des_key(keys+7, DESKEY(ks));
211 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
212 DESKEY(ks), DES_ENCRYPT);
214 setup_des_key(keys+14, DESKEY(ks));
215 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
216 DESKEY(ks), DES_ENCRYPT);
220 * Set up lanmanager and nt hashed passwords
223 mkhash(const char *password,
224 unsigned char *nonce, /* 8 bytes */
225 unsigned char *lmresp /* must fit 0x18 bytes */
226 #ifdef USE_NTRESPONSES
227 , unsigned char *ntresp /* must fit 0x18 bytes */
231 unsigned char lmbuffer[21];
232 #ifdef USE_NTRESPONSES
233 unsigned char ntbuffer[21];
236 static const unsigned char magic[] = {
237 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
240 int len = strlen(password);
242 /* make it fit at least 14 bytes */
243 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
248 for (i=0; i<len; i++)
249 pw[i] = TOUPPER (password[i]);
255 /* create LanManager hashed password */
258 setup_des_key(pw, DESKEY(ks));
259 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
260 DESKEY(ks), DES_ENCRYPT);
262 setup_des_key(pw+7, DESKEY(ks));
263 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
264 DESKEY(ks), DES_ENCRYPT);
266 memset(lmbuffer+16, 0, 5);
268 /* create LM responses */
269 calc_resp(lmbuffer, nonce, lmresp);
271 #ifdef USE_NTRESPONSES
273 /* create NT hashed password */
276 len = strlen(password);
278 for (i=0; i<len; i++) {
279 pw[2*i] = password[i];
284 MD4_Update(&MD4, pw, 2*len);
285 MD4_Final(ntbuffer, &MD4);
287 memset(ntbuffer+16, 0, 5);
290 calc_resp(ntbuffer, nonce, ntresp);
294 #define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
295 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
296 (((x) >>16)&0xff), ((x)>>24)
298 /* this is for creating ntlm header output */
300 ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
303 const char *domain=""; /* empty */
304 const char *host=""; /* empty */
305 int domlen=strlen(domain);
306 int hostlen = strlen(host);
307 int hostoff; /* host name offset */
308 int domoff; /* domain name offset */
311 char ntlmbuf[256]; /* enough, unless the host/domain is very long */
313 /* point to the address of the pointer that holds the string to sent to the
314 server, which is for a plain host or for a HTTP proxy */
319 /* not set means empty */
326 switch(ntlm->state) {
327 case NTLMSTATE_TYPE1:
328 default: /* for the weird cases we (re)start here */
330 domoff = hostoff + hostlen;
332 DEBUGP (("Creating a type-1 NTLM message.\n"));
334 /* Create and send a type-1 message:
336 Index Description Content
337 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
339 8 NTLM Message Type long (0x01000000)
341 16 Supplied Domain security buffer(*)
342 24 Supplied Workstation security buffer(*)
343 32 start of data block
347 snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
348 "\x01%c%c%c" /* 32-bit type = 1 */
349 "%c%c%c%c" /* 32-bit NTLM flag field */
350 "%c%c" /* domain length */
351 "%c%c" /* domain allocated space */
352 "%c%c" /* domain name offset */
353 "%c%c" /* 2 zeroes */
354 "%c%c" /* host length */
355 "%c%c" /* host allocated space */
356 "%c%c" /* host name offset */
357 "%c%c" /* 2 zeroes */
359 "%s", /* domain string */
360 0, /* trailing zero */
361 0,0,0, /* part of type-1 long */
364 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
365 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
378 /* initial packet length */
379 size = 32 + hostlen + domlen;
381 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
382 base64_encode (ntlmbuf, size, base64);
384 output = concat_strings ("NTLM ", base64, (char *) 0);
387 case NTLMSTATE_TYPE2:
388 /* We received the type-2 already, create a type-3 message:
390 Index Description Content
391 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
393 8 NTLM Message Type long (0x03000000)
394 12 LM/LMv2 Response security buffer(*)
395 20 NTLM/NTLMv2 Response security buffer(*)
396 28 Domain Name security buffer(*)
397 36 User Name security buffer(*)
398 44 Workstation Name security buffer(*)
399 (52) Session Key (optional) security buffer(*)
400 (60) Flags (optional) long
401 52 (64) start of data block
409 unsigned char lmresp[0x18]; /* fixed-size */
410 #ifdef USE_NTRESPONSES
411 unsigned char ntresp[0x18]; /* fixed-size */
416 DEBUGP (("Creating a type-3 NTLM message.\n"));
418 usr = strchr(user, '\\');
420 usr = strchr(user, '/');
424 domlen = usr - domain;
429 userlen = strlen(usr);
431 mkhash(passwd, &ntlm->nonce[0], lmresp
432 #ifdef USE_NTRESPONSES
437 domoff = 64; /* always */
438 useroff = domoff + domlen;
439 hostoff = useroff + userlen;
440 lmrespoff = hostoff + hostlen;
441 ntrespoff = lmrespoff + 0x18;
443 /* Create the big type-3 message binary blob */
445 size = snprintf (ntlmbuf, sizeof(ntlmbuf),
447 "\x03%c%c%c" /* type-3, 32 bits */
449 "%c%c%c%c" /* LanManager length + allocated space */
450 "%c%c" /* LanManager offset */
451 "%c%c" /* 2 zeroes */
453 "%c%c" /* NT-response length */
454 "%c%c" /* NT-response allocated space */
455 "%c%c" /* NT-response offset */
456 "%c%c" /* 2 zeroes */
458 "%c%c" /* domain length */
459 "%c%c" /* domain allocated space */
460 "%c%c" /* domain name offset */
461 "%c%c" /* 2 zeroes */
463 "%c%c" /* user length */
464 "%c%c" /* user allocated space */
465 "%c%c" /* user offset */
466 "%c%c" /* 2 zeroes */
468 "%c%c" /* host length */
469 "%c%c" /* host allocated space */
470 "%c%c" /* host offset */
471 "%c%c%c%c%c%c" /* 6 zeroes */
473 "\xff\xff" /* message length */
474 "%c%c" /* 2 zeroes */
476 "\x01\x82" /* flags */
477 "%c%c" /* 2 zeroes */
482 /* LanManager response */
485 0, /* zero termination */
486 0,0,0, /* type-3 long, the 24 upper bits */
488 SHORTPAIR(0x18), /* LanManager response length, twice */
490 SHORTPAIR(lmrespoff),
493 #ifdef USE_NTRESPONSES
494 SHORTPAIR(0x18), /* NT-response length, twice */
500 SHORTPAIR(ntrespoff),
516 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
524 ntlmbuf[62]=ntlmbuf[63]=0;
526 /* Make sure that the user and domain strings fit in the target buffer
527 before we copy them there. */
528 if(size + userlen + domlen >= sizeof(ntlmbuf))
531 memcpy(&ntlmbuf[size], domain, domlen);
534 memcpy(&ntlmbuf[size], usr, userlen);
537 /* we append the binary hashes to the end of the blob */
538 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
539 memcpy(&ntlmbuf[size], lmresp, 0x18);
543 #ifdef USE_NTRESPONSES
544 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
545 memcpy(&ntlmbuf[size], ntresp, 0x18);
550 ntlmbuf[56] = size & 0xff;
551 ntlmbuf[57] = size >> 8;
553 /* convert the binary blob into base64 */
554 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
555 base64_encode (ntlmbuf, size, base64);
557 output = concat_strings ("NTLM ", base64, (char *) 0);
559 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
564 case NTLMSTATE_TYPE3:
565 /* connection is already authenticated,
566 * don't send a header in future requests */