113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci
2713498266Sopenharmony_ci#if defined(USE_NTLM) && !defined(USE_WINDOWS_SSPI)
2813498266Sopenharmony_ci
2913498266Sopenharmony_ci/*
3013498266Sopenharmony_ci * NTLM details:
3113498266Sopenharmony_ci *
3213498266Sopenharmony_ci * https://davenport.sourceforge.net/ntlm.html
3313498266Sopenharmony_ci * https://www.innovation.ch/java/ntlm.html
3413498266Sopenharmony_ci */
3513498266Sopenharmony_ci
3613498266Sopenharmony_ci#define DEBUG_ME 0
3713498266Sopenharmony_ci
3813498266Sopenharmony_ci#include "urldata.h"
3913498266Sopenharmony_ci#include "sendf.h"
4013498266Sopenharmony_ci#include "curl_ntlm_core.h"
4113498266Sopenharmony_ci#include "curl_gethostname.h"
4213498266Sopenharmony_ci#include "curl_multibyte.h"
4313498266Sopenharmony_ci#include "curl_md5.h"
4413498266Sopenharmony_ci#include "warnless.h"
4513498266Sopenharmony_ci#include "rand.h"
4613498266Sopenharmony_ci#include "vtls/vtls.h"
4713498266Sopenharmony_ci#include "strdup.h"
4813498266Sopenharmony_ci
4913498266Sopenharmony_ci#define BUILDING_CURL_NTLM_MSGS_C
5013498266Sopenharmony_ci#include "vauth/vauth.h"
5113498266Sopenharmony_ci#include "vauth/ntlm.h"
5213498266Sopenharmony_ci#include "curl_endian.h"
5313498266Sopenharmony_ci#include "curl_printf.h"
5413498266Sopenharmony_ci
5513498266Sopenharmony_ci/* The last #include files should be: */
5613498266Sopenharmony_ci#include "curl_memory.h"
5713498266Sopenharmony_ci#include "memdebug.h"
5813498266Sopenharmony_ci
5913498266Sopenharmony_ci/* "NTLMSSP" signature is always in ASCII regardless of the platform */
6013498266Sopenharmony_ci#define NTLMSSP_SIGNATURE "\x4e\x54\x4c\x4d\x53\x53\x50"
6113498266Sopenharmony_ci
6213498266Sopenharmony_ci/* The fixed host name we provide, in order to not leak our real local host
6313498266Sopenharmony_ci   name. Copy the name used by Firefox. */
6413498266Sopenharmony_ci#define NTLM_HOSTNAME "WORKSTATION"
6513498266Sopenharmony_ci
6613498266Sopenharmony_ci#if DEBUG_ME
6713498266Sopenharmony_ci# define DEBUG_OUT(x) x
6813498266Sopenharmony_cistatic void ntlm_print_flags(FILE *handle, unsigned long flags)
6913498266Sopenharmony_ci{
7013498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_UNICODE)
7113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_UNICODE ");
7213498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_OEM)
7313498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_OEM ");
7413498266Sopenharmony_ci  if(flags & NTLMFLAG_REQUEST_TARGET)
7513498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_REQUEST_TARGET ");
7613498266Sopenharmony_ci  if(flags & (1<<3))
7713498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_3 ");
7813498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_SIGN)
7913498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_SIGN ");
8013498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_SEAL)
8113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_SEAL ");
8213498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE)
8313498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE ");
8413498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_LM_KEY)
8513498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_LM_KEY ");
8613498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_NTLM_KEY)
8713498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM_KEY ");
8813498266Sopenharmony_ci  if(flags & (1<<10))
8913498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_10 ");
9013498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_ANONYMOUS)
9113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_ANONYMOUS ");
9213498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED)
9313498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED ");
9413498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED)
9513498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED ");
9613498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_LOCAL_CALL)
9713498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_LOCAL_CALL ");
9813498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_ALWAYS_SIGN)
9913498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_ALWAYS_SIGN ");
10013498266Sopenharmony_ci  if(flags & NTLMFLAG_TARGET_TYPE_DOMAIN)
10113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_TARGET_TYPE_DOMAIN ");
10213498266Sopenharmony_ci  if(flags & NTLMFLAG_TARGET_TYPE_SERVER)
10313498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_TARGET_TYPE_SERVER ");
10413498266Sopenharmony_ci  if(flags & NTLMFLAG_TARGET_TYPE_SHARE)
10513498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_TARGET_TYPE_SHARE ");
10613498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY)
10713498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_NTLM2_KEY ");
10813498266Sopenharmony_ci  if(flags & NTLMFLAG_REQUEST_INIT_RESPONSE)
10913498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_REQUEST_INIT_RESPONSE ");
11013498266Sopenharmony_ci  if(flags & NTLMFLAG_REQUEST_ACCEPT_RESPONSE)
11113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_REQUEST_ACCEPT_RESPONSE ");
11213498266Sopenharmony_ci  if(flags & NTLMFLAG_REQUEST_NONNT_SESSION_KEY)
11313498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_REQUEST_NONNT_SESSION_KEY ");
11413498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_TARGET_INFO)
11513498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_TARGET_INFO ");
11613498266Sopenharmony_ci  if(flags & (1<<24))
11713498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_24 ");
11813498266Sopenharmony_ci  if(flags & (1<<25))
11913498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_25 ");
12013498266Sopenharmony_ci  if(flags & (1<<26))
12113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_26 ");
12213498266Sopenharmony_ci  if(flags & (1<<27))
12313498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_27 ");
12413498266Sopenharmony_ci  if(flags & (1<<28))
12513498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_UNKNOWN_28 ");
12613498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_128)
12713498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_128 ");
12813498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_KEY_EXCHANGE)
12913498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_KEY_EXCHANGE ");
13013498266Sopenharmony_ci  if(flags & NTLMFLAG_NEGOTIATE_56)
13113498266Sopenharmony_ci    fprintf(handle, "NTLMFLAG_NEGOTIATE_56 ");
13213498266Sopenharmony_ci}
13313498266Sopenharmony_ci
13413498266Sopenharmony_cistatic void ntlm_print_hex(FILE *handle, const char *buf, size_t len)
13513498266Sopenharmony_ci{
13613498266Sopenharmony_ci  const char *p = buf;
13713498266Sopenharmony_ci
13813498266Sopenharmony_ci  (void) handle;
13913498266Sopenharmony_ci
14013498266Sopenharmony_ci  fprintf(stderr, "0x");
14113498266Sopenharmony_ci  while(len-- > 0)
14213498266Sopenharmony_ci    fprintf(stderr, "%02.2x", (unsigned int)*p++);
14313498266Sopenharmony_ci}
14413498266Sopenharmony_ci#else
14513498266Sopenharmony_ci# define DEBUG_OUT(x) Curl_nop_stmt
14613498266Sopenharmony_ci#endif
14713498266Sopenharmony_ci
14813498266Sopenharmony_ci/*
14913498266Sopenharmony_ci * ntlm_decode_type2_target()
15013498266Sopenharmony_ci *
15113498266Sopenharmony_ci * This is used to decode the "target info" in the NTLM type-2 message
15213498266Sopenharmony_ci * received.
15313498266Sopenharmony_ci *
15413498266Sopenharmony_ci * Parameters:
15513498266Sopenharmony_ci *
15613498266Sopenharmony_ci * data      [in]     - The session handle.
15713498266Sopenharmony_ci * type2ref  [in]     - The type-2 message.
15813498266Sopenharmony_ci * ntlm      [in/out] - The NTLM data struct being used and modified.
15913498266Sopenharmony_ci *
16013498266Sopenharmony_ci * Returns CURLE_OK on success.
16113498266Sopenharmony_ci */
16213498266Sopenharmony_cistatic CURLcode ntlm_decode_type2_target(struct Curl_easy *data,
16313498266Sopenharmony_ci                                         const struct bufref *type2ref,
16413498266Sopenharmony_ci                                         struct ntlmdata *ntlm)
16513498266Sopenharmony_ci{
16613498266Sopenharmony_ci  unsigned short target_info_len = 0;
16713498266Sopenharmony_ci  unsigned int target_info_offset = 0;
16813498266Sopenharmony_ci  const unsigned char *type2 = Curl_bufref_ptr(type2ref);
16913498266Sopenharmony_ci  size_t type2len = Curl_bufref_len(type2ref);
17013498266Sopenharmony_ci
17113498266Sopenharmony_ci#if defined(CURL_DISABLE_VERBOSE_STRINGS)
17213498266Sopenharmony_ci  (void) data;
17313498266Sopenharmony_ci#endif
17413498266Sopenharmony_ci
17513498266Sopenharmony_ci  if(type2len >= 48) {
17613498266Sopenharmony_ci    target_info_len = Curl_read16_le(&type2[40]);
17713498266Sopenharmony_ci    target_info_offset = Curl_read32_le(&type2[44]);
17813498266Sopenharmony_ci    if(target_info_len > 0) {
17913498266Sopenharmony_ci      if((target_info_offset > type2len) ||
18013498266Sopenharmony_ci         (target_info_offset + target_info_len) > type2len ||
18113498266Sopenharmony_ci         target_info_offset < 48) {
18213498266Sopenharmony_ci        infof(data, "NTLM handshake failure (bad type-2 message). "
18313498266Sopenharmony_ci              "Target Info Offset Len is set incorrect by the peer");
18413498266Sopenharmony_ci        return CURLE_BAD_CONTENT_ENCODING;
18513498266Sopenharmony_ci      }
18613498266Sopenharmony_ci
18713498266Sopenharmony_ci      free(ntlm->target_info); /* replace any previous data */
18813498266Sopenharmony_ci      ntlm->target_info = Curl_memdup(&type2[target_info_offset],
18913498266Sopenharmony_ci                                      target_info_len);
19013498266Sopenharmony_ci      if(!ntlm->target_info)
19113498266Sopenharmony_ci        return CURLE_OUT_OF_MEMORY;
19213498266Sopenharmony_ci    }
19313498266Sopenharmony_ci  }
19413498266Sopenharmony_ci
19513498266Sopenharmony_ci  ntlm->target_info_len = target_info_len;
19613498266Sopenharmony_ci
19713498266Sopenharmony_ci  return CURLE_OK;
19813498266Sopenharmony_ci}
19913498266Sopenharmony_ci
20013498266Sopenharmony_ci/*
20113498266Sopenharmony_ci  NTLM message structure notes:
20213498266Sopenharmony_ci
20313498266Sopenharmony_ci  A 'short' is a 'network short', a little-endian 16-bit unsigned value.
20413498266Sopenharmony_ci
20513498266Sopenharmony_ci  A 'long' is a 'network long', a little-endian, 32-bit unsigned value.
20613498266Sopenharmony_ci
20713498266Sopenharmony_ci  A 'security buffer' represents a triplet used to point to a buffer,
20813498266Sopenharmony_ci  consisting of two shorts and one long:
20913498266Sopenharmony_ci
21013498266Sopenharmony_ci    1. A 'short' containing the length of the buffer content in bytes.
21113498266Sopenharmony_ci    2. A 'short' containing the allocated space for the buffer in bytes.
21213498266Sopenharmony_ci    3. A 'long' containing the offset to the start of the buffer in bytes,
21313498266Sopenharmony_ci       from the beginning of the NTLM message.
21413498266Sopenharmony_ci*/
21513498266Sopenharmony_ci
21613498266Sopenharmony_ci/*
21713498266Sopenharmony_ci * Curl_auth_is_ntlm_supported()
21813498266Sopenharmony_ci *
21913498266Sopenharmony_ci * This is used to evaluate if NTLM is supported.
22013498266Sopenharmony_ci *
22113498266Sopenharmony_ci * Parameters: None
22213498266Sopenharmony_ci *
22313498266Sopenharmony_ci * Returns TRUE as NTLM as handled by libcurl.
22413498266Sopenharmony_ci */
22513498266Sopenharmony_cibool Curl_auth_is_ntlm_supported(void)
22613498266Sopenharmony_ci{
22713498266Sopenharmony_ci  return TRUE;
22813498266Sopenharmony_ci}
22913498266Sopenharmony_ci
23013498266Sopenharmony_ci/*
23113498266Sopenharmony_ci * Curl_auth_decode_ntlm_type2_message()
23213498266Sopenharmony_ci *
23313498266Sopenharmony_ci * This is used to decode an NTLM type-2 message. The raw NTLM message is
23413498266Sopenharmony_ci * checked * for validity before the appropriate data for creating a type-3
23513498266Sopenharmony_ci * message is * written to the given NTLM data structure.
23613498266Sopenharmony_ci *
23713498266Sopenharmony_ci * Parameters:
23813498266Sopenharmony_ci *
23913498266Sopenharmony_ci * data     [in]     - The session handle.
24013498266Sopenharmony_ci * type2ref [in]     - The type-2 message.
24113498266Sopenharmony_ci * ntlm     [in/out] - The NTLM data struct being used and modified.
24213498266Sopenharmony_ci *
24313498266Sopenharmony_ci * Returns CURLE_OK on success.
24413498266Sopenharmony_ci */
24513498266Sopenharmony_ciCURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
24613498266Sopenharmony_ci                                             const struct bufref *type2ref,
24713498266Sopenharmony_ci                                             struct ntlmdata *ntlm)
24813498266Sopenharmony_ci{
24913498266Sopenharmony_ci  static const char type2_marker[] = { 0x02, 0x00, 0x00, 0x00 };
25013498266Sopenharmony_ci
25113498266Sopenharmony_ci  /* NTLM type-2 message structure:
25213498266Sopenharmony_ci
25313498266Sopenharmony_ci          Index  Description            Content
25413498266Sopenharmony_ci            0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
25513498266Sopenharmony_ci                                        (0x4e544c4d53535000)
25613498266Sopenharmony_ci            8    NTLM Message Type      long (0x02000000)
25713498266Sopenharmony_ci           12    Target Name            security buffer
25813498266Sopenharmony_ci           20    Flags                  long
25913498266Sopenharmony_ci           24    Challenge              8 bytes
26013498266Sopenharmony_ci          (32)   Context                8 bytes (two consecutive longs) (*)
26113498266Sopenharmony_ci          (40)   Target Information     security buffer (*)
26213498266Sopenharmony_ci          (48)   OS Version Structure   8 bytes (*)
26313498266Sopenharmony_ci  32 (48) (56)   Start of data block    (*)
26413498266Sopenharmony_ci                                        (*) -> Optional
26513498266Sopenharmony_ci  */
26613498266Sopenharmony_ci
26713498266Sopenharmony_ci  CURLcode result = CURLE_OK;
26813498266Sopenharmony_ci  const unsigned char *type2 = Curl_bufref_ptr(type2ref);
26913498266Sopenharmony_ci  size_t type2len = Curl_bufref_len(type2ref);
27013498266Sopenharmony_ci
27113498266Sopenharmony_ci#if defined(CURL_DISABLE_VERBOSE_STRINGS)
27213498266Sopenharmony_ci  (void)data;
27313498266Sopenharmony_ci#endif
27413498266Sopenharmony_ci
27513498266Sopenharmony_ci  ntlm->flags = 0;
27613498266Sopenharmony_ci
27713498266Sopenharmony_ci  if((type2len < 32) ||
27813498266Sopenharmony_ci     (memcmp(type2, NTLMSSP_SIGNATURE, 8) != 0) ||
27913498266Sopenharmony_ci     (memcmp(type2 + 8, type2_marker, sizeof(type2_marker)) != 0)) {
28013498266Sopenharmony_ci    /* This was not a good enough type-2 message */
28113498266Sopenharmony_ci    infof(data, "NTLM handshake failure (bad type-2 message)");
28213498266Sopenharmony_ci    return CURLE_BAD_CONTENT_ENCODING;
28313498266Sopenharmony_ci  }
28413498266Sopenharmony_ci
28513498266Sopenharmony_ci  ntlm->flags = Curl_read32_le(&type2[20]);
28613498266Sopenharmony_ci  memcpy(ntlm->nonce, &type2[24], 8);
28713498266Sopenharmony_ci
28813498266Sopenharmony_ci  if(ntlm->flags & NTLMFLAG_NEGOTIATE_TARGET_INFO) {
28913498266Sopenharmony_ci    result = ntlm_decode_type2_target(data, type2ref, ntlm);
29013498266Sopenharmony_ci    if(result) {
29113498266Sopenharmony_ci      infof(data, "NTLM handshake failure (bad type-2 message)");
29213498266Sopenharmony_ci      return result;
29313498266Sopenharmony_ci    }
29413498266Sopenharmony_ci  }
29513498266Sopenharmony_ci
29613498266Sopenharmony_ci  DEBUG_OUT({
29713498266Sopenharmony_ci    fprintf(stderr, "**** TYPE2 header flags=0x%08.8lx ", ntlm->flags);
29813498266Sopenharmony_ci    ntlm_print_flags(stderr, ntlm->flags);
29913498266Sopenharmony_ci    fprintf(stderr, "\n                  nonce=");
30013498266Sopenharmony_ci    ntlm_print_hex(stderr, (char *)ntlm->nonce, 8);
30113498266Sopenharmony_ci    fprintf(stderr, "\n****\n");
30213498266Sopenharmony_ci    fprintf(stderr, "**** Header %s\n ", header);
30313498266Sopenharmony_ci  });
30413498266Sopenharmony_ci
30513498266Sopenharmony_ci  return result;
30613498266Sopenharmony_ci}
30713498266Sopenharmony_ci
30813498266Sopenharmony_ci/* copy the source to the destination and fill in zeroes in every
30913498266Sopenharmony_ci   other destination byte! */
31013498266Sopenharmony_cistatic void unicodecpy(unsigned char *dest, const char *src, size_t length)
31113498266Sopenharmony_ci{
31213498266Sopenharmony_ci  size_t i;
31313498266Sopenharmony_ci  for(i = 0; i < length; i++) {
31413498266Sopenharmony_ci    dest[2 * i] = (unsigned char)src[i];
31513498266Sopenharmony_ci    dest[2 * i + 1] = '\0';
31613498266Sopenharmony_ci  }
31713498266Sopenharmony_ci}
31813498266Sopenharmony_ci
31913498266Sopenharmony_ci/*
32013498266Sopenharmony_ci * Curl_auth_create_ntlm_type1_message()
32113498266Sopenharmony_ci *
32213498266Sopenharmony_ci * This is used to generate an NTLM type-1 message ready for sending to the
32313498266Sopenharmony_ci * recipient using the appropriate compile time crypto API.
32413498266Sopenharmony_ci *
32513498266Sopenharmony_ci * Parameters:
32613498266Sopenharmony_ci *
32713498266Sopenharmony_ci * data    [in]     - The session handle.
32813498266Sopenharmony_ci * userp   [in]     - The user name in the format User or Domain\User.
32913498266Sopenharmony_ci * passwdp [in]     - The user's password.
33013498266Sopenharmony_ci * service [in]     - The service type such as http, smtp, pop or imap.
33113498266Sopenharmony_ci * host    [in]     - The host name.
33213498266Sopenharmony_ci * ntlm    [in/out] - The NTLM data struct being used and modified.
33313498266Sopenharmony_ci * out     [out]    - The result storage.
33413498266Sopenharmony_ci *
33513498266Sopenharmony_ci * Returns CURLE_OK on success.
33613498266Sopenharmony_ci */
33713498266Sopenharmony_ciCURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
33813498266Sopenharmony_ci                                             const char *userp,
33913498266Sopenharmony_ci                                             const char *passwdp,
34013498266Sopenharmony_ci                                             const char *service,
34113498266Sopenharmony_ci                                             const char *hostname,
34213498266Sopenharmony_ci                                             struct ntlmdata *ntlm,
34313498266Sopenharmony_ci                                             struct bufref *out)
34413498266Sopenharmony_ci{
34513498266Sopenharmony_ci  /* NTLM type-1 message structure:
34613498266Sopenharmony_ci
34713498266Sopenharmony_ci       Index  Description            Content
34813498266Sopenharmony_ci         0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
34913498266Sopenharmony_ci                                     (0x4e544c4d53535000)
35013498266Sopenharmony_ci         8    NTLM Message Type      long (0x01000000)
35113498266Sopenharmony_ci        12    Flags                  long
35213498266Sopenharmony_ci       (16)   Supplied Domain        security buffer (*)
35313498266Sopenharmony_ci       (24)   Supplied Workstation   security buffer (*)
35413498266Sopenharmony_ci       (32)   OS Version Structure   8 bytes (*)
35513498266Sopenharmony_ci  (32) (40)   Start of data block    (*)
35613498266Sopenharmony_ci                                     (*) -> Optional
35713498266Sopenharmony_ci  */
35813498266Sopenharmony_ci
35913498266Sopenharmony_ci  size_t size;
36013498266Sopenharmony_ci
36113498266Sopenharmony_ci  char *ntlmbuf;
36213498266Sopenharmony_ci  const char *host = "";              /* empty */
36313498266Sopenharmony_ci  const char *domain = "";            /* empty */
36413498266Sopenharmony_ci  size_t hostlen = 0;
36513498266Sopenharmony_ci  size_t domlen = 0;
36613498266Sopenharmony_ci  size_t hostoff = 0;
36713498266Sopenharmony_ci  size_t domoff = hostoff + hostlen;  /* This is 0: remember that host and
36813498266Sopenharmony_ci                                         domain are empty */
36913498266Sopenharmony_ci  (void)data;
37013498266Sopenharmony_ci  (void)userp;
37113498266Sopenharmony_ci  (void)passwdp;
37213498266Sopenharmony_ci  (void)service;
37313498266Sopenharmony_ci  (void)hostname;
37413498266Sopenharmony_ci
37513498266Sopenharmony_ci  /* Clean up any former leftovers and initialise to defaults */
37613498266Sopenharmony_ci  Curl_auth_cleanup_ntlm(ntlm);
37713498266Sopenharmony_ci
37813498266Sopenharmony_ci  ntlmbuf = aprintf(NTLMSSP_SIGNATURE "%c"
37913498266Sopenharmony_ci                    "\x01%c%c%c" /* 32-bit type = 1 */
38013498266Sopenharmony_ci                    "%c%c%c%c"   /* 32-bit NTLM flag field */
38113498266Sopenharmony_ci                    "%c%c"       /* domain length */
38213498266Sopenharmony_ci                    "%c%c"       /* domain allocated space */
38313498266Sopenharmony_ci                    "%c%c"       /* domain name offset */
38413498266Sopenharmony_ci                    "%c%c"       /* 2 zeroes */
38513498266Sopenharmony_ci                    "%c%c"       /* host length */
38613498266Sopenharmony_ci                    "%c%c"       /* host allocated space */
38713498266Sopenharmony_ci                    "%c%c"       /* host name offset */
38813498266Sopenharmony_ci                    "%c%c"       /* 2 zeroes */
38913498266Sopenharmony_ci                    "%s"         /* host name */
39013498266Sopenharmony_ci                    "%s",        /* domain string */
39113498266Sopenharmony_ci                    0,           /* trailing zero */
39213498266Sopenharmony_ci                    0, 0, 0,     /* part of type-1 long */
39313498266Sopenharmony_ci
39413498266Sopenharmony_ci                    LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
39513498266Sopenharmony_ci                                NTLMFLAG_REQUEST_TARGET |
39613498266Sopenharmony_ci                                NTLMFLAG_NEGOTIATE_NTLM_KEY |
39713498266Sopenharmony_ci                                NTLMFLAG_NEGOTIATE_NTLM2_KEY |
39813498266Sopenharmony_ci                                NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
39913498266Sopenharmony_ci                    SHORTPAIR(domlen),
40013498266Sopenharmony_ci                    SHORTPAIR(domlen),
40113498266Sopenharmony_ci                    SHORTPAIR(domoff),
40213498266Sopenharmony_ci                    0, 0,
40313498266Sopenharmony_ci                    SHORTPAIR(hostlen),
40413498266Sopenharmony_ci                    SHORTPAIR(hostlen),
40513498266Sopenharmony_ci                    SHORTPAIR(hostoff),
40613498266Sopenharmony_ci                    0, 0,
40713498266Sopenharmony_ci                    host,  /* this is empty */
40813498266Sopenharmony_ci                    domain /* this is empty */);
40913498266Sopenharmony_ci
41013498266Sopenharmony_ci  if(!ntlmbuf)
41113498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
41213498266Sopenharmony_ci
41313498266Sopenharmony_ci  /* Initial packet length */
41413498266Sopenharmony_ci  size = 32 + hostlen + domlen;
41513498266Sopenharmony_ci
41613498266Sopenharmony_ci  DEBUG_OUT({
41713498266Sopenharmony_ci    fprintf(stderr, "* TYPE1 header flags=0x%02.2x%02.2x%02.2x%02.2x "
41813498266Sopenharmony_ci            "0x%08.8x ",
41913498266Sopenharmony_ci            LONGQUARTET(NTLMFLAG_NEGOTIATE_OEM |
42013498266Sopenharmony_ci                        NTLMFLAG_REQUEST_TARGET |
42113498266Sopenharmony_ci                        NTLMFLAG_NEGOTIATE_NTLM_KEY |
42213498266Sopenharmony_ci                        NTLMFLAG_NEGOTIATE_NTLM2_KEY |
42313498266Sopenharmony_ci                        NTLMFLAG_NEGOTIATE_ALWAYS_SIGN),
42413498266Sopenharmony_ci            NTLMFLAG_NEGOTIATE_OEM |
42513498266Sopenharmony_ci            NTLMFLAG_REQUEST_TARGET |
42613498266Sopenharmony_ci            NTLMFLAG_NEGOTIATE_NTLM_KEY |
42713498266Sopenharmony_ci            NTLMFLAG_NEGOTIATE_NTLM2_KEY |
42813498266Sopenharmony_ci            NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
42913498266Sopenharmony_ci    ntlm_print_flags(stderr,
43013498266Sopenharmony_ci                     NTLMFLAG_NEGOTIATE_OEM |
43113498266Sopenharmony_ci                     NTLMFLAG_REQUEST_TARGET |
43213498266Sopenharmony_ci                     NTLMFLAG_NEGOTIATE_NTLM_KEY |
43313498266Sopenharmony_ci                     NTLMFLAG_NEGOTIATE_NTLM2_KEY |
43413498266Sopenharmony_ci                     NTLMFLAG_NEGOTIATE_ALWAYS_SIGN);
43513498266Sopenharmony_ci    fprintf(stderr, "\n****\n");
43613498266Sopenharmony_ci  });
43713498266Sopenharmony_ci
43813498266Sopenharmony_ci  Curl_bufref_set(out, ntlmbuf, size, curl_free);
43913498266Sopenharmony_ci  return CURLE_OK;
44013498266Sopenharmony_ci}
44113498266Sopenharmony_ci
44213498266Sopenharmony_ci/*
44313498266Sopenharmony_ci * Curl_auth_create_ntlm_type3_message()
44413498266Sopenharmony_ci *
44513498266Sopenharmony_ci * This is used to generate an already encoded NTLM type-3 message ready for
44613498266Sopenharmony_ci * sending to the recipient using the appropriate compile time crypto API.
44713498266Sopenharmony_ci *
44813498266Sopenharmony_ci * Parameters:
44913498266Sopenharmony_ci *
45013498266Sopenharmony_ci * data    [in]     - The session handle.
45113498266Sopenharmony_ci * userp   [in]     - The user name in the format User or Domain\User.
45213498266Sopenharmony_ci * passwdp [in]     - The user's password.
45313498266Sopenharmony_ci * ntlm    [in/out] - The NTLM data struct being used and modified.
45413498266Sopenharmony_ci * out     [out]    - The result storage.
45513498266Sopenharmony_ci *
45613498266Sopenharmony_ci * Returns CURLE_OK on success.
45713498266Sopenharmony_ci */
45813498266Sopenharmony_ciCURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
45913498266Sopenharmony_ci                                             const char *userp,
46013498266Sopenharmony_ci                                             const char *passwdp,
46113498266Sopenharmony_ci                                             struct ntlmdata *ntlm,
46213498266Sopenharmony_ci                                             struct bufref *out)
46313498266Sopenharmony_ci{
46413498266Sopenharmony_ci  /* NTLM type-3 message structure:
46513498266Sopenharmony_ci
46613498266Sopenharmony_ci          Index  Description            Content
46713498266Sopenharmony_ci            0    NTLMSSP Signature      Null-terminated ASCII "NTLMSSP"
46813498266Sopenharmony_ci                                        (0x4e544c4d53535000)
46913498266Sopenharmony_ci            8    NTLM Message Type      long (0x03000000)
47013498266Sopenharmony_ci           12    LM/LMv2 Response       security buffer
47113498266Sopenharmony_ci           20    NTLM/NTLMv2 Response   security buffer
47213498266Sopenharmony_ci           28    Target Name            security buffer
47313498266Sopenharmony_ci           36    User Name              security buffer
47413498266Sopenharmony_ci           44    Workstation Name       security buffer
47513498266Sopenharmony_ci          (52)   Session Key            security buffer (*)
47613498266Sopenharmony_ci          (60)   Flags                  long (*)
47713498266Sopenharmony_ci          (64)   OS Version Structure   8 bytes (*)
47813498266Sopenharmony_ci  52 (64) (72)   Start of data block
47913498266Sopenharmony_ci                                          (*) -> Optional
48013498266Sopenharmony_ci  */
48113498266Sopenharmony_ci
48213498266Sopenharmony_ci  CURLcode result = CURLE_OK;
48313498266Sopenharmony_ci  size_t size;
48413498266Sopenharmony_ci  unsigned char ntlmbuf[NTLM_BUFSIZE];
48513498266Sopenharmony_ci  int lmrespoff;
48613498266Sopenharmony_ci  unsigned char lmresp[24]; /* fixed-size */
48713498266Sopenharmony_ci  int ntrespoff;
48813498266Sopenharmony_ci  unsigned int ntresplen = 24;
48913498266Sopenharmony_ci  unsigned char ntresp[24]; /* fixed-size */
49013498266Sopenharmony_ci  unsigned char *ptr_ntresp = &ntresp[0];
49113498266Sopenharmony_ci  unsigned char *ntlmv2resp = NULL;
49213498266Sopenharmony_ci  bool unicode = (ntlm->flags & NTLMFLAG_NEGOTIATE_UNICODE) ? TRUE : FALSE;
49313498266Sopenharmony_ci  char host[HOSTNAME_MAX + 1] = "";
49413498266Sopenharmony_ci  const char *user;
49513498266Sopenharmony_ci  const char *domain = "";
49613498266Sopenharmony_ci  size_t hostoff = 0;
49713498266Sopenharmony_ci  size_t useroff = 0;
49813498266Sopenharmony_ci  size_t domoff = 0;
49913498266Sopenharmony_ci  size_t hostlen = 0;
50013498266Sopenharmony_ci  size_t userlen = 0;
50113498266Sopenharmony_ci  size_t domlen = 0;
50213498266Sopenharmony_ci
50313498266Sopenharmony_ci  memset(lmresp, 0, sizeof(lmresp));
50413498266Sopenharmony_ci  memset(ntresp, 0, sizeof(ntresp));
50513498266Sopenharmony_ci  user = strchr(userp, '\\');
50613498266Sopenharmony_ci  if(!user)
50713498266Sopenharmony_ci    user = strchr(userp, '/');
50813498266Sopenharmony_ci
50913498266Sopenharmony_ci  if(user) {
51013498266Sopenharmony_ci    domain = userp;
51113498266Sopenharmony_ci    domlen = (user - domain);
51213498266Sopenharmony_ci    user++;
51313498266Sopenharmony_ci  }
51413498266Sopenharmony_ci  else
51513498266Sopenharmony_ci    user = userp;
51613498266Sopenharmony_ci
51713498266Sopenharmony_ci  userlen = strlen(user);
51813498266Sopenharmony_ci
51913498266Sopenharmony_ci#ifndef NTLM_HOSTNAME
52013498266Sopenharmony_ci  /* Get the machine's un-qualified host name as NTLM doesn't like the fully
52113498266Sopenharmony_ci     qualified domain name */
52213498266Sopenharmony_ci  if(Curl_gethostname(host, sizeof(host))) {
52313498266Sopenharmony_ci    infof(data, "gethostname() failed, continuing without");
52413498266Sopenharmony_ci    hostlen = 0;
52513498266Sopenharmony_ci  }
52613498266Sopenharmony_ci  else {
52713498266Sopenharmony_ci    hostlen = strlen(host);
52813498266Sopenharmony_ci  }
52913498266Sopenharmony_ci#else
53013498266Sopenharmony_ci  (void)msnprintf(host, sizeof(host), "%s", NTLM_HOSTNAME);
53113498266Sopenharmony_ci  hostlen = sizeof(NTLM_HOSTNAME)-1;
53213498266Sopenharmony_ci#endif
53313498266Sopenharmony_ci
53413498266Sopenharmony_ci  if(ntlm->flags & NTLMFLAG_NEGOTIATE_NTLM2_KEY) {
53513498266Sopenharmony_ci    unsigned char ntbuffer[0x18];
53613498266Sopenharmony_ci    unsigned char entropy[8];
53713498266Sopenharmony_ci    unsigned char ntlmv2hash[0x18];
53813498266Sopenharmony_ci
53913498266Sopenharmony_ci    /* Full NTLM version 2
54013498266Sopenharmony_ci       Although this cannot be negotiated, it is used here if available, as
54113498266Sopenharmony_ci       servers featuring extended security are likely supporting also
54213498266Sopenharmony_ci       NTLMv2. */
54313498266Sopenharmony_ci    result = Curl_rand(data, entropy, 8);
54413498266Sopenharmony_ci    if(result)
54513498266Sopenharmony_ci      return result;
54613498266Sopenharmony_ci
54713498266Sopenharmony_ci    result = Curl_ntlm_core_mk_nt_hash(passwdp, ntbuffer);
54813498266Sopenharmony_ci    if(result)
54913498266Sopenharmony_ci      return result;
55013498266Sopenharmony_ci
55113498266Sopenharmony_ci    result = Curl_ntlm_core_mk_ntlmv2_hash(user, userlen, domain, domlen,
55213498266Sopenharmony_ci                                           ntbuffer, ntlmv2hash);
55313498266Sopenharmony_ci    if(result)
55413498266Sopenharmony_ci      return result;
55513498266Sopenharmony_ci
55613498266Sopenharmony_ci    /* LMv2 response */
55713498266Sopenharmony_ci    result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
55813498266Sopenharmony_ci                                         &ntlm->nonce[0], lmresp);
55913498266Sopenharmony_ci    if(result)
56013498266Sopenharmony_ci      return result;
56113498266Sopenharmony_ci
56213498266Sopenharmony_ci    /* NTLMv2 response */
56313498266Sopenharmony_ci    result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
56413498266Sopenharmony_ci                                           ntlm, &ntlmv2resp, &ntresplen);
56513498266Sopenharmony_ci    if(result)
56613498266Sopenharmony_ci      return result;
56713498266Sopenharmony_ci
56813498266Sopenharmony_ci    ptr_ntresp = ntlmv2resp;
56913498266Sopenharmony_ci  }
57013498266Sopenharmony_ci  else {
57113498266Sopenharmony_ci
57213498266Sopenharmony_ci    unsigned char ntbuffer[0x18];
57313498266Sopenharmony_ci    unsigned char lmbuffer[0x18];
57413498266Sopenharmony_ci
57513498266Sopenharmony_ci    /* NTLM version 1 */
57613498266Sopenharmony_ci
57713498266Sopenharmony_ci    result = Curl_ntlm_core_mk_nt_hash(passwdp, ntbuffer);
57813498266Sopenharmony_ci    if(result)
57913498266Sopenharmony_ci      return result;
58013498266Sopenharmony_ci
58113498266Sopenharmony_ci    Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], ntresp);
58213498266Sopenharmony_ci
58313498266Sopenharmony_ci    result = Curl_ntlm_core_mk_lm_hash(passwdp, lmbuffer);
58413498266Sopenharmony_ci    if(result)
58513498266Sopenharmony_ci      return result;
58613498266Sopenharmony_ci
58713498266Sopenharmony_ci    Curl_ntlm_core_lm_resp(lmbuffer, &ntlm->nonce[0], lmresp);
58813498266Sopenharmony_ci    ntlm->flags &= ~NTLMFLAG_NEGOTIATE_NTLM2_KEY;
58913498266Sopenharmony_ci
59013498266Sopenharmony_ci    /* A safer but less compatible alternative is:
59113498266Sopenharmony_ci     *   Curl_ntlm_core_lm_resp(ntbuffer, &ntlm->nonce[0], lmresp);
59213498266Sopenharmony_ci     * See https://davenport.sourceforge.net/ntlm.html#ntlmVersion2 */
59313498266Sopenharmony_ci  }
59413498266Sopenharmony_ci
59513498266Sopenharmony_ci  if(unicode) {
59613498266Sopenharmony_ci    domlen = domlen * 2;
59713498266Sopenharmony_ci    userlen = userlen * 2;
59813498266Sopenharmony_ci    hostlen = hostlen * 2;
59913498266Sopenharmony_ci  }
60013498266Sopenharmony_ci
60113498266Sopenharmony_ci  lmrespoff = 64; /* size of the message header */
60213498266Sopenharmony_ci  ntrespoff = lmrespoff + 0x18;
60313498266Sopenharmony_ci  domoff = ntrespoff + ntresplen;
60413498266Sopenharmony_ci  useroff = domoff + domlen;
60513498266Sopenharmony_ci  hostoff = useroff + userlen;
60613498266Sopenharmony_ci
60713498266Sopenharmony_ci  /* Create the big type-3 message binary blob */
60813498266Sopenharmony_ci  size = msnprintf((char *)ntlmbuf, NTLM_BUFSIZE,
60913498266Sopenharmony_ci                   NTLMSSP_SIGNATURE "%c"
61013498266Sopenharmony_ci                   "\x03%c%c%c"  /* 32-bit type = 3 */
61113498266Sopenharmony_ci
61213498266Sopenharmony_ci                   "%c%c"  /* LanManager length */
61313498266Sopenharmony_ci                   "%c%c"  /* LanManager allocated space */
61413498266Sopenharmony_ci                   "%c%c"  /* LanManager offset */
61513498266Sopenharmony_ci                   "%c%c"  /* 2 zeroes */
61613498266Sopenharmony_ci
61713498266Sopenharmony_ci                   "%c%c"  /* NT-response length */
61813498266Sopenharmony_ci                   "%c%c"  /* NT-response allocated space */
61913498266Sopenharmony_ci                   "%c%c"  /* NT-response offset */
62013498266Sopenharmony_ci                   "%c%c"  /* 2 zeroes */
62113498266Sopenharmony_ci
62213498266Sopenharmony_ci                   "%c%c"  /* domain length */
62313498266Sopenharmony_ci                   "%c%c"  /* domain allocated space */
62413498266Sopenharmony_ci                   "%c%c"  /* domain name offset */
62513498266Sopenharmony_ci                   "%c%c"  /* 2 zeroes */
62613498266Sopenharmony_ci
62713498266Sopenharmony_ci                   "%c%c"  /* user length */
62813498266Sopenharmony_ci                   "%c%c"  /* user allocated space */
62913498266Sopenharmony_ci                   "%c%c"  /* user offset */
63013498266Sopenharmony_ci                   "%c%c"  /* 2 zeroes */
63113498266Sopenharmony_ci
63213498266Sopenharmony_ci                   "%c%c"  /* host length */
63313498266Sopenharmony_ci                   "%c%c"  /* host allocated space */
63413498266Sopenharmony_ci                   "%c%c"  /* host offset */
63513498266Sopenharmony_ci                   "%c%c"  /* 2 zeroes */
63613498266Sopenharmony_ci
63713498266Sopenharmony_ci                   "%c%c"  /* session key length (unknown purpose) */
63813498266Sopenharmony_ci                   "%c%c"  /* session key allocated space (unknown purpose) */
63913498266Sopenharmony_ci                   "%c%c"  /* session key offset (unknown purpose) */
64013498266Sopenharmony_ci                   "%c%c"  /* 2 zeroes */
64113498266Sopenharmony_ci
64213498266Sopenharmony_ci                   "%c%c%c%c",  /* flags */
64313498266Sopenharmony_ci
64413498266Sopenharmony_ci                   /* domain string */
64513498266Sopenharmony_ci                   /* user string */
64613498266Sopenharmony_ci                   /* host string */
64713498266Sopenharmony_ci                   /* LanManager response */
64813498266Sopenharmony_ci                   /* NT response */
64913498266Sopenharmony_ci
65013498266Sopenharmony_ci                   0,                /* null-termination */
65113498266Sopenharmony_ci                   0, 0, 0,          /* type-3 long, the 24 upper bits */
65213498266Sopenharmony_ci
65313498266Sopenharmony_ci                   SHORTPAIR(0x18),  /* LanManager response length, twice */
65413498266Sopenharmony_ci                   SHORTPAIR(0x18),
65513498266Sopenharmony_ci                   SHORTPAIR(lmrespoff),
65613498266Sopenharmony_ci                   0x0, 0x0,
65713498266Sopenharmony_ci
65813498266Sopenharmony_ci                   SHORTPAIR(ntresplen),  /* NT-response length, twice */
65913498266Sopenharmony_ci                   SHORTPAIR(ntresplen),
66013498266Sopenharmony_ci                   SHORTPAIR(ntrespoff),
66113498266Sopenharmony_ci                   0x0, 0x0,
66213498266Sopenharmony_ci
66313498266Sopenharmony_ci                   SHORTPAIR(domlen),
66413498266Sopenharmony_ci                   SHORTPAIR(domlen),
66513498266Sopenharmony_ci                   SHORTPAIR(domoff),
66613498266Sopenharmony_ci                   0x0, 0x0,
66713498266Sopenharmony_ci
66813498266Sopenharmony_ci                   SHORTPAIR(userlen),
66913498266Sopenharmony_ci                   SHORTPAIR(userlen),
67013498266Sopenharmony_ci                   SHORTPAIR(useroff),
67113498266Sopenharmony_ci                   0x0, 0x0,
67213498266Sopenharmony_ci
67313498266Sopenharmony_ci                   SHORTPAIR(hostlen),
67413498266Sopenharmony_ci                   SHORTPAIR(hostlen),
67513498266Sopenharmony_ci                   SHORTPAIR(hostoff),
67613498266Sopenharmony_ci                   0x0, 0x0,
67713498266Sopenharmony_ci
67813498266Sopenharmony_ci                   0x0, 0x0,
67913498266Sopenharmony_ci                   0x0, 0x0,
68013498266Sopenharmony_ci                   0x0, 0x0,
68113498266Sopenharmony_ci                   0x0, 0x0,
68213498266Sopenharmony_ci
68313498266Sopenharmony_ci                   LONGQUARTET(ntlm->flags));
68413498266Sopenharmony_ci
68513498266Sopenharmony_ci  DEBUGASSERT(size == 64);
68613498266Sopenharmony_ci  DEBUGASSERT(size == (size_t)lmrespoff);
68713498266Sopenharmony_ci
68813498266Sopenharmony_ci  /* We append the binary hashes */
68913498266Sopenharmony_ci  if(size < (NTLM_BUFSIZE - 0x18)) {
69013498266Sopenharmony_ci    memcpy(&ntlmbuf[size], lmresp, 0x18);
69113498266Sopenharmony_ci    size += 0x18;
69213498266Sopenharmony_ci  }
69313498266Sopenharmony_ci
69413498266Sopenharmony_ci  DEBUG_OUT({
69513498266Sopenharmony_ci    fprintf(stderr, "**** TYPE3 header lmresp=");
69613498266Sopenharmony_ci    ntlm_print_hex(stderr, (char *)&ntlmbuf[lmrespoff], 0x18);
69713498266Sopenharmony_ci  });
69813498266Sopenharmony_ci
69913498266Sopenharmony_ci  /* ntresplen + size should not be risking an integer overflow here */
70013498266Sopenharmony_ci  if(ntresplen + size > sizeof(ntlmbuf)) {
70113498266Sopenharmony_ci    failf(data, "incoming NTLM message too big");
70213498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
70313498266Sopenharmony_ci  }
70413498266Sopenharmony_ci  DEBUGASSERT(size == (size_t)ntrespoff);
70513498266Sopenharmony_ci  memcpy(&ntlmbuf[size], ptr_ntresp, ntresplen);
70613498266Sopenharmony_ci  size += ntresplen;
70713498266Sopenharmony_ci
70813498266Sopenharmony_ci  DEBUG_OUT({
70913498266Sopenharmony_ci    fprintf(stderr, "\n   ntresp=");
71013498266Sopenharmony_ci    ntlm_print_hex(stderr, (char *)&ntlmbuf[ntrespoff], ntresplen);
71113498266Sopenharmony_ci  });
71213498266Sopenharmony_ci
71313498266Sopenharmony_ci  free(ntlmv2resp);/* Free the dynamic buffer allocated for NTLMv2 */
71413498266Sopenharmony_ci
71513498266Sopenharmony_ci  DEBUG_OUT({
71613498266Sopenharmony_ci    fprintf(stderr, "\n   flags=0x%02.2x%02.2x%02.2x%02.2x 0x%08.8x ",
71713498266Sopenharmony_ci            LONGQUARTET(ntlm->flags), ntlm->flags);
71813498266Sopenharmony_ci    ntlm_print_flags(stderr, ntlm->flags);
71913498266Sopenharmony_ci    fprintf(stderr, "\n****\n");
72013498266Sopenharmony_ci  });
72113498266Sopenharmony_ci
72213498266Sopenharmony_ci  /* Make sure that the domain, user and host strings fit in the
72313498266Sopenharmony_ci     buffer before we copy them there. */
72413498266Sopenharmony_ci  if(size + userlen + domlen + hostlen >= NTLM_BUFSIZE) {
72513498266Sopenharmony_ci    failf(data, "user + domain + host name too big");
72613498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
72713498266Sopenharmony_ci  }
72813498266Sopenharmony_ci
72913498266Sopenharmony_ci  DEBUGASSERT(size == domoff);
73013498266Sopenharmony_ci  if(unicode)
73113498266Sopenharmony_ci    unicodecpy(&ntlmbuf[size], domain, domlen / 2);
73213498266Sopenharmony_ci  else
73313498266Sopenharmony_ci    memcpy(&ntlmbuf[size], domain, domlen);
73413498266Sopenharmony_ci
73513498266Sopenharmony_ci  size += domlen;
73613498266Sopenharmony_ci
73713498266Sopenharmony_ci  DEBUGASSERT(size == useroff);
73813498266Sopenharmony_ci  if(unicode)
73913498266Sopenharmony_ci    unicodecpy(&ntlmbuf[size], user, userlen / 2);
74013498266Sopenharmony_ci  else
74113498266Sopenharmony_ci    memcpy(&ntlmbuf[size], user, userlen);
74213498266Sopenharmony_ci
74313498266Sopenharmony_ci  size += userlen;
74413498266Sopenharmony_ci
74513498266Sopenharmony_ci  DEBUGASSERT(size == hostoff);
74613498266Sopenharmony_ci  if(unicode)
74713498266Sopenharmony_ci    unicodecpy(&ntlmbuf[size], host, hostlen / 2);
74813498266Sopenharmony_ci  else
74913498266Sopenharmony_ci    memcpy(&ntlmbuf[size], host, hostlen);
75013498266Sopenharmony_ci
75113498266Sopenharmony_ci  size += hostlen;
75213498266Sopenharmony_ci
75313498266Sopenharmony_ci  /* Return the binary blob. */
75413498266Sopenharmony_ci  result = Curl_bufref_memdup(out, ntlmbuf, size);
75513498266Sopenharmony_ci
75613498266Sopenharmony_ci  Curl_auth_cleanup_ntlm(ntlm);
75713498266Sopenharmony_ci
75813498266Sopenharmony_ci  return result;
75913498266Sopenharmony_ci}
76013498266Sopenharmony_ci
76113498266Sopenharmony_ci/*
76213498266Sopenharmony_ci * Curl_auth_cleanup_ntlm()
76313498266Sopenharmony_ci *
76413498266Sopenharmony_ci * This is used to clean up the NTLM specific data.
76513498266Sopenharmony_ci *
76613498266Sopenharmony_ci * Parameters:
76713498266Sopenharmony_ci *
76813498266Sopenharmony_ci * ntlm    [in/out] - The NTLM data struct being cleaned up.
76913498266Sopenharmony_ci *
77013498266Sopenharmony_ci */
77113498266Sopenharmony_civoid Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm)
77213498266Sopenharmony_ci{
77313498266Sopenharmony_ci  /* Free the target info */
77413498266Sopenharmony_ci  Curl_safefree(ntlm->target_info);
77513498266Sopenharmony_ci
77613498266Sopenharmony_ci  /* Reset any variables */
77713498266Sopenharmony_ci  ntlm->target_info_len = 0;
77813498266Sopenharmony_ci}
77913498266Sopenharmony_ci
78013498266Sopenharmony_ci#endif /* USE_NTLM && !USE_WINDOWS_SSPI */
781