Home | History | Annotate | Download | only in lib
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at http://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 
     23 #include "curl_setup.h"
     24 
     25 #if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
     26 
     27 /*
     28  * NTLM details:
     29  *
     30  * http://davenport.sourceforge.net/ntlm.html
     31  * http://www.innovation.ch/java/ntlm.html
     32  */
     33 
     34 #define DEBUG_ME 0
     35 
     36 #include "urldata.h"
     37 #include "non-ascii.h"
     38 #include "sendf.h"
     39 #include "curl_base64.h"
     40 #include "curl_ntlm_core.h"
     41 #include "curl_gethostname.h"
     42 #include "curl_multibyte.h"
     43 #include "warnless.h"
     44 
     45 #include "vtls/vtls.h"
     46 
     47 #ifdef USE_NSS
     48 #include "vtls/nssg.h" /* for Curl_nss_force_init() */
     49 #endif
     50 
     51 #define BUILDING_CURL_NTLM_MSGS_C
     52 #include "curl_ntlm_msgs.h"
     53 #include "curl_sasl.h"
     54 #include "curl_endian.h"
     55 #include "curl_printf.h"
     56 
     57 /* The last #include files should be: */
     58 #include "curl_memory.h"
     59 #include "memdebug.h"
     60 
     61 /* "NTLMSSP" signature is always in ASCII regardless of the platform */
     62 #define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
     63 
     64 #define SHORTPAIR(x) ((x) & 0xff), (((x) >> 8) & 0xff)
     65 #define LONGQUARTET(x) ((x) & 0xff), (((x) >> 8) & 0xff), \
     66   (((x) >> 16) & 0xff), (((x) >> 24) & 0xff)
     67 
     68 #if DEBUG_ME
     69 # define DEBUG_OUT(x) x
     70 static void ntlm_print_flags(FILE *handle, unsigned long flags)
     71 {
     72   if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
     73     fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
     74   if(flags & NTLMFLAG_NEGOTIATE_OEM)
     75     fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
     76   if(flags & NTLMFLAG_REQUEST_TARGET)
     77     fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
     78   if(flags & (1<<3))
     79     fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
     80   if(flags & NTLMFLAG_NEGOTIATE_SIGN)
     81     fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
     82   if(flags & NTLMFLAG_NEGOTIATE_SEAL)
     83     fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
     84   if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
     85     fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
     86   if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
     87     fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
     88   if(flags & NTLMFLAG_NEGOTIATE_NETWARE)
     89     fprintf(handle, "NTLMFLAG_NEGOTIATE_NETWARE ");
     90   if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
     91     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
     92   if(flags & (1<<10))
     93     fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
     94   if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
     95     fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
     96   if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
     97     fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
     98   if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
     99     fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
    100   if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
    101     fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
    102   if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
    103     fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
    104   if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
    105     fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
    106   if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
    107     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
    108   if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
    109     fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
    110   if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
    111     fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
    112   if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
    113     fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
    114   if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
    115     fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
    116   if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
    117     fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
    118   if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
    119     fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
    120   if(flags & (1<<24))
    121     fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
    122   if(flags & (1<<25))
    123     fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
    124   if(flags & (1<<26))
    125     fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
    126   if(flags & (1<<27))
    127     fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
    128   if(flags & (1<<28))
    129     fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
    130   if(flags & NTLMFLAG_NEGOTIATE_128)
    131     fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
    132   if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
    133     fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
    134   if(flags & NTLMFLAG_NEGOTIATE_56)
    135     fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
    136 }
    137 
    138 static void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
    139 {
    140   const char *p = buf;
    141   (void)handle;
    142   fprintf(stderr, "0x");
    143   while(len-- > 0)
    144     fprintf(stderr, "%02.2x", (unsigned int)*p++);
    145 }
    146 #else
    147 # define DEBUG_OUT(x) Curl_nop_stmt
    148 #endif
    149 
    150 /*
    151  * ntlm_decode_type2_target()
    152  *
    153  * This is used to decode the "target info" in the ntlm type-2 message
    154  * received.
    155  *
    156  * Parameters:
    157  *
    158  * data      [in]     - The session handle.
    159  * buffer    [in]     - The decoded type-2 message.
    160  * size      [in]     - The input buffer size, at least 32 bytes.
    161  * ntlm      [in/out] - The ntlm data struct being used and modified.
    162  *
    163  * Returns CURLE_OK on success.
    164  */
    165 static CURLcode ntlm_decode_type2_target(struct SessionHandle *data,
    166                                          unsigned char *buffer,
    167                                          size_t size,
    168                                          struct ntlmdata *ntlm)
    169 {
    170   unsigned short target_info_len = 0;
    171   unsigned int target_info_offset = 0;
    172 
    173   if(size >= 48) {
    174     target_info_len = Curl_read16_le(&buffer[40]);
    175     target_info_offset = Curl_read32_le(&buffer[44]);
    176     if(target_info_len > 0) {
    177       if(((target_info_offset + target_info_len) > size) ||
    178          (target_info_offset < 48)) {
    179         infof(data, "NTLM handshake failure (bad type-2 message). "
    180                     "Target Info Offset Len is set incorrect by the peer\n");
    181         return CURLE_BAD_CONTENT_ENCODING;
    182       }
    183 
    184       ntlm->target_info = malloc(target_info_len);
    185       if(!ntlm->target_info)
    186         return CURLE_OUT_OF_MEMORY;
    187 
    188       memcpy(ntlm->target_info, &buffer[target_info_offset], target_info_len);
    189     }
    190   }
    191 
    192   ntlm->target_info_len = target_info_len;
    193 
    194   return CURLE_OK;
    195 }
    196 
    197 /*
    198   NTLM message structure notes:
    199 
    200   A 'short' is a 'network short', a little-endian 16-bit unsigned value.
    201 
    202   A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
    203 
    204   A 'security buffer' represents a triplet used to point to a buffer,
    205   consisting of two shorts and one long:
    206 
    207     1. A 'short' containing the length of the buffer content in bytes.
    208     2. A 'short' containing the allocated space for the buffer in bytes.
    209     3. A 'long' containing the offset to the start of the buffer in bytes,
    210        from the beginning of the NTLM message.
    211 */
    212 
    213 /*
    214  * Curl_sasl_decode_ntlm_type2_message()
    215  *
    216  * This is used to decode an already encoded NTLM type-2 message. The message
    217  * is first decoded from a base64 string into a raw NTLM message and checked
    218  * for validity before the appropriate data for creating a type-3 message is
    219  * written to the given NTLM data structure.
    220  *
    221  * Parameters:
    222  *
    223  * data     [in]     - The session handle.
    224  * type2msg [in]     - The base64 encoded type-2 message.
    225  * ntlm     [in/out] - The ntlm data struct being used and modified.
    226  *
    227  * Returns CURLE_OK on success.
    228  */
    229 CURLcode Curl_sasl_decode_ntlm_type2_message(struct SessionHandle *data,
    230                                              const char *type2msg,
    231                                              struct ntlmdata *ntlm)
    232 {
    233   static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
    234 
    235   /* NTLM type-2 message structure:
    236 
    237           Index  Description            Content
    238             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
    239                                         (0x4e544c4d53535000)
    240             8    NTLM Message Type      long (0x02000000)
    241            12    Target Name            security buffer
    242            20    Flags                  long
    243            24    Challenge              8 bytes
    244           (32)   Context                8 bytes (two consecutive longs) (*)
    245           (40)   Target Information     security buffer (*)
    246           (48)   OS Version Structure   8 bytes (*)
    247   32 (48) (56)   Start of data block    (*)
    248                                         (*) -> Optional
    249   */
    250 
    251   CURLcode result = CURLE_OK;
    252   unsigned char *type2 = NULL;
    253   size_t type2_len = 0;
    254 
    255 #if defined(USE_NSS)
    256   /* Make sure the crypto backend is initialized */
    257   result = Curl_nss_force_init(data);
    258   if(result)
    259     return result;
    260 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
    261   (void)data;
    262 #endif
    263 
    264   /* Decode the base-64 encoded type-2 message */
    265   if(strlen(type2msg) && *type2msg != '=') {
    266     result = Curl_base64_decode(type2msg, &type2, &type2_len);
    267     if(result)
    268       return result;
    269   }
    270 
    271   /* Ensure we have a valid type-2 message */
    272   if(!type2) {
    273     infof(data, "NTLM handshake failure (empty type-2 message)\n");
    274     return CURLE_BAD_CONTENT_ENCODING;
    275   }
    276 
    277   ntlm->flags = 0;
    278 
    279   if((type2_len < 32) ||
    280      (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
    281      (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
    282     /* This was not a good enough type-2 message */
    283     free(type2);
    284     infof(data, "NTLM handshake failure (bad type-2 message)\n");
    285     return CURLE_BAD_CONTENT_ENCODING;
    286   }
    287 
    288   ntlm->flags = Curl_read32_le(&type2[20]);
    289   memcpy(ntlm->nonce, &type2[24], 8);
    290 
    291   if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
    292     result = ntlm_decode_type2_target(data, type2, type2_len, ntlm);
    293     if(result) {
    294       free(type2);
    295       infof(data, "NTLM handshake failure (bad type-2 message)\n");
    296       return result;
    297     }
    298   }
    299 
    300   DEBUG_OUT({
    301     fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
    302     ntlm_print_flags(stderr, ntlm->flags);
    303     fprintf(stderr, "\n                  nonce=");
    304     ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
    305     fprintf(stderr, "\n****\n");
    306     fprintf(stderr, "**** Header %s\n ", header);
    307   });
    308 
    309   free(type2);
    310 
    311   return result;
    312 }
    313 
    314 /* copy the source to the destination and fill in zeroes in every
    315    other destination byte! */
    316 static void unicodecpy(unsigned char *dest, const char *src, size_t length)
    317 {
    318   size_t i;
    319   for(i = 0; i < length; i++) {
    320     dest[2 * i] = (unsigned char)src[i];
    321     dest[2 * i + 1] = '\0';
    322   }
    323 }
    324 
    325 /*
    326  * Curl_sasl_create_ntlm_type1_message()
    327  *
    328  * This is used to generate an already encoded NTLM type-1 message ready for
    329  * sending to the recipient using the appropriate compile time crypto API.
    330  *
    331  * Parameters:
    332  *
    333  * userp   [in]     - The user name in the format User or Domain\User.
    334  * passdwp [in]     - The user's password.
    335  * ntlm    [in/out] - The ntlm data struct being used and modified.
    336  * outptr  [in/out] - The address where a pointer to newly allocated memory
    337  *                    holding the result will be stored upon completion.
    338  * outlen  [out]    - The length of the output message.
    339  *
    340  * Returns CURLE_OK on success.
    341  */
    342 CURLcode Curl_sasl_create_ntlm_type1_message(const char *userp,
    343                                              const char *passwdp,
    344                                              struct ntlmdata *ntlm,
    345                                              char **outptr, size_t *outlen)
    346 {
    347   /* NTLM type-1 message structure:
    348 
    349        Index  Description            Content
    350          0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
    351                                      (0x4e544c4d53535000)
    352          8    NTLM Message Type      long (0x01000000)
    353         12    Flags                  long
    354        (16)   Supplied Domain        security buffer (*)
    355        (24)   Supplied Workstation   security buffer (*)
    356        (32)   OS Version Structure   8 bytes (*)
    357   (32) (40)   Start of data block    (*)
    358                                      (*) -> Optional
    359   */
    360 
    361   size_t size;
    362 
    363   unsigned char ntlmbuf[NTLM_BUFSIZE];
    364   const char *host = "";              /* empty */
    365   const char *domain = "";            /* empty */
    366   size_t hostlen = 0;
    367   size_t domlen = 0;
    368   size_t hostoff = 0;
    369   size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
    370                                          domain are empty */
    371   (void)userp;
    372   (void)passwdp;
    373 
    374   /* Clean up any former leftovers and initialise to defaults */
    375   Curl_sasl_ntlm_cleanup(ntlm);
    376 
    377 #if USE_NTRESPONSES && USE_NTLM2SESSION
    378 #define NTLM2FLAG NTLMFLAG_NEGOTIATE_NTLM2_KEY
    379 #else
    380 #define NTLM2FLAG 0
    381 #endif
    382   snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
    383            NTLMSSP_SIGNATURE "%c"
    384            "\x01%c%c%c" /* 32-bit type = 1 */
    385            "%c%c%c%c"   /* 32-bit NTLM flag field */
    386            "%c%c"       /* domain length */
    387            "%c%c"       /* domain allocated space */
    388            "%c%c"       /* domain name offset */
    389            "%c%c"       /* 2 zeroes */
    390            "%c%c"       /* host length */
    391            "%c%c"       /* host allocated space */
    392            "%c%c"       /* host name offset */
    393            "%c%c"       /* 2 zeroes */
    394            "%s"         /* host name */
    395            "%s",        /* domain string */
    396            0,           /* trailing zero */
    397            0, 0, 0,     /* part of type-1 long */
    398 
    399            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
    400                        NTLMFLAG_REQUEST_TARGET |
    401                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
    402                        NTLM2FLAG |
    403                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
    404            SHORTPAIR(domlen),
    405            SHORTPAIR(domlen),
    406            SHORTPAIR(domoff),
    407            0, 0,
    408            SHORTPAIR(hostlen),
    409            SHORTPAIR(hostlen),
    410            SHORTPAIR(hostoff),
    411            0, 0,
    412            host,  /* this is empty */
    413            domain /* this is empty */);
    414 
    415   /* Initial packet length */
    416   size = 32 + hostlen + domlen;
    417 
    418   DEBUG_OUT({
    419     fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
    420             "0x%08.8x ",
    421             LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
    422                         NTLMFLAG_REQUEST_TARGET |
    423                         NTLMFLAG_NEGOTIATE_NTLM_KEY |
    424                         NTLM2FLAG |
    425                         NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
    426             NTLMFLAG_NEGOTIATE_OEM |
    427             NTLMFLAG_REQUEST_TARGET |
    428             NTLMFLAG_NEGOTIATE_NTLM_KEY |
    429             NTLM2FLAG |
    430             NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
    431     ntlm_print_flags(stderr,
    432                      NTLMFLAG_NEGOTIATE_OEM |
    433                      NTLMFLAG_REQUEST_TARGET |
    434                      NTLMFLAG_NEGOTIATE_NTLM_KEY |
    435                      NTLM2FLAG |
    436                      NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
    437     fprintf(stderr, "\n****\n");
    438   });
    439 
    440   /* Return with binary blob encoded into base64 */
    441   return Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
    442 }
    443 
    444 /*
    445  * Curl_sasl_create_ntlm_type3_message()
    446  *
    447  * This is used to generate an already encoded NTLM type-3 message ready for
    448  * sending to the recipient using the appropriate compile time crypto API.
    449  *
    450  * Parameters:
    451  *
    452  * data    [in]     - The session handle.
    453  * userp   [in]     - The user name in the format User or Domain\User.
    454  * passdwp [in]     - The user's password.
    455  * ntlm    [in/out] - The ntlm data struct being used and modified.
    456  * outptr  [in/out] - The address where a pointer to newly allocated memory
    457  *                    holding the result will be stored upon completion.
    458  * outlen  [out]    - The length of the output message.
    459  *
    460  * Returns CURLE_OK on success.
    461  */
    462 CURLcode Curl_sasl_create_ntlm_type3_message(struct SessionHandle *data,
    463                                              const char *userp,
    464                                              const char *passwdp,
    465                                              struct ntlmdata *ntlm,
    466                                              char **outptr, size_t *outlen)
    467 
    468 {
    469   /* NTLM type-3 message structure:
    470 
    471           Index  Description            Content
    472             0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
    473                                         (0x4e544c4d53535000)
    474             8    NTLM Message Type      long (0x03000000)
    475            12    LM/LMv2 Response       security buffer
    476            20    NTLM/NTLMv2 Response   security buffer
    477            28    Target Name            security buffer
    478            36    User Name              security buffer
    479            44    Workstation Name       security buffer
    480           (52)   Session Key            security buffer (*)
    481           (60)   Flags                  long (*)
    482           (64)   OS Version Structure   8 bytes (*)
    483   52 (64) (72)   Start of data block
    484                                           (*) -> Optional
    485   */
    486 
    487   CURLcode result = CURLE_OK;
    488   size_t size;
    489   unsigned char ntlmbuf[NTLM_BUFSIZE];
    490   int lmrespoff;
    491   unsigned char lmresp[24]; /* fixed-size */
    492 #if USE_NTRESPONSES
    493   int ntrespoff;
    494   unsigned int ntresplen = 24;
    495   unsigned char ntresp[24]; /* fixed-size */
    496   unsigned char *ptr_ntresp = &ntresp[0];
    497   unsigned char *ntlmv2resp = NULL;
    498 #endif
    499   bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
    500   char host[HOSTNAME_MAX + 1] = "";
    501   const char *user;
    502   const char *domain = "";
    503   size_t hostoff = 0;
    504   size_t useroff = 0;
    505   size_t domoff = 0;
    506   size_t hostlen = 0;
    507   size_t userlen = 0;
    508   size_t domlen = 0;
    509 
    510   user = strchr(userp, '\\');
    511   if(!user)
    512     user = strchr(userp, '/');
    513 
    514   if(user) {
    515     domain = userp;
    516     domlen = (user - domain);
    517     user++;
    518   }
    519   else
    520     user = userp;
    521 
    522   if(user)
    523     userlen = strlen(user);
    524 
    525   /* Get the machine's un-qualified host name as NTLM doesn't like the fully
    526      qualified domain name */
    527   if(Curl_gethostname(host, sizeof(host))) {
    528     infof(data, "gethostname() failed, continuing without!\n");
    529     hostlen = 0;
    530   }
    531   else {
    532     hostlen = strlen(host);
    533   }
    534 
    535 #if USE_NTRESPONSES && USE_NTLM_V2
    536   if(ntlm->target_info_len) {
    537     unsigned char ntbuffer[0x18];
    538     unsigned int entropy[2];
    539     unsigned char ntlmv2hash[0x18];
    540 
    541     entropy[0] = Curl_rand(data);
    542     entropy[1] = Curl_rand(data);
    543 
    544     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
    545     if(result)
    546       return result;
    547 
    548     result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
    549                                            ntbuffer, ntlmv2hash);
    550     if(result)
    551       return result;
    552 
    553     /* LMv2 response */
    554     result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
    555                                          (unsigned char *)&entropy[0],
    556                                          &ntlm->nonce[0], lmresp);
    557     if(result)
    558       return result;
    559 
    560     /* NTLMv2 response */
    561     result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
    562                                            (unsigned char *)&entropy[0],
    563                                            ntlm, &ntlmv2resp, &ntresplen);
    564     if(result)
    565       return result;
    566 
    567     ptr_ntresp = ntlmv2resp;
    568   }
    569   else
    570 #endif
    571 
    572 #if USE_NTRESPONSES && USE_NTLM2SESSION
    573   /* We don't support NTLM2 if we don't have USE_NTRESPONSES */
    574   if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
    575     unsigned char ntbuffer[0x18];
    576     unsigned char tmp[0x18];
    577     unsigned char md5sum[MD5_DIGEST_LENGTH];
    578     unsigned int entropy[2];
    579 
    580     /* Need to create 8 bytes random data */
    581     entropy[0] = Curl_rand(data);
    582     entropy[1] = Curl_rand(data);
    583 
    584     /* 8 bytes random data as challenge in lmresp */
    585     memcpy(lmresp, entropy, 8);
    586 
    587     /* Pad with zeros */
    588     memset(lmresp + 8, 0, 0x10);
    589 
    590     /* Fill tmp with challenge(nonce?) + entropy */
    591     memcpy(tmp, &ntlm->nonce[0], 8);
    592     memcpy(tmp + 8, entropy, 8);
    593 
    594     result = Curl_ssl_md5sum(tmp, 16, md5sum, MD5_DIGEST_LENGTH);
    595     if(!result)
    596       /* We shall only use the first 8 bytes of md5sum, but the des code in
    597          Curl_ntlm_core_lm_resp only encrypt the first 8 bytes */
    598       result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
    599     if(result)
    600       return result;
    601 
    602     Curl_ntlm_core_lm_resp(ntbuffer, md5sum, ntresp);
    603 
    604     /* End of NTLM2 Session code */
    605 
    606   }
    607   else
    608 #endif
    609   {
    610 
    611 #if USE_NTRESPONSES
    612     unsigned char ntbuffer[0x18];
    613 #endif
    614     unsigned char lmbuffer[0x18];
    615 
    616 #if USE_NTRESPONSES
    617     result = Curl_ntlm_core_mk_nt_hash(data, passwdp, ntbuffer);
    618     if(result)
    619       return result;
    620 
    621     Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
    622 #endif
    623 
    624     result = Curl_ntlm_core_mk_lm_hash(data, passwdp, lmbuffer);
    625     if(result)
    626       return result;
    627 
    628     Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
    629 
    630     /* A safer but less compatible alternative is:
    631      *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
    632      * See http://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
    633   }
    634 
    635   if(unicode) {
    636     domlen = domlen * 2;
    637     userlen = userlen * 2;
    638     hostlen = hostlen * 2;
    639   }
    640 
    641   lmrespoff = 64; /* size of the message header */
    642 #if USE_NTRESPONSES
    643   ntrespoff = lmrespoff + 0x18;
    644   domoff = ntrespoff + ntresplen;
    645 #else
    646   domoff = lmrespoff + 0x18;
    647 #endif
    648   useroff = domoff + domlen;
    649   hostoff = useroff + userlen;
    650 
    651   /* Create the big type-3 message binary blob */
    652   size = snprintf((char *)ntlmbuf, NTLM_BUFSIZE,
    653                   NTLMSSP_SIGNATURE "%c"
    654                   "\x03%c%c%c"  /* 32-bit type = 3 */
    655 
    656                   "%c%c"  /* LanManager length */
    657                   "%c%c"  /* LanManager allocated space */
    658                   "%c%c"  /* LanManager offset */
    659                   "%c%c"  /* 2 zeroes */
    660 
    661                   "%c%c"  /* NT-response length */
    662                   "%c%c"  /* NT-response allocated space */
    663                   "%c%c"  /* NT-response offset */
    664                   "%c%c"  /* 2 zeroes */
    665 
    666                   "%c%c"  /* domain length */
    667                   "%c%c"  /* domain allocated space */
    668                   "%c%c"  /* domain name offset */
    669                   "%c%c"  /* 2 zeroes */
    670 
    671                   "%c%c"  /* user length */
    672                   "%c%c"  /* user allocated space */
    673                   "%c%c"  /* user offset */
    674                   "%c%c"  /* 2 zeroes */
    675 
    676                   "%c%c"  /* host length */
    677                   "%c%c"  /* host allocated space */
    678                   "%c%c"  /* host offset */
    679                   "%c%c"  /* 2 zeroes */
    680 
    681                   "%c%c"  /* session key length (unknown purpose) */
    682                   "%c%c"  /* session key allocated space (unknown purpose) */
    683                   "%c%c"  /* session key offset (unknown purpose) */
    684                   "%c%c"  /* 2 zeroes */
    685 
    686                   "%c%c%c%c",  /* flags */
    687 
    688                   /* domain string */
    689                   /* user string */
    690                   /* host string */
    691                   /* LanManager response */
    692                   /* NT response */
    693 
    694                   0,                /* zero termination */
    695                   0, 0, 0,          /* type-3 long, the 24 upper bits */
    696 
    697                   SHORTPAIR(0x18),  /* LanManager response length, twice */
    698                   SHORTPAIR(0x18),
    699                   SHORTPAIR(lmrespoff),
    700                   0x0, 0x0,
    701 
    702 #if USE_NTRESPONSES
    703                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
    704                   SHORTPAIR(ntresplen),
    705                   SHORTPAIR(ntrespoff),
    706                   0x0, 0x0,
    707 #else
    708                   0x0, 0x0,
    709                   0x0, 0x0,
    710                   0x0, 0x0,
    711                   0x0, 0x0,
    712 #endif
    713                   SHORTPAIR(domlen),
    714                   SHORTPAIR(domlen),
    715                   SHORTPAIR(domoff),
    716                   0x0, 0x0,
    717 
    718                   SHORTPAIR(userlen),
    719                   SHORTPAIR(userlen),
    720                   SHORTPAIR(useroff),
    721                   0x0, 0x0,
    722 
    723                   SHORTPAIR(hostlen),
    724                   SHORTPAIR(hostlen),
    725                   SHORTPAIR(hostoff),
    726                   0x0, 0x0,
    727 
    728                   0x0, 0x0,
    729                   0x0, 0x0,
    730                   0x0, 0x0,
    731                   0x0, 0x0,
    732 
    733                   LONGQUARTET(ntlm->flags));
    734 
    735   DEBUGASSERT(size == 64);
    736   DEBUGASSERT(size == (size_t)lmrespoff);
    737 
    738   /* We append the binary hashes */
    739   if(size < (NTLM_BUFSIZE - 0x18)) {
    740     memcpy(&ntlmbuf[size], lmresp, 0x18);
    741     size += 0x18;
    742   }
    743 
    744   DEBUG_OUT({
    745     fprintf(stderr, "**** TYPE3 header lmresp=");
    746     ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
    747   });
    748 
    749 #if USE_NTRESPONSES
    750   if(size < (NTLM_BUFSIZE - ntresplen)) {
    751     DEBUGASSERT(size == (size_t)ntrespoff);
    752     memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
    753     size += ntresplen;
    754   }
    755 
    756   DEBUG_OUT({
    757     fprintf(stderr, "\n   ntresp=");
    758     ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
    759   });
    760 
    761   free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
    762 
    763 #endif
    764 
    765   DEBUG_OUT({
    766     fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
    767             LONGQUARTET(ntlm->flags), ntlm->flags);
    768     ntlm_print_flags(stderr, ntlm->flags);
    769     fprintf(stderr, "\n****\n");
    770   });
    771 
    772   /* Make sure that the domain, user and host strings fit in the
    773      buffer before we copy them there. */
    774   if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
    775     failf(data, "user + domain + host name too big");
    776     return CURLE_OUT_OF_MEMORY;
    777   }
    778 
    779   DEBUGASSERT(size == domoff);
    780   if(unicode)
    781     unicodecpy(&ntlmbuf[size], domain, domlen / 2);
    782   else
    783     memcpy(&ntlmbuf[size], domain, domlen);
    784 
    785   size += domlen;
    786 
    787   DEBUGASSERT(size == useroff);
    788   if(unicode)
    789     unicodecpy(&ntlmbuf[size], user, userlen / 2);
    790   else
    791     memcpy(&ntlmbuf[size], user, userlen);
    792 
    793   size += userlen;
    794 
    795   DEBUGASSERT(size == hostoff);
    796   if(unicode)
    797     unicodecpy(&ntlmbuf[size], host, hostlen / 2);
    798   else
    799     memcpy(&ntlmbuf[size], host, hostlen);
    800 
    801   size += hostlen;
    802 
    803   /* Convert domain, user, and host to ASCII but leave the rest as-is */
    804   result = Curl_convert_to_network(data, (char *)&ntlmbuf[domoff],
    805                                    size - domoff);
    806   if(result)
    807     return CURLE_CONV_FAILED;
    808 
    809   /* Return with binary blob encoded into base64 */
    810   result = Curl_base64_encode(NULL, (char *)ntlmbuf, size, outptr, outlen);
    811 
    812   Curl_sasl_ntlm_cleanup(ntlm);
    813 
    814   return result;
    815 }
    816 
    817 #endif /* USE_NTLM && !USE_WINDOWS_SSPI */
    818