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