1/* NTLM code.
2   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
3   Inc.
4   Contributed by Daniel Stenberg.
5
6This file is part of GNU Wget.
7
8GNU Wget is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13GNU Wget is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with Wget.  If not, see <http://www.gnu.org/licenses/>.
20
21Additional permission under GNU GPL version 3 section 7
22
23If you modify this program, or any covered work, by linking or
24combining it with the OpenSSL project's OpenSSL library (or a
25modified version of that library), containing parts covered by the
26terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27grants you additional permission to convey the resulting work.
28Corresponding Source for a non-source form of such a combination
29shall include the source code for the parts of OpenSSL used as well
30as that of the covered work.  */
31
32#include "wget.h"
33
34/* NTLM details:
35
36   http://davenport.sourceforge.net/ntlm.html
37   http://www.innovation.ch/java/ntlm.html
38
39*/
40
41#include <stdio.h>
42#include <string.h>
43#include <stdlib.h>
44
45#include <openssl/des.h>
46#include <openssl/md4.h>
47#include <openssl/opensslv.h>
48
49#include "utils.h"
50#include "http-ntlm.h"
51
52#if OPENSSL_VERSION_NUMBER < 0x00907001L
53#define DES_key_schedule des_key_schedule
54#define DES_cblock des_cblock
55#define DES_set_odd_parity des_set_odd_parity
56#define DES_set_key des_set_key
57#define DES_ecb_encrypt des_ecb_encrypt
58
59/* This is how things were done in the old days */
60#define DESKEY(x) x
61#define DESKEYARG(x) x
62#else
63/* Modern version */
64#define DESKEYARG(x) *x
65#define DESKEY(x) &x
66#endif
67
68/* Define this to make the type-3 message include the NT response message */
69#define USE_NTRESPONSES 1
70
71/* Flag bits definitions available at on
72   http://davenport.sourceforge.net/ntlm.html */
73
74#define NTLMFLAG_NEGOTIATE_UNICODE               (1<<0)
75#define NTLMFLAG_NEGOTIATE_OEM                   (1<<1)
76#define NTLMFLAG_REQUEST_TARGET                  (1<<2)
77/* unknown (1<<3) */
78#define NTLMFLAG_NEGOTIATE_SIGN                  (1<<4)
79#define NTLMFLAG_NEGOTIATE_SEAL                  (1<<5)
80#define NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE        (1<<6)
81#define NTLMFLAG_NEGOTIATE_LM_KEY                (1<<7)
82#define NTLMFLAG_NEGOTIATE_NETWARE               (1<<8)
83#define NTLMFLAG_NEGOTIATE_NTLM_KEY              (1<<9)
84/* unknown (1<<10) */
85/* unknown (1<<11) */
86#define NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED       (1<<12)
87#define NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED  (1<<13)
88#define NTLMFLAG_NEGOTIATE_LOCAL_CALL            (1<<14)
89#define NTLMFLAG_NEGOTIATE_ALWAYS_SIGN           (1<<15)
90#define NTLMFLAG_TARGET_TYPE_DOMAIN              (1<<16)
91#define NTLMFLAG_TARGET_TYPE_SERVER              (1<<17)
92#define NTLMFLAG_TARGET_TYPE_SHARE               (1<<18)
93#define NTLMFLAG_NEGOTIATE_NTLM2_KEY             (1<<19)
94#define NTLMFLAG_REQUEST_INIT_RESPONSE           (1<<20)
95#define NTLMFLAG_REQUEST_ACCEPT_RESPONSE         (1<<21)
96#define NTLMFLAG_REQUEST_NONNT_SESSION_KEY       (1<<22)
97#define NTLMFLAG_NEGOTIATE_TARGET_INFO           (1<<23)
98/* unknown (1<24) */
99/* unknown (1<25) */
100/* unknown (1<26) */
101/* unknown (1<27) */
102/* unknown (1<28) */
103#define NTLMFLAG_NEGOTIATE_128                   (1<<29)
104#define NTLMFLAG_NEGOTIATE_KEY_EXCHANGE          (1<<30)
105#define NTLMFLAG_NEGOTIATE_56                    (1<<31)
106
107/*
108  (*) = A "security buffer" is a triplet consisting of two shorts and one
109  long:
110
111  1. a 'short' containing the length of the buffer in bytes
112  2. a 'short' containing the allocated space for the buffer in bytes
113  3. a 'long' containing the offset to the start of the buffer from the
114     beginning of the NTLM message, in bytes.
115*/
116
117/* return true on success, false otherwise */
118bool
119ntlm_input (struct ntlmdata *ntlm, const char *header)
120{
121  if (0 != strncmp (header, "NTLM", 4))
122    return false;
123
124  header += 4;
125  while (*header && c_isspace(*header))
126    header++;
127
128  if (*header)
129    {
130      /* We got a type-2 message here:
131
132         Index   Description         Content
133         0       NTLMSSP Signature   Null-terminated ASCII "NTLMSSP"
134                                     (0x4e544c4d53535000)
135         8       NTLM Message Type   long (0x02000000)
136         12      Target Name         security buffer(*)
137         20      Flags               long
138         24      Challenge           8 bytes
139         (32)    Context (optional)  8 bytes (two consecutive longs)
140         (40)    Target Information  (optional) security buffer(*)
141         32 (48) start of data block
142      */
143      int size;
144      char *buffer = (char *) alloca (strlen (header));
145
146      DEBUGP (("Received a type-2 NTLM message.\n"));
147
148      size = base64_decode (header, buffer);
149      if (size < 0)
150        return false;           /* malformed base64 from server */
151
152      ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
153
154      if (size >= 48)
155        /* the nonce of interest is index [24 .. 31], 8 bytes */
156        memcpy (ntlm->nonce, &buffer[24], 8);
157
158      /* at index decimal 20, there's a 32bit NTLM flag field */
159    }
160  else
161    {
162      if (ntlm->state >= NTLMSTATE_TYPE1)
163        {
164          DEBUGP (("Unexpected empty NTLM message.\n"));
165          return false; /* this is an error */
166        }
167
168      DEBUGP (("Empty NTLM message, starting transaction.\n"));
169      ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
170    }
171
172  return true;
173}
174
175/*
176 * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
177 * key schedule ks is also set.
178 */
179static void
180setup_des_key(unsigned char *key_56,
181              DES_key_schedule DESKEYARG(ks))
182{
183  DES_cblock key;
184
185  key[0] = key_56[0];
186  key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
187  key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
188  key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
189  key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
190  key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
191  key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
192  key[7] =  (key_56[6] << 1) & 0xFF;
193
194  DES_set_odd_parity(&key);
195  DES_set_key(&key, ks);
196}
197
198 /*
199  * takes a 21 byte array and treats it as 3 56-bit DES keys. The
200  * 8 byte plaintext is encrypted with each key and the resulting 24
201  * bytes are stored in the results array.
202  */
203static void
204calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
205{
206  DES_key_schedule ks;
207
208  setup_des_key(keys, DESKEY(ks));
209  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) results,
210                  DESKEY(ks), DES_ENCRYPT);
211
212  setup_des_key(keys+7, DESKEY(ks));
213  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+8),
214                  DESKEY(ks), DES_ENCRYPT);
215
216  setup_des_key(keys+14, DESKEY(ks));
217  DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
218                  DESKEY(ks), DES_ENCRYPT);
219}
220
221/*
222 * Set up lanmanager and nt hashed passwords
223 */
224static void
225mkhash(const char *password,
226       unsigned char *nonce,    /* 8 bytes */
227       unsigned char *lmresp    /* must fit 0x18 bytes */
228#ifdef USE_NTRESPONSES
229       , unsigned char *ntresp  /* must fit 0x18 bytes */
230#endif
231  )
232{
233  unsigned char lmbuffer[21];
234#ifdef USE_NTRESPONSES
235  unsigned char ntbuffer[21];
236#endif
237  unsigned char *pw;
238  static const unsigned char magic[] = {
239    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
240  };
241  int i;
242  int len = strlen(password);
243
244  /* make it fit at least 14 bytes */
245  pw = (unsigned char *) alloca (len < 7 ? 14 : len * 2);
246
247  if (len > 14)
248    len = 14;
249
250  for (i=0; i<len; i++)
251    pw[i] = c_toupper (password[i]);
252
253  for (; i<14; i++)
254    pw[i] = 0;
255
256  {
257    /* create LanManager hashed password */
258    DES_key_schedule ks;
259
260    setup_des_key(pw, DESKEY(ks));
261    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
262                    DESKEY(ks), DES_ENCRYPT);
263
264    setup_des_key(pw+7, DESKEY(ks));
265    DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
266                    DESKEY(ks), DES_ENCRYPT);
267
268    memset(lmbuffer+16, 0, 5);
269  }
270  /* create LM responses */
271  calc_resp(lmbuffer, nonce, lmresp);
272
273#ifdef USE_NTRESPONSES
274  {
275    /* create NT hashed password */
276    MD4_CTX MD4;
277
278    len = strlen(password);
279
280    for (i=0; i<len; i++) {
281      pw[2*i]   = password[i];
282      pw[2*i+1] = 0;
283    }
284
285    MD4_Init(&MD4);
286    MD4_Update(&MD4, pw, 2*len);
287    MD4_Final(ntbuffer, &MD4);
288
289    memset(ntbuffer+16, 0, 5);
290  }
291
292  calc_resp(ntbuffer, nonce, ntresp);
293#endif
294}
295
296#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
297#define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
298  (((x) >>16)&0xff), ((x)>>24)
299
300/* this is for creating ntlm header output */
301char *
302ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
303             bool *ready)
304{
305  const char *domain=""; /* empty */
306  const char *host=""; /* empty */
307  int domlen=strlen(domain);
308  int hostlen = strlen(host);
309  int hostoff; /* host name offset */
310  int domoff;  /* domain name offset */
311  int size;
312  char *base64;
313  char ntlmbuf[256]; /* enough, unless the host/domain is very long */
314
315  /* point to the address of the pointer that holds the string to sent to the
316     server, which is for a plain host or for a HTTP proxy */
317  char *output;
318
319  *ready = false;
320
321  /* not set means empty */
322  if(!user)
323    user="";
324
325  if(!passwd)
326    passwd="";
327
328  switch(ntlm->state) {
329  case NTLMSTATE_TYPE1:
330  default: /* for the weird cases we (re)start here */
331    hostoff = 32;
332    domoff = hostoff + hostlen;
333
334    DEBUGP (("Creating a type-1 NTLM message.\n"));
335
336    /* Create and send a type-1 message:
337
338    Index Description          Content
339    0     NTLMSSP Signature    Null-terminated ASCII "NTLMSSP"
340                               (0x4e544c4d53535000)
341    8     NTLM Message Type    long (0x01000000)
342    12    Flags                long
343    16    Supplied Domain      security buffer(*)
344    24    Supplied Workstation security buffer(*)
345    32    start of data block
346
347    */
348
349    snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
350              "\x01%c%c%c" /* 32-bit type = 1 */
351              "%c%c%c%c"   /* 32-bit NTLM flag field */
352              "%c%c"  /* domain length */
353              "%c%c"  /* domain allocated space */
354              "%c%c"  /* domain name offset */
355              "%c%c"  /* 2 zeroes */
356              "%c%c"  /* host length */
357              "%c%c"  /* host allocated space */
358              "%c%c"  /* host name offset */
359              "%c%c"  /* 2 zeroes */
360              "%s"   /* host name */
361              "%s",  /* domain string */
362              0,     /* trailing zero */
363              0,0,0, /* part of type-1 long */
364
365              LONGQUARTET(
366                NTLMFLAG_NEGOTIATE_OEM|      /*   2 */
367                NTLMFLAG_NEGOTIATE_NTLM_KEY  /* 200 */
368                /* equals 0x0202 */
369                ),
370              SHORTPAIR(domlen),
371              SHORTPAIR(domlen),
372              SHORTPAIR(domoff),
373              0,0,
374              SHORTPAIR(hostlen),
375              SHORTPAIR(hostlen),
376              SHORTPAIR(hostoff),
377              0,0,
378              host, domain);
379
380    /* initial packet length */
381    size = 32 + hostlen + domlen;
382
383    base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
384    base64_encode (ntlmbuf, size, base64);
385
386    output = concat_strings ("NTLM ", base64, (char *) 0);
387    break;
388
389  case NTLMSTATE_TYPE2:
390    /* We received the type-2 already, create a type-3 message:
391
392    Index   Description            Content
393    0       NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
394                                   (0x4e544c4d53535000)
395    8       NTLM Message Type      long (0x03000000)
396    12      LM/LMv2 Response       security buffer(*)
397    20      NTLM/NTLMv2 Response   security buffer(*)
398    28      Domain Name            security buffer(*)
399    36      User Name              security buffer(*)
400    44      Workstation Name       security buffer(*)
401    (52)    Session Key (optional) security buffer(*)
402    (60)    Flags (optional)       long
403    52 (64) start of data block
404
405    */
406
407  {
408    int lmrespoff;
409    int ntrespoff;
410    int useroff;
411    unsigned char lmresp[0x18]; /* fixed-size */
412#ifdef USE_NTRESPONSES
413    unsigned char ntresp[0x18]; /* fixed-size */
414#endif
415    const char *usr;
416    int userlen;
417
418    DEBUGP (("Creating a type-3 NTLM message.\n"));
419
420    usr = strchr(user, '\\');
421    if(!usr)
422      usr = strchr(user, '/');
423
424    if (usr) {
425      domain = user;
426      domlen = usr - domain;
427      usr++;
428    }
429    else
430      usr = user;
431    userlen = strlen(usr);
432
433    mkhash(passwd, &ntlm->nonce[0], lmresp
434#ifdef USE_NTRESPONSES
435           , ntresp
436#endif
437      );
438
439    domoff = 64; /* always */
440    useroff = domoff + domlen;
441    hostoff = useroff + userlen;
442    lmrespoff = hostoff + hostlen;
443    ntrespoff = lmrespoff + 0x18;
444
445    /* Create the big type-3 message binary blob */
446
447    size = snprintf (ntlmbuf, sizeof(ntlmbuf),
448                     "NTLMSSP%c"
449                     "\x03%c%c%c" /* type-3, 32 bits */
450
451                     "%c%c%c%c" /* LanManager length + allocated space */
452                     "%c%c" /* LanManager offset */
453                     "%c%c" /* 2 zeroes */
454
455                     "%c%c" /* NT-response length */
456                     "%c%c" /* NT-response allocated space */
457                     "%c%c" /* NT-response offset */
458                     "%c%c" /* 2 zeroes */
459
460                     "%c%c"  /* domain length */
461                     "%c%c"  /* domain allocated space */
462                     "%c%c"  /* domain name offset */
463                     "%c%c"  /* 2 zeroes */
464
465                     "%c%c"  /* user length */
466                     "%c%c"  /* user allocated space */
467                     "%c%c"  /* user offset */
468                     "%c%c"  /* 2 zeroes */
469
470                     "%c%c"  /* host length */
471                     "%c%c"  /* host allocated space */
472                     "%c%c"  /* host offset */
473                     "%c%c%c%c%c%c"  /* 6 zeroes */
474
475                     "\xff\xff"  /* message length */
476                     "%c%c"  /* 2 zeroes */
477
478                     "\x01\x82" /* flags */
479                     "%c%c"  /* 2 zeroes */
480
481                     /* domain string */
482                     /* user string */
483                     /* host string */
484                     /* LanManager response */
485                     /* NT response */
486                     ,
487                     0, /* zero termination */
488                     0,0,0, /* type-3 long, the 24 upper bits */
489
490                     SHORTPAIR(0x18),  /* LanManager response length, twice */
491                     SHORTPAIR(0x18),
492                     SHORTPAIR(lmrespoff),
493                     0x0, 0x0,
494
495#ifdef USE_NTRESPONSES
496                     SHORTPAIR(0x18),  /* NT-response length, twice */
497                     SHORTPAIR(0x18),
498#else
499                     0x0, 0x0,
500                     0x0, 0x0,
501#endif
502                     SHORTPAIR(ntrespoff),
503                     0x0, 0x0,
504
505                     SHORTPAIR(domlen),
506                     SHORTPAIR(domlen),
507                     SHORTPAIR(domoff),
508                     0x0, 0x0,
509
510                     SHORTPAIR(userlen),
511                     SHORTPAIR(userlen),
512                     SHORTPAIR(useroff),
513                     0x0, 0x0,
514
515                     SHORTPAIR(hostlen),
516                     SHORTPAIR(hostlen),
517                     SHORTPAIR(hostoff),
518                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
519
520                     0x0, 0x0,
521
522                     0x0, 0x0);
523
524    /* size is now 64 */
525    size=64;
526    ntlmbuf[62]=ntlmbuf[63]=0;
527
528    /* Make sure that the user and domain strings fit in the target buffer
529       before we copy them there. */
530    if(((size_t) size + userlen + domlen) >= sizeof(ntlmbuf))
531      return NULL;
532
533    memcpy(&ntlmbuf[size], domain, domlen);
534    size += domlen;
535
536    memcpy(&ntlmbuf[size], usr, userlen);
537    size += userlen;
538
539    /* we append the binary hashes to the end of the blob */
540    if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
541      memcpy(&ntlmbuf[size], lmresp, 0x18);
542      size += 0x18;
543    }
544
545#ifdef USE_NTRESPONSES
546    if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
547      memcpy(&ntlmbuf[size], ntresp, 0x18);
548      size += 0x18;
549    }
550#endif
551
552    ntlmbuf[56] = size & 0xff;
553    ntlmbuf[57] = size >> 8;
554
555    /* convert the binary blob into base64 */
556    base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
557    base64_encode (ntlmbuf, size, base64);
558
559    output = concat_strings ("NTLM ", base64, (char *) 0);
560
561    ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
562    *ready = true;
563  }
564  break;
565
566  case NTLMSTATE_TYPE3:
567    /* connection is already authenticated,
568     * don't send a header in future requests */
569    *ready = true;
570    output = NULL;
571    break;
572  }
573
574  return output;
575}
576