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