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 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 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
341 Format string (merged for pre-ANSI compilers):
343 "\x01%c%c%c" 32-bit type = 1
344 "%c%c%c%c" 32-bit NTLM flag field
346 "%c%c" domain allocated space
347 "%c%c" domain name offset
350 "%c%c" host allocated space
351 "%c%c" host name offset
357 snprintf(ntlmbuf, sizeof(ntlmbuf),
358 "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",
359 0, /* trailing zero */
360 0,0,0, /* part of type-1 long */
363 NTLMFLAG_NEGOTIATE_OEM| /* 2 */
364 NTLMFLAG_NEGOTIATE_NTLM_KEY /* 200 */
377 /* initial packet length */
378 size = 32 + hostlen + domlen;
380 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
381 base64_encode (ntlmbuf, size, base64);
383 output = concat_strings ("NTLM ", base64, (char *) 0);
386 case NTLMSTATE_TYPE2:
387 /* We received the type-2 already, create a type-3 message:
389 Index Description Content
390 0 NTLMSSP Signature Null-terminated ASCII "NTLMSSP"
392 8 NTLM Message Type long (0x03000000)
393 12 LM/LMv2 Response security buffer(*)
394 20 NTLM/NTLMv2 Response security buffer(*)
395 28 Domain Name security buffer(*)
396 36 User Name security buffer(*)
397 44 Workstation Name security buffer(*)
398 (52) Session Key (optional) security buffer(*)
399 (60) Flags (optional) long
400 52 (64) start of data block
408 unsigned char lmresp[0x18]; /* fixed-size */
409 #ifdef USE_NTRESPONSES
410 unsigned char ntresp[0x18]; /* fixed-size */
415 usr = strchr(user, '\\');
417 usr = strchr(user, '/');
421 domlen = usr - domain;
426 userlen = strlen(usr);
428 mkhash(passwd, &ntlm->nonce[0], lmresp
429 #ifdef USE_NTRESPONSES
434 domoff = 64; /* always */
435 useroff = domoff + domlen;
436 hostoff = useroff + userlen;
437 lmrespoff = hostoff + hostlen;
438 ntrespoff = lmrespoff + 0x18;
440 /* Create the big type-3 message binary blob:
442 "\x03%c%c%c" type-3, 32 bits
444 "%c%c%c%c" LanManager length + allocated space
445 "%c%c" LanManager offset
448 "%c%c" NT-response length
449 "%c%c" NT-response allocated space
450 "%c%c" NT-response offset
454 "%c%c" domain allocated space
455 "%c%c" domain name offset
459 "%c%c" user allocated space
464 "%c%c" host allocated space
466 "%c%c%c%c%c%c" 6 zeroes
468 "\xff\xff" message length
474 size = snprintf(ntlmbuf, sizeof(ntlmbuf),
475 "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",
476 0, /* zero termination */
477 0,0,0, /* type-3 long, the 24 upper bits */
479 SHORTPAIR(0x18), /* LanManager response length, twice */
481 SHORTPAIR(lmrespoff),
484 #ifdef USE_NTRESPONSES
485 SHORTPAIR(0x18), /* NT-response length, twice */
491 SHORTPAIR(ntrespoff),
507 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
515 ntlmbuf[62]=ntlmbuf[63]=0;
517 memcpy(&ntlmbuf[size], domain, domlen);
520 memcpy(&ntlmbuf[size], usr, userlen);
523 /* we append the binary hashes to the end of the blob */
524 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
525 memcpy(&ntlmbuf[size], lmresp, 0x18);
529 #ifdef USE_NTRESPONSES
530 if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
531 memcpy(&ntlmbuf[size], ntresp, 0x18);
536 ntlmbuf[56] = size & 0xff;
537 ntlmbuf[57] = size >> 8;
539 /* convert the binary blob into base64 */
540 base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
541 base64_encode (ntlmbuf, size, base64);
543 output = concat_strings ("NTLM ", base64, (char *) 0);
545 ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
550 case NTLMSTATE_TYPE3:
551 /* connection is already authenticated,
552 * don't send a header in future requests */