Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 3 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
FixNamespaceComments: false
ForEachMacros:
- foreach
- Q_FOREACH
Expand All @@ -70,6 +70,7 @@ IncludeCategories:
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
InsertNewlineAtEOF: true
IndentPPDirectives: BeforeHash
IndentWidth: 4
IndentWrappedFunctionNames: false
Expand Down Expand Up @@ -99,7 +100,7 @@ SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 12
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
Expand Down
7 changes: 4 additions & 3 deletions Client/ceflauncher_DLL/CCefApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <cef3/cef/include/cef_app.h>
#include <string>
#include "V8Helpers.h"
#include "CCefAppAuth.h" // IPC message append helpers
#include "CCefAppAuth.h" // IPC message append helpers
using V8Helpers::CV8Handler;

class CCefApp : public CefApp, public CefRenderProcessHandler
Expand Down Expand Up @@ -41,7 +41,8 @@ class CCefApp : public CefApp, public CefRenderProcessHandler
if (!node)
return;

if (node->GetType() == CefDOMNode::Type::DOM_NODE_TYPE_ELEMENT && node->GetFormControlElementType() != CefDOMNode::FormControlType::DOM_FORM_CONTROL_TYPE_UNSUPPORTED)
if (node->GetType() == CefDOMNode::Type::DOM_NODE_TYPE_ELEMENT &&
node->GetFormControlElementType() != CefDOMNode::FormControlType::DOM_FORM_CONTROL_TYPE_UNSUPPORTED)
{
auto message = CefProcessMessage::Create("InputFocus");
message->GetArgumentList()->SetBool(0, true);
Expand Down Expand Up @@ -77,7 +78,7 @@ class CCefApp : public CefApp, public CefRenderProcessHandler
return;

CefRefPtr<CefProcessMessage> message = V8Helpers::SerialiseV8Arguments("TriggerLuaEvent", arguments);
if (!CefAppAuth::AppendAuthCodeToMessage(message)) [[unlikely]] // AUTH: race condition check
if (!CefAppAuth::AppendAuthCodeToMessage(message)) [[unlikely]] // AUTH: race condition check
return;
frame->GetBrowser()->GetMainFrame()->SendProcessMessage(PID_BROWSER, message);
}
Expand Down
6 changes: 3 additions & 3 deletions Client/ceflauncher_DLL/CCefAppAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ namespace CefAppAuth
return false;

auto& authCode = AuthCodeStorage();

// Block messages until initialized (prevents race condition)
if (authCode.empty()) [[unlikely]]
return false;

CefRefPtr<CefListValue> args = message->GetArgumentList();
const auto size = args->GetSize();
const auto size = args->GetSize();
args->SetSize(size + 1);
args->SetString(size, authCode.c_str());
return true;
Expand Down
52 changes: 25 additions & 27 deletions Client/ceflauncher_DLL/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,27 @@
#include <SharedUtil.h>

#ifdef CEF_ENABLE_SANDBOX
#include <cef3/cef/include/cef_sandbox_win.h>
#pragma comment(lib, "cef_sandbox.lib")
#include <cef3/cef/include/cef_sandbox_win.h>
#pragma comment(lib, "cef_sandbox.lib")
#endif

// Return codes
inline constexpr int CEF_INIT_SUCCESS = 0;
inline constexpr int CEF_INIT_ERROR_NO_BASE_DIR = -1;
inline constexpr int CEF_INIT_ERROR_DLL_LOAD_FAILED = -2;
inline constexpr int CEF_INIT_SUCCESS = 0;
inline constexpr int CEF_INIT_ERROR_NO_BASE_DIR = -1;
inline constexpr int CEF_INIT_ERROR_DLL_LOAD_FAILED = -2;

inline constexpr DWORD CEF_PARENT_CHECK_INTERVAL = 1000;
inline constexpr const char* CEF_DLL_NAME = "libcef.dll";
inline constexpr const char* CEF_MTA_SUBDIR = "MTA";
inline constexpr DWORD CEF_PARENT_CHECK_INTERVAL = 1000;
inline constexpr const char* CEF_DLL_NAME = "libcef.dll";
inline constexpr const char* CEF_MTA_SUBDIR = "MTA";

