diff -uwB --recursive curl-7.15.1-orig/lib/http_ntlm.c curl-7.15.1/lib/http_ntlm.c
--- curl-7.15.1-orig/lib/http_ntlm.c	2005-11-14 23:10:52.000000000 +0100
+++ curl-7.15.1/lib/http_ntlm.c	2006-04-03 16:36:38.000000000 +0200
@@ -27,11 +27,16 @@
    http://davenport.sourceforge.net/ntlm.html
    http://www.innovation.ch/java/ntlm.html
 
+   Another implementation:
+   http://lxr.mozilla.org/mozilla/source/security/manager/ssl/src/nsNTLMAuthModule.cpp
+
 */
 
 #ifndef CURL_DISABLE_HTTP
 #ifdef USE_NTLM
 
+#define DEBUG_ME 0
+
 /* -- WIN32 approved -- */
 #include <stdio.h>
 #include <string.h>
@@ -89,6 +94,62 @@
 /* Define this to make the type-3 message include the NT response message */
 #define USE_NTRESPONSES 1
 
+
+static unsigned long readLittleEndianLong(unsigned char *buf /* must point to a 4 bytes buffer*/)
+{
+    return ((unsigned long)buf[0]) | ((unsigned long)buf[1] << 8)
+        | ((unsigned long)buf[2] << 16) | ((unsigned long)buf[3] << 24);
+}
+
+#if DEBUG_ME
+# define DEBUG_OUT(x) x
+static void print_flags(FILE *handle, unsigned long flags)
+{
+  if(flags & NTLMFLAG_NEGOTIATE_UNICODE) fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
+  if(flags & NTLMFLAG_NEGOTIATE_OEM) fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
+  if(flags & NTLMFLAG_REQUEST_TARGET) fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
+  if(flags & (1<<3)) fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
+  if(flags & NTLMFLAG_NEGOTIATE_SIGN) fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
+  if(flags & NTLMFLAG_NEGOTIATE_SEAL) fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
+  if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE) fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
+  if(flags & NTLMFLAG_NEGOTIATE_LM_KEY) fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
+  if(flags & NTLMFLAG_NEGOTIATE_NETWARE) fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
+  if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY) fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
+  if(flags & (1<<10)) fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
+  if(flags & (1<<11)) fprintf(handle, "NTLMFLAG_UNKNOWN_11 ");
+  if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED) fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
+  if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED) fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
+  if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL) fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
+  if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN) fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
+  if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN) fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
+  if(flags & NTLMFLAG_TARGET_TYPE_SERVER) fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
+  if(flags & NTLMFLAG_TARGET_TYPE_SHARE) fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
+  if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
+  if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE) fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
+  if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE) fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
+  if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY) fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
+  if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
+  if(flags & (1<<24)) fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
+  if(flags & (1<<25)) fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
+  if(flags & (1<<26)) fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
+  if(flags & (1<<27)) fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
+  if(flags & (1<<28)) fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
+  if(flags & NTLMFLAG_NEGOTIATE_128) fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
+  if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE) fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
+  if(flags & NTLMFLAG_NEGOTIATE_56) fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
+}
+
+static void print_hex(FILE *handle, const char *buf, size_t len)
+{
+  const char *p = buf;
+  fprintf(stderr, "0x");
+  while (len-- > 0)
+    fprintf(stderr, "%02.2x", (unsigned int)(unsigned char)*p++);
+}
+#else
+# define DEBUG_OUT(x)
+#endif
+
 /*
   (*) = A "security buffer" is a triplet consisting of two shorts and one
   long:
@@ -107,6 +168,9 @@
 {
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
+#ifndef USE_WINDOWS_SSPI
+  static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
+#endif
 
   ntlm = proxy?&conn->proxyntlm:&conn->ntlm;
 
@@ -150,12 +214,31 @@
       ntlm->n_type_2 = size;
       memcpy(ntlm->type_2, buffer, size);
 #else
-      if(size >= 48)
-        /* the nonce of interest is index [24 .. 31], 8 bytes */
+      ntlm->flags = 0;
+
+      if(size < 32) {
+        free(buffer);
+        return CURLNTLM_BAD;
+      }
+      if (memcmp(buffer, "NTLMSSP", 8) != 0) {
+        free(buffer);
+        return CURLNTLM_BAD;
+      }
+      if (memcmp(buffer+8, type2_marker, sizeof(type2_marker)) != 0) {
+        free(buffer);
+        return CURLNTLM_BAD;
+      }
+
+      ntlm->flags = readLittleEndianLong(&buffer[20]);
         memcpy(ntlm->nonce, &buffer[24], 8);
