version_win32: Check build number and platform id
Prior to this change the build number was not checked during version comparison, and the platform id was supposed to be checked but wasn't. Checking the build number is required for enabling "evergreen" Windows 10/11 features (like TLS 1.3). Ref: https://github.com/curl/curl/pull/7784 Closes https://github.com/curl/curl/pull/7824 Closes https://github.com/curl/curl/pull/7867
This commit is contained in:
parent
3467e89bb9
commit
7da636cad5
@ -1127,7 +1127,7 @@ void Curl_sndbufset(curl_socket_t sockfd)
|
||||
static int detectOsState = DETECT_OS_NONE;
|
||||
|
||||
if(detectOsState == DETECT_OS_NONE) {
|
||||
if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
|
||||
if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL))
|
||||
detectOsState = DETECT_OS_VISTA_OR_LATER;
|
||||
else
|
||||
|
||||
@ -83,7 +83,7 @@ CURLcode Curl_sspi_global_init(void)
|
||||
* 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, PLATFORM_WINNT, VERSION_EQUAL))
|
||||
if(curlx_verify_windows_version(4, 0, 0, PLATFORM_WINNT, VERSION_EQUAL))
|
||||
s_hSecDll = Curl_load_library(TEXT("security.dll"));
|
||||
else
|
||||
s_hSecDll = Curl_load_library(TEXT("secur32.dll"));
|
||||
|
||||
@ -104,7 +104,7 @@ CURLcode Curl_win32_init(long flags)
|
||||
|
||||
/* curlx_verify_windows_version must be called during init at least once
|
||||
because it has its own initialization routine. */
|
||||
if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
|
||||
if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL)) {
|
||||
Curl_isVistaOrGreater = TRUE;
|
||||
}
|
||||
|
||||
@ -57,6 +57,8 @@ struct OUR_OSVERSIONINFOEXW {
|
||||
*
|
||||
* majorVersion [in] - The major version number.
|
||||
* minorVersion [in] - The minor version number.
|
||||
* buildVersion [in] - The build version number. If 0, this parameter is
|
||||
* ignored.
|
||||
* platform [in] - The optional platform identifier.
|
||||
* condition [in] - The test condition used to specifier whether we are
|
||||
* checking a version less then, equal to or greater than
|
||||
@ -67,6 +69,7 @@ struct OUR_OSVERSIONINFOEXW {
|
||||
*/
|
||||
bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
const unsigned int minorVersion,
|
||||
const unsigned int buildVersion,
|
||||
const PlatformIdentifier platform,
|
||||
const VersionCondition condition)
|
||||
{
|
||||
@ -118,34 +121,52 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case VERSION_LESS_THAN:
|
||||
if(osver.dwMajorVersion < majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion < minorVersion))
|
||||
osver.dwMinorVersion < minorVersion) ||
|
||||
(buildVersion != 0 &&
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
osver.dwBuildNumber < buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_LESS_THAN_EQUAL:
|
||||
if(osver.dwMajorVersion < majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion <= minorVersion))
|
||||
osver.dwMinorVersion < minorVersion) ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
(buildVersion == 0 ||
|
||||
osver.dwBuildNumber <= buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_EQUAL:
|
||||
if(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion)
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
(buildVersion == 0 ||
|
||||
osver.dwBuildNumber == buildVersion))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_GREATER_THAN_EQUAL:
|
||||
if(osver.dwMajorVersion > majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion >= minorVersion))
|
||||
osver.dwMinorVersion > minorVersion) ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
(buildVersion == 0 ||
|
||||
osver.dwBuildNumber >= buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
|
||||
case VERSION_GREATER_THAN:
|
||||
if(osver.dwMajorVersion > majorVersion ||
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion > minorVersion))
|
||||
osver.dwMinorVersion > minorVersion) ||
|
||||
(buildVersion != 0 &&
|
||||
(osver.dwMajorVersion == majorVersion &&
|
||||
osver.dwMinorVersion == minorVersion &&
|
||||
osver.dwBuildNumber > buildVersion)))
|
||||
matched = TRUE;
|
||||
break;
|
||||
}
|
||||
@ -161,6 +182,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case PLATFORM_WINNT:
|
||||
if(osver.dwPlatformId != VER_PLATFORM_WIN32_NT)
|
||||
matched = FALSE;
|
||||
break;
|
||||
|
||||
default: /* like platform == PLATFORM_DONT_CARE */
|
||||
break;
|
||||
@ -172,8 +194,11 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
struct OUR_OSVERSIONINFOEXW osver;
|
||||
BYTE majorCondition;
|
||||
BYTE minorCondition;
|
||||
BYTE buildCondition;
|
||||
BYTE spMajorCondition;
|
||||
BYTE spMinorCondition;
|
||||
DWORD dwTypeMask = VER_MAJORVERSION | VER_MINORVERSION |
|
||||
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR;
|
||||
|
||||
typedef LONG (APIENTRY *RTLVERIFYVERSIONINFO_FN)
|
||||
(struct OUR_OSVERSIONINFOEXW *, ULONG, ULONGLONG);
|
||||
@ -190,6 +215,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case VERSION_LESS_THAN:
|
||||
majorCondition = VER_LESS;
|
||||
minorCondition = VER_LESS;
|
||||
buildCondition = VER_LESS;
|
||||
spMajorCondition = VER_LESS_EQUAL;
|
||||
spMinorCondition = VER_LESS_EQUAL;
|
||||
break;
|
||||
@ -197,6 +223,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case VERSION_LESS_THAN_EQUAL:
|
||||
majorCondition = VER_LESS_EQUAL;
|
||||
minorCondition = VER_LESS_EQUAL;
|
||||
buildCondition = VER_LESS_EQUAL;
|
||||
spMajorCondition = VER_LESS_EQUAL;
|
||||
spMinorCondition = VER_LESS_EQUAL;
|
||||
break;
|
||||
@ -204,6 +231,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case VERSION_EQUAL:
|
||||
majorCondition = VER_EQUAL;
|
||||
minorCondition = VER_EQUAL;
|
||||
buildCondition = VER_EQUAL;
|
||||
spMajorCondition = VER_GREATER_EQUAL;
|
||||
spMinorCondition = VER_GREATER_EQUAL;
|
||||
break;
|
||||
@ -211,6 +239,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case VERSION_GREATER_THAN_EQUAL:
|
||||
majorCondition = VER_GREATER_EQUAL;
|
||||
minorCondition = VER_GREATER_EQUAL;
|
||||
buildCondition = VER_GREATER_EQUAL;
|
||||
spMajorCondition = VER_GREATER_EQUAL;
|
||||
spMinorCondition = VER_GREATER_EQUAL;
|
||||
break;
|
||||
@ -218,6 +247,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
case VERSION_GREATER_THAN:
|
||||
majorCondition = VER_GREATER;
|
||||
minorCondition = VER_GREATER;
|
||||
buildCondition = VER_GREATER;
|
||||
spMajorCondition = VER_GREATER_EQUAL;
|
||||
spMinorCondition = VER_GREATER_EQUAL;
|
||||
break;
|
||||
@ -230,6 +260,7 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
osver.dwOSVersionInfoSize = sizeof(osver);
|
||||
osver.dwMajorVersion = majorVersion;
|
||||
osver.dwMinorVersion = minorVersion;
|
||||
osver.dwBuildNumber = buildVersion;
|
||||
if(platform == PLATFORM_WINDOWS)
|
||||
osver.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS;
|
||||
else if(platform == PLATFORM_WINNT)
|
||||
@ -239,26 +270,43 @@ bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
cm = VerSetConditionMask(cm, VER_MINORVERSION, minorCondition);
|
||||
cm = VerSetConditionMask(cm, VER_SERVICEPACKMAJOR, spMajorCondition);
|
||||
cm = VerSetConditionMask(cm, VER_SERVICEPACKMINOR, spMinorCondition);
|
||||
if(platform != PLATFORM_DONT_CARE)
|
||||
|
||||
if(platform != PLATFORM_DONT_CARE) {
|
||||
cm = VerSetConditionMask(cm, VER_PLATFORMID, VER_EQUAL);
|
||||
dwTypeMask |= VER_PLATFORMID;
|
||||
}
|
||||
|
||||
/* Later versions of Windows have version functions that may not return the
|
||||
real version of Windows unless the application is so manifested. We prefer
|
||||
the real version always, so we use the Rtl variant of the function when
|
||||
possible. Note though the function signatures have underlying fundamental
|
||||
types that are the same, the return values are different. */
|
||||
if(pRtlVerifyVersionInfo) {
|
||||
matched = !pRtlVerifyVersionInfo(&osver,
|
||||
(VER_MAJORVERSION | VER_MINORVERSION |
|
||||
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
|
||||
cm);
|
||||
}
|
||||
else {
|
||||
matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver,
|
||||
(VER_MAJORVERSION | VER_MINORVERSION |
|
||||
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR),
|
||||
cm);
|
||||
if(pRtlVerifyVersionInfo)
|
||||
matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
|
||||
else
|
||||
matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver, dwTypeMask, cm);
|
||||
|
||||
/* Compare the build number separately. VerifyVersionInfo normally compares
|
||||
major.minor in hierarchical order (eg 1.9 is less than 2.0) but does not
|
||||
do the same for build (eg 1.9 build 222 is not less than 2.0 build 111).
|
||||
Build comparison is only needed when build numbers are equal (eg 1.9 is
|
||||
always less than 2.0 so build comparison is not needed). */
|
||||
if(matched && buildVersion &&
|
||||
(condition == VERSION_EQUAL ||
|
||||
((condition == VERSION_GREATER_THAN_EQUAL ||
|
||||
condition == VERSION_LESS_THAN_EQUAL) &&
|
||||
curlx_verify_windows_version(majorVersion, minorVersion, 0,
|
||||
platform, VERSION_EQUAL)))) {
|
||||
|
||||
cm = VerSetConditionMask(0, VER_BUILDNUMBER, buildCondition);
|
||||
dwTypeMask = VER_BUILDNUMBER;
|
||||
if(pRtlVerifyVersionInfo)
|
||||
matched = !pRtlVerifyVersionInfo(&osver, dwTypeMask, cm);
|
||||
else
|
||||
matched = !!VerifyVersionInfoW((OSVERSIONINFOEXW *)&osver,
|
||||
dwTypeMask, cm);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return matched;
|
||||
|
||||
@ -45,6 +45,7 @@ typedef enum {
|
||||
/* This is used to verify if we are running on a specific windows version */
|
||||
bool curlx_verify_windows_version(const unsigned int majorVersion,
|
||||
const unsigned int minorVersion,
|
||||
const unsigned int buildVersion,
|
||||
const PlatformIdentifier platform,
|
||||
const VersionCondition condition);
|
||||
|
||||
|
||||
@ -774,7 +774,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
|
||||
"schannel: SSL/TLS connection with %s port %hu (step 1/3)",
|
||||
hostname, conn->remote_port));
|
||||
|
||||
if(curlx_verify_windows_version(5, 1, PLATFORM_WINNT,
|
||||
if(curlx_verify_windows_version(5, 1, 0, PLATFORM_WINNT,
|
||||
VERSION_LESS_THAN_EQUAL)) {
|
||||
/* Schannel in Windows XP (OS version 5.1) uses legacy handshakes and
|
||||
algorithms that may not be supported by all servers. */
|
||||
@ -788,7 +788,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
|
||||
BACKEND->use_alpn = conn->bits.tls_enable_alpn &&
|
||||
!GetProcAddress(GetModuleHandle(TEXT("ntdll")),
|
||||
"wine_get_version") &&
|
||||
curlx_verify_windows_version(6, 3, PLATFORM_WINNT,
|
||||
curlx_verify_windows_version(6, 3, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL);
|
||||
#else
|
||||
BACKEND->use_alpn = false;
|
||||
@ -805,7 +805,7 @@ schannel_connect_step1(struct Curl_easy *data, struct connectdata *conn,
|
||||
#else
|
||||
#ifdef HAS_MANUAL_VERIFY_API
|
||||
if(SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) {
|
||||
if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT,
|
||||
if(curlx_verify_windows_version(6, 1, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL)) {
|
||||
BACKEND->use_manual_cred_validation = true;
|
||||
}
|
||||
@ -2045,7 +2045,7 @@ schannel_recv(struct Curl_easy *data, int sockindex,
|
||||
*/
|
||||
if(len && !BACKEND->decdata_offset && BACKEND->recv_connection_closed &&
|
||||
!BACKEND->recv_sspi_close_notify) {
|
||||
bool isWin2k = curlx_verify_windows_version(5, 0, PLATFORM_WINNT,
|
||||
bool isWin2k = curlx_verify_windows_version(5, 0, 0, PLATFORM_WINNT,
|
||||
VERSION_EQUAL);
|
||||
|
||||
if(isWin2k && sspi_status == SEC_E_OK)
|
||||
|
||||
@ -355,7 +355,7 @@ static DWORD cert_get_name_string(struct Curl_easy *data,
|
||||
DWORD i;
|
||||
|
||||
/* CERT_NAME_SEARCH_ALL_NAMES_FLAG is available from Windows 8 onwards. */
|
||||
if(curlx_verify_windows_version(6, 2, PLATFORM_WINNT,
|
||||
if(curlx_verify_windows_version(6, 2, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL)) {
|
||||
#ifdef CERT_NAME_SEARCH_ALL_NAMES_FLAG
|
||||
/* CertGetNameString will provide the 8-bit character string without
|
||||
@ -597,7 +597,8 @@ CURLcode Curl_verify_certificate(struct Curl_easy *data,
|
||||
* trusted certificates. This is only supported on Windows 7+.
|
||||
*/
|
||||
|
||||
if(curlx_verify_windows_version(6, 1, PLATFORM_WINNT, VERSION_LESS_THAN)) {
|
||||
if(curlx_verify_windows_version(6, 1, 0, PLATFORM_WINNT,
|
||||
VERSION_LESS_THAN)) {
|
||||
failf(data, "schannel: this version of Windows is too old to support "
|
||||
"certificate verification via CA bundle file.");
|
||||
result = CURLE_SSL_CACERT_BADFILE;
|
||||
|
||||
@ -768,7 +768,7 @@ CURLcode win32_init(void)
|
||||
{
|
||||
/* curlx_verify_windows_version must be called during init at least once
|
||||
because it has its own initialization routine. */
|
||||
if(curlx_verify_windows_version(6, 0, PLATFORM_WINNT,
|
||||
if(curlx_verify_windows_version(6, 0, 0, PLATFORM_WINNT,
|
||||
VERSION_GREATER_THAN_EQUAL))
|
||||
tool_isVistaOrGreater = true;
|
||||
else
|
||||
|
||||
Loading…
Reference in New Issue
Block a user