]> sjero.net Git - wget/blobdiff - src/http-ntlm.c
NEWS: cite --start-pos
[wget] / src / http-ntlm.c
index 6e35cbbe50e8c116ba9e0afba84fde3c7a26dfb7..591bfb514b9a1619b62a95da31ffac3a0a4ca46e 100644 (file)
@@ -1,12 +1,13 @@
 /* NTLM code.
 /* NTLM code.
-   Copyright (C) 2005 Free Software Foundation, Inc.
-   Donated by Daniel Stenberg.
+   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+   Foundation, Inc.
+   Contributed by Daniel Stenberg.
 
 This file is part of GNU Wget.
 
 GNU Wget is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 This file is part of GNU Wget.
 
 GNU Wget is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
+the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.
 
 GNU Wget is distributed in the hope that it will be useful,
  (at your option) any later version.
 
 GNU Wget is distributed in the hope that it will be useful,
@@ -15,63 +16,63 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+along with Wget.  If not, see <http://www.gnu.org/licenses/>.
 
 
-In addition, as a special exception, the Free Software Foundation
-gives permission to link the code of its release of Wget with the
-OpenSSL project's "OpenSSL" library (or with modified versions of it
-that use the same license as the "OpenSSL" library), and distribute
-the linked executables.  You must obey the GNU General Public License
-in all respects for all of the code used other than "OpenSSL".  If you
-modify this file, you may extend this exception to your version of the
-file, but you are not obligated to do so.  If you do not wish to do
-so, delete this exception statement from your version.  */
+Additional permission under GNU GPL version 3 section 7
 
 
-#include <config.h>
+If you modify this program, or any covered work, by linking or
+combining it with the OpenSSL project's OpenSSL library (or a
+modified version of that library), containing parts covered by the
+terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
+grants you additional permission to convey the resulting work.
+Corresponding Source for a non-source form of such a combination
+shall include the source code for the parts of OpenSSL used as well
+as that of the covered work.  */
+
+#include "wget.h"
 
 /* NTLM details:
 
 /* NTLM details:
-   
+
    http://davenport.sourceforge.net/ntlm.html
    http://www.innovation.ch/java/ntlm.html
 
 */
 
    http://davenport.sourceforge.net/ntlm.html
    http://www.innovation.ch/java/ntlm.html
 
 */
 
-/* -- WIN32 approved -- */
 #include <stdio.h>
 #include <stdio.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif
+#include <string.h>
 #include <stdlib.h>
 
 #include <stdlib.h>
 
-#include <openssl/des.h>
-#include <openssl/md4.h>
-#include <openssl/ssl.h>
-
-#include "wget.h"
 #include "utils.h"
 #include "http-ntlm.h"
 
 #include "utils.h"
 #include "http-ntlm.h"
 
-#if OPENSSL_VERSION_NUMBER < 0x00907001L
-#define DES_key_schedule des_key_schedule
-#define DES_cblock des_cblock
-#define DES_set_odd_parity des_set_odd_parity
-#define DES_set_key des_set_key
-#define DES_ecb_encrypt des_ecb_encrypt
+#ifdef HAVE_NETTLE
+# include <nettle/md4.h>
+# include <nettle/des.h>
+#else
+# include <openssl/des.h>
+# include <openssl/md4.h>
+# include <openssl/opensslv.h>
+
+# if OPENSSL_VERSION_NUMBER < 0x00907001L
+#  define DES_key_schedule des_key_schedule
+#  define DES_cblock des_cblock
+#  define DES_set_odd_parity des_set_odd_parity
+#  define DES_set_key des_set_key
+#  define DES_ecb_encrypt des_ecb_encrypt
 
 /* This is how things were done in the old days */
 
 /* This is how things were done in the old days */
-#define DESKEY(x) x
-#define DESKEYARG(x) x
-#else
+#  define DESKEY(x) x
+#  define DESKEYARG(x) x
+# else
 /* Modern version */
 /* Modern version */
-#define DESKEYARG(x) *x
-#define DESKEY(x) &x
+#  define DESKEYARG(x) *x
+#  define DESKEY(x) &x
+# endif
+
 #endif
 
 /* Define this to make the type-3 message include the NT response message */
 #endif
 
 /* Define this to make the type-3 message include the NT response message */
-#undef USE_NTRESPONSES
+#define USE_NTRESPONSES 1
 \f
 /* Flag bits definitions available at on
    http://davenport.sourceforge.net/ntlm.html */
 \f
 /* Flag bits definitions available at on
    http://davenport.sourceforge.net/ntlm.html */