inline constexpr DWORD PARENT_CHECK_ERROR_NO_QUERY_FUNC = 1;
inline constexpr DWORD PARENT_CHECK_ERROR_QUERY_FAILED = 2;
inline constexpr DWORD PARENT_CHECK_ERROR_OPEN_FAILED = 3;
inline constexpr DWORD PARENT_CHECK_ERROR_NO_QUERY_FUNC = 1;
inline constexpr DWORD PARENT_CHECK_ERROR_QUERY_FAILED = 2;
inline constexpr DWORD PARENT_CHECK_ERROR_OPEN_FAILED = 3;

using NtQueryInformationProcessFunc = NTSTATUS(NTAPI*)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

// Safe parent monitor thread shutdown
std::atomic<bool> g_bShouldTerminateMonitor{false};
std::atomic<bool> g_bShouldTerminateMonitor{false};
std::atomic<HANDLE> g_hMonitorThread{nullptr};

namespace
Expand All @@ -60,19 +60,19 @@ namespace
const auto ntdll = GetModuleHandleW(L"ntdll.dll");
if (!ntdll)
return nullptr;

const auto procAddr = GetProcAddress(ntdll, "NtQueryInformationProcess");
if (!procAddr)
return nullptr;

return reinterpret_cast<NtQueryInformationProcessFunc>(procAddr);
}

[[nodiscard]] auto GetParentProcessId(NtQueryInformationProcessFunc queryFunc) noexcept -> DWORD
{
PROCESS_BASIC_INFORMATION info{};
ULONG returnLength = 0;
ULONG returnLength = 0;

if (const auto status = queryFunc(GetCurrentProcess(), ProcessBasicInformation, &info, sizeof(info), &returnLength);
!NT_SUCCESS(status) || returnLength < sizeof(PROCESS_BASIC_INFORMATION))
{
Expand All @@ -87,7 +87,7 @@ namespace
while (!g_bShouldTerminateMonitor.load(std::memory_order_acquire))
{
const DWORD result = WaitForSingleObject(parentProcess, CEF_PARENT_CHECK_INTERVAL);

if (result == WAIT_OBJECT_0)
{
DWORD exitCode = 0;
Expand All @@ -104,7 +104,7 @@ namespace
}
}
}
} // namespace
} // namespace

DWORD WINAPI CheckParentProcessAliveness(LPVOID) noexcept;

Expand All @@ -120,7 +120,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, [[maybe_unused]] LPVOID l
{
g_bShouldTerminateMonitor.store(true, std::memory_order_release);
}

return TRUE;
}

Expand All @@ -132,28 +132,26 @@ extern "C" [[nodiscard]] __declspec(dllexport) auto InitCEF() noexcept -> int
{
const auto valueStart = pos + 11; // Skip "--kgfiv8n="
const auto valueEnd = cmdLine.find_first_of(L" \t\"", valueStart);
const auto authCodeW = cmdLine.substr(valueStart,
valueEnd == std::wstring_view::npos ? 30 : std::min<size_t>(30, valueEnd - valueStart));

const auto authCodeW = cmdLine.substr(valueStart, valueEnd == std::wstring_view::npos ? 30 : std::min<size_t>(30, valueEnd - valueStart));

std::string authCode;
authCode.reserve(30);
std::transform(authCodeW.begin(), authCodeW.end(), std::back_inserter(authCode),
[](const wchar_t wc) { return static_cast<char>(wc); });

std::transform(authCodeW.begin(), authCodeW.end(), std::back_inserter(authCode), [](const wchar_t wc) { return static_cast<char>(wc); });

CefAppAuth::AuthCodeStorage() = std::move(authCode);
}

const auto baseDir = SharedUtil::GetMTAProcessBaseDir();
if (baseDir.empty())
return CEF_INIT_ERROR_NO_BASE_DIR;

const auto mtaDir = SharedUtil::PathJoin(baseDir, CEF_MTA_SUBDIR);
SetDllDirectoryW(SharedUtil::FromUTF8(mtaDir));

