2 Copyright (C) 2005, 2006, 2007 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>
45 #include <openssl/opensslv.h>
49 #include "http-ntlm.h"
51 #if OPENSSL_VERSION_NUMBER < 0x00907001L
52 #define DES_key_schedule des_key_schedule
53 #define DES_cblock des_cblock
54 #define DES_set_odd_parity des_set_odd_parity
55 #define DES_set_key des_set_key
56 #define DES_ecb_encrypt des_ecb_encrypt
58 /* This is how things were done in the old days */
60 #define DESKEYARG(x) x
63 #define DESKEYARG(x) *x
67 /* Define this to make the type-3 message include the NT response message */
68 #define USE_NTRESPONSES 1
70 /* Flag bits definitions available at on
71 http://davenport.sourceforge.net/ntlm.html */
73 #define NTLMFLAG_NEGOTIATE_UNICODE (1<<0)
74 #define NTLMFLAG_NEGOTIATE_OEM (1<<1)
75 #define NTLMFLAG_REQUEST_TARGET (1<<2)
77 #define NTLMFLAG_NEGOTIATE_SIGN (1<<4)
78 #define NTLMFLAG_NEGOTIATE_SEAL (1<<5)
79 #define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE (1<<6)
80 #define NTLMFLAG_NEGOTIATE_LM_KEY (1<<7)
81 #define NTLMFLAG_NEGOTIATE_NETWARE (1<<8)
82 #define NTLMFLAG_NEGOTIATE_NTLM_KEY (1<<9)
85 #define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED (1<<12)
86 #define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED (1<<13)
87 #define NTLMFLAG_NEGOTIATE_LOCAL_CALL (1<<14)
88 #define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN (1<<15)
89 #define NTLMFLAG_TARGET_TYPE_DOMAIN (1<<16)
90 #define NTLMFLAG_TARGET_TYPE_SERVER (1<<17)
91 #define NTLMFLAG_TARGET_TYPE_SHARE (1<<18)
92 #define NTLMFLAG_NEGOTIATE_NTLM2_KEY (1<<19)
93 #define NTLMFLAG_REQUEST_INIT_RESPONSE (1<<20)
94 #define NTLMFLAG_REQUEST_ACCEPT_RESPONSE (1<<21)
95 #define NTLMFLAG_REQUEST_NONNT_SESSION_KEY (1<<22)
96 #define NTLMFLAG_NEGOTIATE_TARGET_INFO (1<<23)
102 #define NTLMFLAG_NEGOTIATE_128 (1<<29)
103 #define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE (1<<30)
104 #define NTLMFLAG_NEGOTIATE_56 (1<<31)
107 (*) = A "security buffer" is a triplet consisting of two shorts and one
110 1. a 'short' containing the length of the buffer in bytes
111 2. a 'short' containing the allocated space for the buffer in bytes
112 3. a 'long' containing the offset to the start of the buffer from the
113 beginning of the NTLM message, in bytes.
116 /* return true on success, false otherwise */
118 ntlm_input (struct ntlmdata *ntlm, const char *header)
120 if (0 != strncmp (header, "NTLM", 4))
124 while (*header && ISSPACE(*header))
129 /* We got a type-2 message here:
131 Index Description Content
132 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
134 8 NTLM Message Type long (0x02000000)
135 12 Target Name security buffer(*)
138 (32) Context (optional) 8 bytes (two consecutive longs)
139 (40) Target Information (optional) security buffer(*)
140 32 (48) start of data block
143 char *buffer = (char *) alloca (strlen (header));
145 DEBUGP (("Received a type-2 NTLM message.\n"));
147 size = base64_decode (header, buffer);
149 return false; /* malformed base64 from server */
151 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
154 /* the nonce of interest is index [24 .. 31], 8 bytes */
155 memcpy (ntlm->nonce, &buffer[24], 8);
157 /* at index decimal 20, there's a 32bit NTLM flag field */
161 if (ntlm->state >= NTLMSTATE_TYPE1)
163 DEBUGP (("Unexpected empty NTLM message.\n"));
164 return false; /* this is an error */
167 DEBUGP (("Empty NTLM message, starting transaction.\n"));
168 ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
175 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key. The
176 * key schedule ks is also set.
179 setup_des_key(unsigned char *key_56,
180 DES_key_schedule DESKEYARG(ks))
185 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
186 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
187 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
188 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
189 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
190 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
191 key[7] = (key_56[6] << 1) & 0xFF;
193 DES_set_odd_parity(&key);
194 DES_set_key(&key, ks);
198 * takes a 21 byte array and treats it as 3 56-bit DES keys. The
199 * 8 byte plaintext is encrypted with each key and the resulting 24
200 * bytes are stored in the results array.
203 calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
207 setup_des_key(keys, DESKEY(ks));
208 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
209 DESKEY(ks), DES_ENCRYPT);
211 setup_des_key(keys+7, DESKEY(ks));
212 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
213 DESKEY(ks), DES_ENCRYPT);
215 setup_des_key(keys+14, DESKEY(ks));
216 DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
217 DESKEY(ks), DES_ENCRYPT);
221 * Set up lanmanager and nt hashed passwords
224 mkhash(const char *password,
225 unsigned char *nonce, /* 8 bytes */
226 unsigned char *lmresp /* must fit 0x18 bytes */
227 #ifdef USE_NTRESPONSES
228 , unsigned char *ntresp /* must fit 0x18 bytes */
232 unsigned char lmbuffer[21];
233 #ifdef USE_NTRESPONSES
234 unsigned char ntbuffer[21];
237 static const unsigned char magic[] = {
238 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
241 int len = strlen(password);
243 /* make it fit at least 14 bytes */
244 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
249 for (i=0; i<len; i++)
250 pw[i] = TOUPPER (password[i]);
256 /* create LanManager hashed password */
259 setup_des_key(pw, DESKEY(ks));
260 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
261 DESKEY(ks), DES_ENCRYPT);
263 setup_des_key(pw+7, DESKEY(ks));
264 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
265 DESKEY(ks), DES_ENCRYPT);
267 memset(lmbuffer+16, 0, 5);
269 /* create LM responses */
270 calc_resp(lmbuffer, nonce, lmresp);
272 #ifdef USE_NTRESPONSES
274 /* create NT hashed password */
277 len = strlen(password);
279 for (i=0; i<len; i++) {
280 pw[2*i] = password[i];
285 MD4_Update(&MD4, pw, 2*len);
286 MD4_Final(ntbuffer, &MD4);
288 memset(ntbuffer+16, 0, 5);
291 calc_resp(ntbuffer, nonce, ntresp);
295 #define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
296 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
297 (((x) >>16)&0xff), ((x)>>24)
299 /* this is for creating ntlm header output */
301 ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
304 const char *domain=""; /* empty */
305 const char *host=""; /* empty */
306 int domlen=strlen(domain);
307 int hostlen = strlen(host);
308 int hostoff; /* host name offset */
309 int domoff; /* domain name offset */
312 char ntlmbuf[256]; /* enough, unless the host/domain is very long */
314 /* point to the address of the pointer that holds the string to sent to the
315 server, which is for a plain host or for a HTTP proxy */
320 /* not set means empty */
327 switch(ntlm->state) {
328 case NTLMSTATE_TYPE1:
329 default: /* for the weird cases we (re)start here */
331 domoff = hostoff + hostlen;
333 DEBUGP (("Creating a type-1 NTLM message.\n"));
335 /* Create and send a type-1 message:
337 Index Description Content
338 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
340 8 NTLM Message Type long (0x01000000)
342 16 Supplied Domain security buffer(*)
343 24 Supplied Workstation security buffer(*)
344 32 start of data block
348 snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
349 "\x01%c%c%c" /* 32-bit type = 1 */
350 "%c%c%c%c" /* 32-bit NTLM flag field */
351 "%c%c" /* domain length */
352 "%c%c" /* domain allocated space */
353 "%c%c" /* domain name offset */
354 "%c%c" /* 2 zeroes */
355 "%c%c" /* host length */
356 "%c%c" /* host allocated space */
357 "%c%c" /* host name offset */
358 "%c%c" /* 2 zeroes */
360 "%s", /* domain string */
361 0, /* trailing zero */
362 0,0,0, /* part of type-1 long */
365 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
366 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
379 /* initial packet length */
380 size = 32 + hostlen + domlen;
382 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
383 base64_encode (ntlmbuf, size, base64);
385 output = concat_strings ("NTLM ", base64, (char *) 0);
388 case NTLMSTATE_TYPE2:
389 /* We received the type-2 already, create a type-3 message:
391 Index Description Content
392 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
394 8 NTLM Message Type long (0x03000000)
395 12 LM/LMv2 Response security buffer(*)
396 20 NTLM/NTLMv2 Response security buffer(*)
397 28 Domain Name security buffer(*)
398 36 User Name security buffer(*)
399 44 Workstation Name security buffer(*)
400 (52) Session Key (optional) security buffer(*)
401 (60) Flags (optional) long
402 52 (64) start of data block
410 unsigned char lmresp[0x18]; /* fixed-size */
411 #ifdef USE_NTRESPONSES
412 unsigned char ntresp[0x18]; /* fixed-size */
417 DEBUGP (("Creating a type-3 NTLM message.\n"));
419 usr = strchr(user, '\\');
421 usr = strchr(user, '/');
425 domlen = usr - domain;
430 userlen = strlen(usr);
432 mkhash(passwd, &ntlm->nonce[0], lmresp
433 #ifdef USE_NTRESPONSES
438 domoff = 64; /* always */
439 useroff = domoff + domlen;
440 hostoff = useroff + userlen;
441 lmrespoff = hostoff + hostlen;
442 ntrespoff = lmrespoff + 0x18;
444 /* Create the big type-3 message binary blob */
446 size = snprintf (ntlmbuf, sizeof(ntlmbuf),
448 "\x03%c%c%c" /* type-3, 32 bits */
450 "%c%c%c%c" /* LanManager length + allocated space */
451 "%c%c" /* LanManager offset */
452 "%c%c" /* 2 zeroes */
454 "%c%c" /* NT-response length */
455 "%c%c" /* NT-response allocated space */
456 "%c%c" /* NT-response offset */
457 "%c%c" /* 2 zeroes */
459 "%c%c" /* domain length */
460 "%c%c" /* domain allocated space */
461 "%c%c" /* domain name offset */
462 "%c%c" /* 2 zeroes */
464 "%c%c" /* user length */
465 "%c%c" /* user allocated space */
466 "%c%c" /* user offset */
467 "%c%c" /* 2 zeroes */
469 "%c%c" /* host length */
470 "%c%c" /* host allocated space */
471 "%c%c" /* host offset */
472 "%c%c%c%c%c%c" /* 6 zeroes */
474 "\xff\xff" /* message length */
475 "%c%c" /* 2 zeroes */
477 "\x01\x82" /* flags */
478 "%c%c" /* 2 zeroes */
483 /* LanManager response */
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 /* Make sure that the user and domain strings fit in the target buffer
528 before we copy them there. */
529 if(size + userlen + domlen >= sizeof(ntlmbuf))
532 memcpy(&ntlmbuf[size], domain, domlen);
535 memcpy(&ntlmbuf[size], usr, userlen);
538 /* we append the binary hashes to the end of the blob */
539 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
540 memcpy(&ntlmbuf[size], lmresp, 0x18);
544 #ifdef USE_NTRESPONSES
545 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
546 memcpy(&ntlmbuf[size], ntresp, 0x18);
551 ntlmbuf[56] = size & 0xff;
552 ntlmbuf[57] = size >> 8;
554 /* convert the binary blob into base64 */
555 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
556 base64_encode (ntlmbuf, size, base64);
558 output = concat_strings ("NTLM ", base64, (char *) 0);
560 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
565 case NTLMSTATE_TYPE3:
566 /* connection is already authenticated,
567 * don't send a header in future requests */