Add workaround for broken TLS SNI in Windows 8.1 for the archive updater
Asking users to download update (manifests) via an insecure connection is not ideal, but considering most of them downloaded the original test build via an insecure connection in the first place it might be ok Unfortunately the detection is not perfect, so genuine TLS attacks can be misinterpreted as the bug; completely invalid/expired/otherwise broken certificates should be rejected though
This commit is contained in:
parent
3d468a2364
commit
9b657018c6
@ -20,7 +20,21 @@
|
|||||||
#include "Main.h"
|
#include "Main.h"
|
||||||
#include <winhttp.h>
|
#include <winhttp.h>
|
||||||
|
|
||||||
BOOL HTTPGetFile (CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *responseCode)
|
__declspec(thread) bool invalidCN = false;
|
||||||
|
|
||||||
|
static void CALLBACK WinHTTPStatusCallback(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
|
||||||
|
{
|
||||||
|
if (dwStatusInformationLength != 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((*(DWORD*)lpvStatusInformation) & ~(WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID | WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((*(DWORD*)lpvStatusInformation) & WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID)
|
||||||
|
invalidCN = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL HTTPGetFile(CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *responseCode, HTTPGetFileWin81TLSSNIBugHandler h)
|
||||||
{
|
{
|
||||||
HINTERNET hSession = NULL;
|
HINTERNET hSession = NULL;
|
||||||
HINTERNET hConnect = NULL;
|
HINTERNET hConnect = NULL;
|
||||||
@ -54,10 +68,14 @@ BOOL HTTPGetFile (CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *response
|
|||||||
if (urlComponents.nPort == 443)
|
if (urlComponents.nPort == 443)
|
||||||
secure = TRUE;
|
secure = TRUE;
|
||||||
|
|
||||||
|
retry:
|
||||||
hSession = WinHttpOpen(OBS_VERSION_STRING, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
hSession = WinHttpOpen(OBS_VERSION_STRING, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
|
||||||
if (!hSession)
|
if (!hSession)
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
||||||
|
if (secure)
|
||||||
|
WinHttpSetStatusCallback(hSession, WinHTTPStatusCallback, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, NULL);
|
||||||
|
|
||||||
hConnect = WinHttpConnect(hSession, hostName, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0);
|
hConnect = WinHttpConnect(hSession, hostName, secure ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT, 0);
|
||||||
if (!hConnect)
|
if (!hConnect)
|
||||||
goto failure;
|
goto failure;
|
||||||
@ -68,11 +86,20 @@ BOOL HTTPGetFile (CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *response
|
|||||||
|
|
||||||
BOOL bResults = WinHttpSendRequest(hRequest, extraHeaders, extraHeaders ? -1 : 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
|
BOOL bResults = WinHttpSendRequest(hRequest, extraHeaders, extraHeaders ? -1 : 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
|
||||||
|
|
||||||
// End the request.
|
if (!bResults)
|
||||||
if (bResults)
|
{
|
||||||
bResults = WinHttpReceiveResponse(hRequest, NULL);
|
DWORD err = GetLastError();
|
||||||
else
|
if (err == ERROR_WINHTTP_SECURE_FAILURE && invalidCN && h && h())
|
||||||
|
{
|
||||||
|
secure = 0;
|
||||||
|
WinHttpSetStatusCallback(hSession, nullptr, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, NULL);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
goto failure;
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End the request.
|
||||||
|
bResults = WinHttpReceiveResponse(hRequest, NULL);
|
||||||
|
|
||||||
TCHAR statusCode[8];
|
TCHAR statusCode[8];
|
||||||
DWORD statusCodeLen;
|
DWORD statusCodeLen;
|
||||||
@ -121,7 +148,10 @@ BOOL HTTPGetFile (CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *response
|
|||||||
|
|
||||||
failure:
|
failure:
|
||||||
if (hSession)
|
if (hSession)
|
||||||
|
{
|
||||||
|
WinHttpSetStatusCallback(hSession, nullptr, WINHTTP_CALLBACK_FLAG_SECURE_FAILURE, NULL);
|
||||||
WinHttpCloseHandle(hSession);
|
WinHttpCloseHandle(hSession);
|
||||||
|
}
|
||||||
if (hConnect)
|
if (hConnect)
|
||||||
WinHttpCloseHandle(hConnect);
|
WinHttpCloseHandle(hConnect);
|
||||||
if (hRequest)
|
if (hRequest)
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
BOOL HTTPGetFile (CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *responseCode);
|
typedef bool(HTTPGetFileWin81TLSSNIBugHandler)();
|
||||||
|
|
||||||
|
BOOL HTTPGetFile(CTSTR url, CTSTR outputPath, CTSTR extraHeaders, int *responseCode, HTTPGetFileWin81TLSSNIBugHandler h = nullptr);
|
||||||
|
|
||||||
String CreateHTTPURL(String host, String path, String extra=String(), bool secure=false);
|
String CreateHTTPURL(String host, String path, String extra=String(), bool secure=false);
|
@ -99,7 +99,7 @@ BOOL CalculateFileHash (TCHAR *path, BYTE *hash)
|
|||||||
#define MANIFEST_URL "https://builds.catchexception.org/update.json"
|
#define MANIFEST_URL "https://builds.catchexception.org/update.json"
|
||||||
#define UPDATER_PATH "/updates/org.catchexception.builds.updater.exe"
|
#define UPDATER_PATH "/updates/org.catchexception.builds.updater.exe"
|
||||||
#define UPDATE_CHANNEL "master"
|
#define UPDATE_CHANNEL "master"
|
||||||
*/
|
//*/
|
||||||
|
|
||||||
#ifndef MANIFEST_WITH_ARCHIVES
|
#ifndef MANIFEST_WITH_ARCHIVES
|
||||||
#define MANIFEST_WITH_ARCHIVES 0
|
#define MANIFEST_WITH_ARCHIVES 0
|
||||||
@ -372,6 +372,11 @@ bool ParseUpdateManifest (TCHAR *path, BOOL *updatesAvailable, String &descripti
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Win81TLSSNIBugHandler()
|
||||||
|
{
|
||||||
|
return OSGetVersion() == 8 && OBSMessageBox(hwndMain, Str("Updater.Win81TLSSNIBug"), nullptr, MB_YESNOCANCEL | MB_DEFBUTTON2) == IDYES;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD WINAPI CheckUpdateThread (VOID *arg)
|
DWORD WINAPI CheckUpdateThread (VOID *arg)
|
||||||
{
|
{
|
||||||
int responseCode;
|
int responseCode;
|
||||||
@ -421,7 +426,11 @@ DWORD WINAPI CheckUpdateThread (VOID *arg)
|
|||||||
scat(extraHeaders, strGUID);
|
scat(extraHeaders, strGUID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MANIFEST_WITH_ARCHIVES
|
||||||
|
if (HTTPGetFile(TEXT(MANIFEST_URL), manifestPath, extraHeaders, &responseCode, Win81TLSSNIBugHandler))
|
||||||
|
#else
|
||||||
if (HTTPGetFile(TEXT(MANIFEST_URL), manifestPath, extraHeaders, &responseCode))
|
if (HTTPGetFile(TEXT(MANIFEST_URL), manifestPath, extraHeaders, &responseCode))
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
if (responseCode == 200 || responseCode == 304)
|
if (responseCode == 200 || responseCode == 304)
|
||||||
{
|
{
|
||||||
|
@ -381,6 +381,7 @@ Updater.NewUpdates="The following updates are available:\r\n\r\n"
|
|||||||
Updater.RunningWarning="OBS will be restarted to install the updates.\r\n\r\nAre you sure you want to continue?"
|
Updater.RunningWarning="OBS will be restarted to install the updates.\r\n\r\nAre you sure you want to continue?"
|
||||||
Updater.UpdatesAvailable="Updates are available"
|
Updater.UpdatesAvailable="Updates are available"
|
||||||
Updater.NoUpdatesAvailable="No updates are available"
|
Updater.NoUpdatesAvailable="No updates are available"
|
||||||
|
Updater.Win81TLSSNIBug="Due to a bug in Windows 8.1 the secure update check failed. Do you want to retry the update check via an insecure connection?"
|
||||||
|
|
||||||
MainMenu.Help.LogFiles="Log Files"
|
MainMenu.Help.LogFiles="Log Files"
|
||||||
MainMenu.Help.AnalyzeCurrentLog="Analyze current Log File"
|
MainMenu.Help.AnalyzeCurrentLog="Analyze current Log File"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user