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#ifdef USE_WINDOWS_SSPI
2813498266Sopenharmony_ci
2913498266Sopenharmony_ci#include <curl/curl.h>
3013498266Sopenharmony_ci#include "curl_sspi.h"
3113498266Sopenharmony_ci#include "curl_multibyte.h"
3213498266Sopenharmony_ci#include "system_win32.h"
3313498266Sopenharmony_ci#include "version_win32.h"
3413498266Sopenharmony_ci#include "warnless.h"
3513498266Sopenharmony_ci
3613498266Sopenharmony_ci/* The last #include files should be: */
3713498266Sopenharmony_ci#include "curl_memory.h"
3813498266Sopenharmony_ci#include "memdebug.h"
3913498266Sopenharmony_ci
4013498266Sopenharmony_ci/* We use our own typedef here since some headers might lack these */
4113498266Sopenharmony_citypedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
4213498266Sopenharmony_ci
4313498266Sopenharmony_ci/* See definition of SECURITY_ENTRYPOINT in sspi.h */
4413498266Sopenharmony_ci#ifdef UNICODE
4513498266Sopenharmony_ci#  ifdef _WIN32_WCE
4613498266Sopenharmony_ci#    define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
4713498266Sopenharmony_ci#  else
4813498266Sopenharmony_ci#    define SECURITYENTRYPOINT "InitSecurityInterfaceW"
4913498266Sopenharmony_ci#  endif
5013498266Sopenharmony_ci#else
5113498266Sopenharmony_ci#  define SECURITYENTRYPOINT "InitSecurityInterfaceA"
5213498266Sopenharmony_ci#endif
5313498266Sopenharmony_ci
5413498266Sopenharmony_ci/* Handle of security.dll or secur32.dll, depending on Windows version */
5513498266Sopenharmony_ciHMODULE s_hSecDll = NULL;
5613498266Sopenharmony_ci
5713498266Sopenharmony_ci/* Pointer to SSPI dispatch table */
5813498266Sopenharmony_ciPSecurityFunctionTable s_pSecFn = NULL;
5913498266Sopenharmony_ci
6013498266Sopenharmony_ci/*
6113498266Sopenharmony_ci * Curl_sspi_global_init()
6213498266Sopenharmony_ci *
6313498266Sopenharmony_ci * This is used to load the Security Service Provider Interface (SSPI)
6413498266Sopenharmony_ci * dynamic link library portably across all Windows versions, without
6513498266Sopenharmony_ci * the need to directly link libcurl, nor the application using it, at
6613498266Sopenharmony_ci * build time.
6713498266Sopenharmony_ci *
6813498266Sopenharmony_ci * Once this function has been executed, Windows SSPI functions can be
6913498266Sopenharmony_ci * called through the Security Service Provider Interface dispatch table.
7013498266Sopenharmony_ci *
7113498266Sopenharmony_ci * Parameters:
7213498266Sopenharmony_ci *
7313498266Sopenharmony_ci * None.
7413498266Sopenharmony_ci *
7513498266Sopenharmony_ci * Returns CURLE_OK on success.
7613498266Sopenharmony_ci */
7713498266Sopenharmony_ciCURLcode Curl_sspi_global_init(void)
7813498266Sopenharmony_ci{
7913498266Sopenharmony_ci  INITSECURITYINTERFACE_FN pInitSecurityInterface;
8013498266Sopenharmony_ci
8113498266Sopenharmony_ci  /* If security interface is not yet initialized try to do this */
8213498266Sopenharmony_ci  if(!s_hSecDll) {
8313498266Sopenharmony_ci    /* Security Service Provider Interface (SSPI) functions are located in
8413498266Sopenharmony_ci     * security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
8513498266Sopenharmony_ci     * have both these DLLs (security.dll forwards calls to secur32.dll) */
8613498266Sopenharmony_ci
8713498266Sopenharmony_ci    /* Load SSPI dll into the address space of the calling process */
8813498266Sopenharmony_ci    if(curlx_verify_windows_version(4, 0, 0, PLATFORM_WINNT, VERSION_EQUAL))
8913498266Sopenharmony_ci      s_hSecDll = Curl_load_library(TEXT("security.dll"));
9013498266Sopenharmony_ci    else
9113498266Sopenharmony_ci      s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
9213498266Sopenharmony_ci    if(!s_hSecDll)
9313498266Sopenharmony_ci      return CURLE_FAILED_INIT;
9413498266Sopenharmony_ci
9513498266Sopenharmony_ci    /* Get address of the InitSecurityInterfaceA function from the SSPI dll */
9613498266Sopenharmony_ci    pInitSecurityInterface =
9713498266Sopenharmony_ci      CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN,
9813498266Sopenharmony_ci                          (GetProcAddress(s_hSecDll, SECURITYENTRYPOINT)));
9913498266Sopenharmony_ci    if(!pInitSecurityInterface)
10013498266Sopenharmony_ci      return CURLE_FAILED_INIT;
10113498266Sopenharmony_ci
10213498266Sopenharmony_ci    /* Get pointer to Security Service Provider Interface dispatch table */
10313498266Sopenharmony_ci    s_pSecFn = pInitSecurityInterface();
10413498266Sopenharmony_ci    if(!s_pSecFn)
10513498266Sopenharmony_ci      return CURLE_FAILED_INIT;
10613498266Sopenharmony_ci  }
10713498266Sopenharmony_ci
10813498266Sopenharmony_ci  return CURLE_OK;
10913498266Sopenharmony_ci}
11013498266Sopenharmony_ci
11113498266Sopenharmony_ci/*
11213498266Sopenharmony_ci * Curl_sspi_global_cleanup()
11313498266Sopenharmony_ci *
11413498266Sopenharmony_ci * This deinitializes the Security Service Provider Interface from libcurl.
11513498266Sopenharmony_ci *
11613498266Sopenharmony_ci * Parameters:
11713498266Sopenharmony_ci *
11813498266Sopenharmony_ci * None.
11913498266Sopenharmony_ci */
12013498266Sopenharmony_civoid Curl_sspi_global_cleanup(void)
12113498266Sopenharmony_ci{
12213498266Sopenharmony_ci  if(s_hSecDll) {
12313498266Sopenharmony_ci    FreeLibrary(s_hSecDll);
12413498266Sopenharmony_ci    s_hSecDll = NULL;
12513498266Sopenharmony_ci    s_pSecFn = NULL;
12613498266Sopenharmony_ci  }
12713498266Sopenharmony_ci}
12813498266Sopenharmony_ci
12913498266Sopenharmony_ci/*
13013498266Sopenharmony_ci * Curl_create_sspi_identity()
13113498266Sopenharmony_ci *
13213498266Sopenharmony_ci * This is used to populate a SSPI identity structure based on the supplied
13313498266Sopenharmony_ci * username and password.
13413498266Sopenharmony_ci *
13513498266Sopenharmony_ci * Parameters:
13613498266Sopenharmony_ci *
13713498266Sopenharmony_ci * userp    [in]     - The user name in the format User or Domain\User.
13813498266Sopenharmony_ci * passwdp  [in]     - The user's password.
13913498266Sopenharmony_ci * identity [in/out] - The identity structure.
14013498266Sopenharmony_ci *
14113498266Sopenharmony_ci * Returns CURLE_OK on success.
14213498266Sopenharmony_ci */
14313498266Sopenharmony_ciCURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
14413498266Sopenharmony_ci                                   SEC_WINNT_AUTH_IDENTITY *identity)
14513498266Sopenharmony_ci{
14613498266Sopenharmony_ci  xcharp_u useranddomain;
14713498266Sopenharmony_ci  xcharp_u user, dup_user;
14813498266Sopenharmony_ci  xcharp_u domain, dup_domain;
14913498266Sopenharmony_ci  xcharp_u passwd, dup_passwd;
15013498266Sopenharmony_ci  size_t domlen = 0;
15113498266Sopenharmony_ci
15213498266Sopenharmony_ci  domain.const_tchar_ptr = TEXT("");
15313498266Sopenharmony_ci
15413498266Sopenharmony_ci  /* Initialize the identity */
15513498266Sopenharmony_ci  memset(identity, 0, sizeof(*identity));
15613498266Sopenharmony_ci
15713498266Sopenharmony_ci  useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)userp);
15813498266Sopenharmony_ci  if(!useranddomain.tchar_ptr)
15913498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
16013498266Sopenharmony_ci
16113498266Sopenharmony_ci  user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('\\'));
16213498266Sopenharmony_ci  if(!user.const_tchar_ptr)
16313498266Sopenharmony_ci    user.const_tchar_ptr = _tcschr(useranddomain.const_tchar_ptr, TEXT('/'));
16413498266Sopenharmony_ci
16513498266Sopenharmony_ci  if(user.tchar_ptr) {
16613498266Sopenharmony_ci    domain.tchar_ptr = useranddomain.tchar_ptr;
16713498266Sopenharmony_ci    domlen = user.tchar_ptr - useranddomain.tchar_ptr;
16813498266Sopenharmony_ci    user.tchar_ptr++;
16913498266Sopenharmony_ci  }
17013498266Sopenharmony_ci  else {
17113498266Sopenharmony_ci    user.tchar_ptr = useranddomain.tchar_ptr;
17213498266Sopenharmony_ci    domain.const_tchar_ptr = TEXT("");
17313498266Sopenharmony_ci    domlen = 0;
17413498266Sopenharmony_ci  }
17513498266Sopenharmony_ci
17613498266Sopenharmony_ci  /* Setup the identity's user and length */
17713498266Sopenharmony_ci  dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
17813498266Sopenharmony_ci  if(!dup_user.tchar_ptr) {
17913498266Sopenharmony_ci    curlx_unicodefree(useranddomain.tchar_ptr);
18013498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
18113498266Sopenharmony_ci  }
18213498266Sopenharmony_ci  identity->User = dup_user.tbyte_ptr;
18313498266Sopenharmony_ci  identity->UserLength = curlx_uztoul(_tcslen(dup_user.tchar_ptr));
18413498266Sopenharmony_ci  dup_user.tchar_ptr = NULL;
18513498266Sopenharmony_ci
18613498266Sopenharmony_ci  /* Setup the identity's domain and length */
18713498266Sopenharmony_ci  dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
18813498266Sopenharmony_ci  if(!dup_domain.tchar_ptr) {
18913498266Sopenharmony_ci    curlx_unicodefree(useranddomain.tchar_ptr);
19013498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
19113498266Sopenharmony_ci  }
19213498266Sopenharmony_ci  _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
19313498266Sopenharmony_ci  *(dup_domain.tchar_ptr + domlen) = TEXT('\0');
19413498266Sopenharmony_ci  identity->Domain = dup_domain.tbyte_ptr;
19513498266Sopenharmony_ci  identity->DomainLength = curlx_uztoul(domlen);
19613498266Sopenharmony_ci  dup_domain.tchar_ptr = NULL;
19713498266Sopenharmony_ci
19813498266Sopenharmony_ci  curlx_unicodefree(useranddomain.tchar_ptr);
19913498266Sopenharmony_ci
20013498266Sopenharmony_ci  /* Setup the identity's password and length */
20113498266Sopenharmony_ci  passwd.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)passwdp);
20213498266Sopenharmony_ci  if(!passwd.tchar_ptr)
20313498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
20413498266Sopenharmony_ci  dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
20513498266Sopenharmony_ci  if(!dup_passwd.tchar_ptr) {
20613498266Sopenharmony_ci    curlx_unicodefree(passwd.tchar_ptr);
20713498266Sopenharmony_ci    return CURLE_OUT_OF_MEMORY;
20813498266Sopenharmony_ci  }
20913498266Sopenharmony_ci  identity->Password = dup_passwd.tbyte_ptr;
21013498266Sopenharmony_ci  identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
21113498266Sopenharmony_ci  dup_passwd.tchar_ptr = NULL;
21213498266Sopenharmony_ci
21313498266Sopenharmony_ci  curlx_unicodefree(passwd.tchar_ptr);
21413498266Sopenharmony_ci
21513498266Sopenharmony_ci  /* Setup the identity's flags */
21613498266Sopenharmony_ci  identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;
21713498266Sopenharmony_ci
21813498266Sopenharmony_ci  return CURLE_OK;
21913498266Sopenharmony_ci}
22013498266Sopenharmony_ci
22113498266Sopenharmony_ci/*
22213498266Sopenharmony_ci * Curl_sspi_free_identity()
22313498266Sopenharmony_ci *
22413498266Sopenharmony_ci * This is used to free the contents of a SSPI identifier structure.
22513498266Sopenharmony_ci *
22613498266Sopenharmony_ci * Parameters:
22713498266Sopenharmony_ci *
22813498266Sopenharmony_ci * identity [in/out] - The identity structure.
22913498266Sopenharmony_ci */
23013498266Sopenharmony_civoid Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity)
23113498266Sopenharmony_ci{
23213498266Sopenharmony_ci  if(identity) {
23313498266Sopenharmony_ci    Curl_safefree(identity->User);
23413498266Sopenharmony_ci    Curl_safefree(identity->Password);
23513498266Sopenharmony_ci    Curl_safefree(identity->Domain);
23613498266Sopenharmony_ci  }
23713498266Sopenharmony_ci}
23813498266Sopenharmony_ci
23913498266Sopenharmony_ci#endif /* USE_WINDOWS_SSPI */
240