-      /* FIX: add an else here! */
 
-      /* at index decimal 20, there's a 32bit NTLM flag field */
+      DEBUG_OUT({
+          fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
+          print_flags(stderr, ntlm->flags);
+          fprintf(stderr, "\n                  nonce=");
+          print_hex(stderr, ntlm->nonce, 8);
+          fprintf(stderr, "\n****\n");
+      });
 
       free(buffer);
 #endif
@@ -199,7 +282,7 @@
   * 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,
+static void lm_resp(unsigned char *keys,
                       unsigned char *plaintext,
                       unsigned char *results)
 {
@@ -218,35 +301,19 @@
                   DESKEY(ks), DES_ENCRYPT);
 }
 
+
 /*
- * Set up lanmanager and nt hashed passwords
+ * Set up lanmanager hashed password
  */
-static void mkhash(char *password,
-                   unsigned char *nonce,  /* 8 bytes */
-                   unsigned char *lmresp  /* must fit 0x18 bytes */
-#ifdef USE_NTRESPONSES
-                   , unsigned char *ntresp  /* must fit 0x18 bytes */
-#endif
-  )
-{
-  /* 21 bytes fits 3 7-bytes chunks, as we use 56 bit (7 bytes) as DES input,
-     and we add three different ones, see the calc_resp() function */
-  unsigned char lmbuffer[21];
-#ifdef USE_NTRESPONSES
-  unsigned char ntbuffer[21];
-#endif
-  unsigned char *pw;
+static void mk_lm_hash(char *password, unsigned char *lmbuffer /* 21 bytes */)
+{
+  unsigned char pw[14];
   static const unsigned char magic[] = {
-    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25
+    0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 // i.e. KGS!@#$%
   };
   unsigned int i;
   size_t len = strlen(password);
 
-  /* make it fit at least 14 bytes */
-  pw = malloc(len<7?14:len*2);
-  if(!pw)
-    return; /* this will lead to a badly generated package */
-
   if (len > 14)
     len = 14;
 
@@ -257,7 +324,8 @@
     pw[i] = 0;
 
   {
-    /* create LanManager hashed password */
+    /* Create LanManager hashed password. */
+
     DES_key_schedule ks;
 
     setup_des_key(pw, DESKEY(ks));
@@ -268,35 +336,45 @@
     DES_ecb_encrypt((DES_cblock *)magic, (DES_cblock *)(lmbuffer+8),
                     DESKEY(ks), DES_ENCRYPT);
 
-    memset(lmbuffer+16, 0, sizeof(lmbuffer)-16);
+    memset(lmbuffer + 16, 0, 21 - 16);
+  }
   }
-  /* create LM responses */
-  calc_resp(lmbuffer, nonce, lmresp);
 
-#ifdef USE_NTRESPONSES
+#if USE_NTRESPONSES
+static void utf8_to_unicode_le(unsigned char *dest, const char *src, size_t srclen)
   {
-    /* create NT hashed password */
-    MD4_CTX MD4;
+  int i;
+  for (i=0; i<srclen; i++) {
+    dest[2*i]   = (unsigned char)src[i];
+    dest[2*i+1] =   '\0';
+  }
+}
 
-    len = strlen(password);
+/*
+ * Set up nt hashed passwords
+ */
+static void mk_nt_hash(char *password, unsigned char *ntbuffer /* 21 bytes */)
+{
+  size_t len = strlen(password);
+  unsigned char *pw = malloc(len*2);
 
-    for (i=0; i<len; i++) {
-      pw[2*i]   = password[i];
-      pw[2*i+1] = 0;
-    }
+  utf8_to_unicode_le(pw, password, len);
+
+  {
+    /* Create NT hashed password. */
+    MD4_CTX MD4;
 
     MD4_Init(&MD4);
     MD4_Update(&MD4, pw, 2*len);
     MD4_Final(ntbuffer, &MD4);
 
-    memset(ntbuffer+16, 0, sizeof(ntbuffer)-16);
+    memset(ntbuffer + 16, 0, 21 - 16);
   }
 
-  calc_resp(ntbuffer, nonce, ntresp);
-#endif
-
   free(pw);
 }
+#endif
+
 
 #endif
 
@@ -324,16 +402,18 @@
 
 #endif
 
-#define SHORTPAIR(x) ((x) & 0xff), ((x) >> 8)
+#define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8)&0xff), \
-  (((x) >>16)&0xff), ((x)>>24)
+  (((x) >>16)&0xff), (((x)>>24) & 0xff)
+
+#define HOSTNAME_MAX 1024
 
 /* this is for creating ntlm header output */
 CURLcode Curl_output_ntlm(struct connectdata *conn,
                           bool proxy)
 {
   const char *domain=""; /* empty */
-  const char *host=""; /* empty */
+  char host [HOSTNAME_MAX+ 1] = ""; /* empty */
 #ifndef USE_WINDOWS_SSPI
   int domlen=(int)strlen(domain);
   int hostlen = (int)strlen(host);
@@ -342,7 +422,7 @@
 #endif
   size_t size;
   char *base64=NULL;
-  unsigned char ntlmbuf[512]; /* enough, unless the host/domain is very long */
+  unsigned char ntlmbuf[1024]; /* enough, unless the user+host+domain is very long */
 
   /* point to the address of the pointer that holds the string to sent to the
      server, which is for a plain host or for a HTTP proxy */
@@ -500,8 +580,8 @@
     size = buf.cbBuffer;
   }
 #else
-    hostoff = 32;
-    domoff = hostoff + hostlen;
+    hostoff = 0;
+    domoff = hostoff + hostlen; /* This is 0: remember that host and domain are empty */
 
     /* Create and send a type-1 message:
 
@@ -533,9 +613,11 @@
              0,0,0, /* part of type-1 long */
 
              LONGQUARTET(
-               NTLMFLAG_NEGOTIATE_OEM|      /*   2 */
-               NTLMFLAG_NEGOTIATE_NTLM_KEY  /* 200 */
-               /* equals 0x0202 */
+               NTLMFLAG_NEGOTIATE_OEM|
+               NTLMFLAG_REQUEST_TARGET|
+               NTLMFLAG_NEGOTIATE_NTLM_KEY|
+               NTLMFLAG_NEGOTIATE_ALWAYS_SIGN/*|
+               NTLMFLAG_NEGOTIATE_NTLM2_KEY*/
                ),
              SHORTPAIR(domlen),
              SHORTPAIR(domlen),
@@ -545,13 +627,24 @@
              SHORTPAIR(hostlen),
              SHORTPAIR(hostoff),
              0,0,
-             host, domain);
+             host /* this is empty */, domain /* this is empty */);
 
     /* initial packet length */
     size = 32 + hostlen + domlen;
 #endif
 
