summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWyatt O'Day <wyatt@wyday.com>2021-10-07 06:58:39 -0400
committerJay Satiro <raysatiro@yahoo.com>2021-12-02 03:39:14 -0500
commit7da636cad560f1643004fac42363dde76e705d9f (patch)
tree3cd4512092921322890d6c229a3e20dd39efb3a8
parent3467e89bb97e6c87c77e82a046c59cb4b2d29a74 (diff)
downloadcurl-7da636cad560f1643004fac42363dde76e705d9f.tar.gz
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
-rw-r--r--lib/connect.c2
-rw-r--r--lib/curl_sspi.c2
-rw-r--r--lib/system_win32.c2
-rw-r--r--lib/version_win32.c82
-rw-r--r--lib/version_win32.h1
-rw-r--r--lib/vtls/schannel.c8
-rw-r--r--lib/vtls/schannel_verify.c5
-rw-r--r--src/tool_doswin.c2
8 files changed, 77 insertions, 27 deletions
diff --git a/lib/connect.c b/lib/connect.c
index 94490805a..c57387549 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -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
diff --git a/lib/curl_sspi.c b/lib/curl_sspi.c
index 06841ddec..29a98bb32 100644
--- a/lib/curl_sspi.c
+++ b/lib/curl_sspi.c
@@ -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"));
diff --git a/lib/system_win32.c b/lib/system_win32.c
index d4e194831..9a6dd9cef 100644
--- a/lib/system_win32.c
+++ b/lib/system_win32.c
@@ -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;
}
diff --git a/lib/version_win32.c b/lib/version_win32.c
index 2f845413c..79a2aa6ab 100644
--- a/lib/version_win32.c
+++ b/lib/version_win32.c
@@ -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;
diff --git a/lib/version_win32.h b/lib/version_win32.h
index 9b1bd8887..f5bfef426 100644
--- a/lib/version_win32.h
+++ b/lib/version_win32.h
@@ -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);
diff --git a/lib/vtls/schannel.c b/lib/vtls/schannel.c
index 44c59e779..5d18037e8 100644
--- a/lib/vtls/schannel.c
+++ b/lib/vtls/schannel.c
@@ -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)
diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c
index 1b283d045..4966cd494 100644
--- a/lib/vtls/schannel_verify.c
+++ b/lib/vtls/schannel_verify.c
@@ -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;
diff --git a/src/tool_doswin.c b/src/tool_doswin.c
index 1ad9cddc3..2390fab7f 100644
--- a/src/tool_doswin.c
+++ b/src/tool_doswin.c
@@ -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