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>
51 #include <openssl/ssl.h>
55 #include "http-ntlm.h"
57 #if OPENSSL_VERSION_NUMBER < 0x00907001L
58 #define DES_key_schedule des_key_schedule
59 #define DES_cblock des_cblock
60 #define DES_set_odd_parity des_set_odd_parity
61 #define DES_set_key des_set_key
62 #define DES_ecb_encrypt des_ecb_encrypt
64 /* This is how things were done in the old days */
66 #define DESKEYARG(x) x
69 #define DESKEYARG(x) *x
73 /* Define this to make the type-3 message include the NT response message */
74 #undef USE_NTRESPONSES
76 /* Flag bits definitions available at on
77 http://davenport.sourceforge.net/ntlm.html */
79 #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
80 #define NTLMFLAG_NEGOTIATE_OEM (1<<1)
81 #define NTLMFLAG_REQUEST_TARGET (1<<2)
83 #define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
84 #define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
85 #define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
86 #define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
87 #define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
88 #define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
91 #define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
92 #define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
93 #define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
94 #define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
95 #define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
96 #define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
97 #define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
98 #define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
99 #define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
100 #define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
101 #define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
102 #define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
108 #define NTLMFLAG_NEGOTIATE_128 (1<<29)
109 #define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
110 #define NTLMFLAG_NEGOTIATE_56 (1<<31)
113 (*) = A "security buffer" is a triplet consisting of two shorts and one
116 1. a 'short' containing the length of the buffer in bytes
117 2. a 'short' containing the allocated space for the buffer in bytes
118 3. a 'long' containing the offset to the start of the buffer from the
119 beginning of the NTLM message, in bytes.
122 /* return 1 on success, 0 otherwise */
123 int 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.
183 static void setup_des_key(unsigned char *key_56,
184 DES_key_schedule DESKEYARG(ks))
189 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
190 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
191 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
192 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
193 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
194 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
195 key[7] = (key_56[6] << 1) & 0xFF;
197 DES_set_odd_parity(&key);
198 DES_set_key(&key, ks);
202 * takes a 21 byte array and treats it as 3 56-bit DES keys. The
203 * 8 byte plaintext is encrypted with each key and the resulting 24
204 * bytes are stored in the results array.
206 static void calc_resp(unsigned char *keys,
207 unsigned char *plaintext,
208 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
228 static void mkhash(const char *password,
229 unsigned char *nonce, /* 8 bytes */
230 unsigned char *lmresp /* must fit 0x18 bytes */
231 #ifdef USE_NTRESPONSES
232 , unsigned char *ntresp /* must fit 0x18 bytes */
236 unsigned char lmbuffer[21];
237 #ifdef USE_NTRESPONSES
238 unsigned char ntbuffer[21];
241 static const unsigned char magic[] = {
242 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
245 int len = strlen(password);
247 /* make it fit at least 14 bytes */
248 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
253 for (i=0; i<len; i++)
254 pw[i] = TOUPPER (password[i]);
260 /* create LanManager hashed password */
263 setup_des_key(pw, DESKEY(ks));
264 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
265 DESKEY(ks), DES_ENCRYPT);
267 setup_des_key(pw+7, DESKEY(ks));
268 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
269 DESKEY(ks), DES_ENCRYPT);
271 memset(lmbuffer+16, 0, 5);
273 /* create LM responses */
274 calc_resp(lmbuffer, nonce, lmresp);
276 #ifdef USE_NTRESPONSES
278 /* create NT hashed password */
281 len = strlen(password);
283 for (i=0; i<len; i++) {
284 pw[2*i] = password[i];
289 MD4_Update(&MD4, pw, 2*len);
290 MD4_Final(ntbuffer, &MD4);
292 memset(ntbuffer+16, 0, 5);
295 calc_resp(ntbuffer, nonce, ntresp);
299 #define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
300 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
301 (((x) >>16)&0xff), ((x)>>24)
303 /* this is for creating ntlm header output */
304 char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
307 const char *domain=""; /* empty */
308 const char *host=""; /* empty */
309 int domlen=strlen(domain);
310 int hostlen = strlen(host);
311 int hostoff; /* host name offset */
312 int domoff; /* domain name offset */
315 char ntlmbuf[256]; /* enough, unless the host/domain is very long */
317 /* point to the address of the pointer that holds the string to sent to the
318 server, which is for a plain host or for a HTTP proxy */
323 /* not set means empty */
330 switch(ntlm->state) {
331 case NTLMSTATE_TYPE1:
332 default: /* for the weird cases we (re)start here */
334 domoff = hostoff + hostlen;
336 DEBUGP (("Creating a type-1 NTLM message.\n"));
338 /* Create and send a type-1 message:
340 Index Description Content
341 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
343 8 NTLM Message Type long (0x01000000)
345 16 Supplied Domain security buffer(*)
346 24 Supplied Workstation security buffer(*)
347 32 start of data block
349 Format string (merged for pre-ANSI compilers):
351 "\x01%c%c%c" 32-bit type = 1
352 "%c%c%c%c" 32-bit NTLM flag field
354 "%c%c" domain allocated space
355 "%c%c" domain name offset
358 "%c%c" host allocated space
359 "%c%c" host name offset
365 snprintf(ntlmbuf, sizeof(ntlmbuf),
366 "NTLMSSP%c\x01%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",
367 0, /* trailing zero */
368 0,0,0, /* part of type-1 long */
371 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
372 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
385 /* initial packet length */
386 size = 32 + hostlen + domlen;
388 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
389 base64_encode (ntlmbuf, size, base64);
391 output = concat_strings ("NTLM ", base64, (char *) 0);
394 case NTLMSTATE_TYPE2:
395 /* We received the type-2 already, create a type-3 message:
397 Index Description Content
398 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
400 8 NTLM Message Type long (0x03000000)
401 12 LM/LMv2 Response security buffer(*)
402 20 NTLM/NTLMv2 Response security buffer(*)
403 28 Domain Name security buffer(*)
404 36 User Name security buffer(*)
405 44 Workstation Name security buffer(*)
406 (52) Session Key (optional) security buffer(*)
407 (60) Flags (optional) long
408 52 (64) start of data block
416 unsigned char lmresp[0x18]; /* fixed-size */
417 #ifdef USE_NTRESPONSES
418 unsigned char ntresp[0x18]; /* fixed-size */
423 DEBUGP (("Creating a type-3 NTLM message.\n"));
425 usr = strchr(user, '\\');
427 usr = strchr(user, '/');
431 domlen = usr - domain;
436 userlen = strlen(usr);
438 mkhash(passwd, &ntlm->nonce[0], lmresp
439 #ifdef USE_NTRESPONSES
444 domoff = 64; /* always */
445 useroff = domoff + domlen;
446 hostoff = useroff + userlen;
447 lmrespoff = hostoff + hostlen;
448 ntrespoff = lmrespoff + 0x18;
450 /* Create the big type-3 message binary blob:
452 "\x03%c%c%c" type-3, 32 bits
454 "%c%c%c%c" LanManager length + allocated space
455 "%c%c" LanManager offset
458 "%c%c" NT-response length
459 "%c%c" NT-response allocated space
460 "%c%c" NT-response offset
464 "%c%c" domain allocated space
465 "%c%c" domain name offset
469 "%c%c" user allocated space
474 "%c%c" host allocated space
476 "%c%c%c%c%c%c" 6 zeroes
478 "\xff\xff" message length
484 size = snprintf(ntlmbuf, sizeof(ntlmbuf),
485 "NTLMSSP%c\x03%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\xff\xff%c%c\x01\x82%c%c",
486 0, /* zero termination */
487 0,0,0, /* type-3 long, the 24 upper bits */
489 SHORTPAIR(0x18), /* LanManager response length, twice */
491 SHORTPAIR(lmrespoff),
494 #ifdef USE_NTRESPONSES
495 SHORTPAIR(0x18), /* NT-response length, twice */
501 SHORTPAIR(ntrespoff),
517 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
525 ntlmbuf[62]=ntlmbuf[63]=0;
527 memcpy(&ntlmbuf[size], domain, domlen);
530 memcpy(&ntlmbuf[size], usr, userlen);
533 /* we append the binary hashes to the end of the blob */
534 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
535 memcpy(&ntlmbuf[size], lmresp, 0x18);
539 #ifdef USE_NTRESPONSES
540 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
541 memcpy(&ntlmbuf[size], ntresp, 0x18);
546 ntlmbuf[56] = size & 0xff;
547 ntlmbuf[57] = size >> 8;
549 /* convert the binary blob into base64 */
550 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
551 base64_encode (ntlmbuf, size, base64);
553 output = concat_strings ("NTLM ", base64, (char *) 0);
555 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
560 case NTLMSTATE_TYPE3:
561 /* connection is already authenticated,
562 * don't send a header in future requests */