-    /* now keeper of the base64 encoded package size */
+    DEBUG_OUT({
+        fprintf(stderr, "**** TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
+                LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM|
+                            NTLMFLAG_REQUEST_TARGET|
+                            NTLMFLAG_NEGOTIATE_NTLM_KEY|
+                            NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
+                NTLMFLAG_NEGOTIATE_OEM| NTLMFLAG_REQUEST_TARGET| NTLMFLAG_NEGOTIATE_NTLM_KEY| NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+        print_flags(stderr, NTLMFLAG_NEGOTIATE_OEM| NTLMFLAG_REQUEST_TARGET| NTLMFLAG_NEGOTIATE_NTLM_KEY| NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
+        fprintf(stderr, "\n****\n");
+    });
+
+    /* now size is the size of the base64 encoded package size */
     size = Curl_base64_encode((char *)ntlmbuf, size, &base64);
 
     if(size >0 ) {
@@ -567,7 +660,7 @@
     break;
 
   case NTLMSTATE_TYPE2:
-    /* We received the type-2 already, create a type-3 message:
+    /* We received the type-2 message already, create a type-3 message:
 
     Index   Description            Content
     0       NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
@@ -622,12 +715,12 @@
 
 #else
     int lmrespoff;
+    unsigned char lmresp[24]; /* fixed-size */
+#if USE_NTRESPONSES
     int ntrespoff;
-    int useroff;
-    unsigned char lmresp[0x18]; /* fixed-size */
-#ifdef USE_NTRESPONSES
-    unsigned char ntresp[0x18]; /* fixed-size */
+    unsigned char ntresp[24]; /* fixed-size */
 #endif
+    int useroff;
     const char *user;
     int userlen;
 
@@ -644,24 +737,43 @@
       user = userp;
     userlen = (int)strlen(user);
 
-    mkhash(passwdp, &ntlm->nonce[0], lmresp
-#ifdef USE_NTRESPONSES
-           , ntresp
+    if (gethostname(host, HOSTNAME_MAX))
+      return CURLE_RECV_ERROR; /* TODO need a more specific error here */
+    hostlen = strlen(host);
+
+    {
+#if USE_NTRESPONSES
+      unsigned char ntbuffer[0x18];
+#endif
+      unsigned char lmbuffer[0x18];
+
+#if USE_NTRESPONSES
+      mk_nt_hash(passwdp, ntbuffer);
+      lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
 #endif
-      );
 
-    domoff = 64; /* always */
+      mk_lm_hash(passwdp, lmbuffer);
+      lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
+      /* TODO alternative: lm_resp(ntbuffer, &ntlm->nonce[0], lmresp); */
+    }
+
+    lmrespoff = 64; /* size of the message header */
+#if USE_NTRESPONSES
+    ntrespoff = lmrespoff + 0x18;
+    domoff = ntrespoff + 0x18;
+#else
+    domoff = lmrespoff + 0x18;
+#endif
     useroff = domoff + domlen;
     hostoff = useroff + userlen;
-    lmrespoff = hostoff + hostlen;
-    ntrespoff = lmrespoff + 0x18;
 
     /* Create the big type-3 message binary blob */
     size = snprintf((char *)ntlmbuf, sizeof(ntlmbuf),
                     "NTLMSSP%c"
                     "\x03%c%c%c" /* type-3, 32 bits */
 
-                    "%c%c%c%c" /* LanManager length + allocated space */
+                    "%c%c" /* LanManager length */
+                    "%c%c" /* LanManager allocated space */
                     "%c%c" /* LanManager offset */
                     "%c%c" /* 2 zeroes */
 
@@ -683,14 +795,15 @@
                     "%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"  /* session key length (unknown purpose) */
+                    "%c%c"  /* session key allocated space (unknown purpose) */
+                    "%c%c"  /* session key offset (unknown purpose) */
                     "%c%c"  /* 2 zeroes */
 
+                    "%c%c%c%c" /* flags */
+
                     /* domain string */
                     /* user string */
                     /* host string */
@@ -705,16 +818,17 @@
                     SHORTPAIR(lmrespoff),
                     0x0, 0x0,
 
-#ifdef USE_NTRESPONSES
+#if USE_NTRESPONSES
                     SHORTPAIR(0x18),  /* NT-response length, twice */
                     SHORTPAIR(0x18),
+                    SHORTPAIR(ntrespoff),
+                    0x0, 0x0,
 #else
                     0x0, 0x0,
                     0x0, 0x0,
-#endif
-                    SHORTPAIR(ntrespoff),
                     0x0, 0x0,
-
+                    0x0, 0x0,
+#endif
                     SHORTPAIR(domlen),
                     SHORTPAIR(domlen),
                     SHORTPAIR(domoff),
@@ -728,44 +842,68 @@
                     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;
-
-    /* Make sure that the user and domain strings fit in the target buffer
-       before we copy them there. */
-    if(size + userlen + domlen >= sizeof(ntlmbuf)) {
-      failf(conn->data, "user + domain name too big");
-      return CURLE_OUT_OF_MEMORY;
-    }
-
-    memcpy(&ntlmbuf[size], domain, domlen);
-    size += domlen;
+                    0x0, 0x0,
+                    0x0, 0x0,
+                    0x0, 0x0,
+                    0x0, 0x0,
 
-    memcpy(&ntlmbuf[size], user, userlen);
-    size += userlen;
+                    LONGQUARTET(ntlm->flags));
+    DEBUG_OUT(assert(size==64));
 
-    /* we append the binary hashes to the end of the blob */
+    DEBUG_OUT(assert(size == lmrespoff));
+    /* We append the binary hashes */
     if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
       memcpy(&ntlmbuf[size], lmresp, 0x18);
       size += 0x18;
     }
 
-#ifdef USE_NTRESPONSES
+    DEBUG_OUT({
+        fprintf(stderr, "**** TYPE3 header lmresp=");
+        print_hex(stderr, &ntlmbuf[lmrespoff], 0x18);
+    });
+
+#if USE_NTRESPONSES
     if(size < ((int)sizeof(ntlmbuf) - 0x18)) {
+      DEBUG_OUT(assert(size == ntrespoff));
       memcpy(&ntlmbuf[size], ntresp, 0x18);
       size += 0x18;
     }
+
+    DEBUG_OUT({
+        fprintf(stderr, "\n                  ntresp=");
+        print_hex(stderr, &ntlmbuf[ntrespoff], 0x18);
+    });
+
 #endif
 
-    ntlmbuf[56] = (unsigned char)(size & 0xff);
-    ntlmbuf[57] = (unsigned char)(size >> 8);
+    DEBUG_OUT({
+        fprintf(stderr, "\n                  flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
+                LONGQUARTET(ntlm->flags), ntlm->flags);
+        print_flags(stderr, ntlm->flags);
+        fprintf(stderr, "\n****\n");
+    });
+
+
+    /* Make sure that the domain, user and host strings fit in the target buffer
+       before we copy them there. */
+    if(size + userlen + domlen + hostlen >= sizeof(ntlmbuf)) {
+      failf(conn->data, "user + domain + host name too big");
+      return CURLE_OUT_OF_MEMORY;
+    }
+
+    DEBUG_OUT(assert(size == domoff));
+    memcpy(&ntlmbuf[size], domain, domlen);
+    size += domlen;
+
+    DEBUG_OUT(assert(size == useroff));
+    memcpy(&ntlmbuf[size], user, userlen);
+    size += userlen;
+
+    DEBUG_OUT(assert(size == hostoff));
+    memcpy(&ntlmbuf[size], host, hostlen);
+    size += hostlen;
 
 #endif
 
Only in curl-7.15.1/lib: http_ntlm.c~
diff -uwB --recursive curl-7.15.1-orig/lib/urldata.h curl-7.15.1/lib/urldata.h
--- curl-7.15.1-orig/lib/urldata.h	2005-11-29 00:06:00.000000000 +0100
+++ curl-7.15.1/lib/urldata.h	2006-04-03 16:06:45.000000000 +0200
@@ -221,6 +221,7 @@
   void *type_2;
   int n_type_2;
 #else
+  unsigned long flags;
   unsigned char nonce[8];
 #endif
 };

