Commit a299fabe authored by Rakesh Soma's avatar Rakesh Soma Committed by Commit Bot

Fix the failing tests on win-asan for [1]. Seems like returning an empty "username" as part of

MakeUserNameForAccount() doesn't fail creation of user on some of the windows instances.

This fix explicitly returns a failure when we want to fail the login UI instead of depending on
"create user" to fail for "empty username" instead.

Note that currently the error_text is set as IDS_INTERNAL_ERROR_BASE. Explicit error handling
with appropriate error messages would be done in a followup change (already filed a bug for it).

[1] https://chromium-review.googlesource.com/c/chromium/src/+/1659512/24

Bug: 976543
Change-Id: Ic4d92f5ef647d0f3cd5fd50c1f52b588c94a3afd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1672234
Commit-Queue: Rakesh Soma <rakeshsoma@google.com>
Reviewed-by: default avatarTien Mai <tienmai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#672133}
parent f27ee9fe
...@@ -29,10 +29,12 @@ ...@@ -29,10 +29,12 @@
#include "base/files/file.h" #include "base/files/file.h"
#include "base/files/file_enumerator.h" #include "base/files/file_enumerator.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/no_destructor.h" #include "base/no_destructor.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/win/current_module.h" #include "base/win/current_module.h"
...@@ -727,6 +729,22 @@ void SecurelyClearBuffer(void* buffer, size_t length) { ...@@ -727,6 +729,22 @@ void SecurelyClearBuffer(void* buffer, size_t length) {
::RtlSecureZeroMemory(buffer, length); ::RtlSecureZeroMemory(buffer, length);
} }
std::string SearchForKeyInStringDictUTF8(
const std::string& json_string,
const std::initializer_list<base::StringPiece>& path) {
DCHECK(path.size() > 0);
base::Optional<base::Value> json_obj =
base::JSONReader::Read(json_string, base::JSON_ALLOW_TRAILING_COMMAS);
if (!json_obj || !json_obj->is_dict()) {
LOGFN(ERROR) << "base::JSONReader::Read failed to translate to JSON";
return std::string();
}
const std::string* value =
json_obj->FindStringPath(base::JoinString(path, "."));
return value ? *value : std::string();
}
base::string16 GetDictString(const base::Value& dict, const char* name) { base::string16 GetDictString(const base::Value& dict, const char* name) {
DCHECK(name); DCHECK(name);
DCHECK(dict.is_dict()); DCHECK(dict.is_dict());
......
...@@ -232,9 +232,18 @@ void SecurelyClearBuffer(void* buffer, size_t length); ...@@ -232,9 +232,18 @@ void SecurelyClearBuffer(void* buffer, size_t length);
// Helpers to get strings from base::Values that are expected to be // Helpers to get strings from base::Values that are expected to be
// DictionaryValues. // DictionaryValues.
base::string16 GetDictString(const base::Value& dict, const char* name); base::string16 GetDictString(const base::Value& dict, const char* name);
base::string16 GetDictString(const std::unique_ptr<base::Value>& dict, base::string16 GetDictString(const std::unique_ptr<base::Value>& dict,
const char* name); const char* name);
// Perform a recursive search on a nested dictionary object. Note that the
// names provided in the input should be in order. Below is an example : Lets
// say the json object is {"key1": {"key2": {"key3": "value1"}}, "key4":
// "value2"}. Then to search for the key "key3", this method should be called
// by providing the names vector as {"key1", "key2", "key3"}.
std::string SearchForKeyInStringDictUTF8(
const std::string& json_string,
const std::initializer_list<base::StringPiece>& path);
std::string GetDictStringUTF8(const base::Value& dict, const char* name); std::string GetDictStringUTF8(const base::Value& dict, const char* name);
std::string GetDictStringUTF8(const std::unique_ptr<base::Value>& dict, std::string GetDictStringUTF8(const std::unique_ptr<base::Value>& dict,
const char* name); const char* name);
......
...@@ -72,6 +72,11 @@ void OSUserManager::SetInstanceForTesting(OSUserManager* instance) { ...@@ -72,6 +72,11 @@ void OSUserManager::SetInstanceForTesting(OSUserManager* instance) {
*GetInstanceStorage() = instance; *GetInstanceStorage() = instance;
} }
// static
bool OSUserManager::IsDeviceDomainJoined() {
return base::win::IsEnrolledToDomain();
}
// static // static
base::string16 OSUserManager::GetLocalDomain() { base::string16 OSUserManager::GetLocalDomain() {
// If the domain is the current computer, then there is no domain controller. // If the domain is the current computer, then there is no domain controller.
......
...@@ -99,6 +99,9 @@ class [[clang::lto_visibility_public]] OSUserManager { ...@@ -99,6 +99,9 @@ class [[clang::lto_visibility_public]] OSUserManager {
// to another. // to another.
static void SetInstanceForTesting(OSUserManager* instance); static void SetInstanceForTesting(OSUserManager* instance);
// Checks if the device is domain joined.
virtual bool IsDeviceDomainJoined();
protected: protected:
OSUserManager() {} OSUserManager() {}
......
...@@ -69,6 +69,12 @@ HRESULT WinHttpUrlFetcher::SetRequestBody(const char* body) { ...@@ -69,6 +69,12 @@ HRESULT WinHttpUrlFetcher::SetRequestBody(const char* body) {
return S_OK; return S_OK;
} }
HRESULT WinHttpUrlFetcher::SetHttpRequestTimeout(const int timeout_in_millis) {
DCHECK(timeout_in_millis);
timeout_in_millis_ = timeout_in_millis;
return S_OK;
}
HRESULT WinHttpUrlFetcher::Fetch(std::vector<char>* response) { HRESULT WinHttpUrlFetcher::Fetch(std::vector<char>* response) {
USES_CONVERSION; USES_CONVERSION;
DCHECK(response); DCHECK(response);
...@@ -93,6 +99,19 @@ HRESULT WinHttpUrlFetcher::Fetch(std::vector<char>* response) { ...@@ -93,6 +99,19 @@ HRESULT WinHttpUrlFetcher::Fetch(std::vector<char>* response) {
connect.Set(connect_tmp); connect.Set(connect_tmp);
} }
{
// Set timeout if specified.
if (timeout_in_millis_ != 0) {
if (!::WinHttpSetTimeouts(session_.Get(), timeout_in_millis_,
timeout_in_millis_, timeout_in_millis_,
timeout_in_millis_)) {
HRESULT hr = HRESULT_FROM_WIN32(::GetLastError());
LOGFN(ERROR) << "WinHttpSetTimeouts hr=" << putHR(hr);
return hr;
}
}
}
{ {
bool use_post = !body_.empty(); bool use_post = !body_.empty();
ScopedWinHttpHandle::Handle request = ::WinHttpOpenRequest( ScopedWinHttpHandle::Handle request = ::WinHttpOpenRequest(
......
...@@ -27,6 +27,7 @@ class WinHttpUrlFetcher { ...@@ -27,6 +27,7 @@ class WinHttpUrlFetcher {
virtual HRESULT SetRequestHeader(const char* name, const char* value); virtual HRESULT SetRequestHeader(const char* name, const char* value);
virtual HRESULT SetRequestBody(const char* body); virtual HRESULT SetRequestBody(const char* body);
virtual HRESULT SetHttpRequestTimeout(const int timeout_in_millis);
virtual HRESULT Fetch(std::vector<char>* response); virtual HRESULT Fetch(std::vector<char>* response);
virtual HRESULT Close(); virtual HRESULT Close();
...@@ -48,6 +49,7 @@ class WinHttpUrlFetcher { ...@@ -48,6 +49,7 @@ class WinHttpUrlFetcher {
std::string body_; std::string body_;
ScopedWinHttpHandle session_; ScopedWinHttpHandle session_;
ScopedWinHttpHandle request_; ScopedWinHttpHandle request_;
int timeout_in_millis_ = 0;
// Gets storage of the function pointer used to create instances of this // Gets storage of the function pointer used to create instances of this
// class for tests. // class for tests.
......
...@@ -141,6 +141,7 @@ HRESULT FakeOSUserManager::AddUser(const wchar_t* username, ...@@ -141,6 +141,7 @@ HRESULT FakeOSUserManager::AddUser(const wchar_t* username,
return AddUser(username, password, fullname, comment, add_to_users_group, return AddUser(username, password, fullname, comment, add_to_users_group,
OSUserManager::GetLocalDomain().c_str(), sid, error); OSUserManager::GetLocalDomain().c_str(), sid, error);
} }
HRESULT FakeOSUserManager::AddUser(const wchar_t* username, HRESULT FakeOSUserManager::AddUser(const wchar_t* username,
const wchar_t* password, const wchar_t* password,
const wchar_t* fullname, const wchar_t* fullname,
...@@ -159,6 +160,11 @@ HRESULT FakeOSUserManager::AddUser(const wchar_t* username, ...@@ -159,6 +160,11 @@ HRESULT FakeOSUserManager::AddUser(const wchar_t* username,
if (should_fail_user_creation_) if (should_fail_user_creation_)
return E_FAIL; return E_FAIL;
// Username or password cannot be empty.
if (username == nullptr || !username[0] || password == nullptr ||
!password[0])
return E_FAIL;
bool user_found = username_to_info_.count(username) > 0; bool user_found = username_to_info_.count(username) > 0;
if (user_found) { if (user_found) {
...@@ -271,6 +277,10 @@ HRESULT FakeOSUserManager::CreateLogonToken(const wchar_t* domain, ...@@ -271,6 +277,10 @@ HRESULT FakeOSUserManager::CreateLogonToken(const wchar_t* domain,
return token->IsValid() ? S_OK : HRESULT_FROM_WIN32(::GetLastError()); return token->IsValid() ? S_OK : HRESULT_FROM_WIN32(::GetLastError());
} }
bool FakeOSUserManager::IsDeviceDomainJoined() {
return is_device_domain_joined_;
}
HRESULT FakeOSUserManager::GetUserSID(const wchar_t* domain, HRESULT FakeOSUserManager::GetUserSID(const wchar_t* domain,
const wchar_t* username, const wchar_t* username,
PSID* sid) { PSID* sid) {
...@@ -579,17 +589,30 @@ void FakeWinHttpUrlFetcherFactory::SetFakeResponse( ...@@ -579,17 +589,30 @@ void FakeWinHttpUrlFetcherFactory::SetFakeResponse(
Response(headers, response, send_response_event_handle); Response(headers, response, send_response_event_handle);
} }
void FakeWinHttpUrlFetcherFactory::SetFakeFailedResponse(const GURL& url,
HRESULT failed_hr) {
// Make sure that the HRESULT set is a failed attempt.
DCHECK(FAILED(failed_hr));
failed_http_fetch_hr_[url] = failed_hr;
}
std::unique_ptr<WinHttpUrlFetcher> FakeWinHttpUrlFetcherFactory::Create( std::unique_ptr<WinHttpUrlFetcher> FakeWinHttpUrlFetcherFactory::Create(
const GURL& url) { const GURL& url) {
if (fake_responses_.count(url) == 0) if (fake_responses_.count(url) == 0 && failed_http_fetch_hr_.count(url) == 0)
return nullptr; return nullptr;
const Response& response = fake_responses_[url];
FakeWinHttpUrlFetcher* fetcher = new FakeWinHttpUrlFetcher(std::move(url)); FakeWinHttpUrlFetcher* fetcher = new FakeWinHttpUrlFetcher(std::move(url));
fetcher->response_headers_ = response.headers;
fetcher->response_ = response.response; if (fake_responses_.count(url) != 0) {
fetcher->send_response_event_handle_ = response.send_response_event_handle; const Response& response = fake_responses_[url];
fetcher->response_headers_ = response.headers;
fetcher->response_ = response.response;
fetcher->send_response_event_handle_ = response.send_response_event_handle;
} else {
DCHECK(failed_http_fetch_hr_.count(url) > 0);
fetcher->response_hr_ = failed_http_fetch_hr_[url];
}
++requests_created_; ++requests_created_;
return std::unique_ptr<WinHttpUrlFetcher>(fetcher); return std::unique_ptr<WinHttpUrlFetcher>(fetcher);
...@@ -605,6 +628,9 @@ bool FakeWinHttpUrlFetcher::IsValid() const { ...@@ -605,6 +628,9 @@ bool FakeWinHttpUrlFetcher::IsValid() const {
} }
HRESULT FakeWinHttpUrlFetcher::Fetch(std::vector<char>* response) { HRESULT FakeWinHttpUrlFetcher::Fetch(std::vector<char>* response) {
if (FAILED(response_hr_))
return response_hr_;
if (send_response_event_handle_ != INVALID_HANDLE_VALUE) if (send_response_event_handle_ != INVALID_HANDLE_VALUE)
::WaitForSingleObject(send_response_event_handle_, INFINITE); ::WaitForSingleObject(send_response_event_handle_, INFINITE);
......
...@@ -69,6 +69,15 @@ class FakeOSUserManager : public OSUserManager { ...@@ -69,6 +69,15 @@ class FakeOSUserManager : public OSUserManager {
bool add_to_users_group, bool add_to_users_group,
BSTR* sid, BSTR* sid,
DWORD* error) override; DWORD* error) override;
// Add a user to the OS with domain associated with it.
HRESULT AddUser(const wchar_t* username,
const wchar_t* password,
const wchar_t* fullname,
const wchar_t* comment,
bool add_to_users_group,
const wchar_t* domain,
BSTR* sid,
DWORD* error);
HRESULT ChangeUserPassword(const wchar_t* domain, HRESULT ChangeUserPassword(const wchar_t* domain,
const wchar_t* username, const wchar_t* username,
const wchar_t* password, const wchar_t* password,
...@@ -103,10 +112,16 @@ class FakeOSUserManager : public OSUserManager { ...@@ -103,10 +112,16 @@ class FakeOSUserManager : public OSUserManager {
const wchar_t* username, const wchar_t* username,
bool allow) override; bool allow) override;
bool IsDeviceDomainJoined() override;
void SetShouldFailUserCreation(bool should_fail) { void SetShouldFailUserCreation(bool should_fail) {
should_fail_user_creation_ = should_fail; should_fail_user_creation_ = should_fail;
} }
void SetIsDeviceDomainJoined(bool is_device_domain_joined) {
is_device_domain_joined_ = is_device_domain_joined;
}
struct UserInfo { struct UserInfo {
UserInfo(const wchar_t* domain, UserInfo(const wchar_t* domain,
const wchar_t* password, const wchar_t* password,
...@@ -165,16 +180,7 @@ class FakeOSUserManager : public OSUserManager { ...@@ -165,16 +180,7 @@ class FakeOSUserManager : public OSUserManager {
DWORD next_rid_ = 0; DWORD next_rid_ = 0;
std::map<base::string16, UserInfo> username_to_info_; std::map<base::string16, UserInfo> username_to_info_;
bool should_fail_user_creation_ = false; bool should_fail_user_creation_ = false;
bool is_device_domain_joined_ = false;
// Add a user to the OS with domain associated with it.
HRESULT AddUser(const wchar_t* username,
const wchar_t* password,
const wchar_t* fullname,
const wchar_t* comment,
bool add_to_users_group,
const wchar_t* domain,
BSTR* sid,
DWORD* error);
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -273,6 +279,12 @@ class FakeWinHttpUrlFetcherFactory { ...@@ -273,6 +279,12 @@ class FakeWinHttpUrlFetcherFactory {
const WinHttpUrlFetcher::Headers& headers, const WinHttpUrlFetcher::Headers& headers,
const std::string& response, const std::string& response,
HANDLE send_response_event_handle = INVALID_HANDLE_VALUE); HANDLE send_response_event_handle = INVALID_HANDLE_VALUE);
// Sets the response as a failed http attempt. The return result
// from http_url_fetcher.Fetch() would be set as the input HRESULT
// to this method.
void SetFakeFailedResponse(const GURL& url, HRESULT failed_hr);
size_t requests_created() const { return requests_created_; } size_t requests_created() const { return requests_created_; }
private: private:
...@@ -293,6 +305,7 @@ class FakeWinHttpUrlFetcherFactory { ...@@ -293,6 +305,7 @@ class FakeWinHttpUrlFetcherFactory {
}; };
std::map<GURL, Response> fake_responses_; std::map<GURL, Response> fake_responses_;
std::map<GURL, HRESULT> failed_http_fetch_hr_;
size_t requests_created_ = 0; size_t requests_created_ = 0;
}; };
...@@ -316,6 +329,7 @@ class FakeWinHttpUrlFetcher : public WinHttpUrlFetcher { ...@@ -316,6 +329,7 @@ class FakeWinHttpUrlFetcher : public WinHttpUrlFetcher {
Headers response_headers_; Headers response_headers_;
std::string response_; std::string response_;
HANDLE send_response_event_handle_; HANDLE send_response_event_handle_;
HRESULT response_hr_ = S_OK;
}; };
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
......
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