blob: b53dd7f2c3581b228bbbcc32609d01c842716fad [file] [log] [blame]
// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "login_manager/device_policy_service.h"
#include <algorithm>
#include <set>
#include <string>
#include <vector>
#include <base/bind.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/message_loop/message_loop.h>
#include <base/message_loop/message_loop_proxy.h>
#include <base/run_loop.h>
#include <crypto/scoped_nss_types.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "bindings/chrome_device_policy.pb.h"
#include "bindings/device_management_backend.pb.h"
#include "bindings/install_attributes.pb.h"
#include "login_manager/matchers.h"
#include "login_manager/mock_metrics.h"
#include "login_manager/mock_mitigator.h"
#include "login_manager/mock_nss_util.h"
#include "login_manager/mock_policy_key.h"
#include "login_manager/mock_policy_service.h"
#include "login_manager/mock_policy_store.h"
namespace em = enterprise_management;
using google::protobuf::RepeatedPtrField;
using testing::AnyNumber;
using testing::AtLeast;
using testing::DoAll;
using testing::Expectation;
using testing::Mock;
using testing::Return;
using testing::ReturnRef;
using testing::Sequence;
using testing::StrictMock;
using testing::WithArg;
using testing::_;
namespace {
ACTION_P(AssignVector, str) {
arg0->assign(str.begin(), str.end());
}
} // namespace
namespace login_manager {
class DevicePolicyServiceTest : public ::testing::Test {
public:
DevicePolicyServiceTest()
: owner_("user@somewhere"),
fake_sig_("fake_signature"),
fake_key_("fake_key"),
new_fake_sig_("new_fake_signature"),
store_(NULL) {
fake_key_vector_.assign(fake_key_.begin(), fake_key_.end());
completion_ = MockPolicyService::CreateDoNothing();
}
virtual void SetUp() {
ASSERT_TRUE(tmpdir_.CreateUniqueTempDir());
serial_recovery_flag_file_ =
tmpdir_.path().AppendASCII("serial_recovery_flag");
policy_file_ = tmpdir_.path().AppendASCII("policy");
install_attributes_file_ =
tmpdir_.path().AppendASCII("install_attributes.pb");
}
void InitPolicy(const em::ChromeDeviceSettingsProto& settings,
const std::string& owner,
const std::string& signature,
const std::string& request_token,
bool valid_serial_number_missing) {
std::string settings_str;
ASSERT_TRUE(settings.SerializeToString(&settings_str));
em::PolicyData policy_data;
policy_data.set_policy_type(DevicePolicyService::kDevicePolicyType);
policy_data.set_policy_value(settings_str);
if (!owner.empty())
policy_data.set_username(owner);
if (!request_token.empty())
policy_data.set_request_token(request_token);
if (valid_serial_number_missing)
policy_data.set_valid_serial_number_missing(true);
std::string policy_data_str;
ASSERT_TRUE(policy_data.SerializeToString(&policy_data_str));
policy_proto_.Clear();
policy_proto_.set_policy_data(policy_data_str);
policy_proto_.set_policy_data_signature(signature);
ASSERT_TRUE(policy_proto_.SerializeToString(&policy_str_));
}
void InitEmptyPolicy(const std::string& owner,
const std::string& signature,
const std::string& request_token) {
em::ChromeDeviceSettingsProto settings;
InitPolicy(settings, owner, signature, request_token, false);
}
void InitService(NssUtil* nss) {
store_ = new StrictMock<MockPolicyStore>;
metrics_.reset(new MockMetrics);
mitigator_.reset(new StrictMock<MockMitigator>);
scoped_refptr<base::MessageLoopProxy> message_loop(
base::MessageLoopProxy::current());
service_.reset(new DevicePolicyService(serial_recovery_flag_file_,
policy_file_,
install_attributes_file_,
scoped_ptr<PolicyStore>(store_),
&key_,
message_loop,
metrics_.get(),
mitigator_.get(),
nss));
// Allow the key to be read any time.
EXPECT_CALL(key_, public_key_der())
.WillRepeatedly(ReturnRef(fake_key_vector_));
}
void RecordNewPolicy(const em::PolicyFetchResponse& policy) {
new_policy_proto_.CopyFrom(policy);
}
void ExpectMitigating(bool mitigating) {
EXPECT_CALL(*mitigator_.get(), Mitigating())
.WillRepeatedly(Return(mitigating));
}
void ExpectGetPolicy(Sequence sequence,
const em::PolicyFetchResponse& policy) {
EXPECT_CALL(*store_, Get())
.InSequence(sequence)
.WillRepeatedly(ReturnRef(policy));
}
void ExpectInstallNewOwnerPolicy(Sequence sequence, MockNssUtil* nss) {
Expectation get_policy =
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
Expectation compare_keys =
EXPECT_CALL(key_, Equals(_)).WillRepeatedly(Return(false));
Expectation sign =
EXPECT_CALL(*nss, Sign(_, _, _, _))
.After(get_policy)
.WillOnce(DoAll(WithArg<2>(AssignVector(new_fake_sig_)),
Return(true)));
Expectation set_policy =
EXPECT_CALL(*store_, Set(_))
.InSequence(sequence)
.After(sign, compare_keys)
.WillOnce(Invoke(this, &DevicePolicyServiceTest::RecordNewPolicy));
}
void ExpectFailedInstallNewOwnerPolicy(Sequence sequence, MockNssUtil* nss) {
Expectation get_policy =
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
Expectation compare_keys =
EXPECT_CALL(key_, Equals(_)).WillRepeatedly(Return(false));
Expectation sign =
EXPECT_CALL(*nss, Sign(_, _, _, _))
.After(get_policy)
.WillOnce(DoAll(WithArg<2>(AssignVector(new_fake_sig_)),
Return(false)));
}
void ExpectPersistKeyAndPolicy() {
Mock::VerifyAndClearExpectations(&key_);
Mock::VerifyAndClearExpectations(store_);
EXPECT_CALL(key_, Persist()).WillOnce(Return(true));
EXPECT_CALL(*store_, Persist()).WillOnce(Return(true));
base::RunLoop().RunUntilIdle();
}
void ExpectNoPersistKeyAndPolicy() {
Mock::VerifyAndClearExpectations(&key_);
Mock::VerifyAndClearExpectations(store_);
EXPECT_CALL(key_, Persist()).Times(0);
EXPECT_CALL(*store_, Persist()).Times(0);
base::RunLoop().RunUntilIdle();
}
void ExpectKeyPopulated(bool key_populated) {
EXPECT_CALL(key_, HaveCheckedDisk()).WillRepeatedly(Return(true));
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(key_populated));
}
LoginMetrics::PolicyFileState SimulateNullPolicy() {
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(new_policy_proto_));
return LoginMetrics::NOT_PRESENT;
}
LoginMetrics::PolicyFileState SimulateGoodPolicy() {
InitEmptyPolicy(owner_, fake_sig_, "");
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
return LoginMetrics::GOOD;
}
LoginMetrics::PolicyFileState SimulateNullPrefs() {
EXPECT_CALL(*store_, DefunctPrefsFilePresent()).WillOnce(Return(false));
return LoginMetrics::NOT_PRESENT;
}
LoginMetrics::PolicyFileState SimulateExtantPrefs() {
EXPECT_CALL(*store_, DefunctPrefsFilePresent()).WillOnce(Return(true));
return LoginMetrics::GOOD;
}
LoginMetrics::PolicyFileState SimulateNullOwnerKey() {
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(false));
return LoginMetrics::NOT_PRESENT;
}
LoginMetrics::PolicyFileState SimulateBadOwnerKey(MockNssUtil* nss) {
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(true));
EXPECT_CALL(*nss, CheckPublicKeyBlob(fake_key_vector_))
.WillRepeatedly(Return(false));
return LoginMetrics::MALFORMED;
}
LoginMetrics::PolicyFileState SimulateGoodOwnerKey(MockNssUtil* nss) {
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(true));
EXPECT_CALL(*nss, CheckPublicKeyBlob(fake_key_vector_))
.WillRepeatedly(Return(true));
return LoginMetrics::GOOD;
}
bool PolicyAllowsNewUsers(const em::ChromeDeviceSettingsProto settings) {
InitPolicy(settings, owner_, fake_sig_, "", false);
return DevicePolicyService::PolicyAllowsNewUsers(policy_proto_);
}
em::PolicyFetchResponse policy_proto_;
std::string policy_str_;
em::PolicyFetchResponse new_policy_proto_;
std::string owner_;
std::string fake_sig_;
std::string fake_key_;
std::vector<uint8_t> fake_key_vector_;
std::string new_fake_sig_;
base::MessageLoop loop_;
base::ScopedTempDir tmpdir_;
base::FilePath serial_recovery_flag_file_;
base::FilePath policy_file_;
base::FilePath install_attributes_file_;
// Use StrictMock to make sure that no unexpected policy or key mutations can
// occur without the test failing.
StrictMock<MockPolicyKey> key_;
StrictMock<MockPolicyStore>* store_;
scoped_ptr<MockMetrics> metrics_;
scoped_ptr<StrictMock<MockMitigator>> mitigator_;
PolicyService::Completion completion_;
scoped_ptr<DevicePolicyService> service_;
};
TEST_F(DevicePolicyServiceTest, CheckAndHandleOwnerLogin_SuccessEmptyPolicy) {
KeyCheckUtil nss;
InitService(&nss);
em::ChromeDeviceSettingsProto settings;
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).Times(0);
ExpectKeyPopulated(true);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(1);
PolicyService::Error error;
bool is_owner = false;
EXPECT_TRUE(service_->CheckAndHandleOwnerLogin(
owner_, nss.GetSlot(), &is_owner, &error));
EXPECT_TRUE(is_owner);
}
TEST_F(DevicePolicyServiceTest, CheckAndHandleOwnerLogin_NotOwner) {
KeyFailUtil nss;
InitService(&nss);
ASSERT_NO_FATAL_FAILURE(InitEmptyPolicy(owner_, fake_sig_, ""));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).Times(0);
ExpectKeyPopulated(true);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(1);
PolicyService::Error error;
bool is_owner = true;
EXPECT_TRUE(service_->CheckAndHandleOwnerLogin(
"regular_user@somewhere", nss.GetSlot(), &is_owner, &error));
EXPECT_FALSE(is_owner);
}
TEST_F(DevicePolicyServiceTest, CheckAndHandleOwnerLogin_EnterpriseDevice) {
KeyFailUtil nss;
InitService(&nss);
ASSERT_NO_FATAL_FAILURE(InitEmptyPolicy(owner_, fake_sig_, "fake_token"));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).Times(0);
ExpectKeyPopulated(true);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(0);
PolicyService::Error error;
bool is_owner = true;
EXPECT_TRUE(service_->CheckAndHandleOwnerLogin(
owner_, nss.GetSlot(), &is_owner, &error));
EXPECT_FALSE(is_owner);
}
TEST_F(DevicePolicyServiceTest, CheckAndHandleOwnerLogin_MissingKey) {
KeyFailUtil nss;
InitService(&nss);
ASSERT_NO_FATAL_FAILURE(InitEmptyPolicy(owner_, fake_sig_, ""));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).InSequence(s).WillOnce(
Return(true));
ExpectKeyPopulated(true);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(1);
PolicyService::Error error;
bool is_owner = false;
EXPECT_TRUE(service_->CheckAndHandleOwnerLogin(
owner_, nss.GetSlot(), &is_owner, &error));
EXPECT_TRUE(is_owner);
}
TEST_F(DevicePolicyServiceTest,
CheckAndHandleOwnerLogin_MissingPublicKeyOwner) {
KeyFailUtil nss;
InitService(&nss);
ASSERT_NO_FATAL_FAILURE(InitEmptyPolicy(owner_, fake_sig_, ""));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).InSequence(s).WillOnce(
Return(true));
ExpectKeyPopulated(true);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(1);
PolicyService::Error error;
bool is_owner = false;
EXPECT_TRUE(service_->CheckAndHandleOwnerLogin(
owner_, nss.GetSlot(), &is_owner, &error));
EXPECT_TRUE(is_owner);
}
TEST_F(DevicePolicyServiceTest,
CheckAndHandleOwnerLogin_MissingPublicKeyNonOwner) {
KeyFailUtil nss;
InitService(&nss);
ASSERT_NO_FATAL_FAILURE(InitEmptyPolicy(owner_, fake_sig_, ""));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).Times(0);
ExpectKeyPopulated(false);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(1);
PolicyService::Error error;
bool is_owner = true;
EXPECT_TRUE(service_->CheckAndHandleOwnerLogin(
"other@somwhere", nss.GetSlot(), &is_owner, &error));
EXPECT_FALSE(is_owner);
}
TEST_F(DevicePolicyServiceTest, CheckAndHandleOwnerLogin_MitigationFailure) {
KeyFailUtil nss;
InitService(&nss);
ASSERT_NO_FATAL_FAILURE(InitEmptyPolicy(owner_, fake_sig_, ""));
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(*mitigator_.get(), Mitigate(_)).InSequence(s).WillOnce(
Return(false));
ExpectKeyPopulated(true);
EXPECT_CALL(*metrics_.get(), SendConsumerAllowsNewUsers(_)).Times(1);
PolicyService::Error error;
bool is_owner = false;
EXPECT_FALSE(service_->CheckAndHandleOwnerLogin(
owner_, nss.GetSlot(), &is_owner, &error));
}
TEST_F(DevicePolicyServiceTest, PolicyAllowsNewUsers) {
em::ChromeDeviceSettingsProto allowed;
allowed.mutable_allow_new_users()->set_allow_new_users(true);
EXPECT_TRUE(PolicyAllowsNewUsers(allowed));
allowed.mutable_user_whitelist();
EXPECT_TRUE(PolicyAllowsNewUsers(allowed));
allowed.mutable_user_whitelist()->add_user_whitelist("a@b");
EXPECT_TRUE(PolicyAllowsNewUsers(allowed));
em::ChromeDeviceSettingsProto broken;
broken.mutable_allow_new_users()->set_allow_new_users(false);
EXPECT_TRUE(PolicyAllowsNewUsers(broken));
em::ChromeDeviceSettingsProto disallowed = broken;
disallowed.mutable_user_whitelist();
disallowed.mutable_user_whitelist()->add_user_whitelist("a@b");
EXPECT_FALSE(PolicyAllowsNewUsers(disallowed));
em::ChromeDeviceSettingsProto not_disallowed;
EXPECT_TRUE(PolicyAllowsNewUsers(not_disallowed));
not_disallowed.mutable_user_whitelist();
EXPECT_TRUE(PolicyAllowsNewUsers(not_disallowed));
em::ChromeDeviceSettingsProto implicitly_disallowed = not_disallowed;
implicitly_disallowed.mutable_user_whitelist()->add_user_whitelist("a@b");
EXPECT_FALSE(PolicyAllowsNewUsers(implicitly_disallowed));
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_SuccessNewKey) {
KeyCheckUtil nss;
InitService(&nss);
ExpectMitigating(false);
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(key_, PopulateFromBuffer(fake_key_vector_))
.InSequence(s)
.WillOnce(Return(true));
EXPECT_CALL(*store_, Set(PolicyEq(em::PolicyFetchResponse())));
ExpectInstallNewOwnerPolicy(s, &nss);
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
ExpectPersistKeyAndPolicy();
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_SuccessMitigating) {
KeyCheckUtil nss;
InitService(&nss);
ExpectMitigating(true);
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(key_, IsPopulated()).InSequence(s).WillRepeatedly(Return(true));
EXPECT_CALL(key_, ClobberCompromisedKey(fake_key_vector_))
.InSequence(s)
.WillOnce(Return(true));
EXPECT_CALL(*store_, Set(_)).Times(0);
ExpectInstallNewOwnerPolicy(s, &nss);
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
ExpectPersistKeyAndPolicy();
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_FailedMitigating) {
KeyCheckUtil nss;
InitService(&nss);
ExpectMitigating(true);
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(key_, IsPopulated()).InSequence(s).WillRepeatedly(Return(true));
EXPECT_CALL(key_, ClobberCompromisedKey(fake_key_vector_))
.InSequence(s)
.WillOnce(Return(true));
ExpectFailedInstallNewOwnerPolicy(s, &nss);
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
ExpectNoPersistKeyAndPolicy();
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_SuccessAddOwner) {
KeyCheckUtil nss;
InitService(&nss);
em::ChromeDeviceSettingsProto settings;
settings.mutable_user_whitelist()->add_user_whitelist("a@b");
settings.mutable_user_whitelist()->add_user_whitelist("c@d");
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
ExpectMitigating(false);
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(key_, PopulateFromBuffer(fake_key_vector_))
.InSequence(s)
.WillOnce(Return(true));
EXPECT_CALL(*store_, Set(PolicyEq(em::PolicyFetchResponse())));
ExpectInstallNewOwnerPolicy(s, &nss);
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
ExpectPersistKeyAndPolicy();
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_NoPrivateKey) {
KeyFailUtil nss;
InitService(&nss);
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_NewKeyInstallFails) {
KeyCheckUtil nss;
InitService(&nss);
ExpectMitigating(false);
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(key_, PopulateFromBuffer(fake_key_vector_))
.InSequence(s)
.WillOnce(Return(false));
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
}
TEST_F(DevicePolicyServiceTest, ValidateAndStoreOwnerKey_KeyClobberFails) {
KeyCheckUtil nss;
InitService(&nss);
ExpectMitigating(true);
Sequence s;
ExpectGetPolicy(s, policy_proto_);
EXPECT_CALL(key_, IsPopulated()).InSequence(s).WillRepeatedly(Return(true));
EXPECT_CALL(key_, ClobberCompromisedKey(fake_key_vector_))
.InSequence(s)
.WillOnce(Return(false));
service_->ValidateAndStoreOwnerKey(owner_, fake_key_, nss.GetSlot());
}
TEST_F(DevicePolicyServiceTest, KeyMissing_Present) {
MockNssUtil nss;
InitService(&nss);
ExpectKeyPopulated(true);
EXPECT_FALSE(service_->KeyMissing());
}
TEST_F(DevicePolicyServiceTest, KeyMissing_NoDiskCheck) {
MockNssUtil nss;
InitService(&nss);
EXPECT_CALL(key_, HaveCheckedDisk()).WillRepeatedly(Return(false));
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(false));
EXPECT_FALSE(service_->KeyMissing());
}
TEST_F(DevicePolicyServiceTest, KeyMissing_CheckedAndMissing) {
MockNssUtil nss;
InitService(&nss);
ExpectKeyPopulated(false);
EXPECT_TRUE(service_->KeyMissing());
}
TEST_F(DevicePolicyServiceTest, Metrics_NoKeyNoPolicyNoPrefs) {
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = SimulateNullOwnerKey();
status.policy_file_state = SimulateNullPolicy();
status.defunct_prefs_file_state = SimulateNullPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(true, true);
}
TEST_F(DevicePolicyServiceTest, Metrics_UnloadableKeyNoPolicyNoPrefs) {
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = LoginMetrics::MALFORMED;
status.policy_file_state = SimulateNullPolicy();
status.defunct_prefs_file_state = SimulateNullPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(false, true);
}
TEST_F(DevicePolicyServiceTest, Metrics_BadKeyNoPolicyNoPrefs) {
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = SimulateBadOwnerKey(&nss);
status.policy_file_state = SimulateNullPolicy();
status.defunct_prefs_file_state = SimulateNullPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(true, true);
}
TEST_F(DevicePolicyServiceTest, Metrics_GoodKeyNoPolicyNoPrefs) {
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = SimulateGoodOwnerKey(&nss);
status.policy_file_state = SimulateNullPolicy();
status.defunct_prefs_file_state = SimulateNullPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(true, true);
}
TEST_F(DevicePolicyServiceTest, Metrics_GoodKeyUnloadablePolicyNoPrefs) {
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = SimulateGoodOwnerKey(&nss);
status.policy_file_state = LoginMetrics::MALFORMED;
status.defunct_prefs_file_state = SimulateNullPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(true, false);
}
TEST_F(DevicePolicyServiceTest, Metrics_GoodKeyGoodPolicyNoPrefs) {
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = SimulateGoodOwnerKey(&nss);
status.policy_file_state = SimulateGoodPolicy();
status.defunct_prefs_file_state = SimulateNullPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(true, true);
}
TEST_F(DevicePolicyServiceTest, Metrics_GoodKeyNoPolicyExtantPrefs) {
// This is http://crosbug.com/24361
MockNssUtil nss;
InitService(&nss);
LoginMetrics::PolicyFilesStatus status;
status.owner_key_file_state = SimulateGoodOwnerKey(&nss);
status.policy_file_state = SimulateNullPolicy();
status.defunct_prefs_file_state = SimulateExtantPrefs();
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(StatusEq(status)))
.Times(1);
service_->ReportPolicyFileMetrics(true, true);
}
TEST_F(DevicePolicyServiceTest, SerialRecoveryFlagFileInitialization) {
MockNssUtil nss;
InitService(&nss);
EXPECT_CALL(nss, CheckPublicKeyBlob(fake_key_vector_))
.WillRepeatedly(Return(true));
EXPECT_CALL(key_, PopulateFromDiskIfPossible()).WillRepeatedly(Return(true));
EXPECT_CALL(key_, HaveCheckedDisk()).WillRepeatedly(Return(true));
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, LoadOrCreate()).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
EXPECT_CALL(*store_, DefunctPrefsFilePresent()).WillRepeatedly(Return(true));
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(_)).Times(AnyNumber());
// Fake the policy file existence.
base::WriteFile(policy_file_, ".", 1);
em::ChromeDeviceSettingsProto settings;
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "t", true));
EXPECT_TRUE(service_->Initialize());
EXPECT_TRUE(base::PathExists(serial_recovery_flag_file_));
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
EXPECT_TRUE(service_->Initialize());
EXPECT_FALSE(base::PathExists(serial_recovery_flag_file_));
// Fake the policy file gone.
base::DeleteFile(policy_file_, false);
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
EXPECT_TRUE(service_->Initialize());
EXPECT_TRUE(base::PathExists(serial_recovery_flag_file_));
}
TEST_F(DevicePolicyServiceTest, RecoverOwnerKeyFromPolicy) {
MockNssUtil nss;
InitService(&nss);
EXPECT_CALL(nss, CheckPublicKeyBlob(fake_key_vector_))
.WillRepeatedly(Return(true));
EXPECT_CALL(key_, PopulateFromDiskIfPossible()).WillRepeatedly(Return(false));
EXPECT_CALL(key_, PopulateFromBuffer(_)).WillRepeatedly(Return(true));
EXPECT_CALL(key_, ClobberCompromisedKey(_)).WillRepeatedly(Return(true));
EXPECT_CALL(key_, IsPopulated()).WillRepeatedly(Return(true));
EXPECT_CALL(key_, Persist()).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, LoadOrCreate()).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
EXPECT_CALL(*store_, DefunctPrefsFilePresent()).WillRepeatedly(Return(false));
EXPECT_CALL(*metrics_.get(), SendPolicyFilesStatus(_)).Times(AnyNumber());
em::ChromeDeviceSettingsProto settings;
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
EXPECT_FALSE(service_->Initialize());
policy_proto_.set_new_public_key(fake_key_);
EXPECT_TRUE(service_->Initialize());
}
TEST_F(DevicePolicyServiceTest, SerialRecoveryFlagFileUpdating) {
// Fake the policy file existence.
base::WriteFile(policy_file_, ".", 1);
MockNssUtil nss;
InitService(&nss);
em::ChromeDeviceSettingsProto settings;
EXPECT_FALSE(base::PathExists(serial_recovery_flag_file_));
EXPECT_CALL(key_, Verify(_, _, _, _)).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Set(_)).Times(AnyNumber());
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
// Installing a policy blob that doesn't have a request token (indicates local
// owner) should not create the file.
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", true));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
EXPECT_FALSE(base::PathExists(serial_recovery_flag_file_));
// Storing an enterprise policy blob with the |valid_serial_number_missing|
// flag set should create the flag file.
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "t", true));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
EXPECT_TRUE(base::PathExists(serial_recovery_flag_file_));
// Storing bad policy shouldn't remove the file.
EXPECT_FALSE(
service_->Store(NULL, 0, completion_, PolicyService::KEY_CLOBBER));
EXPECT_TRUE(base::PathExists(serial_recovery_flag_file_));
// Clearing the flag should remove the file.
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "t", false));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
EXPECT_FALSE(base::PathExists(serial_recovery_flag_file_));
// Create install attributes file to mock enterprise enrolled device.
cryptohome::SerializedInstallAttributes install_attributes;
cryptohome::SerializedInstallAttributes_Attribute* attribute =
install_attributes.add_attributes();
attribute->set_name(DevicePolicyService::kAttrEnterpriseMode);
attribute->set_value(std::string(DevicePolicyService::kEnterpriseDeviceMode) +
"\0"); // Sadly, values contain trailing zeroes.
std::string serialized;
EXPECT_TRUE(install_attributes.SerializeToString(&serialized));
base::WriteFile(
install_attributes_file_, serialized.c_str(), serialized.size());
// In case DM tokens exists, the flag file should not be created.
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "t", false));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
EXPECT_FALSE(base::PathExists(serial_recovery_flag_file_));
// Missing DM token should lead to creation of flag file.
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
EXPECT_TRUE(base::PathExists(serial_recovery_flag_file_));
}
TEST_F(DevicePolicyServiceTest, GetSettings) {
MockNssUtil nss;
InitService(&nss);
// No policy blob should result in an empty settings protobuf.
em::ChromeDeviceSettingsProto settings;
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
EXPECT_EQ(service_->GetSettings().SerializeAsString(),
settings.SerializeAsString());
Mock::VerifyAndClearExpectations(store_);
// Storing new policy should cause the settings to update as well.
settings.mutable_metrics_enabled()->set_metrics_enabled(true);
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "t", true));
EXPECT_CALL(key_, Verify(_, _, _, _)).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Persist()).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Set(_)).Times(AnyNumber());
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(service_->GetSettings().SerializeAsString(),
settings.SerializeAsString());
}
TEST_F(DevicePolicyServiceTest, StartUpFlagsSanitizer) {
MockNssUtil nss;
InitService(&nss);
em::ChromeDeviceSettingsProto settings;
// Some valid flags.
settings.mutable_start_up_flags()->add_flags("a");
settings.mutable_start_up_flags()->add_flags("bb");
settings.mutable_start_up_flags()->add_flags("-c");
settings.mutable_start_up_flags()->add_flags("--d");
// Some invalid ones.
settings.mutable_start_up_flags()->add_flags("");
settings.mutable_start_up_flags()->add_flags("-");
settings.mutable_start_up_flags()->add_flags("--");
ASSERT_NO_FATAL_FAILURE(InitPolicy(settings, owner_, fake_sig_, "", false));
EXPECT_CALL(key_, Verify(_, _, _, _)).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Persist()).WillRepeatedly(Return(true));
EXPECT_CALL(*store_, Set(_)).Times(AnyNumber());
EXPECT_CALL(*store_, Get()).WillRepeatedly(ReturnRef(policy_proto_));
EXPECT_TRUE(
service_->Store(reinterpret_cast<const uint8_t*>(policy_str_.c_str()),
policy_str_.size(),
completion_,
PolicyService::KEY_CLOBBER));
base::RunLoop().RunUntilIdle();
std::vector<std::string> flags = service_->GetStartUpFlags();
EXPECT_EQ(6, flags.size());
EXPECT_EQ("--policy-switches-begin", flags[0]);
EXPECT_EQ("--a", flags[1]);
EXPECT_EQ("--bb", flags[2]);
EXPECT_EQ("-c", flags[3]);
EXPECT_EQ("--d", flags[4]);
EXPECT_EQ("--policy-switches-end", flags[5]);
}
} // namespace login_manager