if (FAILED(__HrLoadAllImportsForDll(CEF_DLL_NAME)))
return CEF_INIT_ERROR_DLL_LOAD_FAILED;

const CefMainArgs mainArgs(GetModuleHandleW(nullptr));
const CefMainArgs mainArgs(GetModuleHandleW(nullptr));
const CefRefPtr<CCefApp> app{new CCefApp};

void* sandboxInfo = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion Client/ceflauncher_DLL/V8Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,4 @@ namespace V8Helpers
CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(name, handler);
object->SetValue(name, func, V8_PROPERTY_ATTRIBUTE_NONE);
}
} // namespace V8Helpers
}
8 changes: 4 additions & 4 deletions Client/cefweb/CAjaxResourceHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,13 @@ void CAjaxResourceHandler::GetResponseHeaders(CefRefPtr<CefResponse> response, i
constexpr int HTTP_OK = 200;
response->SetStatus(HTTP_OK);
response->SetStatusText("OK");

// Use default MIME type if none provided
if (!m_strMime.empty())
response->SetMimeType(m_strMime);
else
response->SetMimeType("application/octet-stream");

response_length = -1;
}

Expand Down Expand Up @@ -116,10 +116,10 @@ bool CAjaxResourceHandler::ReadResponse(void* data_out, int bytes_to_read, int&
const auto copyBytes = std::min(static_cast<size_t>(bytes_to_read), remainingBytes);

memcpy(data_out, m_strResponse.c_str() + m_DataOffset, copyBytes);

// copyBytes is bounded by bytes_to_read (an int), so cast is always safe
bytes_read = static_cast<int>(copyBytes);

m_DataOffset += copyBytes;

return true;
Expand Down
4 changes: 2 additions & 2 deletions Client/cefweb/CAjaxResourceHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class CAjaxResourceHandler : public CefResourceHandler, public CAjaxResourceHand

std::vector<std::string>& GetGetData() override { return m_vecGetData; }
std::vector<std::string>& GetPostData() override { return m_vecPostData; }
void SetResponse(std::string data) override;
void SetResponse(std::string data) override;

// CefResourceHandler
virtual void Cancel() override;
Expand All @@ -37,7 +37,7 @@ class CAjaxResourceHandler : public CefResourceHandler, public CAjaxResourceHand
DISALLOW_COPY_AND_ASSIGN(CAjaxResourceHandler);

private:
CefRefPtr<CefCallback> m_callback;
CefRefPtr<CefCallback> m_callback;
std::vector<std::string> m_vecGetData;
std::vector<std::string> m_vecPostData;
std::string m_strResponse;
Expand Down
32 changes: 13 additions & 19 deletions Client/cefweb/CWebApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <cef3/cef/include/cef_stream.h>
#include <cef3/cef/include/wrapper/cef_stream_resource_handler.h>
#include "CAjaxResourceHandler.h"
#include "CWebAppAuth.h" // IPC code generation
#include "CWebAppAuth.h" // IPC code generation
#include <cstdlib>

namespace
Expand Down Expand Up @@ -106,14 +106,11 @@ namespace
if (disableGpu)
commandLine->AppendSwitch("disable-gpu");
}
} // namespace
} // namespace