@@ -119,14 +120,15 @@ so, delete this exception statement from your version.  */
      beginning of the NTLM message, in bytes.
 */
 
      beginning of the NTLM message, in bytes.
 */
 
-/* return 1 on success, 0 otherwise */
-int ntlm_input (struct ntlmdata *ntlm, const char *header)
+/* return true on success, false otherwise */
+bool
+ntlm_input (struct ntlmdata *ntlm, const char *header)
 {
   if (0 != strncmp (header, "NTLM", 4))
 {
   if (0 != strncmp (header, "NTLM", 4))
-    return 0;
+    return false;
 
   header += 4;
 
   header += 4;
-  while (*header && ISSPACE(*header))
+  while (*header && c_isspace(*header))
     header++;
 
   if (*header)
     header++;
 
   if (*header)
@@ -147,9 +149,11 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header)
       int size;
       char *buffer = (char *) alloca (strlen (header));
 
       int size;
       char *buffer = (char *) alloca (strlen (header));
 
+      DEBUGP (("Received a type-2 NTLM message.\n"));
+
       size = base64_decode (header, buffer);
       if (size < 0)
       size = base64_decode (header, buffer);
       if (size < 0)
-       return 0;               /* malformed base64 from server */
+        return false;           /* malformed base64 from server */
 
       ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
 
 
       ntlm->state = NTLMSTATE_TYPE2; /* we got a type-2 */
 
@@ -162,20 +166,44 @@ int ntlm_input (struct ntlmdata *ntlm, const char *header)
   else
     {
       if (ntlm->state >= NTLMSTATE_TYPE1)
   else
     {
       if (ntlm->state >= NTLMSTATE_TYPE1)
-        return 0; /* this is an error */
+        {
+          DEBUGP (("Unexpected empty NTLM message.\n"));
+          return false; /* this is an error */
+        }
 
 
+      DEBUGP (("Empty NTLM message, starting transaction.\n"));
       ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
     }
 
       ntlm->state = NTLMSTATE_TYPE1; /* we should sent away a type-1 */
     }
 
-  return 1;
+  return true;
 }
 
 /*
  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
  * key schedule ks is also set.
  */
 }
 
 /*
  * Turns a 56 bit key into the 64 bit, odd parity key and sets the key.  The
  * key schedule ks is also set.
  */
