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