[[nodiscard]] CefRefPtr<CefResourceHandler> CWebApp::HandleError(const SString& strError, unsigned int uiError)
{
auto stream = CefStreamReader::CreateForData(
(void*)strError.c_str(),
strError.length()
);
auto stream = CefStreamReader::CreateForData((void*)strError.c_str(), strError.length());
if (!stream)
return nullptr;
return CefRefPtr<CefResourceHandler>(new CefStreamResourceHandler(uiError, strError, "text/plain", CefResponse::HeaderMap(), stream));
Expand All @@ -131,7 +128,7 @@ void CWebApp::OnBeforeChildProcessLaunch(CefRefPtr<CefCommandLine> command_line)

const CefString processType = command_line->GetSwitchValue("type");
ConfigureCommandLineSwitches(command_line, processType);

// Attach IPC validation code for render processes
// This runs in browser process context where g_pCore and webCore are valid
// The auth code is generated in CWebCore constructor and passed to subprocesses
Expand Down Expand Up @@ -183,10 +180,10 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
if (std::size(path) < 2)
return HandleError("404 - Not found", 404);

path = path.substr(1); // Remove slash at the front
path = path.substr(1); // Remove slash at the front
if (const auto slashPos = path.find('/'); slashPos == std::string::npos)
{
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr unsigned int CODE_404 = 404;
return HandleError(ERROR_404, CODE_404);
}
Expand All @@ -197,7 +194,7 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef

if (resourcePath.empty())
{
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr unsigned int CODE_404 = 404;
return HandleError(ERROR_404, CODE_404);
}
Expand Down Expand Up @@ -251,7 +248,7 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
{
// Limit to 5MiB and allow byte data only
constexpr size_t MAX_POST_SIZE = 5 * 1024 * 1024;
size_t bytesCount = post->GetBytesCount();
size_t bytesCount = post->GetBytesCount();
if (bytesCount > MAX_POST_SIZE || post->GetType() != CefPostDataElement::Type::PDE_TYPE_BYTES)
continue;

Expand Down Expand Up @@ -294,7 +291,7 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
// Calculate absolute path
if (!pWebView->GetFullPathFromLocal(path))
{
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr unsigned int CODE_404 = 404;
return HandleError(ERROR_404, CODE_404);
}
Expand All @@ -303,7 +300,7 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
CBuffer fileData;
if (!pWebView->VerifyFile(path, fileData))
{
static constexpr auto ERROR_403 = "403 - Access Denied";
static constexpr auto ERROR_403 = "403 - Access Denied";
static constexpr unsigned int CODE_403 = 403;
return HandleError(ERROR_403, CODE_403);
}
Expand All @@ -315,17 +312,14 @@ CefRefPtr<CefResourceHandler> CWebApp::Create(CefRefPtr<CefBrowser> browser, Cef
fileData = CBuffer(emptyStr, std::size(emptyStr));
}

auto stream = CefStreamReader::CreateForData(
fileData.GetData(),
fileData.GetSize()
);
auto stream = CefStreamReader::CreateForData(fileData.GetData(), fileData.GetSize());
if (!stream)
{
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr auto ERROR_404 = "404 - Not found";
static constexpr unsigned int CODE_404 = 404;
return HandleError(ERROR_404, CODE_404);
}

return CefRefPtr<CefResourceHandler>(new CefStreamResourceHandler(mimeType, stream));
}
}
Expand Down
12 changes: 6 additions & 6 deletions Client/cefweb/CWebAppAuth.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,18 @@ namespace WebAppAuth

// Auth code configuration
inline constexpr std::size_t AUTH_CODE_LENGTH = 30;
inline constexpr char AUTH_CODE_MIN_CHAR = 'A';
inline constexpr char AUTH_CODE_MAX_CHAR = 'Z';
inline constexpr char AUTH_CODE_MIN_CHAR = 'A';
inline constexpr char AUTH_CODE_MAX_CHAR = 'Z';

// Generates random 30-character auth code (A-Z)
[[nodiscard]] inline std::string GenerateAuthCode()
{
std::array<char, AUTH_CODE_LENGTH> buffer{};

// Use mt19937 with time-based seed (fast, cryptographic strength not needed for DoS prevention)
static std::mt19937 rng(static_cast<unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count()));
static std::mt19937 rng(static_cast<unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count()));
std::uniform_int_distribution<int> dist(0, AUTH_CODE_MAX_CHAR - AUTH_CODE_MIN_CHAR);

for (auto& ch : buffer)
ch = static_cast<char>(AUTH_CODE_MIN_CHAR + dist(rng));

Expand All @@ -77,7 +77,7 @@ namespace WebAppAuth
return;

const std::lock_guard<std::mutex> lock{GetSharedAuthMutex()};

// Always use webCore->m_AuthCode (already populated in CWebCore constructor)
// No need for fallback - webCore is guaranteed to exist before this is called
if (!::g_pCore || !IsReadablePointer(::g_pCore, sizeof(void*))) [[unlikely]]
Expand Down
Loading
Loading