-static void setup_des_key(unsigned char *key_56,
-                          DES_key_schedule DESKEYARG(ks))
+#ifdef HAVE_NETTLE
+static void
+setup_des_key(unsigned char *key_56,
+              struct des_ctx *des)
+{
+  unsigned char key[8];
+
+  key[0] = key_56[0];
+  key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
+  key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
+  key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
+  key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
+  key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
+  key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
+  key[7] =  (key_56[6] << 1) & 0xFF;
+
+  nettle_des_set_key(des, key);
+}
+#else
+static void
+setup_des_key(unsigned char *key_56,
+              DES_key_schedule DESKEYARG(ks))
 {
   DES_cblock key;
 
 {
   DES_cblock key;
 
@@ -191,16 +219,28 @@ static void setup_des_key(unsigned char *key_56,
   DES_set_odd_parity(&key);
   DES_set_key(&key, ks);
 }
   DES_set_odd_parity(&key);
   DES_set_key(&key, ks);
 }
+#endif
 
  /*
   * takes a 21 byte array and treats it as 3 56-bit DES keys. The
   * 8 byte plaintext is encrypted with each key and the resulting 24
   * bytes are stored in the results array.
   */
 
  /*
   * takes a 21 byte array and treats it as 3 56-bit DES keys. The
   * 8 byte plaintext is encrypted with each key and the resulting 24
   * bytes are stored in the results array.
   */
-static void calc_resp(unsigned char *keys,
-                      unsigned char *plaintext,
-                      unsigned char *results)
+static void
+calc_resp(unsigned char *keys, unsigned char *plaintext, unsigned char *results)
 {
 {
+#ifdef HAVE_NETTLE
+  struct des_ctx des;
+
+  setup_des_key(keys, &des);
+  nettle_des_encrypt(&des, 8, results, plaintext);
+
+  setup_des_key(keys + 7, &des);
+  nettle_des_encrypt(&des, 8, results + 8, plaintext);
+
+  setup_des_key(keys + 14, &des);
+  nettle_des_encrypt(&des, 8, results + 16, plaintext);
+#else
   DES_key_schedule ks;
 
   setup_des_key(keys, DESKEY(ks));
   DES_key_schedule ks;
 
   setup_des_key(keys, DESKEY(ks));
@@ -214,16 +254,18 @@ static void calc_resp(unsigned char *keys,
   setup_des_key(keys+14, DESKEY(ks));
   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
                   DESKEY(ks), DES_ENCRYPT);
   setup_des_key(keys+14, DESKEY(ks));
   DES_ecb_encrypt((DES_cblock*) plaintext, (DES_cblock*) (results+16),
                   DESKEY(ks), DES_ENCRYPT);
+#endif
 }
 
 /*
  * Set up lanmanager and nt hashed passwords
  */
 }
 
 /*
  * Set up lanmanager and nt hashed passwords
  */
-static void mkhash(const char *password,
-                   unsigned char *nonce,  /* 8 bytes */
-                   unsigned char *lmresp  /* must fit 0x18 bytes */
+static void
+mkhash(const char *password,
+       unsigned char *nonce,    /* 8 bytes */
+       unsigned char *lmresp    /* must fit 0x18 bytes */
 #ifdef USE_NTRESPONSES
 #ifdef USE_NTRESPONSES
-                   , unsigned char *ntresp  /* must fit 0x18 bytes */
+       , unsigned char *ntresp  /* must fit 0x18 bytes */
 #endif
   )
 {
 #endif
   )
 {
@@ -243,24 +285,34 @@ static void mkhash(const char *password,
 
   if (len > 14)
     len = 14;
 
   if (len > 14)
     len = 14;
-  
+
   for (i=0; i<len; i++)
   for (i=0; i<len; i++)
-    pw[i] = TOUPPER (password[i]);
+    pw[i] = c_toupper (password[i]);
 
   for (; i<14; i++)
     pw[i] = 0;
 
   {
     /* create LanManager hashed password */
 
   for (; i<14; i++)
     pw[i] = 0;
 
   {
     /* create LanManager hashed password */
+#ifdef HAVE_NETTLE
+    struct des_ctx des;
+
+    setup_des_key(pw, &des);
+    nettle_des_encrypt(&des, 8, lmbuffer, magic);
+
+    setup_des_key(pw + 7, &des);
+    nettle_des_encrypt(&des, 8, lmbuffer + 8, magic);
+#else
     DES_key_schedule ks;
 
     setup_des_key(pw, DESKEY(ks));
     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
                     DESKEY(ks), DES_ENCRYPT);
     DES_key_schedule ks;
 
     setup_des_key(pw, DESKEY(ks));
     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)lmbuffer,
                     DESKEY(ks), DES_ENCRYPT);
-  
+
     setup_des_key(pw+7, DESKEY(ks));
     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
                     DESKEY(ks), DES_ENCRYPT);
     setup_des_key(pw+7, DESKEY(ks));
     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
                     DESKEY(ks), DES_ENCRYPT);
+#endif
 
     memset(lmbuffer+16, 0, 5);
   }
 
     memset(lmbuffer+16, 0, 5);
   }
@@ -269,8 +321,11 @@ static void mkhash(const char *password,
 
 #ifdef USE_NTRESPONSES
   {
 
 #ifdef USE_NTRESPONSES
   {
-    /* create NT hashed password */
+#ifdef HAVE_NETTLE
+    struct md4_ctx MD4;
+#else
     MD4_CTX MD4;
     MD4_CTX MD4;
+#endif
 
     len = strlen(password);
 
 
     len = strlen(password);
 
@@ -279,9 +334,16 @@ static void mkhash(const char *password,
       pw[2*i+1] = 0;
     }
 
       pw[2*i+1] = 0;
     }
 
+#ifdef HAVE_NETTLE
+    nettle_md4_init(&MD4);
+    nettle_md4_update(&MD4, 2*len, pw);
+    nettle_md4_digest(&MD4, MD4_DIGEST_SIZE, ntbuffer);
+#else
+    /* create NT hashed password */
     MD4_Init(&MD4);
     MD4_Update(&MD4, pw, 2*len);
     MD4_Final(ntbuffer, &MD4);
     MD4_Init(&MD4);
     MD4_Update(&MD4, pw, 2*len);
     MD4_Final(ntbuffer, &MD4);
+#endif
 
     memset(ntbuffer+16, 0, 5);
   }
 
     memset(ntbuffer+16, 0, 5);
   }
