windows: reduce/stop loading DLLs at runtime

- replace dynamic `InitSecurityInterface()` call with early binding and
  link `secur32` system DLL.
  The library and function are available in all supported curl Windows
  targets, meaning WinXP or newer.  Add small hack for mingw32ce to
  make it build.

- detect and use `if_nametoindex()` on Windows when available. Link
  `iphlpapi` system DLL. Requires targeting Vista or newer.
  Replacing the dynamic call and the pre-load optimization for lib3026.

Suggested-by: Jay Satiro

Closes #17413
This commit is contained in:
Viktor Szakats 2025-05-21 19:37:55 +02:00
parent c129d0b1a8
commit 0d71b18153
No known key found for this signature in database
GPG key ID: B5ABD165E2AEF201
16 changed files with 186 additions and 182 deletions

View file

@ -37,23 +37,6 @@
#include "curl_memory.h"
#include "memdebug.h"
/* We use our own typedef here since some headers might lack these */
typedef PSecurityFunctionTable (APIENTRY *INITSECURITYINTERFACE_FN)(VOID);
/* See definition of SECURITY_ENTRYPOINT in sspi.h */
#ifdef UNICODE
# ifdef UNDER_CE
# define SECURITYENTRYPOINT L"InitSecurityInterfaceW"
# else
# define SECURITYENTRYPOINT "InitSecurityInterfaceW"
# endif
#else
# define SECURITYENTRYPOINT "InitSecurityInterfaceA"
#endif
/* Handle of security.dll or secur32.dll, depending on Windows version */
HMODULE Curl_hSecDll = NULL;
/* Pointer to SSPI dispatch table */
PSecurityFunctionTable Curl_pSecFn = NULL;
@ -76,31 +59,14 @@ PSecurityFunctionTable Curl_pSecFn = NULL;
*/
CURLcode Curl_sspi_global_init(void)
{
INITSECURITYINTERFACE_FN pInitSecurityInterface;
/* If security interface is not yet initialized try to do this */
if(!Curl_hSecDll) {
/* Security Service Provider Interface (SSPI) functions are located in
* security.dll on WinNT 4.0 and in secur32.dll on Win9x. Win2K and XP
* have both these DLLs (security.dll forwards calls to secur32.dll) */
/* Load SSPI dll into the address space of the calling process */
if(curlx_verify_windows_version(4, 0, 0, PLATFORM_WINNT, VERSION_EQUAL))
Curl_hSecDll = Curl_load_library(TEXT("security.dll"));
else
Curl_hSecDll = Curl_load_library(TEXT("secur32.dll"));
if(!Curl_hSecDll)
return CURLE_FAILED_INIT;
/* Get address of the InitSecurityInterfaceA function from the SSPI dll */
pInitSecurityInterface =
CURLX_FUNCTION_CAST(INITSECURITYINTERFACE_FN,
(GetProcAddress(Curl_hSecDll, SECURITYENTRYPOINT)));
if(!pInitSecurityInterface)
return CURLE_FAILED_INIT;
if(!Curl_pSecFn) {
/* Get pointer to Security Service Provider Interface dispatch table */
Curl_pSecFn = pInitSecurityInterface();
#ifdef __MINGW32CE__
Curl_pSecFn = InitSecurityInterfaceW();
#else
Curl_pSecFn = InitSecurityInterface();
#endif
if(!Curl_pSecFn)
return CURLE_FAILED_INIT;
}
@ -119,9 +85,7 @@ CURLcode Curl_sspi_global_init(void)
*/
void Curl_sspi_global_cleanup(void)
{
if(Curl_hSecDll) {
FreeLibrary(Curl_hSecDll);
Curl_hSecDll = NULL;
if(Curl_pSecFn) {
Curl_pSecFn = NULL;
}
}

View file

@ -57,7 +57,6 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
void Curl_sspi_free_identity(SEC_WINNT_AUTH_IDENTITY *identity);
/* Forward-declaration of global variables defined in curl_sspi.c */
extern HMODULE Curl_hSecDll;
extern PSecurityFunctionTable Curl_pSecFn;
/* Provide some definitions missing in old headers */

View file

@ -178,10 +178,10 @@ CURLcode Curl_output_ntlm(struct Curl_easy *data, bool proxy)
passwdp = "";
#ifdef USE_WINDOWS_SSPI
if(!Curl_hSecDll) {
if(!Curl_pSecFn) {
/* not thread safe and leaks - use curl_global_init() to avoid */
CURLcode err = Curl_sspi_global_init();
if(!Curl_hSecDll)
if(!Curl_pSecFn)
return err;
}
#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS

View file

@ -36,12 +36,17 @@
#include "curl_memory.h"
#include "memdebug.h"
#ifndef HAVE_IF_NAMETOINDEX
/* Handle of iphlpapp.dll */
static HMODULE s_hIpHlpApiDll = NULL;
/* Pointer to the if_nametoindex function */
IF_NAMETOINDEX_FN Curl_if_nametoindex = NULL;
/* This is used to dynamically load DLLs */
static HMODULE curl_load_library(LPCTSTR filename);
#endif
/* Curl_win32_init() performs Win32 global initialization */
CURLcode Curl_win32_init(long flags)
{
@ -90,7 +95,8 @@ CURLcode Curl_win32_init(long flags)
}
#endif
s_hIpHlpApiDll = Curl_load_library(TEXT("iphlpapi.dll"));
#ifndef HAVE_IF_NAMETOINDEX
s_hIpHlpApiDll = curl_load_library(TEXT("iphlpapi.dll"));
if(s_hIpHlpApiDll) {
/* Get the address of the if_nametoindex function */
#ifdef UNDER_CE
@ -106,6 +112,7 @@ CURLcode Curl_win32_init(long flags)
if(pIfNameToIndex)
Curl_if_nametoindex = pIfNameToIndex;
}
#endif
/* curlx_verify_windows_version must be called during init at least once
because it has its own initialization routine. */
@ -123,11 +130,13 @@ CURLcode Curl_win32_init(long flags)
/* Curl_win32_cleanup() is the opposite of Curl_win32_init() */
void Curl_win32_cleanup(long init_flags)
{
#ifndef HAVE_IF_NAMETOINDEX
if(s_hIpHlpApiDll) {
FreeLibrary(s_hIpHlpApiDll);
s_hIpHlpApiDll = NULL;
Curl_if_nametoindex = NULL;
}
#endif
#ifdef USE_WINDOWS_SSPI
Curl_sspi_global_cleanup();
@ -140,11 +149,13 @@ void Curl_win32_cleanup(long init_flags)
}
}
#if !defined(LOAD_WITH_ALTERED_SEARCH_PATH)
#ifndef HAVE_IF_NAMETOINDEX
#ifndef LOAD_WITH_ALTERED_SEARCH_PATH
#define LOAD_WITH_ALTERED_SEARCH_PATH 0x00000008
#endif
#if !defined(LOAD_LIBRARY_SEARCH_SYSTEM32)
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
#endif
@ -163,7 +174,7 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
#endif
/*
* Curl_load_library()
* curl_load_library()
*
* This is used to dynamically load DLLs using the most secure method available
* for the version of Windows that we are running on.
@ -176,7 +187,7 @@ typedef HMODULE (APIENTRY *LOADLIBRARYEX_FN)(LPCTSTR, HANDLE, DWORD);
*
* Returns the handle of the module on success; otherwise NULL.
*/
HMODULE Curl_load_library(LPCTSTR filename)
static HMODULE curl_load_library(LPCTSTR filename)
{
#if !defined(CURL_WINDOWS_UWP) && !defined(UNDER_CE)
HMODULE hModule = NULL;
@ -228,7 +239,6 @@ HMODULE Curl_load_library(LPCTSTR filename)
hModule = pLoadLibraryEx ?
pLoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH) :
LoadLibrary(path);
}
free(path);
}
@ -240,5 +250,6 @@ HMODULE Curl_load_library(LPCTSTR filename)
return NULL;
#endif
}
#endif /* !HAVE_IF_NAMETOINDEX */
#endif /* _WIN32 */

