2 Copyright (C) 2005 Free Software Foundation, Inc.
3 Donated 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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables. You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL". If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so. If you do not wish to do
29 so, delete this exception statement from your version. */
35 http://davenport.sourceforge.net/ntlm.html
36 http://www.innovation.ch/java/ntlm.html
40 /* -- WIN32 approved -- */
49 #include <openssl/des.h>
50 #include <openssl/md4.h>
54 #include "http-ntlm.h"
56 #if OPENSSL_VERSION_NUMBER < 0x00907001L
57 #define DES_key_schedule des_key_schedule
58 #define DES_cblock des_cblock
59 #define DES_set_odd_parity des_set_odd_parity
60 #define DES_set_key des_set_key
61 #define DES_ecb_encrypt des_ecb_encrypt
63 /* This is how things were done in the old days */
65 #define DESKEYARG(x) x
68 #define DESKEYARG(x) *x
72 /* Define this to make the type-3 message include the NT response message */
73 #define USE_NTRESPONSES 1
75 /* Flag bits definitions available at on
76 http://davenport.sourceforge.net/ntlm.html */
78 #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
79 #define NTLMFLAG_NEGOTIATE_OEM (1<<1)
80 #define NTLMFLAG_REQUEST_TARGET (1<<2)
82 #define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
83 #define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
84 #define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
85 #define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
86 #define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
87 #define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
90 #define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
91 #define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
92 #define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
93 #define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
94 #define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
95 #define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
96 #define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
97 #define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
98 #define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
99 #define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
100 #define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
101 #define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
107 #define NTLMFLAG_NEGOTIATE_128 (1<<29)
108 #define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
109 #define NTLMFLAG_NEGOTIATE_56 (1<<31)
112 (*) = A "security buffer" is a triplet consisting of two shorts and one
115 1. a 'short' containing the length of the buffer in bytes
116 2. a 'short' containing the allocated space for the buffer in bytes
117 3. a 'long' containing the offset to the start of the buffer from the
118 beginning of the NTLM message, in bytes.
121 /* return 1 on success, 0 otherwise */
123 ntlm_input (struct ntlmdata *ntlm, const char *header)
125 if (0 != strncmp (header, "NTLM", 4))
129 while (*header && ISSPACE(*header))
134 /* We got a type-2 message here:
136 Index Description Content
137 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
139 8 NTLM Message Type long (0x02000000)
140 12 Target Name security buffer(*)
143 (32) Context (optional) 8 bytes (two consecutive longs)
144 (40) Target Information (optional) security buffer(*)
145 32 (48) start of data block
148 char *buffer = (char *) alloca (strlen (header));
150 DEBUGP (("Received a type-2 NTLM message.\n"));
152 size = base64_decode (header, buffer);
154 return 0; /* malformed base64 from server */
156 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
159 /* the nonce of interest is index [24 .. 31], 8 bytes */
160 memcpy (ntlm->nonce, &buffer[24], 8);
162 /* at index decimal 20, there's a 32bit NTLM flag field */
166 if (ntlm->state >= NTLMSTATE_TYPE1)
168 DEBUGP (("Unexpected empty NTLM message.\n"));
169 return 0; /* this is an error */
172 DEBUGP (("Empty NTLM message, starting transaction.\n"));
173 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
180 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
181 * key schedule ks is also set.
184 setup_des_key(unsigned char *key_56,
185 DES_key_schedule DESKEYARG(ks))
190 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
191 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
192 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
193 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
194 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
195 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
196 key[7] = (key_56[6] << 1) & 0xFF;
198 DES_set_odd_parity(&key);
199 DES_set_key(&key, ks);
203 * takes a 21 byte array and treats it as 3 56-bit DES keys. The
204 * 8 byte plaintext is encrypted with each key and the resulting 24
205 * bytes are stored in the results array.
208 calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
212 setup_des_key(keys, DESKEY(ks));
213 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
214 DESKEY(ks), DES_ENCRYPT);
216 setup_des_key(keys+7, DESKEY(ks));
217 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
218 DESKEY(ks), DES_ENCRYPT);
220 setup_des_key(keys+14, DESKEY(ks));
221 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
222 DESKEY(ks), DES_ENCRYPT);
226 * Set up lanmanager and nt hashed passwords
229 mkhash(const char *password,
230 unsigned char *nonce, /* 8 bytes */
231 unsigned char *lmresp /* must fit 0x18 bytes */
232 #ifdef USE_NTRESPONSES
233 , unsigned char *ntresp /* must fit 0x18 bytes */
237 unsigned char lmbuffer[21];
238 #ifdef USE_NTRESPONSES
239 unsigned char ntbuffer[21];
242 static const unsigned char magic[] = {
243 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
246 int len = strlen(password);
248 /* make it fit at least 14 bytes */
249 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
254 for (i=0; i<len; i++)
255 pw[i] = TOUPPER (password[i]);
261 /* create LanManager hashed password */
264 setup_des_key(pw, DESKEY(ks));
265 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
266 DESKEY(ks), DES_ENCRYPT);
268 setup_des_key(pw+7, DESKEY(ks));
269 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
270 DESKEY(ks), DES_ENCRYPT);
272 memset(lmbuffer+16, 0, 5);
274 /* create LM responses */
275 calc_resp(lmbuffer, nonce, lmresp);
277 #ifdef USE_NTRESPONSES
279 /* create NT hashed password */
282 len = strlen(password);
284 for (i=0; i<len; i++) {
285 pw[2*i] = password[i];
290 MD4_Update(&MD4, pw, 2*len);
291 MD4_Final(ntbuffer, &MD4);
293 memset(ntbuffer+16, 0, 5);
296 calc_resp(ntbuffer, nonce, ntresp);
300 #define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
301 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
302 (((x) >>16)&0xff), ((x)>>24)
304 /* this is for creating ntlm header output */
306 ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
309 const char *domain=""; /* empty */
310 const char *host=""; /* empty */
311 int domlen=strlen(domain);
312 int hostlen = strlen(host);
313 int hostoff; /* host name offset */
314 int domoff; /* domain name offset */
317 char ntlmbuf[256]; /* enough, unless the host/domain is very long */
319 /* point to the address of the pointer that holds the string to sent to the
320 server, which is for a plain host or for a HTTP proxy */
325 /* not set means empty */
332 switch(ntlm->state) {
333 case NTLMSTATE_TYPE1:
334 default: /* for the weird cases we (re)start here */
336 domoff = hostoff + hostlen;
338 DEBUGP (("Creating a type-1 NTLM message.\n"));
340 /* Create and send a type-1 message:
342 Index Description Content
343 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
345 8 NTLM Message Type long (0x01000000)
347 16 Supplied Domain security buffer(*)
348 24 Supplied Workstation security buffer(*)
349 32 start of data block
351 Format string (merged for pre-ANSI compilers):
353 "\x01%c%c%c" 32-bit type = 1
354 "%c%c%c%c" 32-bit NTLM flag field
356 "%c%c" domain allocated space
357 "%c%c" domain name offset
360 "%c%c" host allocated space
361 "%c%c" host name offset
367 snprintf(ntlmbuf, sizeof(ntlmbuf),
368 "NTLMSSP%c\001%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%s%s",
369 0, /* trailing zero */
370 0,0,0, /* part of type-1 long */
373 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
374 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
387 /* initial packet length */
388 size = 32 + hostlen + domlen;
390 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
391 base64_encode (ntlmbuf, size, base64);
393 output = concat_strings ("NTLM ", base64, (char *) 0);
396 case NTLMSTATE_TYPE2:
397 /* We received the type-2 already, create a type-3 message:
399 Index Description Content
400 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
402 8 NTLM Message Type long (0x03000000)
403 12 LM/LMv2 Response security buffer(*)
404 20 NTLM/NTLMv2 Response security buffer(*)
405 28 Domain Name security buffer(*)
406 36 User Name security buffer(*)
407 44 Workstation Name security buffer(*)
408 (52) Session Key (optional) security buffer(*)
409 (60) Flags (optional) long
410 52 (64) start of data block
418 unsigned char lmresp[0x18]; /* fixed-size */
419 #ifdef USE_NTRESPONSES
420 unsigned char ntresp[0x18]; /* fixed-size */
425 DEBUGP (("Creating a type-3 NTLM message.\n"));
427 usr = strchr(user, '\\');
429 usr = strchr(user, '/');
433 domlen = usr - domain;
438 userlen = strlen(usr);
440 mkhash(passwd, &ntlm->nonce[0], lmresp
441 #ifdef USE_NTRESPONSES
446 domoff = 64; /* always */
447 useroff = domoff + domlen;
448 hostoff = useroff + userlen;
449 lmrespoff = hostoff + hostlen;
450 ntrespoff = lmrespoff + 0x18;
452 /* Create the big type-3 message binary blob:
454 "\x03%c%c%c" type-3, 32 bits
456 "%c%c%c%c" LanManager length + allocated space
457 "%c%c" LanManager offset
460 "%c%c" NT-response length
461 "%c%c" NT-response allocated space
462 "%c%c" NT-response offset
466 "%c%c" domain allocated space
467 "%c%c" domain name offset
471 "%c%c" user allocated space
476 "%c%c" host allocated space
478 "%c%c%c%c%c%c" 6 zeroes
480 "\xff\xff" message length
486 size = snprintf(ntlmbuf, sizeof(ntlmbuf),
487 "NTLMSSP%c\003%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\377\377%c%c\001\202%c%c",
488 0, /* zero termination */
489 0,0,0, /* type-3 long, the 24 upper bits */
491 SHORTPAIR(0x18), /* LanManager response length, twice */
493 SHORTPAIR(lmrespoff),
496 #ifdef USE_NTRESPONSES
497 SHORTPAIR(0x18), /* NT-response length, twice */
503 SHORTPAIR(ntrespoff),
519 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
527 ntlmbuf[62]=ntlmbuf[63]=0;
529 memcpy(&ntlmbuf[size], domain, domlen);
532 memcpy(&ntlmbuf[size], usr, userlen);
535 /* we append the binary hashes to the end of the blob */
536 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
537 memcpy(&ntlmbuf[size], lmresp, 0x18);
541 #ifdef USE_NTRESPONSES
542 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
543 memcpy(&ntlmbuf[size], ntresp, 0x18);
548 ntlmbuf[56] = size & 0xff;
549 ntlmbuf[57] = size >> 8;
551 /* convert the binary blob into base64 */
552 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
553 base64_encode (ntlmbuf, size, base64);
555 output = concat_strings ("NTLM ", base64, (char *) 0);
557 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
562 case NTLMSTATE_TYPE3:
563 /* connection is already authenticated,
564 * don't send a header in future requests */