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