login: Check TPM firmware update device policy
For enterprise-managed devices, TPM firmware updates require
permission by the administrator. Allow the update to be started if the
respective device policy is in place.
BUG=chromium:762030
TEST=unit test
Reviewed-on: https://chromium-review.googlesource.com/679655
Commit-Ready: Mattias Nissler <mnissler@chromium.org>
Tested-by: Mattias Nissler <mnissler@chromium.org>
Reviewed-by: Dan Erat <derat@chromium.org>
Change-Id: Icbbf43b18420be60303f919182369c63f0600674
Reviewed-on: https://chromium-review.googlesource.com/700674
Reviewed-by: Mattias Nissler <mnissler@chromium.org>
Tested-by: Mattias Nissler <mnissler@chromium.org>
diff --git a/login_manager/mock_device_policy_service.h b/login_manager/mock_device_policy_service.h
index 20bfa7f..1f70fe5 100644
--- a/login_manager/mock_device_policy_service.h
+++ b/login_manager/mock_device_policy_service.h
@@ -46,9 +46,6 @@
void set_crossystem(Crossystem* crossystem) { crossystem_ = crossystem; }
void set_vpd_process(VpdProcess* vpd_process) { vpd_process_ = vpd_process; }
-
- private:
- enterprise_management::ChromeDeviceSettingsProto proto_;
};
} // namespace login_manager
diff --git a/login_manager/session_manager_impl.cc b/login_manager/session_manager_impl.cc
index 3344f83..c60a2ca 100644
--- a/login_manager/session_manager_impl.cc
+++ b/login_manager/session_manager_impl.cc
@@ -883,11 +883,14 @@
// For remotely managed devices, make sure the requested update mode matches
// the admin-configured one in device policy.
if (device_policy_->InstallAttributesEnterpriseMode()) {
- // TODO(mnissler): Verify that device policy matches |update_mode|.
- auto error = CreateError(dbus_error::kNotAvailable,
- "Not yet supported on enterprise devices.");
- response->ReplyWithError(error.get());
- return;
+ const enterprise_management::TPMFirmwareUpdateSettingsProto& settings =
+ device_policy_->GetSettings().tpm_firmware_update_settings();
+ if (!settings.allow_user_initiated_powerwash()) {
+ auto error = CreateError(dbus_error::kNotAvailable,
+ "Policy doesn't allow TPM firmware update.");
+ response->ReplyWithError(error.get());
+ return;
+ }
}
// Check whether a firmware update is present.
diff --git a/login_manager/session_manager_impl_unittest.cc b/login_manager/session_manager_impl_unittest.cc
index 0abf67f..f3db6af 100644
--- a/login_manager/session_manager_impl_unittest.cc
+++ b/login_manager/session_manager_impl_unittest.cc
@@ -82,6 +82,7 @@
using ::testing::Mock;
using ::testing::NotNull;
using ::testing::Return;
+using ::testing::ReturnRef;
using ::testing::SaveArg;
using ::testing::SetArgumentPointee;
using ::testing::StartsWith;
@@ -95,6 +96,8 @@
using brillo::cryptohome::home::kGuestUserName;
using enterprise_management::ChromeDeviceSettingsProto;
+using enterprise_management::PolicyData;
+using enterprise_management::PolicyFetchResponse;
using std::map;
using std::string;
@@ -347,7 +350,9 @@
system_clock_proxy_.get());
impl_->SetSystemClockLastSyncInfoRetryDelayForTesting(base::TimeDelta());
- device_policy_service_ = new MockDevicePolicyService();
+ device_policy_store_ = new MockPolicyStore();
+ device_policy_service_ = new MockDevicePolicyService(
+ std::unique_ptr<MockPolicyStore>(device_policy_store_), &owner_key_);
user_policy_service_factory_ =
new testing::NiceMock<MockUserPolicyServiceFactory>();
ON_CALL(*user_policy_service_factory_, Create(_))
@@ -553,6 +558,7 @@
// on them after we hand them off.
// Owned by SessionManagerImpl.
MockInitDaemonController* init_controller_ = nullptr;
+ MockPolicyStore* device_policy_store_ = nullptr;
MockDevicePolicyService* device_policy_service_ = nullptr;
MockUserPolicyServiceFactory* user_policy_service_factory_ = nullptr;
map<string, MockPolicyService*> user_policy_services_;
@@ -2173,6 +2179,8 @@
ON_CALL(vpd_process_, RunInBackground(_, _, _))
.WillByDefault(
Invoke(this, &StartTPMFirmwareUpdateTest::RunVpdProcess));
+ ON_CALL(*device_policy_store_, Get())
+ .WillByDefault(ReturnRef(policy_));
SetFileExists(SessionManagerImpl::kTPMFirmwareUpdateAvailableFile, true);
}
@@ -2248,6 +2256,12 @@
vpd_status_ = status;
}
+ void SetPolicy(const ChromeDeviceSettingsProto& settings) {
+ PolicyData policy_data;
+ CHECK(settings.SerializeToString(policy_data.mutable_policy_value()));
+ CHECK(policy_data.SerializeToString(policy_.mutable_policy_data()));
+ }
+
std::string update_mode_ = "first_boot";
std::string existing_vpd_params_;
std::string expected_vpd_params_ = "mode:first_boot";
@@ -2256,6 +2270,7 @@
bool vpd_spawned_ = true;
bool vpd_status_ = true;
VpdProcess::CompletionCallback completion_;
+ PolicyFetchResponse policy_;
};
TEST_F(StartTPMFirmwareUpdateTest, Success_FirstBoot) {
@@ -2283,12 +2298,22 @@
ExpectError(dbus_error::kInvalidParameter);
}
-TEST_F(StartTPMFirmwareUpdateTest, Enterprise) {
+TEST_F(StartTPMFirmwareUpdateTest, EnterpriseNotSet) {
EXPECT_CALL(*device_policy_service_, InstallAttributesEnterpriseMode())
.WillRepeatedly(Return(true));
ExpectError(dbus_error::kNotAvailable);
}
+TEST_F(StartTPMFirmwareUpdateTest, EnterpriseAllowed) {
+ EXPECT_CALL(*device_policy_service_, InstallAttributesEnterpriseMode())
+ .WillRepeatedly(Return(true));
+ ChromeDeviceSettingsProto settings;
+ settings.mutable_tpm_firmware_update_settings()
+ ->set_allow_user_initiated_powerwash(true);
+ SetPolicy(settings);
+ ExpectDeviceRestart();
+}
+
TEST_F(StartTPMFirmwareUpdateTest, VpdSpawnError) {
SetVpdSpawned(false);
ExpectError(dbus_error::kVpdUpdateFailed);