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