xref: /third_party/curl/lib/vauth/ntlm_sspi.c (revision 13498266)
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_WINDOWS_SSPI) && defined(USE_NTLM)
2813498266Sopenharmony_ci
2913498266Sopenharmony_ci#include <curl/curl.h>
3013498266Sopenharmony_ci
3113498266Sopenharmony_ci#include "vauth/vauth.h"
3213498266Sopenharmony_ci#include "urldata.h"
3313498266Sopenharmony_ci#include "curl_ntlm_core.h"
3413498266Sopenharmony_ci#include "warnless.h"
3513498266Sopenharmony_ci#include "curl_multibyte.h"
3613498266Sopenharmony_ci#include "sendf.h"
3713498266Sopenharmony_ci#include "strdup.h"
3813498266Sopenharmony_ci
3913498266Sopenharmony_ci/* The last #include files should be: */
4013498266Sopenharmony_ci#include "curl_memory.h"
4113498266Sopenharmony_ci#include "memdebug.h"
4213498266Sopenharmony_ci
4313498266Sopenharmony_ci/*
4413498266Sopenharmony_ci * Curl_auth_is_ntlm_supported()
4513498266Sopenharmony_ci *
4613498266Sopenharmony_ci * This is used to evaluate if NTLM is supported.
4713498266Sopenharmony_ci *
4813498266Sopenharmony_ci * Parameters: None
4913498266Sopenharmony_ci *
5013498266Sopenharmony_ci * Returns TRUE if NTLM is supported by Windows SSPI.
5113498266Sopenharmony_ci */
5213498266Sopenharmony_cibool Curl_auth_is_ntlm_supported(void)
5313498266Sopenharmony_ci{
5413498266Sopenharmony_ci  PSecPkgInfo SecurityPackage;
5513498266Sopenharmony_ci  SECURITY_STATUS status;
5613498266Sopenharmony_ci
5713498266Sopenharmony_ci  /* Query the security package for NTLM */
5813498266Sopenharmony_ci  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
5913498266Sopenharmony_ci                                              &SecurityPackage);
6013498266Sopenharmony_ci
6113498266Sopenharmony_ci  /* Release the package buffer as it is not required anymore */
6213498266Sopenharmony_ci  if(status == SEC_E_OK) {
6313498266Sopenharmony_ci    s_pSecFn->FreeContextBuffer(SecurityPackage);
6413498266Sopenharmony_ci  }
6513498266Sopenharmony_ci
6613498266Sopenharmony_ci  return (status == SEC_E_OK ? TRUE : FALSE);
6713498266Sopenharmony_ci}
6813498266Sopenharmony_ci
6913498266Sopenharmony_ci/*
7013498266Sopenharmony_ci * Curl_auth_create_ntlm_type1_message()
7113498266Sopenharmony_ci *
7213498266Sopenharmony_ci * This is used to generate an already encoded NTLM type-1 message ready for
7313498266Sopenharmony_ci * sending to the recipient.
7413498266Sopenharmony_ci *
7513498266Sopenharmony_ci * Parameters:
7613498266Sopenharmony_ci *
7713498266Sopenharmony_ci * data    [in]     - The session handle.
7813498266Sopenharmony_ci * userp   [in]     - The user name in the format User or Domain\User.
7913498266Sopenharmony_ci * passwdp [in]     - The user's password.
8013498266Sopenharmony_ci * service [in]     - The service type such as http, smtp, pop or imap.
8113498266Sopenharmony_ci * host    [in]     - The host name.
8213498266Sopenharmony_ci * ntlm    [in/out] - The NTLM data struct being used and modified.
8313498266Sopenharmony_ci * out     [out]    - The result storage.
8413498266Sopenharmony_ci *
8513498266Sopenharmony_ci * Returns CURLE_OK on success.
8613498266Sopenharmony_ci */
8713498266Sopenharmony_ciCURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
8813498266Sopenharmony_ci                                             const char *userp,
8913498266Sopenharmony_ci                                             const char *passwdp,
9013498266Sopenharmony_ci                                             const char *service,
9113498266Sopenharmony_ci                                             const char *host,
9213498266Sopenharmony_ci                                             struct ntlmdata *ntlm,
9313498266Sopenharmony_ci                                             struct bufref *out)
9413498266Sopenharmony_ci{
9513498266Sopenharmony_ci  PSecPkgInfo SecurityPackage;
9613498266Sopenharmony_ci  SecBuffer type_1_buf;
9713498266Sopenharmony_ci  SecBufferDesc type_1_desc;
9813498266Sopenharmony_ci  SECURITY_STATUS status;
9913498266Sopenharmony_ci  unsigned long attrs;
10013498266Sopenharmony_ci  TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
10113498266Sopenharmony_ci
10213498266Sopenharmony_ci  /* Clean up any former leftovers and initialise to defaults */
10313498266Sopenharmony_ci  Curl_auth_cleanup_ntlm(ntlm);
10413498266Sopenharmony_ci
10513498266Sopenharmony_ci  /* Query the security package for NTLM */
10613498266Sopenharmony_ci  status = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(SP_NAME_NTLM),
10713498266Sopenharmony_ci                                              &SecurityPackage);
10813498266Sopenharmony_ci  if(status != SEC_E_OK) {
10913498266Sopenharmony_ci    failf(data, "SSPI: couldn't get auth info");
11013498266Sopenharmony_ci    return CURLE_AUTH_ERROR;
11113498266Sopenharmony_ci  }
11213498266Sopenharmony_ci
11313498266Sopenharmony_ci  ntlm->token_max = SecurityPackage->cbMaxToken;
11413498266Sopenharmony_ci
11513498266Sopenharmony_ci  /* Release the package buffer as it is not required anymore */
11613498266Sopenharmony_ci  s_pSecFn->FreeContextBuffer(SecurityPackage);
11713498266Sopenharmony_ci
11813498266Sopenharmony_ci  /* Allocate our output buffer */
11913498266Sopenharmony_ci  ntlm->output_token = malloc(ntlm->token_max);
12013498266Sopenharmony_ci  if(!ntlm->output_token)
12113498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
12213498266Sopenharmony_ci
12313498266Sopenharmony_ci  if(userp && *userp) {
12413498266Sopenharmony_ci    CURLcode result;
12513498266Sopenharmony_ci
12613498266Sopenharmony_ci    /* Populate our identity structure */
12713498266Sopenharmony_ci    result = Curl_create_sspi_identity(userp, passwdp, &ntlm->identity);
12813498266Sopenharmony_ci    if(result)
12913498266Sopenharmony_ci      return result;
13013498266Sopenharmony_ci
13113498266Sopenharmony_ci    /* Allow proper cleanup of the identity structure */
13213498266Sopenharmony_ci    ntlm->p_identity = &ntlm->identity;
13313498266Sopenharmony_ci  }
13413498266Sopenharmony_ci  else
13513498266Sopenharmony_ci    /* Use the current Windows user */
13613498266Sopenharmony_ci    ntlm->p_identity = NULL;
13713498266Sopenharmony_ci
13813498266Sopenharmony_ci  /* Allocate our credentials handle */
13913498266Sopenharmony_ci  ntlm->credentials = calloc(1, sizeof(CredHandle));
14013498266Sopenharmony_ci  if(!ntlm->credentials)
14113498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
14213498266Sopenharmony_ci
14313498266Sopenharmony_ci  /* Acquire our credentials handle */
14413498266Sopenharmony_ci  status = s_pSecFn->AcquireCredentialsHandle(NULL,
14513498266Sopenharmony_ci                                              (TCHAR *) TEXT(SP_NAME_NTLM),
14613498266Sopenharmony_ci                                              SECPKG_CRED_OUTBOUND, NULL,
14713498266Sopenharmony_ci                                              ntlm->p_identity, NULL, NULL,
14813498266Sopenharmony_ci                                              ntlm->credentials, &expiry);
14913498266Sopenharmony_ci  if(status != SEC_E_OK)
15013498266Sopenharmony_ci    return CURLE_LOGIN_DENIED;
15113498266Sopenharmony_ci
15213498266Sopenharmony_ci  /* Allocate our new context handle */
15313498266Sopenharmony_ci  ntlm->context = calloc(1, sizeof(CtxtHandle));
15413498266Sopenharmony_ci  if(!ntlm->context)
15513498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
15613498266Sopenharmony_ci
15713498266Sopenharmony_ci  ntlm->spn = Curl_auth_build_spn(service, host, NULL);
15813498266Sopenharmony_ci  if(!ntlm->spn)
15913498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
16013498266Sopenharmony_ci
16113498266Sopenharmony_ci  /* Setup the type-1 "output" security buffer */
16213498266Sopenharmony_ci  type_1_desc.ulVersion = SECBUFFER_VERSION;
16313498266Sopenharmony_ci  type_1_desc.cBuffers  = 1;
16413498266Sopenharmony_ci  type_1_desc.pBuffers  = &type_1_buf;
16513498266Sopenharmony_ci  type_1_buf.BufferType = SECBUFFER_TOKEN;
16613498266Sopenharmony_ci  type_1_buf.pvBuffer   = ntlm->output_token;
16713498266Sopenharmony_ci  type_1_buf.cbBuffer   = curlx_uztoul(ntlm->token_max);
16813498266Sopenharmony_ci
16913498266Sopenharmony_ci  /* Generate our type-1 message */
17013498266Sopenharmony_ci  status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
17113498266Sopenharmony_ci                                               ntlm->spn,
17213498266Sopenharmony_ci                                               0, 0, SECURITY_NETWORK_DREP,
17313498266Sopenharmony_ci                                               NULL, 0,
17413498266Sopenharmony_ci                                               ntlm->context, &type_1_desc,
17513498266Sopenharmony_ci                                               &attrs, &expiry);
17613498266Sopenharmony_ci  if(status == SEC_I_COMPLETE_NEEDED ||
17713498266Sopenharmony_ci    status == SEC_I_COMPLETE_AND_CONTINUE)
17813498266Sopenharmony_ci    s_pSecFn->CompleteAuthToken(ntlm->context, &type_1_desc);
17913498266Sopenharmony_ci  else if(status == SEC_E_INSUFFICIENT_MEMORY)
18013498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
18113498266Sopenharmony_ci  else if(status != SEC_E_OK && status != SEC_I_CONTINUE_NEEDED)
18213498266Sopenharmony_ci    return CURLE_AUTH_ERROR;
18313498266Sopenharmony_ci
18413498266Sopenharmony_ci  /* Return the response. */
18513498266Sopenharmony_ci  Curl_bufref_set(out, ntlm->output_token, type_1_buf.cbBuffer, NULL);
18613498266Sopenharmony_ci  return CURLE_OK;
18713498266Sopenharmony_ci}
18813498266Sopenharmony_ci
18913498266Sopenharmony_ci/*
19013498266Sopenharmony_ci * Curl_auth_decode_ntlm_type2_message()
19113498266Sopenharmony_ci *
19213498266Sopenharmony_ci * This is used to decode an already encoded NTLM type-2 message.
19313498266Sopenharmony_ci *
19413498266Sopenharmony_ci * Parameters:
19513498266Sopenharmony_ci *
19613498266Sopenharmony_ci * data     [in]     - The session handle.
19713498266Sopenharmony_ci * type2    [in]     - The type-2 message.
19813498266Sopenharmony_ci * ntlm     [in/out] - The NTLM data struct being used and modified.
19913498266Sopenharmony_ci *
20013498266Sopenharmony_ci * Returns CURLE_OK on success.
20113498266Sopenharmony_ci */
20213498266Sopenharmony_ciCURLcode Curl_auth_decode_ntlm_type2_message(struct Curl_easy *data,
20313498266Sopenharmony_ci                                             const struct bufref *type2,
20413498266Sopenharmony_ci                                             struct ntlmdata *ntlm)
20513498266Sopenharmony_ci{
20613498266Sopenharmony_ci#if defined(CURL_DISABLE_VERBOSE_STRINGS)
20713498266Sopenharmony_ci  (void) data;
20813498266Sopenharmony_ci#endif
20913498266Sopenharmony_ci
21013498266Sopenharmony_ci  /* Ensure we have a valid type-2 message */
21113498266Sopenharmony_ci  if(!Curl_bufref_len(type2)) {
21213498266Sopenharmony_ci    infof(data, "NTLM handshake failure (empty type-2 message)");
21313498266Sopenharmony_ci    return CURLE_BAD_CONTENT_ENCODING;
21413498266Sopenharmony_ci  }
21513498266Sopenharmony_ci
21613498266Sopenharmony_ci  /* Store the challenge for later use */
21713498266Sopenharmony_ci  ntlm->input_token = Curl_memdup0((const char *)Curl_bufref_ptr(type2),
21813498266Sopenharmony_ci                                   Curl_bufref_len(type2));
21913498266Sopenharmony_ci  if(!ntlm->input_token)
22013498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
22113498266Sopenharmony_ci  ntlm->input_token_len = Curl_bufref_len(type2);
22213498266Sopenharmony_ci
22313498266Sopenharmony_ci  return CURLE_OK;
22413498266Sopenharmony_ci}
22513498266Sopenharmony_ci
22613498266Sopenharmony_ci/*
22713498266Sopenharmony_ci* Curl_auth_create_ntlm_type3_message()
22813498266Sopenharmony_ci * Curl_auth_create_ntlm_type3_message()
22913498266Sopenharmony_ci *
23013498266Sopenharmony_ci * This is used to generate an already encoded NTLM type-3 message ready for
23113498266Sopenharmony_ci * sending to the recipient.
23213498266Sopenharmony_ci *
23313498266Sopenharmony_ci * Parameters:
23413498266Sopenharmony_ci *
23513498266Sopenharmony_ci * data    [in]     - The session handle.
23613498266Sopenharmony_ci * userp   [in]     - The user name in the format User or Domain\User.
23713498266Sopenharmony_ci * passwdp [in]     - The user's password.
23813498266Sopenharmony_ci * ntlm    [in/out] - The NTLM data struct being used and modified.
23913498266Sopenharmony_ci * out     [out]    - The result storage.
24013498266Sopenharmony_ci *
24113498266Sopenharmony_ci * Returns CURLE_OK on success.
24213498266Sopenharmony_ci */
24313498266Sopenharmony_ciCURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
24413498266Sopenharmony_ci                                             const char *userp,
24513498266Sopenharmony_ci                                             const char *passwdp,
24613498266Sopenharmony_ci                                             struct ntlmdata *ntlm,
24713498266Sopenharmony_ci                                             struct bufref *out)
24813498266Sopenharmony_ci{
24913498266Sopenharmony_ci  CURLcode result = CURLE_OK;
25013498266Sopenharmony_ci  SecBuffer type_2_bufs[2];
25113498266Sopenharmony_ci  SecBuffer type_3_buf;
25213498266Sopenharmony_ci  SecBufferDesc type_2_desc;
25313498266Sopenharmony_ci  SecBufferDesc type_3_desc;
25413498266Sopenharmony_ci  SECURITY_STATUS status;
25513498266Sopenharmony_ci  unsigned long attrs;
25613498266Sopenharmony_ci  TimeStamp expiry; /* For Windows 9x compatibility of SSPI calls */
25713498266Sopenharmony_ci
25813498266Sopenharmony_ci#if defined(CURL_DISABLE_VERBOSE_STRINGS)
25913498266Sopenharmony_ci  (void) data;
26013498266Sopenharmony_ci#endif
26113498266Sopenharmony_ci  (void) passwdp;
26213498266Sopenharmony_ci  (void) userp;
26313498266Sopenharmony_ci
26413498266Sopenharmony_ci  /* Setup the type-2 "input" security buffer */
26513498266Sopenharmony_ci  type_2_desc.ulVersion     = SECBUFFER_VERSION;
26613498266Sopenharmony_ci  type_2_desc.cBuffers      = 1;
26713498266Sopenharmony_ci  type_2_desc.pBuffers      = &type_2_bufs[0];
26813498266Sopenharmony_ci  type_2_bufs[0].BufferType = SECBUFFER_TOKEN;
26913498266Sopenharmony_ci  type_2_bufs[0].pvBuffer   = ntlm->input_token;
27013498266Sopenharmony_ci  type_2_bufs[0].cbBuffer   = curlx_uztoul(ntlm->input_token_len);
27113498266Sopenharmony_ci
27213498266Sopenharmony_ci#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
27313498266Sopenharmony_ci  /* ssl context comes from schannel.
27413498266Sopenharmony_ci  * When extended protection is used in IIS server,
27513498266Sopenharmony_ci  * we have to pass a second SecBuffer to the SecBufferDesc
27613498266Sopenharmony_ci  * otherwise IIS will not pass the authentication (401 response).
27713498266Sopenharmony_ci  * Minimum supported version is Windows 7.
27813498266Sopenharmony_ci  * https://docs.microsoft.com/en-us/security-updates
27913498266Sopenharmony_ci  * /SecurityAdvisories/2009/973811
28013498266Sopenharmony_ci  */
28113498266Sopenharmony_ci  if(ntlm->sslContext) {
28213498266Sopenharmony_ci    SEC_CHANNEL_BINDINGS channelBindings;
28313498266Sopenharmony_ci    SecPkgContext_Bindings pkgBindings;
28413498266Sopenharmony_ci    pkgBindings.Bindings = &channelBindings;
28513498266Sopenharmony_ci    status = s_pSecFn->QueryContextAttributes(
28613498266Sopenharmony_ci      ntlm->sslContext,
28713498266Sopenharmony_ci      SECPKG_ATTR_ENDPOINT_BINDINGS,
28813498266Sopenharmony_ci      &pkgBindings
28913498266Sopenharmony_ci    );
29013498266Sopenharmony_ci    if(status == SEC_E_OK) {
29113498266Sopenharmony_ci      type_2_desc.cBuffers++;
29213498266Sopenharmony_ci      type_2_bufs[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
29313498266Sopenharmony_ci      type_2_bufs[1].cbBuffer = pkgBindings.BindingsLength;
29413498266Sopenharmony_ci      type_2_bufs[1].pvBuffer = pkgBindings.Bindings;
29513498266Sopenharmony_ci    }
29613498266Sopenharmony_ci  }
29713498266Sopenharmony_ci#endif
29813498266Sopenharmony_ci
29913498266Sopenharmony_ci  /* Setup the type-3 "output" security buffer */
30013498266Sopenharmony_ci  type_3_desc.ulVersion = SECBUFFER_VERSION;
30113498266Sopenharmony_ci  type_3_desc.cBuffers  = 1;
30213498266Sopenharmony_ci  type_3_desc.pBuffers  = &type_3_buf;
30313498266Sopenharmony_ci  type_3_buf.BufferType = SECBUFFER_TOKEN;
30413498266Sopenharmony_ci  type_3_buf.pvBuffer   = ntlm->output_token;
30513498266Sopenharmony_ci  type_3_buf.cbBuffer   = curlx_uztoul(ntlm->token_max);
30613498266Sopenharmony_ci
30713498266Sopenharmony_ci  /* Generate our type-3 message */
30813498266Sopenharmony_ci  status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
30913498266Sopenharmony_ci                                               ntlm->context,
31013498266Sopenharmony_ci                                               ntlm->spn,
31113498266Sopenharmony_ci                                               0, 0, SECURITY_NETWORK_DREP,
31213498266Sopenharmony_ci                                               &type_2_desc,
31313498266Sopenharmony_ci                                               0, ntlm->context,
31413498266Sopenharmony_ci                                               &type_3_desc,
31513498266Sopenharmony_ci                                               &attrs, &expiry);
31613498266Sopenharmony_ci  if(status != SEC_E_OK) {
31713498266Sopenharmony_ci    infof(data, "NTLM handshake failure (type-3 message): Status=%lx",
31813498266Sopenharmony_ci          status);
31913498266Sopenharmony_ci
32013498266Sopenharmony_ci    if(status == SEC_E_INSUFFICIENT_MEMORY)
32113498266Sopenharmony_ci      return CURLE_OUT_OF_MEMORY;
32213498266Sopenharmony_ci
32313498266Sopenharmony_ci    return CURLE_AUTH_ERROR;
32413498266Sopenharmony_ci  }
32513498266Sopenharmony_ci
32613498266Sopenharmony_ci  /* Return the response. */
32713498266Sopenharmony_ci  result = Curl_bufref_memdup(out, ntlm->output_token, type_3_buf.cbBuffer);
32813498266Sopenharmony_ci  Curl_auth_cleanup_ntlm(ntlm);
32913498266Sopenharmony_ci  return result;
33013498266Sopenharmony_ci}
33113498266Sopenharmony_ci
33213498266Sopenharmony_ci/*
33313498266Sopenharmony_ci * Curl_auth_cleanup_ntlm()
33413498266Sopenharmony_ci *
33513498266Sopenharmony_ci * This is used to clean up the NTLM specific data.
33613498266Sopenharmony_ci *
33713498266Sopenharmony_ci * Parameters:
33813498266Sopenharmony_ci *
33913498266Sopenharmony_ci * ntlm    [in/out] - The NTLM data struct being cleaned up.
34013498266Sopenharmony_ci *
34113498266Sopenharmony_ci */
34213498266Sopenharmony_civoid Curl_auth_cleanup_ntlm(struct ntlmdata *ntlm)
34313498266Sopenharmony_ci{
34413498266Sopenharmony_ci  /* Free our security context */
34513498266Sopenharmony_ci  if(ntlm->context) {
34613498266Sopenharmony_ci    s_pSecFn->DeleteSecurityContext(ntlm->context);
34713498266Sopenharmony_ci    free(ntlm->context);
34813498266Sopenharmony_ci    ntlm->context = NULL;
34913498266Sopenharmony_ci  }
35013498266Sopenharmony_ci
35113498266Sopenharmony_ci  /* Free our credentials handle */
35213498266Sopenharmony_ci  if(ntlm->credentials) {
35313498266Sopenharmony_ci    s_pSecFn->FreeCredentialsHandle(ntlm->credentials);
35413498266Sopenharmony_ci    free(ntlm->credentials);
35513498266Sopenharmony_ci    ntlm->credentials = NULL;
35613498266Sopenharmony_ci  }
35713498266Sopenharmony_ci
35813498266Sopenharmony_ci  /* Free our identity */
35913498266Sopenharmony_ci  Curl_sspi_free_identity(ntlm->p_identity);
36013498266Sopenharmony_ci  ntlm->p_identity = NULL;
36113498266Sopenharmony_ci
36213498266Sopenharmony_ci  /* Free the input and output tokens */
36313498266Sopenharmony_ci  Curl_safefree(ntlm->input_token);
36413498266Sopenharmony_ci  Curl_safefree(ntlm->output_token);
36513498266Sopenharmony_ci
36613498266Sopenharmony_ci  /* Reset any variables */
36713498266Sopenharmony_ci  ntlm->token_max = 0;
36813498266Sopenharmony_ci
36913498266Sopenharmony_ci  Curl_safefree(ntlm->spn);
37013498266Sopenharmony_ci}
37113498266Sopenharmony_ci
37213498266Sopenharmony_ci#endif /* USE_WINDOWS_SSPI && USE_NTLM */
373