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 unsigned char *buffer = (unsigned char *) alloca (strlen (header));
150 size = base64_decode (header, buffer);
152 return 0; /* malformed base64 from server */
154 ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
157 /* the nonce of interest is index [24 .. 31], 8 bytes */
158 memcpy (ntlm->nonce, &buffer[24], 8);
160 /* at index decimal 20, there's a 32bit NTLM flag field */
164 if (ntlm->state >= NTLMSTATE_TYPE1)
165 return 0; /* this is an error */
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.
177 static void setup_des_key(unsigned char *key_56,
178 DES_key_schedule DESKEYARG(ks))
183 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
184 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
185 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
186 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
187 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
188 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
189 key[7] = (key_56[6] << 1) & 0xFF;
191 DES_set_odd_parity(&key);
192 DES_set_key(&key, ks);
196 * takes a 21 byte array and treats it as 3 56-bit DES keys. The
197 * 8 byte plaintext is encrypted with each key and the resulting 24
198 * bytes are stored in the results array.
200 static void calc_resp(unsigned char *keys,
201 unsigned char *plaintext,
202 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
222 static void mkhash(const char *password,
223 unsigned char *nonce, /* 8 bytes */
224 unsigned char *lmresp /* must fit 0x18 bytes */
225 #ifdef USE_NTRESPONSES
226 , unsigned char *ntresp /* must fit 0x18 bytes */
230 unsigned char lmbuffer[21];
231 #ifdef USE_NTRESPONSES
232 unsigned char ntbuffer[21];
235 static const unsigned char magic[] = {
236 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
239 int len = strlen(password);
241 /* make it fit at least 14 bytes */
242 pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
247 for (i=0; i<len; i++)
248 pw[i] = TOUPPER (password[i]);
254 /* create LanManager hashed password */
257 setup_des_key(pw, DESKEY(ks));
258 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
259 DESKEY(ks), DES_ENCRYPT);
261 setup_des_key(pw+7, DESKEY(ks));
262 DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
263 DESKEY(ks), DES_ENCRYPT);
265 memset(lmbuffer+16, 0, 5);
267 /* create LM responses */
268 calc_resp(lmbuffer, nonce, lmresp);
270 #ifdef USE_NTRESPONSES
272 /* create NT hashed password */
275 len = strlen(password);
277 for (i=0; i<len; i++) {
278 pw[2*i] = password[i];
283 MD4_Update(&MD4, pw, 2*len);
284 MD4_Final(ntbuffer, &MD4);
286 memset(ntbuffer+16, 0, 5);
289 calc_resp(ntbuffer, nonce, ntresp);
293 #define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
294 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
295 (((x) >>16)&0xff), ((x)>>24)
297 /* this is for creating ntlm header output */
298 char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
301 const char *domain=""; /* empty */
302 const char *host=""; /* empty */
303 int domlen=strlen(domain);
304 int hostlen = strlen(host);
305 int hostoff; /* host name offset */
306 int domoff; /* domain name offset */
309 unsigned char ntlmbuf[256]; /* enough, unless the host/domain is very long */
311 /* point to the address of the pointer that holds the string to sent to the
312 server, which is for a plain host or for a HTTP proxy */
317 /* not set means empty */
324 switch(ntlm->state) {
325 case NTLMSTATE_TYPE1:
326 default: /* for the weird cases we (re)start here */
328 domoff = hostoff + hostlen;
330 /* Create and send a type-1 message:
332 Index Description Content
333 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
335 8 NTLM Message Type long (0x01000000)
337 16 Supplied Domain security buffer(*)
338 24 Supplied Workstation security buffer(*)
339 32 start of data block
343 snprintf((char *)ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
344 "\x01%c%c%c" /* 32-bit type = 1 */
345 "%c%c%c%c" /* 32-bit NTLM flag field */
346 "%c%c" /* domain length */
347 "%c%c" /* domain allocated space */
348 "%c%c" /* domain name offset */
349 "%c%c" /* 2 zeroes */
350 "%c%c" /* host length */
351 "%c%c" /* host allocated space */
352 "%c%c" /* host name offset */
353 "%c%c" /* 2 zeroes */
355 "%s", /* domain string */
356 0, /* trailing zero */
357 0,0,0, /* part of type-1 long */
360 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
361 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
374 /* initial packet length */
375 size = 32 + hostlen + domlen;
377 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
378 base64_encode (ntlmbuf, base64, size);
380 output = concat_strings ("NTLM ", base64, (char *) 0);
383 case NTLMSTATE_TYPE2:
384 /* We received the type-2 already, create a type-3 message:
386 Index Description Content
387 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
389 8 NTLM Message Type long (0x03000000)
390 12 LM/LMv2 Response security buffer(*)
391 20 NTLM/NTLMv2 Response security buffer(*)
392 28 Domain Name security buffer(*)
393 36 User Name security buffer(*)
394 44 Workstation Name security buffer(*)
395 (52) Session Key (optional) security buffer(*)
396 (60) Flags (optional) long
397 52 (64) start of data block
405 unsigned char lmresp[0x18]; /* fixed-size */
406 #ifdef USE_NTRESPONSES
407 unsigned char ntresp[0x18]; /* fixed-size */
412 usr = strchr(user, '\\');
414 usr = strchr(user, '/');
418 domlen = usr - domain;
423 userlen = strlen(usr);
425 mkhash(passwd, &ntlm->nonce[0], lmresp
426 #ifdef USE_NTRESPONSES
431 domoff = 64; /* always */
432 useroff = domoff + domlen;
433 hostoff = useroff + userlen;
434 lmrespoff = hostoff + hostlen;
435 ntrespoff = lmrespoff + 0x18;
437 /* Create the big type-3 message binary blob */
438 size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
440 "\x03%c%c%c" /* type-3, 32 bits */
442 "%c%c%c%c" /* LanManager length + allocated space */
443 "%c%c" /* LanManager offset */
444 "%c%c" /* 2 zeroes */
446 "%c%c" /* NT-response length */
447 "%c%c" /* NT-response allocated space */
448 "%c%c" /* NT-response offset */
449 "%c%c" /* 2 zeroes */
451 "%c%c" /* domain length */
452 "%c%c" /* domain allocated space */
453 "%c%c" /* domain name offset */
454 "%c%c" /* 2 zeroes */
456 "%c%c" /* user length */
457 "%c%c" /* user allocated space */
458 "%c%c" /* user offset */
459 "%c%c" /* 2 zeroes */
461 "%c%c" /* host length */
462 "%c%c" /* host allocated space */
463 "%c%c" /* host offset */
464 "%c%c%c%c%c%c" /* 6 zeroes */
466 "\xff\xff" /* message length */
467 "%c%c" /* 2 zeroes */
469 "\x01\x82" /* flags */
470 "%c%c" /* 2 zeroes */
475 /* LanManager response */
478 0, /* zero termination */
479 0,0,0, /* type-3 long, the 24 upper bits */
481 SHORTPAIR(0x18), /* LanManager response length, twice */
483 SHORTPAIR(lmrespoff),
486 #ifdef USE_NTRESPONSES
487 SHORTPAIR(0x18), /* NT-response length, twice */
493 SHORTPAIR(ntrespoff),
509 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
517 ntlmbuf[62]=ntlmbuf[63]=0;
519 memcpy(&ntlmbuf[size], domain, domlen);
522 memcpy(&ntlmbuf[size], usr, userlen);
525 /* we append the binary hashes to the end of the blob */
526 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
527 memcpy(&ntlmbuf[size], lmresp, 0x18);
531 #ifdef USE_NTRESPONSES
532 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
533 memcpy(&ntlmbuf[size], ntresp, 0x18);
538 ntlmbuf[56] = size & 0xff;
539 ntlmbuf[57] = size >> 8;
541 /* convert the binary blob into base64 */
542 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
543 base64_encode (ntlmbuf, base64, size);
545 output = concat_strings ("NTLM ", base64, (char *) 0);
547 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
552 case NTLMSTATE_TYPE3:
553 /* connection is already authenticated,
554 * don't send a header in future requests */