diff options
author | teor <teor@torproject.org> | 2019-03-14 06:56:09 +1000 |
---|---|---|
committer | teor <teor@torproject.org> | 2019-03-14 06:56:09 +1000 |
commit | f3b17a6b261e1feef05dafac247b96b3ea90a521 (patch) | |
tree | 57c013d53194e974bbd6622a6af198cf6d603874 | |
parent | c03b1b3f08b0588c9ba36b2097d372cb62cfdc22 (diff) | |
parent | 66f944f79b9ae0d7383f9bf55c8d8cd4bdacf216 (diff) | |
download | tor-f3b17a6b261e1feef05dafac247b96b3ea90a521.tar.gz tor-f3b17a6b261e1feef05dafac247b96b3ea90a521.zip |
Merge remote-tracking branch 'tor-github/pr/795' into maint-0.3.4
-rw-r--r-- | changes/bug28096 | 13 | ||||
-rw-r--r-- | src/common/compat.c | 95 |
2 files changed, 77 insertions, 31 deletions
diff --git a/changes/bug28096 b/changes/bug28096 new file mode 100644 index 0000000000..6847df9798 --- /dev/null +++ b/changes/bug28096 @@ -0,0 +1,13 @@ + o Minor bugfixes (Windows): + - Correctly identify Windows 8.1, Windows 10, and Windows Server 2008 + and later from their NT versions. + Fixes bug 28096; bugfix on 0.2.2.34; reported by Keifer Bly. + - On recent Windows versions, the GetVersionEx() function may report + an earlier Windows version than the running OS. To avoid user + confusion, add "[or later]" to Tor's version string on affected + versions of Windows. + Fixes bug 28096; bugfix on 0.2.2.34; reported by Keifer Bly. + - Remove Windows versions that were never supported by the + GetVersionEx() function. Stop duplicating the latest Windows + version in get_uname(). + Fixes bug 28096; bugfix on 0.2.2.34; reported by Keifer Bly. diff --git a/src/common/compat.c b/src/common/compat.c index 6fdd6ecf00..f8c4bdb4d8 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -2703,22 +2703,33 @@ get_uname,(void)) #ifdef _WIN32 OSVERSIONINFOEX info; int i; + int is_client = 0; + int is_server = 0; const char *plat = NULL; static struct { - unsigned major; unsigned minor; const char *version; + unsigned major; unsigned minor; + const char *client_version; const char *server_version; } win_version_table[] = { - { 6, 2, "Windows 8" }, - { 6, 1, "Windows 7" }, - { 6, 0, "Windows Vista" }, - { 5, 2, "Windows Server 2003" }, - { 5, 1, "Windows XP" }, - { 5, 0, "Windows 2000" }, - /* { 4, 0, "Windows NT 4.0" }, */ - { 4, 90, "Windows Me" }, - { 4, 10, "Windows 98" }, - /* { 4, 0, "Windows 95" } */ - { 3, 51, "Windows NT 3.51" }, - { 0, 0, NULL } + /* This table must be sorted in descending order. + * Sources: + * https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_versions + * https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ + * ns-winnt-_osversioninfoexa#remarks + */ + /* Windows Server 2019 is indistinguishable from Windows Server 2016 + * using GetVersionEx(). + { 10, 0, NULL, "Windows Server 2019" }, */ + { 10, 0, "Windows 10", "Windows Server 2016" }, + { 6, 3, "Windows 8.1", "Windows Server 2012 R2" }, + { 6, 2, "Windows 8", "Windows Server 2012" }, + { 6, 1, "Windows 7", "Windows Server 2008 R2" }, + { 6, 0, "Windows Vista", "Windows Server 2008" }, + { 5, 2, "Windows XP Professional", "Windows Server 2003" }, + /* Windows XP did not have a server version, but we need something here */ + { 5, 1, "Windows XP", "Windows XP Server" }, + { 5, 0, "Windows 2000 Professional", "Windows 2000 Server" }, + /* Earlier versions are not supported by GetVersionEx(). */ + { 0, 0, NULL, NULL } }; memset(&info, 0, sizeof(info)); info.dwOSVersionInfoSize = sizeof(info); @@ -2728,25 +2739,34 @@ get_uname,(void)) uname_result_is_set = 1; return uname_result; } - if (info.dwMajorVersion == 4 && info.dwMinorVersion == 0) { - if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) - plat = "Windows NT 4.0"; - else - plat = "Windows 95"; +#ifdef VER_NT_SERVER + if (info.wProductType == VER_NT_SERVER || + info.wProductType == VER_NT_DOMAIN_CONTROLLER) { + is_server = 1; } else { - for (i=0; win_version_table[i].major>0; ++i) { - if (win_version_table[i].major == info.dwMajorVersion && - win_version_table[i].minor == info.dwMinorVersion) { - plat = win_version_table[i].version; - break; + is_client = 1; + } +#endif + /* Search the version table for a matching version */ + for (i=0; win_version_table[i].major>0; ++i) { + if (win_version_table[i].major == info.dwMajorVersion && + win_version_table[i].minor == info.dwMinorVersion) { + if (is_server) { + plat = win_version_table[i].server_version; + } else { + /* Use client versions for clients, and when we don't know if it + * is a client or a server. */ + plat = win_version_table[i].client_version; } + break; } } if (plat) { strlcpy(uname_result, plat, sizeof(uname_result)); } else { - if (info.dwMajorVersion > 6 || - (info.dwMajorVersion==6 && info.dwMinorVersion>2)) + if (info.dwMajorVersion > win_version_table[0].major || + (info.dwMajorVersion == win_version_table[0].major && + info.dwMinorVersion > win_version_table[0].minor)) tor_snprintf(uname_result, sizeof(uname_result), "Very recent version of Windows [major=%d,minor=%d]", (int)info.dwMajorVersion,(int)info.dwMinorVersion); @@ -2755,12 +2775,25 @@ get_uname,(void)) "Unrecognized version of Windows [major=%d,minor=%d]", (int)info.dwMajorVersion,(int)info.dwMinorVersion); } -#ifdef VER_NT_SERVER - if (info.wProductType == VER_NT_SERVER || - info.wProductType == VER_NT_DOMAIN_CONTROLLER) { - strlcat(uname_result, " [server]", sizeof(uname_result)); - } -#endif /* defined(VER_NT_SERVER) */ + /* Now append extra information to the name. + * + * Microsoft's API documentation says that on Windows 8.1 and later, + * GetVersionEx returns Windows 8 (6.2) for applications without an + * app compatibility manifest (including tor's default build). + * + * But in our testing, we have seen the actual Windows version on + * Windows Server 2012 R2, even without a manifest. */ + if (info.dwMajorVersion > 6 || + (info.dwMajorVersion == 6 && info.dwMinorVersion >= 2)) { + /* When GetVersionEx() returns Windows 8, the actual OS may be any + * later version. */ + strlcat(uname_result, " [or later]", sizeof(uname_result)); + } + /* When we don't know if the OS is a client or server version, we use + * the client version, and this qualifier. */ + if (!is_server && !is_client) { + strlcat(uname_result, " [client or server]", sizeof(uname_result)); + } #else /* !(defined(_WIN32)) */ /* LCOV_EXCL_START -- can't provoke uname failure */ strlcpy(uname_result, "Unknown platform", sizeof(uname_result)); |