Commit 042c5e67 authored by Rakesh Soma's avatar Rakesh Soma Committed by Commit Bot

When there is more than one username mapping for the cloud identity user, GCPW falls back to

new account creation irrespective of whether both those user mappings exist on the device.
We should instead fallback to new user creation only if we have multiple valid user mappings
on the device.

Bug: 1137547
Change-Id: I9924a3b07235a05472f35998fb5be869c43d83c1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2465584
Commit-Queue: Rakesh Soma <rakeshsoma@google.com>
Reviewed-by: default avatarYusuf Sengul <yusufsn@google.com>
Cr-Commit-Position: refs/heads/master@{#816695}
parent 7540893b
...@@ -247,9 +247,11 @@ HRESULT GetUserAndDomainInfo( ...@@ -247,9 +247,11 @@ HRESULT GetUserAndDomainInfo(
BSTR* error_text) { BSTR* error_text) {
base::string16 user_name; base::string16 user_name;
base::string16 domain_name; base::string16 domain_name;
OSUserManager* os_user_manager = OSUserManager::Get();
DCHECK(os_user_manager);
bool is_ad_user = bool is_ad_user =
OSUserManager::Get()->IsDeviceDomainJoined() && !sam_account_name.empty(); os_user_manager->IsDeviceDomainJoined() && !sam_account_name.empty();
// Login via existing AD account mapping when the device is domain joined if // Login via existing AD account mapping when the device is domain joined if
// the AD account mapping is available. // the AD account mapping is available.
if (is_ad_user) { if (is_ad_user) {
...@@ -302,6 +304,14 @@ HRESULT GetUserAndDomainInfo( ...@@ -302,6 +304,14 @@ HRESULT GetUserAndDomainInfo(
re2::RE2::FullMatch(local_account_name, "un:([^,]+)(?:,sn:([^,]+))?", re2::RE2::FullMatch(local_account_name, "un:([^,]+)(?:,sn:([^,]+))?",
&username, &serial_number); &username, &serial_number);
// Only collect those user names that exist on the windows device.
base::string16 existing_sid;
HRESULT hr = os_user_manager->GetUserSID(
OSUserManager::GetLocalDomain().c_str(),
base::UTF8ToUTF16(username).c_str(), &existing_sid);
if (FAILED(hr))
continue;
LOGFN(VERBOSE) << "RE2 username : " << username; LOGFN(VERBOSE) << "RE2 username : " << username;
LOGFN(VERBOSE) << "RE2 serial_number : " << serial_number; LOGFN(VERBOSE) << "RE2 serial_number : " << serial_number;
...@@ -334,8 +344,6 @@ HRESULT GetUserAndDomainInfo( ...@@ -334,8 +344,6 @@ HRESULT GetUserAndDomainInfo(
domain_name = OSUserManager::GetLocalDomain(); domain_name = OSUserManager::GetLocalDomain();
} }
OSUserManager* os_user_manager = OSUserManager::Get();
DCHECK(os_user_manager);
LOGFN(VERBOSE) << "Get user sid for user " << user_name << " and domain name " LOGFN(VERBOSE) << "Get user sid for user " << user_name << " and domain name "
<< domain_name; << domain_name;
HRESULT hr = os_user_manager->GetUserSID(domain_name.c_str(), HRESULT hr = os_user_manager->GetUserSID(domain_name.c_str(),
......
...@@ -1832,6 +1832,49 @@ TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, ...@@ -1832,6 +1832,49 @@ TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0)); ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
} }
// Customer configured invalid local account info.
TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
GetSerialization_InvalidLocalAccountToSerialNumberConfigured) {
// Set token result a valid access token.
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
// Set a fake serial number.
base::string16 serial_number = L"1234";
GoogleRegistrationDataForTesting g_registration_data(serial_number);
const wchar_t invalid_user_name_1[] = L"invalid_user_name_1";
const wchar_t invalid_user_name_2[] = L"invalid_user_name_2";
// Invalid configuration in admin sdk. Don't set valid usernames.
std::string admin_sdk_response = base::StringPrintf(
"{\"customSchemas\": {\"Enhanced_desktop_security\": "
"{\"Local_Windows_accounts\":"
"[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls,sn:%ls\"}]}}}",
invalid_user_name_1, serial_number.c_str(), invalid_user_name_2,
serial_number.c_str());
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
admin_sdk_response);
Microsoft::WRL::ComPtr<ITestCredential> test;
ASSERT_EQ(S_OK, cred_.As(&test));
ASSERT_EQ(S_OK, StartLogonProcessAndWait());
// Make sure new user was created since no valid mapping was found.
PSID sid = nullptr;
fake_os_user_manager()->GetUserSID(OSUserManager::GetLocalDomain().c_str(),
kDefaultUsername, &sid);
ASSERT_NE(nullptr, sid);
// New user is created.
EXPECT_EQ(2ul, fake_os_user_manager()->GetUserCount());
ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
}
TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, MultipleLocalAccountInfo) { TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, MultipleLocalAccountInfo) {
// Add the user as a local user. // Add the user as a local user.
const wchar_t user_name[] = L"local_user"; const wchar_t user_name[] = L"local_user";
...@@ -1976,6 +2019,223 @@ TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, ...@@ -1976,6 +2019,223 @@ TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
ASSERT_TRUE(test->IsAuthenticationResultsEmpty()); ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
} }
TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
OnlyOneValidUserToSerialMapping) {
// Add the user as a local user.
const wchar_t user_name[] = L"local_user";
const wchar_t password[] = L"password";
CComBSTR local_sid;
DWORD error;
HRESULT hr = fake_os_user_manager()->AddUser(
user_name, password, L"fullname", L"comment", true, &local_sid, &error);
ASSERT_EQ(S_OK, hr);
ASSERT_EQ(0u, error);
// Set token result as a valid access token.
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
std::string admin_sdk_response;
// Set a fake serial number.
base::string16 serial_number = L"1234";
GoogleRegistrationDataForTesting g_registration_data(serial_number);
const wchar_t another_user_name1[] = L"another_local_user_1";
// Set valid response from admin sdk with Local_Windows_accounts containing
// multiple mappings with matching "serial_number" in it and another
// one without serial number.
admin_sdk_response = base::StringPrintf(
"{\"customSchemas\": {\"Enhanced_desktop_security\": "
"{\"Local_Windows_accounts\":"
"[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls,sn:%ls\" }]}}}",
another_user_name1, serial_number.c_str(), user_name,
serial_number.c_str());
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
admin_sdk_response);
Microsoft::WRL::ComPtr<ITestCredential> test;
ASSERT_EQ(S_OK, cred_.As(&test));
ASSERT_EQ(S_OK, StartLogonProcessAndWait());
EXPECT_EQ(test->GetFinalEmail(), kDefaultEmail);
// Make sure no user was created and the login happens on the
// existing user instead.
PSID sid = nullptr;
EXPECT_EQ(
HRESULT_FROM_WIN32(NERR_UserNotFound),
fake_os_user_manager()->GetUserSID(
OSUserManager::GetLocalDomain().c_str(), kDefaultUsername, &sid));
ASSERT_EQ(nullptr, sid);
// Finishing logon process should trigger credential changed and trigger
// GetSerialization.
ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
// Verify that the registry entry for the user was created.
std::wstring sid_str(local_sid, SysStringLen(local_sid));
wchar_t gaia_id[256];
ULONG length = base::size(gaia_id);
HRESULT gaia_id_hr =
GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
ASSERT_EQ(S_OK, gaia_id_hr);
ASSERT_TRUE(gaia_id[0]);
// Verify that the authentication results dictionary is now empty.
ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
}
TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, OnlyOneValidUserMapping) {
// Add the user as a local user.
const wchar_t user_name[] = L"local_user";
const wchar_t password[] = L"password";
CComBSTR local_sid;
DWORD error;
HRESULT hr = fake_os_user_manager()->AddUser(
user_name, password, L"fullname", L"comment", true, &local_sid, &error);
ASSERT_EQ(S_OK, hr);
ASSERT_EQ(0u, error);
// Set token result as a valid access token.
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
std::string admin_sdk_response;
// Set a fake serial number.
base::string16 serial_number = L"1234";
GoogleRegistrationDataForTesting g_registration_data(serial_number);
const wchar_t another_user_name1[] = L"another_local_user_1";
// Set valid response from admin sdk with Local_Windows_accounts containing
// multiple mappings with matching "serial_number" in it and another
// one without serial number.
admin_sdk_response = base::StringPrintf(
"{\"customSchemas\": {\"Enhanced_desktop_security\": "
"{\"Local_Windows_accounts\":"
"[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls,sn:%ls\" }]}}}",
another_user_name1, serial_number.c_str(), user_name,
serial_number.c_str());
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
admin_sdk_response);
Microsoft::WRL::ComPtr<ITestCredential> test;
ASSERT_EQ(S_OK, cred_.As(&test));
ASSERT_EQ(S_OK, StartLogonProcessAndWait());
EXPECT_EQ(test->GetFinalEmail(), kDefaultEmail);
// Make sure no user was created and the login happens on the
// existing user instead.
PSID sid = nullptr;
EXPECT_EQ(
HRESULT_FROM_WIN32(NERR_UserNotFound),
fake_os_user_manager()->GetUserSID(
OSUserManager::GetLocalDomain().c_str(), kDefaultUsername, &sid));
ASSERT_EQ(nullptr, sid);
// Finishing logon process should trigger credential changed and trigger
// GetSerialization.
ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
// Verify that the registry entry for the user was created.
std::wstring sid_str(local_sid, SysStringLen(local_sid));
wchar_t gaia_id[256];
ULONG length = base::size(gaia_id);
HRESULT gaia_id_hr =
GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
ASSERT_EQ(S_OK, gaia_id_hr);
ASSERT_TRUE(gaia_id[0]);
// Verify that the authentication results dictionary is now empty.
ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
}
TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
InvalidUsersToSerialNumberMapping) {
// Add the user as a local user.
const wchar_t user_name[] = L"local_user";
const wchar_t password[] = L"password";
CComBSTR local_sid;
DWORD error;
HRESULT hr = fake_os_user_manager()->AddUser(
user_name, password, L"fullname", L"comment", true, &local_sid, &error);
ASSERT_EQ(S_OK, hr);
ASSERT_EQ(0u, error);
// Set token result as a valid access token.
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(gaia_urls_->oauth2_token_url().spec().c_str()),
FakeWinHttpUrlFetcher::Headers(), "{\"access_token\": \"dummy_token\"}");
std::string admin_sdk_response;
// Set a fake serial number.
base::string16 serial_number = L"1234";
GoogleRegistrationDataForTesting g_registration_data(serial_number);
const wchar_t another_user_name1[] = L"another_local_user_1";
const wchar_t another_user_name2[] = L"another_local_user_2";
// Set valid response from admin sdk with Local_Windows_accounts containing
// multiple mappings with matching "serial_number" in it and another
// one without serial number.
admin_sdk_response = base::StringPrintf(
"{\"customSchemas\": {\"Enhanced_desktop_security\": "
"{\"Local_Windows_accounts\":"
"[{ \"value\": \"un:%ls,sn:%ls\" },{ \"value\": \"un:%ls,sn:%ls\" },{ "
" \"value\": \"un:%ls\" }]}}}",
another_user_name1, serial_number.c_str(), another_user_name2,
serial_number.c_str(), user_name);
fake_http_url_fetcher_factory()->SetFakeResponse(
GURL(get_cd_user_url_.c_str()), FakeWinHttpUrlFetcher::Headers(),
admin_sdk_response);
Microsoft::WRL::ComPtr<ITestCredential> test;
ASSERT_EQ(S_OK, cred_.As(&test));
ASSERT_EQ(S_OK, StartLogonProcessAndWait());
EXPECT_EQ(test->GetFinalEmail(), kDefaultEmail);
// Make sure no user was created and the login happens on the
// existing user instead.
PSID sid = nullptr;
EXPECT_EQ(
HRESULT_FROM_WIN32(NERR_UserNotFound),
fake_os_user_manager()->GetUserSID(
OSUserManager::GetLocalDomain().c_str(), kDefaultUsername, &sid));
ASSERT_EQ(nullptr, sid);
// Finishing logon process should trigger credential changed and trigger
// GetSerialization.
ASSERT_EQ(S_OK, FinishLogonProcess(true, true, 0));
// Verify that the registry entry for the user was created.
std::wstring sid_str(local_sid, SysStringLen(local_sid));
wchar_t gaia_id[256];
ULONG length = base::size(gaia_id);
HRESULT gaia_id_hr =
GetUserProperty(sid_str.c_str(), kUserId, gaia_id, &length);
ASSERT_EQ(S_OK, gaia_id_hr);
ASSERT_TRUE(gaia_id[0]);
// Verify that the authentication results dictionary is now empty.
ASSERT_TRUE(test->IsAuthenticationResultsEmpty());
}
TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest, TEST_F(GcpGaiaCredentialBaseCloudLocalAccountTest,
MultipleValidLocalAccountInfoMapping) { MultipleValidLocalAccountInfoMapping) {
// Set token result as a valid access token. // Set token result as a valid access token.
......
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