@@ -295,8 +357,9 @@ static void mkhash(const char *password,
   (((x) >>16)&0xff), ((x)>>24)
 
 /* this is for creating ntlm header output */
   (((x) >>16)&0xff), ((x)>>24)
 
 /* this is for creating ntlm header output */
-char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
-                  int *ready)
+char *
+ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
+             bool *ready)
 {
   const char *domain=""; /* empty */
   const char *host=""; /* empty */
 {
   const char *domain=""; /* empty */
   const char *host=""; /* empty */
@@ -312,7 +375,7 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
      server, which is for a plain host or for a HTTP proxy */
   char *output;
 
      server, which is for a plain host or for a HTTP proxy */
   char *output;
 
-  *ready = 0;
+  *ready = false;
 
   /* not set means empty */
   if(!user)
 
   /* not set means empty */
   if(!user)
@@ -320,13 +383,15 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
 
   if(!passwd)
     passwd="";
 
   if(!passwd)
     passwd="";
-  
+
   switch(ntlm->state) {
   case NTLMSTATE_TYPE1:
   default: /* for the weird cases we (re)start here */
     hostoff = 32;
     domoff = hostoff + hostlen;
   switch(ntlm->state) {
   case NTLMSTATE_TYPE1:
   default: /* for the weird cases we (re)start here */
     hostoff = 32;
     domoff = hostoff + hostlen;
-    
+
+    DEBUGP (("Creating a type-1 NTLM message.\n"));
+
     /* Create and send a type-1 message:
 
     Index Description          Content
     /* Create and send a type-1 message:
 
     Index Description          Content
@@ -338,51 +403,48 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
     24    Supplied Workstation security buffer(*)
     32    start of data block
 
     24    Supplied Workstation security buffer(*)
     32    start of data block
 
-    Format string (merged for pre-ANSI compilers):
-      "NTLMSSP%c"
-      "\x01%c%c%c" 32-bit type = 1
-      "%c%c%c%c"   32-bit NTLM flag field
-      "%c%c"  domain length
-      "%c%c"  domain allocated space
-      "%c%c"  domain name offset
-      "%c%c"  2 zeroes
-      "%c%c"  host length
-      "%c%c"  host allocated space
-      "%c%c"  host name offset
-      "%c%c"  2 zeroes
-      "%s"    host name
-      "%s"   domain string
     */
 
     */
 
-    snprintf(ntlmbuf, sizeof(ntlmbuf),
-            "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",
-             0,     /* trailing zero */
-             0,0,0, /* part of type-1 long */
-
-             LONGQUARTET(
-               NTLMFLAG_NEGOTIATE_OEM|      /*   2 */
-               NTLMFLAG_NEGOTIATE_NTLM_KEY  /* 200 */
-               /* equals 0x0202 */
-               ),
-             SHORTPAIR(domlen),
-             SHORTPAIR(domlen),
-             SHORTPAIR(domoff),
-             0,0,
-             SHORTPAIR(hostlen),
-             SHORTPAIR(hostlen),
-             SHORTPAIR(hostoff),
-             0,0,
-             host, domain);
+    snprintf (ntlmbuf, sizeof(ntlmbuf), "NTLMSSP%c"
+              "\x01%c%c%c" /* 32-bit type = 1 */
+              "%c%c%c%c"   /* 32-bit NTLM flag field */
+              "%c%c"  /* domain length */
+              "%c%c"  /* domain allocated space */
+              "%c%c"  /* domain name offset */
+              "%c%c"  /* 2 zeroes */
+              "%c%c"  /* host length */
+              "%c%c"  /* host allocated space */
+              "%c%c"  /* host name offset */
+              "%c%c"  /* 2 zeroes */
+              "%s"   /* host name */
+              "%s",  /* domain string */
+              0,     /* trailing zero */
+              0,0,0, /* part of type-1 long */
+
+              LONGQUARTET(
+                NTLMFLAG_NEGOTIATE_OEM|      /*   2 */
+                NTLMFLAG_NEGOTIATE_NTLM_KEY  /* 200 */
+                /* equals 0x0202 */
+                ),
+              SHORTPAIR(domlen),
+              SHORTPAIR(domlen),
+              SHORTPAIR(domoff),
+              0,0,
+              SHORTPAIR(hostlen),
+              SHORTPAIR(hostlen),
+              SHORTPAIR(hostoff),
+              0,0,
+              host, domain);
 
     /* initial packet length */
     size = 32 + hostlen + domlen;
 
     base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
 
     /* initial packet length */
     size = 32 + hostlen + domlen;
 
     base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
-    base64_encode (ntlmbuf, base64, size);
+    base64_encode (ntlmbuf, size, base64);
 
     output = concat_strings ("NTLM ", base64, (char *) 0);
     break;
 
     output = concat_strings ("NTLM ", base64, (char *) 0);
     break;
-    
+
   case NTLMSTATE_TYPE2:
     /* We received the type-2 already, create a type-3 message:
 
   case NTLMSTATE_TYPE2:
     /* We received the type-2 already, create a type-3 message:
 
@@ -400,7 +462,7 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
     52 (64) start of data block
 
     */
     52 (64) start of data block
 
     */
-  
+
   {
     int lmrespoff;
     int ntrespoff;
   {
     int lmrespoff;
     int ntrespoff;
@@ -412,12 +474,14 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
     const char *usr;
     int userlen;
 
     const char *usr;
     int userlen;
 
+    DEBUGP (("Creating a type-3 NTLM message.\n"));
+
     usr = strchr(user, '\\');
     if(!usr)
       usr = strchr(user, '/');
 
     if (usr) {
     usr = strchr(user, '\\');
     if(!usr)
       usr = strchr(user, '/');
 
     if (usr) {
-      domain = usr;
+      domain = user;
       domlen = usr - domain;
       usr++;
     }
       domlen = usr - domain;
       usr++;
     }
@@ -437,83 +501,94 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
     lmrespoff = hostoff + hostlen;
     ntrespoff = lmrespoff + 0x18;
 
     lmrespoff = hostoff + hostlen;
     ntrespoff = lmrespoff + 0x18;
 
-    /* Create the big type-3 message binary blob:
-        "NTLMSSP%c"
-        "\x03%c%c%c"  type-3, 32 bits 
-
-        "%c%c%c%c"  LanManager length + allocated space 
-        "%c%c"      LanManager offset 
-        "%c%c"      2 zeroes 
-
-        "%c%c"  NT-response length 
-        "%c%c"  NT-response allocated space 
-        "%c%c"  NT-response offset 
-        "%c%c"  2 zeroes 
-
-        "%c%c"  domain length 
-        "%c%c"  domain allocated space 
-        "%c%c"  domain name offset 
-        "%c%c"  2 zeroes 
-
-        "%c%c"  user length 
-        "%c%c"  user allocated space 
-        "%c%c"  user offset 
-        "%c%c"  2 zeroes 
-
-        "%c%c"  host length 
-        "%c%c"  host allocated space 
-        "%c%c"  host offset 
-        "%c%c%c%c%c%c" 6 zeroes 
-
-        "\xff\xff"   message length 
-        "%c%c"   2 zeroes 
-
-        "\x01\x82"  flags 
-        "%c%c"   2 zeroes */
-
-    size = snprintf(ntlmbuf, sizeof(ntlmbuf),
-                   "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",
-                    0, /* zero termination */
-                    0,0,0, /* type-3 long, the 24 upper bits */
-
-                    SHORTPAIR(0x18),  /* LanManager response length, twice */
-                    SHORTPAIR(0x18),
-                    SHORTPAIR(lmrespoff),
-                    0x0, 0x0,
-                    
+    /* Create the big type-3 message binary blob */
+
+    size = snprintf (ntlmbuf, sizeof(ntlmbuf),
+                     "NTLMSSP%c"
+                     "\x03%c%c%c" /* type-3, 32 bits */
+
+                     "%c%c%c%c" /* LanManager length + allocated space */
+                     "%c%c" /* LanManager offset */
+                     "%c%c" /* 2 zeroes */
+
+                     "%c%c" /* NT-response length */
+                     "%c%c" /* NT-response allocated space */
+                     "%c%c" /* NT-response offset */
+                     "%c%c" /* 2 zeroes */
+
+                     "%c%c"  /* domain length */
+                     "%c%c"  /* domain allocated space */
+                     "%c%c"  /* domain name offset */
+                     "%c%c"  /* 2 zeroes */
+
+                     "%c%c"  /* user length */
+                     "%c%c"  /* user allocated space */
+                     "%c%c"  /* user offset */
+                     "%c%c"  /* 2 zeroes */
+
+                     "%c%c"  /* host length */
+                     "%c%c"  /* host allocated space */
+                     "%c%c"  /* host offset */
+                     "%c%c%c%c%c%c"  /* 6 zeroes */
+
+                     "\xff\xff"  /* message length */
+                     "%c%c"  /* 2 zeroes */
+
+                     "\x01\x82" /* flags */
+                     "%c%c"  /* 2 zeroes */
+
+                     /* domain string */
+                     /* user string */
+                     /* host string */
+                     /* LanManager response */
+                     /* NT response */
+                     ,
+                     0, /* zero termination */
+                     0,0,0, /* type-3 long, the 24 upper bits */
+
+                     SHORTPAIR(0x18),  /* LanManager response length, twice */
+                     SHORTPAIR(0x18),
+                     SHORTPAIR(lmrespoff),
+                     0x0, 0x0,
+
 #ifdef USE_NTRESPONSES
 #ifdef USE_NTRESPONSES
-                    SHORTPAIR(0x18),  /* NT-response length, twice */
-                    SHORTPAIR(0x18),
+                     SHORTPAIR(0x18),  /* NT-response length, twice */
+                     SHORTPAIR(0x18),
 #else
 #else
-                    0x0, 0x0,
-                    0x0, 0x0,
+                     0x0, 0x0,
+                     0x0, 0x0,
 #endif
 #endif
-                    SHORTPAIR(ntrespoff),
-                    0x0, 0x0,
-
-                    SHORTPAIR(domlen),
-                    SHORTPAIR(domlen),
-                    SHORTPAIR(domoff),
-                    0x0, 0x0,
-
-                    SHORTPAIR(userlen),
-                    SHORTPAIR(userlen),
-                    SHORTPAIR(useroff),
-                    0x0, 0x0,
-                    
-                    SHORTPAIR(hostlen),
-                    SHORTPAIR(hostlen),
-                    SHORTPAIR(hostoff),
-                    0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
-             
-                    0x0, 0x0,
-
-                    0x0, 0x0);
+                     SHORTPAIR(ntrespoff),
+                     0x0, 0x0,
+
+                     SHORTPAIR(domlen),
+                     SHORTPAIR(domlen),
+                     SHORTPAIR(domoff),
+                     0x0, 0x0,
+
+                     SHORTPAIR(userlen),
+                     SHORTPAIR(userlen),
+                     SHORTPAIR(useroff),
+                     0x0, 0x0,
+
+                     SHORTPAIR(hostlen),
+                     SHORTPAIR(hostlen),
+                     SHORTPAIR(hostoff),
+                     0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+
+                     0x0, 0x0,
+
+                     0x0, 0x0);
 
     /* size is now 64 */
     size=64;
     ntlmbuf[62]=ntlmbuf[63]=0;
 
 
     /* size is now 64 */
     size=64;
     ntlmbuf[62]=ntlmbuf[63]=0;
 
+    /* Make sure that the user and domain strings fit in the target buffer
+       before we copy them there. */
+    if(((size_t) size + userlen + domlen) >= sizeof(ntlmbuf))
+      return NULL;
+
     memcpy(&ntlmbuf[size], domain, domlen);
     size += domlen;
 
     memcpy(&ntlmbuf[size], domain, domlen);
     size += domlen;
 
@@ -527,7 +602,7 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
     }
 
 #ifdef USE_NTRESPONSES
     }
 
 #ifdef USE_NTRESPONSES
-    if(size < ((int)sizeof(ntlmbuf) - 0x18)) {      
+    if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
       memcpy(&ntlmbuf[size], ntresp, 0x18);
       size += 0x18;
     }
       memcpy(&ntlmbuf[size], ntresp, 0x18);
       size += 0x18;
     }
@@ -538,19 +613,19 @@ char *ntlm_output (struct ntlmdata *ntlm, const char *user, const char *passwd,
 
     /* convert the binary blob into base64 */
     base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
 
     /* convert the binary blob into base64 */
     base64 = (char *) alloca (BASE64_LENGTH (size) + 1);
-    base64_encode (ntlmbuf, base64, size);
+    base64_encode (ntlmbuf, size, base64);
 
     output = concat_strings ("NTLM ", base64, (char *) 0);
 
     ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
 
     output = concat_strings ("NTLM ", base64, (char *) 0);
 
     ntlm->state = NTLMSTATE_TYPE3; /* we sent a type-3 */
-    *ready = 1;
+    *ready = true;
   }
   break;
 
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
      * don't send a header in future requests */
   }
   break;
 
   case NTLMSTATE_TYPE3:
     /* connection is already authenticated,
      * don't send a header in future requests */
-    *ready = 1;
+    *ready = true;
     output = NULL;
     break;
   }
     output = NULL;
     break;
   }