Commit bdb0d41f authored by Pavol Marko's avatar Pavol Marko Committed by Commit Bot

Allow multi sign-in even when policy-pushed trusted CA certs are active

Historically, multi sign-in was disallowed when either the primary
Profile or the Profile being added used / had used policy-pushed CA
certificates. The reason for limiting this was that the certificate
verifier used at that time (NSS) had process-wide caches, so certificate
verification results could leak across Profiles.

Now that we use the built-in certificate verifier, this risk does not
exist, so allow multi sign-in regardless of the policy-pushed
certificate state of the primary / secondary Profiles.

Also move clearing of the local_state pref that tracks policy-pushed
certificate usage for a Profile into UserSessionManagerImpl because
MultiProfileUserController does not have a dependency on the
policy-pushed certs infrastructure anymore. In a follow-up the pref can
likely be migrated to be a user Profile pref now instead of a
local_state pref.

Bug: 718002
Test: unit tests, browser tests
Change-Id: I1006e0cb1cb4c9fdd68f5373e18acb27f5c3eaea
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2297566
Commit-Queue: Pavol Marko <pmarko@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarRyan Sleevi <rsleevi@chromium.org>
Reviewed-by: default avatarDenis Kuznetsov [CET] <antrim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808879}
parent a9e56b9c
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include "chrome/browser/chromeos/policy/external_data_handlers/printers_external_data_handler.h" #include "chrome/browser/chromeos/policy/external_data_handlers/printers_external_data_handler.h"
#include "chrome/browser/chromeos/policy/external_data_handlers/user_avatar_image_external_data_handler.h" #include "chrome/browser/chromeos/policy/external_data_handlers/user_avatar_image_external_data_handler.h"
#include "chrome/browser/chromeos/policy/external_data_handlers/wallpaper_image_external_data_handler.h" #include "chrome/browser/chromeos/policy/external_data_handlers/wallpaper_image_external_data_handler.h"
#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
#include "chrome/browser/chromeos/policy/user_network_configuration_updater.h" #include "chrome/browser/chromeos/policy/user_network_configuration_updater.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/session_length_limiter.h" #include "chrome/browser/chromeos/session_length_limiter.h"
...@@ -1019,6 +1020,9 @@ void ChromeUserManagerImpl::RemoveNonCryptohomeData( ...@@ -1019,6 +1020,9 @@ void ChromeUserManagerImpl::RemoveNonCryptohomeData(
multi_profile_user_controller_->RemoveCachedValues(account_id.GetUserEmail()); multi_profile_user_controller_->RemoveCachedValues(account_id.GetUserEmail());
policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(
account_id.GetUserEmail());
EasyUnlockService::ResetLocalStateForUser(account_id); EasyUnlockService::ResetLocalStateForUser(account_id);
ChromeUserManager::RemoveNonCryptohomeData(account_id); ChromeUserManager::RemoveNonCryptohomeData(account_id);
......
...@@ -9,8 +9,6 @@ ...@@ -9,8 +9,6 @@
#include "ash/public/cpp/login_types.h" #include "ash/public/cpp/login_types.h"
#include "base/bind.h" #include "base/bind.h"
#include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h" #include "chrome/browser/chromeos/login/users/multi_profile_user_controller_delegate.h"
#include "chrome/browser/chromeos/policy/policy_cert_service.h"
#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h" #include "chrome/common/pref_names.h"
...@@ -92,27 +90,10 @@ MultiProfileUserController::GetPrimaryUserPolicy() { ...@@ -92,27 +90,10 @@ MultiProfileUserController::GetPrimaryUserPolicy() {
if (!user) if (!user)
return ALLOWED; return ALLOWED;
// Don't allow any secondary profiles if the primary profile is tainted.
if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(
user->GetAccountId().GetUserEmail())) {
// Check directly in local_state before checking if the primary user has
// a PolicyCertService. Their profile may have been tainted previously
// though they didn't get a PolicyCertService created for this session.
return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED;
}
Profile* profile = ProfileHelper::Get()->GetProfileByUser(user); Profile* profile = ProfileHelper::Get()->GetProfileByUser(user);
if (!profile) if (!profile)
return ALLOWED; return ALLOWED;
// If the primary profile already has policy certificates installed but
// hasn't used them yet then it can become tainted at any time during this
// session disable secondary profiles in this case too.
policy::PolicyCertService* service =
policy::PolicyCertServiceFactory::GetForProfile(profile);
if (service && service->has_policy_certificates())
return NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED;
// No user is allowed if the primary user policy forbids it. // No user is allowed if the primary user policy forbids it.
const std::string behavior = const std::string behavior =
profile->GetPrefs()->GetString(prefs::kMultiProfileUserBehavior); profile->GetPrefs()->GetString(prefs::kMultiProfileUserBehavior);
...@@ -152,11 +133,6 @@ bool MultiProfileUserController::IsUserAllowedInSession( ...@@ -152,11 +133,6 @@ bool MultiProfileUserController::IsUserAllowedInSession(
if (primary_user_email.empty() || primary_user_email == user_email) if (primary_user_email.empty() || primary_user_email == user_email)
return SetUserAllowedReason(reason, ALLOWED); return SetUserAllowedReason(reason, ALLOWED);
// Don't allow profiles potentially tainted by data fetched with policy-pushed
// certificates to join a multiprofile session.
if (policy::PolicyCertServiceFactory::UsedPolicyCertificates(user_email))
return SetUserAllowedReason(reason, NOT_ALLOWED_POLICY_CERT_TAINTED);
UserAllowedInSessionReason primary_user_policy = GetPrimaryUserPolicy(); UserAllowedInSessionReason primary_user_policy = GetPrimaryUserPolicy();
if (primary_user_policy != ALLOWED) if (primary_user_policy != ALLOWED)
return SetUserAllowedReason(reason, primary_user_policy); return SetUserAllowedReason(reason, primary_user_policy);
...@@ -188,7 +164,6 @@ void MultiProfileUserController::RemoveCachedValues( ...@@ -188,7 +164,6 @@ void MultiProfileUserController::RemoveCachedValues(
DictionaryPrefUpdate update(local_state_, DictionaryPrefUpdate update(local_state_,
prefs::kCachedMultiProfileUserBehavior); prefs::kCachedMultiProfileUserBehavior);
update->RemoveWithoutPathExpansion(user_email, NULL); update->RemoveWithoutPathExpansion(user_email, NULL);
policy::PolicyCertServiceFactory::ClearUsedPolicyCertificates(user_email);
} }
std::string MultiProfileUserController::GetCachedValue( std::string MultiProfileUserController::GetCachedValue(
......
...@@ -42,14 +42,6 @@ class MultiProfileUserController { ...@@ -42,14 +42,6 @@ class MultiProfileUserController {
// Owner of the device is not allowed to be added as a secondary user. // Owner of the device is not allowed to be added as a secondary user.
NOT_ALLOWED_OWNER_AS_SECONDARY, NOT_ALLOWED_OWNER_AS_SECONDARY,
// Not allowed since it is potentially "tainted" with policy-pushed
// certificates.
NOT_ALLOWED_POLICY_CERT_TAINTED,
// Not allowed since primary user is already "tainted" with policy-pushed
// certificates.
NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED,
// Not allowed since primary user policy forbids it to be part of // Not allowed since primary user policy forbids it to be part of
// multi-profiles session. // multi-profiles session.
NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS, NOT_ALLOWED_PRIMARY_USER_POLICY_FORBIDS,
......
...@@ -348,9 +348,9 @@ TEST_F(MultiProfileUserControllerTest, ...@@ -348,9 +348,9 @@ TEST_F(MultiProfileUserControllerTest,
} }
TEST_F(MultiProfileUserControllerTest, TEST_F(MultiProfileUserControllerTest,
UsedPolicyCertificatesDisallowedForSecondary) { UsedPolicyCertificatesAllowedForSecondary) {
// Verifies that if a regular user is signed-in then other regular users can // Verifies that if a regular user is signed-in then other regular users can
// be added but tainted users can't. // be added, including users that have used policy-provided trust anchors.
LoginUser(1); LoginUser(1);
// TODO(xiyuan): Remove the following SetPrefBehavor when default is // TODO(xiyuan): Remove the following SetPrefBehavor when default is
...@@ -364,16 +364,15 @@ TEST_F(MultiProfileUserControllerTest, ...@@ -364,16 +364,15 @@ TEST_F(MultiProfileUserControllerTest,
policy::PolicyCertServiceFactory::SetUsedPolicyCertificates( policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(
test_users_[0].GetUserEmail()); test_users_[0].GetUserEmail());
EXPECT_FALSE(controller()->IsUserAllowedInSession( EXPECT_TRUE(controller()->IsUserAllowedInSession(
test_users_[0].GetUserEmail(), &reason)); test_users_[0].GetUserEmail(), &reason));
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_POLICY_CERT_TAINTED, EXPECT_EQ(MultiProfileUserController::ALLOWED, reason);
reason);
} }
TEST_F(MultiProfileUserControllerTest, TEST_F(MultiProfileUserControllerTest,
UsedPolicyCertificatesDisallowsSecondaries) { SecondaryAllowedWhenPrimaryUsedPolicyCertificates) {
// Verifies that if a tainted user is signed-in then no other users can // Verifies that if a tainted user is signed-in then other users can still be
// be added. // added.
policy::PolicyCertServiceFactory::SetUsedPolicyCertificates( policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(
test_users_[0].GetUserEmail()); test_users_[0].GetUserEmail());
LoginUser(0); LoginUser(0);
...@@ -383,19 +382,17 @@ TEST_F(MultiProfileUserControllerTest, ...@@ -383,19 +382,17 @@ TEST_F(MultiProfileUserControllerTest,
profile(0), base::BindRepeating(&TestPolicyCertServiceFactory))); profile(0), base::BindRepeating(&TestPolicyCertServiceFactory)));
MultiProfileUserController::UserAllowedInSessionReason reason; MultiProfileUserController::UserAllowedInSessionReason reason;
EXPECT_FALSE(controller()->IsUserAllowedInSession( EXPECT_TRUE(controller()->IsUserAllowedInSession(
test_users_[1].GetUserEmail(), &reason)); test_users_[1].GetUserEmail(), &reason));
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, EXPECT_EQ(MultiProfileUserController::ALLOWED, reason);
reason); EXPECT_EQ(MultiProfileUserController::ALLOWED,
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED,
MultiProfileUserController::GetPrimaryUserPolicy()); MultiProfileUserController::GetPrimaryUserPolicy());
policy::PolicyCertServiceFactory::SetUsedPolicyCertificates( policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(
test_users_[1].GetUserEmail()); test_users_[1].GetUserEmail());
EXPECT_FALSE(controller()->IsUserAllowedInSession( EXPECT_TRUE(controller()->IsUserAllowedInSession(
test_users_[1].GetUserEmail(), &reason)); test_users_[1].GetUserEmail(), &reason));
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_POLICY_CERT_TAINTED, EXPECT_EQ(MultiProfileUserController::ALLOWED, reason);
reason); EXPECT_EQ(MultiProfileUserController::ALLOWED,
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED,
MultiProfileUserController::GetPrimaryUserPolicy()); MultiProfileUserController::GetPrimaryUserPolicy());
// Flush tasks posted to IO. // Flush tasks posted to IO.
...@@ -405,7 +402,7 @@ TEST_F(MultiProfileUserControllerTest, ...@@ -405,7 +402,7 @@ TEST_F(MultiProfileUserControllerTest,
TEST_F(MultiProfileUserControllerTest, TEST_F(MultiProfileUserControllerTest,
PolicyCertificatesInMemoryDisallowsSecondaries) { PolicyCertificatesInMemoryDisallowsSecondaries) {
// Verifies that if a user is signed-in and has policy certificates installed // Verifies that if a user is signed-in and has policy certificates installed
// then no other users can be added. // then other users can still be added.
LoginUser(0); LoginUser(0);
// TODO(xiyuan): Remove the following SetPrefBehavor when default is // TODO(xiyuan): Remove the following SetPrefBehavor when default is
...@@ -432,11 +429,10 @@ TEST_F(MultiProfileUserControllerTest, ...@@ -432,11 +429,10 @@ TEST_F(MultiProfileUserControllerTest,
net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem")); net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"));
service->SetPolicyTrustAnchorsForTesting(/*trust_anchors=*/certificates); service->SetPolicyTrustAnchorsForTesting(/*trust_anchors=*/certificates);
EXPECT_TRUE(service->has_policy_certificates()); EXPECT_TRUE(service->has_policy_certificates());
EXPECT_FALSE(controller()->IsUserAllowedInSession( EXPECT_TRUE(controller()->IsUserAllowedInSession(
test_users_[1].GetUserEmail(), &reason)); test_users_[1].GetUserEmail(), &reason));
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED, EXPECT_EQ(MultiProfileUserController::ALLOWED, reason);
reason); EXPECT_EQ(MultiProfileUserController::ALLOWED,
EXPECT_EQ(MultiProfileUserController::NOT_ALLOWED_PRIMARY_POLICY_CERT_TAINTED,
MultiProfileUserController::GetPrimaryUserPolicy()); MultiProfileUserController::GetPrimaryUserPolicy());
// Flush tasks posted to IO. // Flush tasks posted to IO.
......
...@@ -3,13 +3,16 @@ ...@@ -3,13 +3,16 @@
// found in the LICENSE file. // found in the LICENSE file.
#include <memory> #include <memory>
#include <string>
#include "base/bind.h" #include "base/bind.h"
#include "base/callback_helpers.h" #include "base/callback_helpers.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/task/current_thread.h" #include "base/task/current_thread.h"
#include "base/threading/thread_restrictions.h" #include "base/threading/thread_restrictions.h"
#include "build/build_config.h" #include "build/build_config.h"
...@@ -32,7 +35,9 @@ ...@@ -32,7 +35,9 @@
#include "chrome/browser/chromeos/policy/user_network_configuration_updater_factory.h" #include "chrome/browser/chromeos/policy/user_network_configuration_updater_factory.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/net/nss_context.h" #include "chrome/browser/net/nss_context.h"
#include "chrome/browser/policy/profile_policy_connector_builder.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
...@@ -55,6 +60,7 @@ ...@@ -55,6 +60,7 @@
#include "components/session_manager/core/session_manager.h" #include "components/session_manager/core/session_manager.h"
#include "components/user_manager/user.h" #include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager.h"
#include "components/user_manager/user_type.h"
#include "components/version_info/version_info.h" #include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -77,6 +83,10 @@ ...@@ -77,6 +83,10 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
#if defined(OS_CHROMEOS)
#include "chromeos/constants/chromeos_switches.h"
#endif
namespace em = enterprise_management; namespace em = enterprise_management;
namespace policy { namespace policy {
...@@ -197,48 +207,54 @@ std::string GetTestCertsFileContents(const std::string& file_name) { ...@@ -197,48 +207,54 @@ std::string GetTestCertsFileContents(const std::string& file_name) {
class UserPolicyCertsHelper { class UserPolicyCertsHelper {
public: public:
UserPolicyCertsHelper() = default; UserPolicyCertsHelper() = default;
~UserPolicyCertsHelper() = default;
// Installs the BrowserPolicyConnector to set user policy. UserPolicyCertsHelper(const UserPolicyCertsHelper& other) = delete;
void SetUpInProcessBrowserTestFixture() { UserPolicyCertsHelper& operator=(const UserPolicyCertsHelper& other) = delete;
is_set_up_ = true;
// Reads in testing certificates.
// Run in ASSERT_NO_FATAL_FAILURE.
void Initialize() {
base::ScopedAllowBlockingForTesting allow_io; base::ScopedAllowBlockingForTesting allow_io;
base::FilePath test_certs_path = GetTestCertsPath(); base::FilePath test_certs_path = GetTestCertsPath();
base::FilePath server_cert_path = test_certs_path.AppendASCII(kServerCert); base::FilePath server_cert_path = test_certs_path.AppendASCII(kServerCert);
server_cert_ = net::ImportCertFromFile(server_cert_path.DirName(), server_cert_ = net::ImportCertFromFile(server_cert_path.DirName(),
server_cert_path.BaseName().value()); server_cert_path.BaseName().value());
ASSERT_TRUE(server_cert_);
base::FilePath root_cert_path = test_certs_path.AppendASCII(kRootCaCert); base::FilePath root_cert_path = test_certs_path.AppendASCII(kRootCaCert);
root_cert_ = net::ImportCertFromFile(root_cert_path.DirName(), root_cert_ = net::ImportCertFromFile(root_cert_path.DirName(),
root_cert_path.BaseName().value()); root_cert_path.BaseName().value());
ASSERT_TRUE(root_cert_);
base::FilePath server_cert_by_intermediate_path = base::FilePath server_cert_by_intermediate_path =
test_certs_path.AppendASCII(kServerCertByIntermediate); test_certs_path.AppendASCII(kServerCertByIntermediate);
server_cert_by_intermediate_ = net::ImportCertFromFile( server_cert_by_intermediate_ = net::ImportCertFromFile(
server_cert_path.DirName(), server_cert_path.DirName(),
server_cert_by_intermediate_path.BaseName().value()); server_cert_by_intermediate_path.BaseName().value());
// Set up the mock policy provider. ASSERT_TRUE(server_cert_by_intermediate_);
EXPECT_CALL(provider_, IsInitializationComplete(testing::_))
.WillRepeatedly(testing::Return(true));
BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
} }
// Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until // Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until
// the notification that policy-provided trust roots have changed is sent from // the notification that policy-provided trust roots have changed is sent from
// |profile|'s UserNetworkConfigurationUpdater. // |profile|'s UserNetworkConfigurationUpdater.
void SetRootCertONCUserPolicy(Profile* profile) { void SetRootCertONCUserPolicy(
Profile* profile,
MockConfigurationPolicyProvider* mock_policy_provider) {
std::string onc_policy_data = GetTestCertsFileContents(kRootCaCertOnc); std::string onc_policy_data = GetTestCertsFileContents(kRootCaCertOnc);
SetONCUserPolicy(profile, onc_policy_data); SetONCUserPolicy(profile, mock_policy_provider, onc_policy_data);
} }
// Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until // Sets the ONC-policy to the blob defined by |kRootCaCertOnc| and waits until
// the notification that policy-provided trust roots have changed is sent from // the notification that policy-provided trust roots have changed is sent from
// |profile|'s UserNetworkConfigurationUpdater. // |profile|'s UserNetworkConfigurationUpdater.
void SetRootAndIntermediateCertsONCUserPolicy(Profile* profile) { void SetRootAndIntermediateCertsONCUserPolicy(
Profile* profile,
MockConfigurationPolicyProvider* mock_policy_provider) {
std::string onc_policy_data = std::string onc_policy_data =
GetTestCertsFileContents(kRootAndIntermediateCaCertsOnc); GetTestCertsFileContents(kRootAndIntermediateCaCertsOnc);
SetONCUserPolicy(profile, onc_policy_data); SetONCUserPolicy(profile, mock_policy_provider, onc_policy_data);
} }
const scoped_refptr<net::X509Certificate>& server_cert() { const scoped_refptr<net::X509Certificate>& server_cert() {
...@@ -252,8 +268,9 @@ class UserPolicyCertsHelper { ...@@ -252,8 +268,9 @@ class UserPolicyCertsHelper {
} }
private: private:
void SetONCUserPolicy(Profile* profile, const std::string& onc_policy_data) { void SetONCUserPolicy(Profile* profile,
ASSERT_TRUE(is_set_up_); MockConfigurationPolicyProvider* mock_policy_provider,
const std::string& onc_policy_data) {
UserNetworkConfigurationUpdater* user_network_configuration_updater = UserNetworkConfigurationUpdater* user_network_configuration_updater =
UserNetworkConfigurationUpdaterFactory::GetForBrowserContext(profile); UserNetworkConfigurationUpdaterFactory::GetForBrowserContext(profile);
...@@ -265,7 +282,7 @@ class UserPolicyCertsHelper { ...@@ -265,7 +282,7 @@ class UserPolicyCertsHelper {
policy.Set(key::kOpenNetworkConfiguration, policy::POLICY_LEVEL_MANDATORY, policy.Set(key::kOpenNetworkConfiguration, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
base::Value(onc_policy_data), nullptr); base::Value(onc_policy_data), nullptr);
provider_.UpdateChromePolicy(policy); mock_policy_provider->UpdateChromePolicy(policy);
// Note that this relies on the implementation detail that the notification // Note that this relies on the implementation detail that the notification
// is sent even if the trust roots effectively remain the same. // is sent even if the trust roots effectively remain the same.
trust_roots_changed_observer.Wait(); trust_roots_changed_observer.Wait();
...@@ -273,12 +290,6 @@ class UserPolicyCertsHelper { ...@@ -273,12 +290,6 @@ class UserPolicyCertsHelper {
&trust_roots_changed_observer); &trust_roots_changed_observer);
} }
// This is set to true when |SetUpInProcessBrowserTestFixture| has been
// called.
bool is_set_up_ = false;
MockConfigurationPolicyProvider provider_;
// Server Certificate which is signed by authority specified in |kRootCaCert|. // Server Certificate which is signed by authority specified in |kRootCaCert|.
scoped_refptr<net::X509Certificate> server_cert_; scoped_refptr<net::X509Certificate> server_cert_;
// Authority Certificate specified in |kRootCaCert|. // Authority Certificate specified in |kRootCaCert|.
...@@ -292,6 +303,111 @@ class UserPolicyCertsHelper { ...@@ -292,6 +303,111 @@ class UserPolicyCertsHelper {
scoped_refptr<net::X509Certificate> server_cert_by_intermediate_; scoped_refptr<net::X509Certificate> server_cert_by_intermediate_;
}; };
// A class that allows testing multiple profiles in a browsertest, each having
// its own MockConfigurationPolicyProvider.
// TODO(https://crbug.com/1127263): Transform this into a general-purpose mixin.
class MultiProfilePolicyProviderHelper {
public:
MultiProfilePolicyProviderHelper() = default;
~MultiProfilePolicyProviderHelper() = default;
MultiProfilePolicyProviderHelper(
const MultiProfilePolicyProviderHelper& other) = delete;
MultiProfilePolicyProviderHelper& operator=(
const MultiProfilePolicyProviderHelper& other) = delete;
void SetUpCommandLine(base::CommandLine* command_line) {
#if defined(OS_CHROMEOS)
command_line->AppendSwitch(
chromeos::switches::kIgnoreUserProfileMappingForTests);
#endif
}
// The test should call this before the initial profile is created by chrome.
void BeforeInitialProfileCreated() {
// Set the overridden policy provider for the first Profile (|profile_1_|).
// Note that the first ptofile will be created automatically by the
// browser initialization.
EXPECT_CALL(policy_for_profile_1_, IsInitializationComplete(testing::_))
.WillRepeatedly(testing::Return(true));
policy::PushProfilePolicyConnectorProviderForTesting(
&policy_for_profile_1_);
}
// The test should call this after the initial profile is created by chrome.
void AfterInitialProfileCreated() {
// Mimics what InProcessBrowserTest does to get the first created Profile.
const BrowserList* browser_list = BrowserList::GetInstance();
ASSERT_FALSE(browser_list->empty());
Browser* first_browser = browser_list->get(0);
profile_1_ = first_browser->profile();
ASSERT_TRUE(profile_1_);
}
// Creates a additional profile. The Profile can then be accessed by
// profile_2() and its policy by policy_for_profile_2(). Should be wrapped in
// ASSERT_NO_FATAL_FAILURE.
void CreateSecondProfile() {
ASSERT_FALSE(profile_2_);
// Prepare policy provider for second profile.
EXPECT_CALL(policy_for_profile_2_, IsInitializationComplete(testing::_))
.WillRepeatedly(testing::Return(true));
policy::PushProfilePolicyConnectorProviderForTesting(
&policy_for_profile_2_);
ProfileManager* profile_manager = g_browser_process->profile_manager();
// Create an additional profile.
base::FilePath path_profile =
profile_manager->GenerateNextProfileDirectoryPath();
base::RunLoop run_loop;
profile_manager->CreateProfileAsync(
path_profile,
base::Bind(&OnProfileInitialized, &profile_2_, run_loop.QuitClosure()),
base::string16(), std::string());
// Run the message loop to allow profile creation to take place; the loop is
// terminated by OnProfileInitialized calling the loop's QuitClosure when
// the profile is created.
run_loop.Run();
// Make sure second profile creation does what we think it does.
ASSERT_TRUE(profile_1() != profile_2());
}
Profile* profile_1() { return profile_1_; }
Profile* profile_2() { return profile_2_; }
// Returns the MockConfigurationPolicyProvider for profile_1.
MockConfigurationPolicyProvider* policy_for_profile_1() {
return &policy_for_profile_1_;
}
// Returns the MockConfigurationPolicyProvider for profile_2.
MockConfigurationPolicyProvider* policy_for_profile_2() {
return &policy_for_profile_2_;
}
private:
// Called when an additional profile has been created.
// The created profile is stored in *|out_created_profile|.
static void OnProfileInitialized(Profile** out_created_profile,
const base::Closure& closure,
Profile* profile,
Profile::CreateStatus status) {
if (status == Profile::CREATE_STATUS_INITIALIZED) {
*out_created_profile = profile;
closure.Run();
}
}
Profile* profile_1_ = nullptr;
Profile* profile_2_ = nullptr;
MockConfigurationPolicyProvider policy_for_profile_1_;
MockConfigurationPolicyProvider policy_for_profile_2_;
};
// Verifies |certificate| with |storage_partition|'s CertVerifier and returns // Verifies |certificate| with |storage_partition|'s CertVerifier and returns
// the result. // the result.
int VerifyTestServerCertInStoragePartition( int VerifyTestServerCertInStoragePartition(
...@@ -399,21 +515,18 @@ bool IsCertInCertificateList( ...@@ -399,21 +515,18 @@ bool IsCertInCertificateList(
// Allows testing if user policy provided trust roots take effect, without // Allows testing if user policy provided trust roots take effect, without
// having device policy. // having device policy.
// The parameter specifies whether the CertVerifierService is enabled.
class PolicyProvidedCertsRegularUserTest class PolicyProvidedCertsRegularUserTest
: public InProcessBrowserTest, : public InProcessBrowserTest,
public ::testing::WithParamInterface<bool> { public ::testing::WithParamInterface<bool> {
protected: protected:
PolicyProvidedCertsRegularUserTest() = default; PolicyProvidedCertsRegularUserTest() = default;
~PolicyProvidedCertsRegularUserTest() = default;
void SetUpOnMainThread() override { void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpOnMainThread(); InProcessBrowserTest::SetUpCommandLine(command_line);
// Use the same testing slot as private and public slot for testing. multi_profile_policy_helper_.SetUpCommandLine(command_line);
test_nss_cert_db_ = std::make_unique<net::NSSCertDatabase>(
crypto::ScopedPK11Slot(
PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */,
crypto::ScopedPK11Slot(
PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */);
} }
void SetUpInProcessBrowserTestFixture() override { void SetUpInProcessBrowserTestFixture() override {
...@@ -426,21 +539,82 @@ class PolicyProvidedCertsRegularUserTest ...@@ -426,21 +539,82 @@ class PolicyProvidedCertsRegularUserTest
} }
InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); InProcessBrowserTest::SetUpInProcessBrowserTestFixture();
user_policy_certs_helper_.SetUpInProcessBrowserTestFixture();
ASSERT_NO_FATAL_FAILURE(
multi_profile_policy_helper_.BeforeInitialProfileCreated());
}
void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
ASSERT_NO_FATAL_FAILURE(
multi_profile_policy_helper_.AfterInitialProfileCreated());
ASSERT_NO_FATAL_FAILURE(user_policy_certs_helper_.Initialize());
// Use the same testing slot as private and public slot for testing.
test_nss_cert_db_ = std::make_unique<net::NSSCertDatabase>(
crypto::ScopedPK11Slot(
PK11_ReferenceSlot(test_nssdb_.slot())) /* public slot */,
crypto::ScopedPK11Slot(
PK11_ReferenceSlot(test_nssdb_.slot())) /* private slot */);
} }
MultiProfilePolicyProviderHelper multi_profile_policy_helper_;
base::test::ScopedFeatureList scoped_feature_list_; base::test::ScopedFeatureList scoped_feature_list_;
UserPolicyCertsHelper user_policy_certs_helper_; UserPolicyCertsHelper user_policy_certs_helper_;
// A NSSCertDatabase is needed for the tests that do something with
// NetworkCertLoader.
crypto::ScopedTestNSSDB test_nssdb_; crypto::ScopedTestNSSDB test_nssdb_;
std::unique_ptr<net::NSSCertDatabase> test_nss_cert_db_; std::unique_ptr<net::NSSCertDatabase> test_nss_cert_db_;
}; };
IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest, TrustAnchorApplied) { IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest, TrustAnchorApplied) {
user_policy_certs_helper_.SetRootCertONCUserPolicy(browser()->profile()); user_policy_certs_helper_.SetRootCertONCUserPolicy(
multi_profile_policy_helper_.profile_1(),
multi_profile_policy_helper_.policy_for_profile_1());
EXPECT_EQ(net::OK, EXPECT_EQ(net::OK,
VerifyTestServerCert(browser()->profile(), VerifyTestServerCert(multi_profile_policy_helper_.profile_1(),
user_policy_certs_helper_.server_cert()));
}
IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest,
PrimaryProfileTrustAnchorDoesNotLeak) {
ASSERT_NO_FATAL_FAILURE(multi_profile_policy_helper_.CreateSecondProfile());
user_policy_certs_helper_.SetRootCertONCUserPolicy(
multi_profile_policy_helper_.profile_1(),
multi_profile_policy_helper_.policy_for_profile_1());
EXPECT_EQ(net::OK,
VerifyTestServerCert(multi_profile_policy_helper_.profile_1(),
user_policy_certs_helper_.server_cert()));
EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
VerifyTestServerCert(multi_profile_policy_helper_.profile_2(),
user_policy_certs_helper_.server_cert()));
}
IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest,
SecondaryProfileTrustAnchorDoesNotLeak) {
ASSERT_NO_FATAL_FAILURE(multi_profile_policy_helper_.CreateSecondProfile());
user_policy_certs_helper_.SetRootCertONCUserPolicy(
multi_profile_policy_helper_.profile_2(),
multi_profile_policy_helper_.policy_for_profile_2());
EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
VerifyTestServerCert(multi_profile_policy_helper_.profile_1(),
user_policy_certs_helper_.server_cert()));
// TODO(https://crbug.com/1127263): That the cert from a secondary user's
// policy is used at all is currently an artifact of the test, which reuses
// the primary user_manager::User for the secondary Profile.
// Fix that and then expect ERR_CERT_AUTHORITY_INVALID here too, and rename
// the test to SecondaryProfileTrustAnchorIgnored.
// Or, allow secondary Profile ONC policy to set trust anchors for the
// secondary Profile.
EXPECT_EQ(net::OK,
VerifyTestServerCert(multi_profile_policy_helper_.profile_2(),
user_policy_certs_helper_.server_cert())); user_policy_certs_helper_.server_cert()));
} }
...@@ -448,19 +622,22 @@ IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest, ...@@ -448,19 +622,22 @@ IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest,
UntrustedIntermediateAuthorityApplied) { UntrustedIntermediateAuthorityApplied) {
// Sanity check: Apply ONC policy which does not mention the intermediate // Sanity check: Apply ONC policy which does not mention the intermediate
// authority. // authority.
user_policy_certs_helper_.SetRootCertONCUserPolicy(browser()->profile()); user_policy_certs_helper_.SetRootCertONCUserPolicy(
multi_profile_policy_helper_.profile_1(),
multi_profile_policy_helper_.policy_for_profile_1());
EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID, EXPECT_EQ(net::ERR_CERT_AUTHORITY_INVALID,
VerifyTestServerCert( VerifyTestServerCert(
browser()->profile(), multi_profile_policy_helper_.profile_1(),
user_policy_certs_helper_.server_cert_by_intermediate())); user_policy_certs_helper_.server_cert_by_intermediate()));
// Now apply ONC policy which mentions the intermediate authority (but does // Now apply ONC policy which mentions the intermediate authority (but does
// not assign trust to it). // not assign trust to it).
user_policy_certs_helper_.SetRootAndIntermediateCertsONCUserPolicy( user_policy_certs_helper_.SetRootAndIntermediateCertsONCUserPolicy(
browser()->profile()); multi_profile_policy_helper_.profile_1(),
multi_profile_policy_helper_.policy_for_profile_1());
EXPECT_EQ(net::OK, EXPECT_EQ(net::OK,
VerifyTestServerCert( VerifyTestServerCert(
browser()->profile(), multi_profile_policy_helper_.profile_1(),
user_policy_certs_helper_.server_cert_by_intermediate())); user_policy_certs_helper_.server_cert_by_intermediate()));
} }
...@@ -478,7 +655,9 @@ IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest, ...@@ -478,7 +655,9 @@ IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsRegularUserTest,
chromeos::NetworkCertLoader::Get()->authority_certs())); chromeos::NetworkCertLoader::Get()->authority_certs()));
NetworkCertLoaderTestObserver network_cert_loader_observer( NetworkCertLoaderTestObserver network_cert_loader_observer(
chromeos::NetworkCertLoader::Get()); chromeos::NetworkCertLoader::Get());
user_policy_certs_helper_.SetRootCertONCUserPolicy(browser()->profile()); user_policy_certs_helper_.SetRootCertONCUserPolicy(
multi_profile_policy_helper_.profile_1(),
multi_profile_policy_helper_.policy_for_profile_1());
network_cert_loader_observer.Wait(); network_cert_loader_observer.Wait();
// Check that |NetworkCertLoader| is aware of the authority certificate. // Check that |NetworkCertLoader| is aware of the authority certificate.
...@@ -522,7 +701,12 @@ class PolicyProvidedCertsDeviceLocalAccountTest ...@@ -522,7 +701,12 @@ class PolicyProvidedCertsDeviceLocalAccountTest
DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
user_policy_certs_helper_.SetUpInProcessBrowserTestFixture(); ASSERT_NO_FATAL_FAILURE(user_policy_certs_helper_.Initialize());
// Set up the mock policy provider.
EXPECT_CALL(user_policy_provider_, IsInitializationComplete(testing::_))
.WillRepeatedly(testing::Return(true));
BrowserPolicyConnector::SetPolicyProviderForTesting(&user_policy_provider_);
device_policy()->policy_data().set_public_key_version(1); device_policy()->policy_data().set_public_key_version(1);
em::ChromeDeviceSettingsProto& proto(device_policy()->payload()); em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
...@@ -548,6 +732,7 @@ class PolicyProvidedCertsDeviceLocalAccountTest ...@@ -548,6 +732,7 @@ class PolicyProvidedCertsDeviceLocalAccountTest
kDeviceLocalAccountId, kDeviceLocalAccountId,
DeviceLocalAccount::TYPE_PUBLIC_SESSION)); DeviceLocalAccount::TYPE_PUBLIC_SESSION));
MockConfigurationPolicyProvider user_policy_provider_;
UserPolicyCertsHelper user_policy_certs_helper_; UserPolicyCertsHelper user_policy_certs_helper_;
crypto::ScopedTestNSSDB test_nssdb_; crypto::ScopedTestNSSDB test_nssdb_;
...@@ -605,7 +790,8 @@ IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsPublicSessionTest, ...@@ -605,7 +790,8 @@ IN_PROC_BROWSER_TEST_P(PolicyProvidedCertsPublicSessionTest,
Browser* browser = browser_list->get(0); Browser* browser = browser_list->get(0);
ASSERT_TRUE(browser); ASSERT_TRUE(browser);
user_policy_certs_helper_.SetRootCertONCUserPolicy(browser->profile()); user_policy_certs_helper_.SetRootCertONCUserPolicy(browser->profile(),
&user_policy_provider_);
EXPECT_EQ(net::OK, EXPECT_EQ(net::OK,
VerifyTestServerCert(browser->profile(), VerifyTestServerCert(browser->profile(),
user_policy_certs_helper_.server_cert())); user_policy_certs_helper_.server_cert()));
......
...@@ -281,9 +281,10 @@ TEST_F(SessionControllerClientImplTest, MultiProfileDisallowedByUserPolicy) { ...@@ -281,9 +281,10 @@ TEST_F(SessionControllerClientImplTest, MultiProfileDisallowedByUserPolicy) {
SessionControllerClientImpl::GetAddUserSessionPolicy()); SessionControllerClientImpl::GetAddUserSessionPolicy());
} }
// Make sure MultiProfile disabled by primary user policy certificates. // Make sure MultiProfile is allowed if the primary user has used
// policy-provided trust anchors.
TEST_F(SessionControllerClientImplTest, TEST_F(SessionControllerClientImplTest,
MultiProfileDisallowedByPolicyCertificates) { MultiProfileAllowedWithPolicyCertificates) {
InitForMultiProfile(); InitForMultiProfile();
user_manager()->AddUser( user_manager()->AddUser(
AccountId::FromUserEmailGaiaId("bb@b.b", "4444444444")); AccountId::FromUserEmailGaiaId("bb@b.b", "4444444444"));
...@@ -295,14 +296,15 @@ TEST_F(SessionControllerClientImplTest, ...@@ -295,14 +296,15 @@ TEST_F(SessionControllerClientImplTest,
SessionControllerClientImpl::GetAddUserSessionPolicy()); SessionControllerClientImpl::GetAddUserSessionPolicy());
policy::PolicyCertServiceFactory::SetUsedPolicyCertificates( policy::PolicyCertServiceFactory::SetUsedPolicyCertificates(
account_id.GetUserEmail()); account_id.GetUserEmail());
EXPECT_EQ(ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER, EXPECT_EQ(ash::AddUserSessionPolicy::ALLOWED,
SessionControllerClientImpl::GetAddUserSessionPolicy()); SessionControllerClientImpl::GetAddUserSessionPolicy());
// Flush tasks posted to IO. // Flush tasks posted to IO.
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
// Make sure MultiProfile disabled by primary user certificates in memory. // Make sure MultiProfile is allowed if the primary user has policy-provided
// trust anchors in memory.
TEST_F(SessionControllerClientImplTest, TEST_F(SessionControllerClientImplTest,
MultiProfileDisallowedByPrimaryUserCertificatesInMemory) { MultiProfileDisallowedByPrimaryUserCertificatesInMemory) {
TestingProfile* user_profile = InitForMultiProfile(); TestingProfile* user_profile = InitForMultiProfile();
...@@ -327,7 +329,7 @@ TEST_F(SessionControllerClientImplTest, ...@@ -327,7 +329,7 @@ TEST_F(SessionControllerClientImplTest,
net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem")); net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"));
service->SetPolicyTrustAnchorsForTesting(/*trust_anchors=*/certificates); service->SetPolicyTrustAnchorsForTesting(/*trust_anchors=*/certificates);
EXPECT_TRUE(service->has_policy_certificates()); EXPECT_TRUE(service->has_policy_certificates());
EXPECT_EQ(ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER, EXPECT_EQ(ash::AddUserSessionPolicy::ALLOWED,
SessionControllerClientImpl::GetAddUserSessionPolicy()); SessionControllerClientImpl::GetAddUserSessionPolicy());
// Flush tasks posted to IO. // Flush tasks posted to IO.
......
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