Commit c2bccea3 authored by Emre Kanlikilicer's avatar Emre Kanlikilicer Committed by Commit Bot

LogonUI uses fixed buffer size to pass the json object to rundll32. To fix the...

LogonUI uses fixed buffer size to pass the json object to rundll32. To fix the issue, first write/read the buffer size to/from the pipe.

Bug: 902911 https://bugs.chromium.org/p/chromium/issues/detail?id=902911
Change-Id: Ibfc23a098c53c4b6c58a979ee38fb46dc38d55bf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825909
Commit-Queue: Emre Kanlikilicer <emreknlk@google.com>
Reviewed-by: default avatarTien Mai <tienmai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#700446}
parent 6c92cc0f
...@@ -160,26 +160,41 @@ void CALLBACK SaveAccountInfoW(HWND /*hwnd*/, ...@@ -160,26 +160,41 @@ void CALLBACK SaveAccountInfoW(HWND /*hwnd*/,
return; return;
} }
char buffer[credential_provider::CGaiaCredentialBase::kAccountInfoBufferSize]; // First, read the buffer size.
DWORD buffer_len_bytes = static_cast<DWORD>(sizeof(buffer)); // In bytes. DWORD buffer_size = 0;
if (!::ReadFile(hStdin, buffer, buffer_len_bytes, &buffer_len_bytes, DWORD bytes_read = 0;
if (!::ReadFile(hStdin, &buffer_size, sizeof(buffer_size), &bytes_read,
nullptr)) { nullptr)) {
HRESULT hr = HRESULT_FROM_WIN32(::GetLastError()); HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());
LOGFN(ERROR) << "ReadFile for buffer size failed. hr=" << putHR(hr);
return;
}
// For security, we check for a max of 1 MB buffer size.
const DWORD kMaxBufferSizeAllowed = 1024 * 1024; // 1MB
if (!buffer_size || buffer_size > kMaxBufferSizeAllowed) {
LOGFN(ERROR) << "Invalid buffer size.";
return;
}
// Second, read the buffer.
std::vector<char> buffer(buffer_size, 0);
if (!::ReadFile(hStdin, buffer.data(), buffer.size(), &bytes_read, nullptr)) {
HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());
LOGFN(ERROR) << "ReadFile hr=" << putHR(hr); LOGFN(ERROR) << "ReadFile hr=" << putHR(hr);
return; return;
} }
buffer[buffer_len_bytes] = 0;
// Don't log |buffer| since it contains sensitive info like password. // Don't log |buffer| since it contains sensitive info like password.
HRESULT hr = S_OK; HRESULT hr = S_OK;
base::Optional<base::Value> properties = base::Optional<base::Value> properties =
base::JSONReader::Read(buffer, base::JSON_ALLOW_TRAILING_COMMAS); base::JSONReader::Read(buffer.data(), base::JSON_ALLOW_TRAILING_COMMAS);
credential_provider::SecurelyClearBuffer(buffer, base::size(buffer)); credential_provider::SecurelyClearBuffer(buffer.data(), buffer.size());
if (!properties || !properties->is_dict()) { if (!properties || !properties->is_dict()) {
LOGFN(ERROR) << "base::JSONReader::Read failed length=" << buffer_len_bytes; LOGFN(ERROR) << "base::JSONReader::Read failed length=" << buffer.size();
hr = E_FAIL; return;
} }
hr = credential_provider::CGaiaCredentialBase::SaveAccountInfo(*properties); hr = credential_provider::CGaiaCredentialBase::SaveAccountInfo(*properties);
......
...@@ -1698,12 +1698,20 @@ HRESULT CGaiaCredentialBase::ForkSaveAccountInfoStub(const base::Value& dict, ...@@ -1698,12 +1698,20 @@ HRESULT CGaiaCredentialBase::ForkSaveAccountInfoStub(const base::Value& dict,
// Write account info to stdin of child process. This buffer is read by // Write account info to stdin of child process. This buffer is read by
// SaveAccountInfoW() in dllmain.cpp. If this fails, chrome won't pick up // SaveAccountInfoW() in dllmain.cpp. If this fails, chrome won't pick up
// the credentials from the credential provider and will need to sign in // the credentials from the credential provider and will need to sign in
// manually. TODO(crbug.com/902911): Figure out how to handle this. // manually.
std::string json; std::string json;
if (base::JSONWriter::Write(dict, &json)) { if (base::JSONWriter::Write(dict, &json)) {
DWORD written; const DWORD buffer_size = json.length() + 1;
if (!::WriteFile(parent_handles.hstdin_write.Get(), json.c_str(), LOGFN(INFO) << "Json size: " << buffer_size;
json.length() + 1, &written, /*lpOverlapped=*/nullptr)) {
DWORD written = 0;
// First, write the buffer size then write the buffer content.
if (!::WriteFile(parent_handles.hstdin_write.Get(), &buffer_size,
sizeof(buffer_size), &written, /*lpOverlapped=*/nullptr)) {
HRESULT hrWrite = HRESULT_FROM_WIN32(::GetLastError());
LOGFN(ERROR) << "WriteFile hr=" << putHR(hrWrite);
} else if (!::WriteFile(parent_handles.hstdin_write.Get(), json.c_str(),
buffer_size, &written, /*lpOverlapped=*/nullptr)) {
HRESULT hrWrite = HRESULT_FROM_WIN32(::GetLastError()); HRESULT hrWrite = HRESULT_FROM_WIN32(::GetLastError());
LOGFN(ERROR) << "WriteFile hr=" << putHR(hrWrite); LOGFN(ERROR) << "WriteFile hr=" << putHR(hrWrite);
} }
......
...@@ -44,10 +44,6 @@ class ATL_NO_VTABLE CGaiaCredentialBase ...@@ -44,10 +44,6 @@ class ATL_NO_VTABLE CGaiaCredentialBase
: public IGaiaCredential, : public IGaiaCredential,
public ICredentialProviderCredential2 { public ICredentialProviderCredential2 {
public: public:
// Size in wchar_t of string buffer to pass account information to background
// process to save that information into the registry.
static const int kAccountInfoBufferSize = 2048;
// Called when the DLL is registered or unregistered. // Called when the DLL is registered or unregistered.
static HRESULT OnDllRegisterServer(); static HRESULT OnDllRegisterServer();
static HRESULT OnDllUnregisterServer(); static HRESULT OnDllUnregisterServer();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment