blob: 088e98b17d7bd270b3394dd932935a013eb49ce7 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_CREDENTIAL_PROVIDER_TEST_GCP_FAKES_H_
#define CHROME_CREDENTIAL_PROVIDER_TEST_GCP_FAKES_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/strings/string16.h"
#include "base/test/test_reg_util_win.h"
#include "base/win/scoped_handle.h"
#include "chrome/credential_provider/gaiacp/associated_user_validator.h"
#include "chrome/credential_provider/gaiacp/internet_availability_checker.h"
#include "chrome/credential_provider/gaiacp/os_process_manager.h"
#include "chrome/credential_provider/gaiacp/os_user_manager.h"
#include "chrome/credential_provider/gaiacp/password_recovery_manager.h"
#include "chrome/credential_provider/gaiacp/scoped_lsa_policy.h"
#include "chrome/credential_provider/gaiacp/scoped_user_profile.h"
#include "chrome/credential_provider/gaiacp/win_http_url_fetcher.h"
namespace base {
class WaitableEvent;
}
namespace credential_provider {
void InitializeRegistryOverrideForTesting(
registry_util::RegistryOverrideManager* registry_override);
///////////////////////////////////////////////////////////////////////////////
class FakeOSProcessManager : public OSProcessManager {
public:
FakeOSProcessManager();
~FakeOSProcessManager() override;
// OSProcessManager
HRESULT GetTokenLogonSID(const base::win::ScopedHandle& token,
PSID* sid) override;
HRESULT SetupPermissionsForLogonSid(PSID sid) override;
HRESULT CreateProcessWithToken(
const base::win::ScopedHandle& logon_token,
const base::CommandLine& command_line,
_STARTUPINFOW* startupinfo,
base::win::ScopedProcessInformation* procinfo) override;
private:
OSProcessManager* original_manager_;
DWORD next_rid_ = 0;
};
///////////////////////////////////////////////////////////////////////////////
class FakeOSUserManager : public OSUserManager {
public:
FakeOSUserManager();
~FakeOSUserManager() override;
// OSUserManager
HRESULT GenerateRandomPassword(wchar_t* password, int length) override;
HRESULT AddUser(const wchar_t* username,
const wchar_t* password,
const wchar_t* fullname,
const wchar_t* comment,
bool add_to_users_group,
BSTR* sid,
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,
const wchar_t* username,
const wchar_t* password,
const wchar_t* old_password) override;
HRESULT SetUserPassword(const wchar_t* domain,
const wchar_t* username,
const wchar_t* password) override;
HRESULT IsWindowsPasswordValid(const wchar_t* domain,
const wchar_t* username,
const wchar_t* password) override;
HRESULT CreateLogonToken(const wchar_t* domain,
const wchar_t* username,
const wchar_t* password,
bool interactive,
base::win::ScopedHandle* token) override;
HRESULT GetUserSID(const wchar_t* domain,
const wchar_t* username,
PSID* sid) override;
HRESULT FindUserBySID(const wchar_t* sid,
wchar_t* username,
DWORD username_size,
wchar_t* domain,
DWORD domain_size) override;
HRESULT RemoveUser(const wchar_t* username, const wchar_t* password) override;
HRESULT GetUserFullname(const wchar_t* domain,
const wchar_t* username,
base::string16* fullname) override;
HRESULT ModifyUserAccessWithLogonHours(const wchar_t* domain,
const wchar_t* username,
bool allow) override;
bool IsDeviceDomainJoined() override;
void SetShouldFailUserCreation(bool 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 {
UserInfo(const wchar_t* domain,
const wchar_t* password,
const wchar_t* fullname,
const wchar_t* comment,
const wchar_t* sid);
UserInfo();
UserInfo(const UserInfo& other);
~UserInfo();
bool operator==(const UserInfo& other) const;
base::string16 domain;
base::string16 password;
base::string16 fullname;
base::string16 comment;
base::string16 sid;
};
const UserInfo GetUserInfo(const wchar_t* username);
// Creates a new unique sid. Free returned sid with FreeSid().
HRESULT CreateNewSID(PSID* sid);
// Creates a fake user with the given |username|, |password|, |fullname|,
// |comment|. If |gaia_id| is non-empty, also associates the user with
// the given gaia id. If |email| is non-empty, sets the email to use for
// reauth to be this one.
// |sid| is allocated and filled with the SID of the new user.
HRESULT CreateTestOSUser(const base::string16& username,
const base::string16& password,
const base::string16& fullname,
const base::string16& comment,
const base::string16& gaia_id,
const base::string16& email,
BSTR* sid);
// Creates a fake user with the given |username|, |password|, |fullname|,
// |comment| and |domain|. If |gaia_id| is non-empty, also associates the
// user with the given gaia id. If |email| is non-empty, sets the email to
// use for reauth to be this one.
// |sid| is allocated and filled with the SID of the new user.
HRESULT CreateTestOSUser(const base::string16& username,
const base::string16& password,
const base::string16& fullname,
const base::string16& comment,
const base::string16& gaia_id,
const base::string16& email,
const base::string16& domain,
BSTR* sid);
size_t GetUserCount() const { return username_to_info_.size(); }
std::vector<std::pair<base::string16, base::string16>> GetUsers() const;
private:
OSUserManager* original_manager_;
DWORD next_rid_ = 0;
std::map<base::string16, UserInfo> username_to_info_;
bool should_fail_user_creation_ = false;
bool is_device_domain_joined_ = false;
};
///////////////////////////////////////////////////////////////////////////////
class FakeScopedLsaPolicyFactory {
public:
FakeScopedLsaPolicyFactory();
virtual ~FakeScopedLsaPolicyFactory();
ScopedLsaPolicy::CreatorCallback GetCreatorCallback();
// PrivateDataMap is a string-to-string key/value store that maps private
// names to their corresponding data strings. The term "private" here is
// used to reflect the name of the underlying OS calls. This data is meant
// to be shared by all ScopedLsaPolicy instances created by this factory.
using PrivateDataMap = std::map<base::string16, base::string16>;
PrivateDataMap& private_data() { return private_data_; }
private:
std::unique_ptr<ScopedLsaPolicy> Create(ACCESS_MASK mask);
ScopedLsaPolicy::CreatorCallback original_creator_;
PrivateDataMap private_data_;
};
class FakeScopedLsaPolicy : public ScopedLsaPolicy {
public:
~FakeScopedLsaPolicy() override;
// ScopedLsaPolicy
HRESULT StorePrivateData(const wchar_t* key, const wchar_t* value) override;
HRESULT RemovePrivateData(const wchar_t* key) override;
HRESULT RetrievePrivateData(const wchar_t* key,
wchar_t* value,
size_t length) override;
HRESULT AddAccountRights(PSID sid, const wchar_t* right) override;
HRESULT RemoveAccount(PSID sid) override;
private:
friend class FakeScopedLsaPolicyFactory;
explicit FakeScopedLsaPolicy(FakeScopedLsaPolicyFactory* factory);
FakeScopedLsaPolicyFactory::PrivateDataMap& private_data() {
return factory_->private_data();
}
FakeScopedLsaPolicyFactory* factory_;
};
///////////////////////////////////////////////////////////////////////////////
// A scoped FakeScopedUserProfile factory. Installs itself when constructed
// and removes itself when deleted.
class FakeScopedUserProfileFactory {
public:
FakeScopedUserProfileFactory();
virtual ~FakeScopedUserProfileFactory();
private:
std::unique_ptr<ScopedUserProfile> Create(const base::string16& sid,
const base::string16& domain,
const base::string16& username,
const base::string16& password);
ScopedUserProfile::CreatorCallback original_creator_;
};
class FakeScopedUserProfile : public ScopedUserProfile {
public:
HRESULT SaveAccountInfo(const base::Value& properties) override;
private:
friend class FakeScopedUserProfileFactory;
FakeScopedUserProfile(const base::string16& sid,
const base::string16& domain,
const base::string16& username,
const base::string16& password);
~FakeScopedUserProfile() override;
bool is_valid_ = false;
};
///////////////////////////////////////////////////////////////////////////////
// A scoped FakeWinHttpUrlFetcher factory. Installs itself when constructed
// and removes itself when deleted.
class FakeWinHttpUrlFetcherFactory {
public:
FakeWinHttpUrlFetcherFactory();
~FakeWinHttpUrlFetcherFactory();
void SetFakeResponse(
const GURL& url,
const WinHttpUrlFetcher::Headers& headers,
const std::string& response,
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_; }
private:
std::unique_ptr<WinHttpUrlFetcher> Create(const GURL& url);
WinHttpUrlFetcher::CreatorCallback original_creator_;
struct Response {
Response();
Response(const Response& rhs);
Response(const WinHttpUrlFetcher::Headers& new_headers,
const std::string& new_response,
HANDLE new_send_response_event_handle);
~Response();
WinHttpUrlFetcher::Headers headers;
std::string response;
HANDLE send_response_event_handle;
};
std::map<GURL, Response> fake_responses_;
std::map<GURL, HRESULT> failed_http_fetch_hr_;
size_t requests_created_ = 0;
};
class FakeWinHttpUrlFetcher : public WinHttpUrlFetcher {
public:
explicit FakeWinHttpUrlFetcher(const GURL& url);
~FakeWinHttpUrlFetcher() override;
using WinHttpUrlFetcher::Headers;
const Headers& response_headers() const { return response_headers_; }
// WinHttpUrlFetcher
bool IsValid() const override;
HRESULT Fetch(std::vector<char>* response) override;
HRESULT Close() override;
private:
friend FakeWinHttpUrlFetcherFactory;
Headers response_headers_;
std::string response_;
HANDLE send_response_event_handle_;
HRESULT response_hr_ = S_OK;
};
///////////////////////////////////////////////////////////////////////////////
class FakeAssociatedUserValidator : public AssociatedUserValidator {
public:
FakeAssociatedUserValidator();
explicit FakeAssociatedUserValidator(base::TimeDelta validation_timeout);
~FakeAssociatedUserValidator() override;
using AssociatedUserValidator::ForceRefreshTokenHandlesForTesting;
using AssociatedUserValidator::IsUserAccessBlockedForTesting;
private:
AssociatedUserValidator* original_validator_ = nullptr;
};
///////////////////////////////////////////////////////////////////////////////
class FakeInternetAvailabilityChecker : public InternetAvailabilityChecker {
public:
enum HasInternetConnectionCheckType { kHicForceYes, kHicForceNo };
FakeInternetAvailabilityChecker(
HasInternetConnectionCheckType has_internet_connection = kHicForceYes);
~FakeInternetAvailabilityChecker() override;
bool HasInternetConnection() override;
void SetHasInternetConnection(
HasInternetConnectionCheckType has_internet_connection);
private:
InternetAvailabilityChecker* original_checker_ = nullptr;
// Used during tests to force the credential provider to believe if an
// internet connection is possible or not. In production the value is
// always set to HIC_CHECK_ALWAYS to perform a real check at runtime.
HasInternetConnectionCheckType has_internet_connection_ = kHicForceYes;
};
///////////////////////////////////////////////////////////////////////////////
class FakePasswordRecoveryManager : public PasswordRecoveryManager {
public:
FakePasswordRecoveryManager();
explicit FakePasswordRecoveryManager(base::TimeDelta request_timeout);
~FakePasswordRecoveryManager() override;
using PasswordRecoveryManager::MakeGenerateKeyPairResponseForTesting;
using PasswordRecoveryManager::MakeGetPrivateKeyResponseForTesting;
using PasswordRecoveryManager::SetRequestTimeoutForTesting;
private:
PasswordRecoveryManager* original_validator_ = nullptr;
};
} // namespace credential_provider
#endif // CHROME_CREDENTIAL_PROVIDER_TEST_GCP_FAKES_H_