View file

@ -36,14 +36,13 @@ extern bool Curl_isVistaOrGreater;
CURLcode Curl_win32_init(long flags);
void Curl_win32_cleanup(long init_flags);
#ifndef HAVE_IF_NAMETOINDEX
/* We use our own typedef here since some headers might lack this */
typedef unsigned int(WINAPI *IF_NAMETOINDEX_FN)(const char *);
/* This is used instead of if_nametoindex if available on Windows */
extern IF_NAMETOINDEX_FN Curl_if_nametoindex;
/* This is used to dynamically load DLLs */
HMODULE Curl_load_library(LPCTSTR filename);
#endif
#else /* _WIN32 */
#define Curl_win32_init(x) CURLE_OK
#endif /* !_WIN32 */

View file

@ -59,6 +59,10 @@
#error "We cannot compile without socket() support!"
#endif
#if defined(HAVE_IF_NAMETOINDEX) && defined(_WIN32)
#include <iphlpapi.h>
#endif
#include <limits.h>
#include "doh.h"
@ -1794,10 +1798,10 @@ static void zonefrom_url(CURLU *uh, struct Curl_easy *data,
#if defined(HAVE_IF_NAMETOINDEX) || defined(_WIN32)
/* Zone identifier is not numeric */
unsigned int scopeidx = 0;
#ifdef _WIN32
scopeidx = Curl_if_nametoindex(zoneid);
#else
#ifdef HAVE_IF_NAMETOINDEX
scopeidx = if_nametoindex(zoneid);
#else
scopeidx = Curl_if_nametoindex(zoneid);
#endif
if(!scopeidx) {
#ifndef CURL_DISABLE_VERBOSE_STRINGS