summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/chromeos/cros/cryptohome_library.cc7
-rw-r--r--chrome/browser/chromeos/login/enterprise_enrollment_screen.cc98
-rw-r--r--chrome/browser/policy/browser_policy_connector.cc32
-rw-r--r--chrome/browser/policy/browser_policy_connector.h5
-rw-r--r--chrome/browser/policy/device_policy_cache.cc34
-rw-r--r--chrome/browser/policy/device_policy_cache.h10
-rw-r--r--chrome/browser/policy/device_policy_cache_unittest.cc136
-rw-r--r--chrome/browser/policy/enterprise_install_attributes.cc112
-rw-r--r--chrome/browser/policy/enterprise_install_attributes.h65
-rw-r--r--chrome/browser/policy/enterprise_install_attributes_unittest.cc55
-rw-r--r--chrome/browser/policy/proto/device_management_backend.proto10
-rw-r--r--chrome/chrome_browser.gypi10
-rw-r--r--chrome/chrome_tests.gypi2
13 files changed, 443 insertions, 133 deletions
diff --git a/chrome/browser/chromeos/cros/cryptohome_library.cc b/chrome/browser/chromeos/cros/cryptohome_library.cc
index 6c20330..55dfa15 100644
--- a/chrome/browser/chromeos/cros/cryptohome_library.cc
+++ b/chrome/browser/chromeos/cros/cryptohome_library.cc
@@ -245,7 +245,8 @@ class CryptohomeLibraryImpl : public CryptohomeLibrary {
class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
public:
- CryptohomeLibraryStubImpl() {}
+ CryptohomeLibraryStubImpl()
+ : locked_(false) {}
virtual ~CryptohomeLibraryStubImpl() {}
bool CheckKey(const std::string& user_email, const std::string& passhash) {
@@ -399,7 +400,7 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
}
bool InstallAttributesIsSecure() {
- return locked_;
+ return false;
}
bool InstallAttributesIsInvalid() {
@@ -407,7 +408,7 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
}
bool InstallAttributesIsFirstInstall() {
- return false;
+ return !locked_;
}
private:
diff --git a/chrome/browser/chromeos/login/enterprise_enrollment_screen.cc b/chrome/browser/chromeos/login/enterprise_enrollment_screen.cc
index 4f6e477..48ed015 100644
--- a/chrome/browser/chromeos/login/enterprise_enrollment_screen.cc
+++ b/chrome/browser/chromeos/login/enterprise_enrollment_screen.cc
@@ -15,7 +15,7 @@
namespace chromeos {
// Retry for InstallAttrs initialization every 500ms.
-const int kLockboxRetryIntervalMs = 500;
+const int kLockRetryIntervalMs = 500;
EnterpriseEnrollmentScreen::EnterpriseEnrollmentScreen(
WizardScreenDelegate* delegate)
@@ -227,79 +227,33 @@ void EnterpriseEnrollmentScreen::WriteInstallAttributesData(
if (!view())
return;
- chromeos::CryptohomeLibrary* cryptohome =
- chromeos::CrosLibrary::Get()->GetCryptohomeLibrary();
- if (!cryptohome) {
- LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs can not "
- << "be accessed.";
- view()->ShowFatalEnrollmentError();
- return;
- }
-
- if (!cryptohome->InstallAttributesIsReady()) {
- // Lockbox is not ready yet, retry later.
- LOG(WARNING) << "Lockbox is not ready yet will retry in "
- << kLockboxRetryIntervalMs << "ms.";
- MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- runnable_method_factory_.NewRunnableMethod(
- &EnterpriseEnrollmentScreen::WriteInstallAttributesData, result),
- kLockboxRetryIntervalMs);
- return;
- }
-
- // Clearing the TPM password seems to be always a good deal.
- if (cryptohome->TpmIsEnabled() &&
- !cryptohome->TpmIsBeingOwned() &&
- cryptohome->TpmIsOwned()) {
- cryptohome->TpmClearStoredPassword();
- }
-
- // Make sure we really have a working InstallAttrs.
- if (cryptohome->InstallAttributesIsInvalid()) {
- LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
- << "is corrupt or failed to initialize!";
- view()->ShowFatalEnrollmentError();
- return;
- }
- if (!cryptohome->InstallAttributesIsFirstInstall()) {
- std::string value;
- if (cryptohome->InstallAttributesGet("enterprise.owned", &value) &&
- value == "true") {
- if (cryptohome->InstallAttributesGet("enterprise.user", &value)) {
- if (value == user_) {
- // If we landed here with a locked InstallAttrs this would mean we
- // only want to reenroll with the DMServer so lock just continue.
- auth_fetcher_->StartIssueAuthToken(
- result.sid, result.lsid,
- GaiaConstants::kDeviceManagementService);
- return;
- }
- }
- }
-
- LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
- << "has been locked already!";
- view()->ShowFatalEnrollmentError();
- return;
- }
-
- // Set values in the InstallAttrs and lock it.
- DCHECK(cryptohome->InstallAttributesIsFirstInstall());
- cryptohome->InstallAttributesSet("enterprise.owned", "true");
- cryptohome->InstallAttributesSet("enterprise.user", user_);
- DCHECK(cryptohome->InstallAttributesCount() == 2);
- cryptohome->InstallAttributesFinalize();
- if (cryptohome->InstallAttributesIsFirstInstall()) {
- LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
- << "can not be sealed!";
- view()->ShowFatalEnrollmentError();
- return;
+ switch (g_browser_process->browser_policy_connector()->LockDevice(user_)) {
+ case policy::EnterpriseInstallAttributes::LOCK_SUCCESS:
+ // Proceed with register and policy fetch.
+ auth_fetcher_->StartIssueAuthToken(
+ result.sid, result.lsid, GaiaConstants::kDeviceManagementService);
+ return;
+ case policy::EnterpriseInstallAttributes::LOCK_NOT_READY:
+ // InstallAttributes not ready yet, retry later.
+ LOG(WARNING) << "Install Attributes not ready yet will retry in "
+ << kLockRetryIntervalMs << "ms.";
+ MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ runnable_method_factory_.NewRunnableMethod(
+ &EnterpriseEnrollmentScreen::WriteInstallAttributesData, result),
+ kLockRetryIntervalMs);
+ return;
+ case policy::EnterpriseInstallAttributes::LOCK_BACKEND_ERROR:
+ view()->ShowFatalEnrollmentError();
+ return;
+ case policy::EnterpriseInstallAttributes::LOCK_WRONG_USER:
+ LOG(ERROR) << "Enrollment can not proceed because the InstallAttrs "
+ << "has been locked already!";
+ view()->ShowFatalEnrollmentError();
+ return;
}
- // Proceed with register and policy fetch.
- auth_fetcher_->StartIssueAuthToken(
- result.sid, result.lsid, GaiaConstants::kDeviceManagementService);
+ NOTREACHED();
}
} // namespace chromeos
diff --git a/chrome/browser/policy/browser_policy_connector.cc b/chrome/browser/policy/browser_policy_connector.cc
index 56f4443..e6f375e 100644
--- a/chrome/browser/policy/browser_policy_connector.cc
+++ b/chrome/browser/policy/browser_policy_connector.cc
@@ -23,8 +23,10 @@
#endif
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/policy/device_policy_cache.h"
#include "chrome/browser/policy/device_policy_identity_strategy.h"
+#include "chrome/browser/policy/enterprise_install_attributes.h"
#endif
namespace policy {
@@ -38,9 +40,12 @@ BrowserPolicyConnector::BrowserPolicyConnector()
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kEnableDevicePolicy)) {
identity_strategy_.reset(new DevicePolicyIdentityStrategy());
+ install_attributes_.reset(new EnterpriseInstallAttributes(
+ chromeos::CrosLibrary::Get()->GetCryptohomeLibrary()));
cloud_policy_subsystem_.reset(new CloudPolicySubsystem(
identity_strategy_.get(),
- new DevicePolicyCache(identity_strategy_.get())));
+ new DevicePolicyCache(identity_strategy_.get(),
+ install_attributes_.get())));
// Initialize the subsystem once the message loops are spinning.
MessageLoop::current()->PostTask(
@@ -149,22 +154,23 @@ bool BrowserPolicyConnector::IsEnterpriseManaged() {
#endif
}
-std::string BrowserPolicyConnector::GetEnterpriseDomain() {
- std::string domain;
+EnterpriseInstallAttributes::LockResult
+ BrowserPolicyConnector::LockDevice(const std::string& user) {
+#if defined(OS_CHROMEOS)
+ if (install_attributes_.get())
+ return install_attributes_->LockDevice(user);
+#endif
+ return EnterpriseInstallAttributes::LOCK_BACKEND_ERROR;
+}
+
+std::string BrowserPolicyConnector::GetEnterpriseDomain() {
#if defined(OS_CHROMEOS)
- // TODO(xiyuan): Find a better way to get enterprise domain.
- std::string username;
- std::string auth_token;
- if (identity_strategy_.get() &&
- identity_strategy_->GetCredentials(&username, &auth_token)) {
- size_t pos = username.find('@');
- if (pos != std::string::npos)
- domain = username.substr(pos + 1);
- }
+ if (install_attributes_.get())
+ return install_attributes_->GetDomain();
#endif
- return domain;
+ return std::string();
}
void BrowserPolicyConnector::StopAutoRetry() {
diff --git a/chrome/browser/policy/browser_policy_connector.h b/chrome/browser/policy/browser_policy_connector.h
index e055a97..de4af72 100644
--- a/chrome/browser/policy/browser_policy_connector.h
+++ b/chrome/browser/policy/browser_policy_connector.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/task.h"
+#include "chrome/browser/policy/enterprise_install_attributes.h"
class PrefService;
class TestingBrowserProcess;
@@ -54,6 +55,9 @@ class BrowserPolicyConnector {
// a local owner).
bool IsEnterpriseManaged();
+ // Locks the device to an enterprise domain.
+ EnterpriseInstallAttributes::LockResult LockDevice(const std::string& user);
+
// Returns the enterprise domain if device is managed.
std::string GetEnterpriseDomain();
@@ -82,6 +86,7 @@ class BrowserPolicyConnector {
#if defined(OS_CHROMEOS)
scoped_ptr<DevicePolicyIdentityStrategy> identity_strategy_;
+ scoped_ptr<EnterpriseInstallAttributes> install_attributes_;
#endif
scoped_ptr<CloudPolicySubsystem> cloud_policy_subsystem_;
diff --git a/chrome/browser/policy/device_policy_cache.cc b/chrome/browser/policy/device_policy_cache.cc
index 6ab2e33..57456fb 100644
--- a/chrome/browser/policy/device_policy_cache.cc
+++ b/chrome/browser/policy/device_policy_cache.cc
@@ -15,6 +15,7 @@
#include "chrome/browser/chromeos/user_cros_settings_provider.h"
#include "chrome/browser/policy/configuration_policy_pref_store.h"
#include "chrome/browser/policy/device_policy_identity_strategy.h"
+#include "chrome/browser/policy/enterprise_install_attributes.h"
#include "chrome/browser/policy/policy_map.h"
#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
@@ -109,8 +110,10 @@ Value* DecodeIntegerValue(google::protobuf::int64 value) {
namespace policy {
DevicePolicyCache::DevicePolicyCache(
- DevicePolicyIdentityStrategy* identity_strategy)
+ DevicePolicyIdentityStrategy* identity_strategy,
+ EnterpriseInstallAttributes* install_attributes)
: identity_strategy_(identity_strategy),
+ install_attributes_(install_attributes),
signed_settings_helper_(chromeos::SignedSettingsHelper::Get()),
starting_up_(true),
ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)) {
@@ -118,8 +121,10 @@ DevicePolicyCache::DevicePolicyCache(
DevicePolicyCache::DevicePolicyCache(
DevicePolicyIdentityStrategy* identity_strategy,
+ EnterpriseInstallAttributes* install_attributes,
chromeos::SignedSettingsHelper* signed_settings_helper)
: identity_strategy_(identity_strategy),
+ install_attributes_(install_attributes),
signed_settings_helper_(signed_settings_helper),
starting_up_(true),
ALLOW_THIS_IN_INITIALIZER_LIST(callback_factory_(this)) {
@@ -135,6 +140,33 @@ void DevicePolicyCache::Load() {
void DevicePolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) {
DCHECK(!starting_up_);
+
+ // Make sure we have an enterprise device.
+ std::string registration_user(install_attributes_->GetRegistrationUser());
+ if (registration_user.empty()) {
+ LOG(WARNING) << "Refusing to accept policy on non-enterprise device.";
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ return;
+ }
+
+ // Check the user this policy is for against the device-locked name.
+ em::PolicyData policy_data;
+ if (!policy_data.ParseFromString(policy.policy_data())) {
+ LOG(WARNING) << "Invalid policy protobuf";
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ return;
+ }
+
+ if (registration_user != policy_data.username()) {
+ LOG(WARNING) << "Refusing policy blob for " << policy_data.username()
+ << " which doesn't match " << registration_user;
+ InformNotifier(CloudPolicySubsystem::LOCAL_ERROR,
+ CloudPolicySubsystem::POLICY_LOCAL_ERROR);
+ return;
+ }
+
set_last_policy_refresh_time(base::Time::NowFromSystemTime());
// Start a store operation.
diff --git a/chrome/browser/policy/device_policy_cache.h b/chrome/browser/policy/device_policy_cache.h
index 3602839..ce29c97 100644
--- a/chrome/browser/policy/device_policy_cache.h
+++ b/chrome/browser/policy/device_policy_cache.h
@@ -17,6 +17,7 @@
namespace policy {
class DevicePolicyIdentityStrategy;
+class EnterpriseInstallAttributes;
class PolicyMap;
namespace em = enterprise_management;
@@ -26,7 +27,8 @@ namespace em = enterprise_management;
class DevicePolicyCache : public CloudPolicyCacheBase,
public chromeos::SignedSettingsHelper::Callback {
public:
- explicit DevicePolicyCache(DevicePolicyIdentityStrategy* identity_strategy);
+ explicit DevicePolicyCache(DevicePolicyIdentityStrategy* identity_strategy,
+ EnterpriseInstallAttributes* install_attributes);
virtual ~DevicePolicyCache();
// CloudPolicyCacheBase implementation:
@@ -46,6 +48,7 @@ class DevicePolicyCache : public CloudPolicyCacheBase,
// singleton.
DevicePolicyCache(
DevicePolicyIdentityStrategy* identity_strategy,
+ EnterpriseInstallAttributes* install_attributes,
chromeos::SignedSettingsHelper* signed_settings_helper);
// CloudPolicyCacheBase implementation:
@@ -55,11 +58,16 @@ class DevicePolicyCache : public CloudPolicyCacheBase,
void PolicyStoreOpCompleted(chromeos::SignedSettings::ReturnCode code);
+ // Checks with immutable attributes whether this is an enterprise device and
+ // read the registration user if this is the case.
+ void CheckImmutableAttributes();
+
static void DecodeDevicePolicy(const em::ChromeDeviceSettingsProto& policy,
PolicyMap* mandatory,
PolicyMap* recommended);
DevicePolicyIdentityStrategy* identity_strategy_;
+ EnterpriseInstallAttributes* install_attributes_;
chromeos::SignedSettingsHelper* signed_settings_helper_;
diff --git a/chrome/browser/policy/device_policy_cache_unittest.cc b/chrome/browser/policy/device_policy_cache_unittest.cc
index 4228470..27b645c 100644
--- a/chrome/browser/policy/device_policy_cache_unittest.cc
+++ b/chrome/browser/policy/device_policy_cache_unittest.cc
@@ -4,7 +4,9 @@
#include "chrome/browser/policy/device_policy_cache.h"
+#include "chrome/browser/chromeos/cros/cryptohome_library.h"
#include "chrome/browser/policy/device_policy_identity_strategy.h"
+#include "chrome/browser/policy/enterprise_install_attributes.h"
#include "policy/configuration_policy_type.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -13,6 +15,9 @@ namespace policy {
namespace {
+// Test registration user name.
+const char kTestUser[] = "test@example.com";
+
using ::chromeos::SignedSettings;
using ::chromeos::SignedSettingsHelper;
using ::testing::_;
@@ -52,33 +57,34 @@ ACTION_P2(MockSignedSettingsHelperRetrievePolicy, status_code, policy) {
arg0->OnRetrievePolicyCompleted(status_code, policy);
}
-em::PolicyFetchResponse* CreateProxyPolicy(const std::string& proxy) {
+void CreatePolicy(em::PolicyFetchResponse* policy,
+ const std::string& user,
+ int refresh_rate) {
// This method omits a few fields which currently aren't needed by tests:
- // timestamp, machine_name, request_token, policy_type, public key info.
+ // timestamp, machine_name, policy_type, public key info.
em::PolicyData signed_response;
em::ChromeDeviceSettingsProto settings;
- em::DeviceProxySettingsProto* proxy_proto =
- settings.mutable_device_proxy_settings();
- proxy_proto->set_proxy_server(proxy);
- proxy_proto->set_proxy_mode("fixed_servers");
+ settings.mutable_policy_refresh_rate()->set_policy_refresh_rate(refresh_rate);
+ signed_response.set_username(user);
+ signed_response.set_request_token("dmtoken");
+ signed_response.set_device_id("deviceid");
EXPECT_TRUE(
settings.SerializeToString(signed_response.mutable_policy_value()));
std::string serialized_signed_response;
EXPECT_TRUE(signed_response.SerializeToString(&serialized_signed_response));
- em::PolicyFetchResponse* response = new em::PolicyFetchResponse;
- response->set_policy_data(serialized_signed_response);
- return response;
+ policy->set_policy_data(serialized_signed_response);
}
} // namespace
class DevicePolicyCacheTest : public testing::Test {
protected:
- DevicePolicyCacheTest() {
- }
+ DevicePolicyCacheTest()
+ : install_attributes_(chromeos::CryptohomeLibrary::GetImpl(true)) {}
virtual void SetUp() {
cache_.reset(new DevicePolicyCache(&identity_strategy_,
+ &install_attributes_,
&signed_settings_helper_));
}
@@ -87,11 +93,17 @@ class DevicePolicyCacheTest : public testing::Test {
cache_.reset();
}
- const PolicyMap& mandatory_policy(const DevicePolicyCache& cache) {
- return cache.mandatory_policy_;
+ void MakeEnterpriseDevice(const char* registration_user) {
+ ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
+ install_attributes_.LockDevice(registration_user));
+ }
+
+ const Value* GetMandatoryPolicy(ConfigurationPolicyType policy) {
+ return cache_->mandatory_policy_.Get(policy);
}
scoped_ptr<DevicePolicyCache> cache_;
+ EnterpriseInstallAttributes install_attributes_;
DevicePolicyIdentityStrategy identity_strategy_;
MockSignedSettingsHelper signed_settings_helper_;
@@ -100,46 +112,98 @@ class DevicePolicyCacheTest : public testing::Test {
};
TEST_F(DevicePolicyCacheTest, Startup) {
- scoped_ptr<em::PolicyFetchResponse> policy_response(
- CreateProxyPolicy("proxy.server"));
+ em::PolicyFetchResponse policy;
+ CreatePolicy(&policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
- *policy_response));
+ policy));
cache_->Load();
- // TODO(jkummerow): This will be EXPECT_GT once policy decoding is
- // implemented in DevicePolicyCache::DecodeDevicePolicy(...).
- EXPECT_EQ(mandatory_policy(*cache_).size(), 0U);
+ testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+ FundamentalValue expected(120);
+ EXPECT_TRUE(Value::Equals(&expected,
+ GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
}
TEST_F(DevicePolicyCacheTest, SetPolicy) {
InSequence s;
+
+ MakeEnterpriseDevice(kTestUser);
+
// Startup.
- scoped_ptr<em::PolicyFetchResponse> policy_response(
- CreateProxyPolicy("proxy.server.old"));
+ em::PolicyFetchResponse policy;
+ CreatePolicy(&policy, kTestUser, 120);
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
- *policy_response));
+ policy));
cache_->Load();
- scoped_ptr<Value> expected(Value::CreateStringValue("proxy.server.old"));
- // TODO(jkummerow): This will be EXPECT_TRUE once policy decoding is
- // implemented in DevicePolicyCache::DecodeDevicePolicy(...).
- EXPECT_FALSE(Value::Equals(
- mandatory_policy(*cache_).Get(kPolicyProxyServer), expected.get()));
testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+ FundamentalValue expected(120);
+ EXPECT_TRUE(Value::Equals(&expected,
+ GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
+
// Set new policy information.
- scoped_ptr<em::PolicyFetchResponse> new_policy_response(
- CreateProxyPolicy("proxy.server.new"));
+ em::PolicyFetchResponse new_policy;
+ CreatePolicy(&new_policy, kTestUser, 300);
EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_, _)).WillOnce(
MockSignedSettingsHelperStorePolicy(chromeos::SignedSettings::SUCCESS));
EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
- *new_policy_response));
- cache_->SetPolicy(*new_policy_response);
- expected.reset(Value::CreateStringValue("proxy.server.new"));
- // TODO(jkummerow): This will be EXPECT_TRUE once policy decoding is
- // implemented in DevicePolicyCache::DecodeDevicePolicy(...).
- EXPECT_FALSE(Value::Equals(
- mandatory_policy(*cache_).Get(kPolicyProxyServer), expected.get()));
+ new_policy));
+ cache_->SetPolicy(new_policy);
+ testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+ FundamentalValue updated_expected(300);
+ EXPECT_TRUE(Value::Equals(&updated_expected,
+ GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
+}
+
+TEST_F(DevicePolicyCacheTest, SetPolicyWrongUser) {
+ InSequence s;
+
+ MakeEnterpriseDevice(kTestUser);
+
+ // Startup.
+ em::PolicyFetchResponse policy;
+ CreatePolicy(&policy, kTestUser, 120);
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
+ MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
+ policy));
+ cache_->Load();
+ testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+
+ // Set new policy information. This should fail due to invalid user.
+ em::PolicyFetchResponse new_policy;
+ CreatePolicy(&new_policy, "foreign_user@example.com", 300);
+ EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_, _)).Times(0);
+ cache_->SetPolicy(new_policy);
+ testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+
+ FundamentalValue expected(120);
+ EXPECT_TRUE(Value::Equals(&expected,
+ GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
+}
+
+TEST_F(DevicePolicyCacheTest, SetPolicyNonEnterpriseDevice) {
+ InSequence s;
+
+ // Startup.
+ em::PolicyFetchResponse policy;
+ CreatePolicy(&policy, kTestUser, 120);
+ EXPECT_CALL(signed_settings_helper_, StartRetrievePolicyOp(_)).WillOnce(
+ MockSignedSettingsHelperRetrievePolicy(SignedSettings::SUCCESS,
+ policy));
+ cache_->Load();
+ testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+
+ // Set new policy information. This should fail due to invalid user.
+ em::PolicyFetchResponse new_policy;
+ CreatePolicy(&new_policy, kTestUser, 120);
+ EXPECT_CALL(signed_settings_helper_, StartStorePolicyOp(_, _)).Times(0);
+ cache_->SetPolicy(new_policy);
+ testing::Mock::VerifyAndClearExpectations(&signed_settings_helper_);
+
+ FundamentalValue expected(120);
+ EXPECT_TRUE(Value::Equals(&expected,
+ GetMandatoryPolicy(kPolicyPolicyRefreshRate)));
}
} // namespace policy
diff --git a/chrome/browser/policy/enterprise_install_attributes.cc b/chrome/browser/policy/enterprise_install_attributes.cc
new file mode 100644
index 0000000..0fec96f
--- /dev/null
+++ b/chrome/browser/policy/enterprise_install_attributes.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/policy/enterprise_install_attributes.h"
+
+#include "base/logging.h"
+#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+
+static const char kAttrEnterpriseOwned[] = "enterprise.owned";
+static const char kAttrEnterpriseUser[] = "enterprise.user";
+
+namespace policy {
+
+EnterpriseInstallAttributes::EnterpriseInstallAttributes(
+ chromeos::CryptohomeLibrary* cryptohome)
+ : cryptohome_(cryptohome),
+ device_locked_(false) {}
+
+EnterpriseInstallAttributes::LockResult EnterpriseInstallAttributes::LockDevice(
+ const std::string& user) {
+ // Check for existing lock first.
+ if (device_locked_) {
+ return !registration_user_.empty() && user == registration_user_ ?
+ LOCK_SUCCESS : LOCK_WRONG_USER;
+ }
+
+ if (!cryptohome_->InstallAttributesIsReady())
+ return LOCK_NOT_READY;
+
+ // Clearing the TPM password seems to be always a good deal.
+ if (cryptohome_->TpmIsEnabled() &&
+ !cryptohome_->TpmIsBeingOwned() &&
+ cryptohome_->TpmIsOwned()) {
+ cryptohome_->TpmClearStoredPassword();
+ }
+
+ // Make sure we really have a working InstallAttrs.
+ if (cryptohome_->InstallAttributesIsInvalid()) {
+ LOG(ERROR) << "Install attributes invalid.";
+ return LOCK_BACKEND_ERROR;
+ }
+
+ if (!cryptohome_->InstallAttributesIsFirstInstall())
+ return LOCK_WRONG_USER;
+
+ // Set values in the InstallAttrs and lock it.
+ if (!cryptohome_->InstallAttributesSet(kAttrEnterpriseOwned, "true") ||
+ !cryptohome_->InstallAttributesSet(kAttrEnterpriseUser, user)) {
+ LOG(ERROR) << "Failed writing attributes";
+ return LOCK_BACKEND_ERROR;
+ }
+
+ if (!cryptohome_->InstallAttributesFinalize() ||
+ cryptohome_->InstallAttributesIsFirstInstall() ||
+ GetRegistrationUser() != user) {
+ LOG(ERROR) << "Failed locking.";
+ return LOCK_BACKEND_ERROR;
+ }
+
+ return LOCK_SUCCESS;
+}
+
+bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
+ ReadImmutableAttributes();
+ return device_locked_ && !registration_user_.empty();
+}
+
+std::string EnterpriseInstallAttributes::GetRegistrationUser() {
+ ReadImmutableAttributes();
+
+ if (!device_locked_)
+ return std::string();
+
+ return registration_user_;
+}
+
+std::string EnterpriseInstallAttributes::GetDomain() {
+ if (!IsEnterpriseDevice())
+ return std::string();
+
+ std::string domain;
+ size_t pos = registration_user_.find('@');
+ if (pos != std::string::npos)
+ domain = registration_user_.substr(pos + 1);
+
+ return domain;
+}
+
+void EnterpriseInstallAttributes::ReadImmutableAttributes() {
+ if (device_locked_)
+ return;
+
+ if (cryptohome_ &&
+ cryptohome_->InstallAttributesIsReady() &&
+ !cryptohome_->InstallAttributesIsInvalid() &&
+ !cryptohome_->InstallAttributesIsFirstInstall()) {
+ device_locked_ = true;
+ std::string enterprise_owned;
+ std::string enterprise_user;
+ if (cryptohome_->InstallAttributesGet(kAttrEnterpriseOwned,
+ &enterprise_owned) &&
+ cryptohome_->InstallAttributesGet(kAttrEnterpriseUser,
+ &enterprise_user) &&
+ enterprise_owned == "true" &&
+ !enterprise_user.empty()) {
+ registration_user_ = enterprise_user;
+ }
+ }
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/enterprise_install_attributes.h b/chrome/browser/policy/enterprise_install_attributes.h
new file mode 100644
index 0000000..90d728a
--- /dev/null
+++ b/chrome/browser/policy/enterprise_install_attributes.h
@@ -0,0 +1,65 @@
+// Copyright (c) 2011 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_BROWSER_POLICY_ENTERPRISE_INSTALL_ATTRIBUTES_H_
+#define CHROME_BROWSER_POLICY_ENTERPRISE_INSTALL_ATTRIBUTES_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+namespace chromeos {
+class CryptohomeLibrary;
+}
+
+namespace policy {
+
+// Brokers access to the enterprise-related installation-time attributes on
+// ChromeOS.
+class EnterpriseInstallAttributes {
+ public:
+ // Return codes for LockDevice().
+ enum LockResult {
+ LOCK_SUCCESS,
+ LOCK_NOT_READY,
+ LOCK_BACKEND_ERROR,
+ LOCK_WRONG_USER,
+ };
+
+ explicit EnterpriseInstallAttributes(chromeos::CryptohomeLibrary* cryptohome);
+
+ // Locks the device to be an enterprise device registered by the given user.
+ // This can also be called after the lock has already been taken, in which
+ // case it checks that the passed user agrees with the locked attribute.
+ LockResult LockDevice(const std::string& user) WARN_UNUSED_RESULT;
+
+ // Checks whether this is an enterprise device.
+ bool IsEnterpriseDevice();
+
+ // Gets the domain this device belongs to or an empty string if the device is
+ // not an enterprise device.
+ std::string GetDomain();
+
+ // Gets the user that registered the device. Returns an empty string if the
+ // device is not an enterprise device.
+ std::string GetRegistrationUser();
+
+ private:
+ // Makes sure the local caches for enterprise-related install attributes are
+ // up-to-date with what cryptohome has.
+ void ReadImmutableAttributes();
+
+ chromeos::CryptohomeLibrary* cryptohome_;
+
+ bool device_locked_;
+ std::string registration_user_;
+
+ DISALLOW_COPY_AND_ASSIGN(EnterpriseInstallAttributes);
+};
+
+} // namespace policy
+
+#endif // CHROME_BROWSER_POLICY_ENTERPRISE_INSTALL_ATTRIBUTES_H_
diff --git a/chrome/browser/policy/enterprise_install_attributes_unittest.cc b/chrome/browser/policy/enterprise_install_attributes_unittest.cc
new file mode 100644
index 0000000..9d69924
--- /dev/null
+++ b/chrome/browser/policy/enterprise_install_attributes_unittest.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2011 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.
+
+#include "chrome/browser/policy/enterprise_install_attributes.h"
+
+#include "chrome/browser/chromeos/cros/cryptohome_library.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace policy {
+
+static const char kTestUser[] = "test@example.com";
+
+class EnterpriseInstallAttributesTest : public testing::Test {
+ protected:
+ EnterpriseInstallAttributesTest()
+ : cryptohome_(chromeos::CryptohomeLibrary::GetImpl(true)),
+ install_attributes_(cryptohome_.get()) {}
+
+ scoped_ptr<chromeos::CryptohomeLibrary> cryptohome_;
+ EnterpriseInstallAttributes install_attributes_;
+};
+
+TEST_F(EnterpriseInstallAttributesTest, Lock) {
+ EXPECT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
+ install_attributes_.LockDevice(kTestUser));
+
+ EXPECT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
+ install_attributes_.LockDevice(kTestUser));
+ EXPECT_EQ(EnterpriseInstallAttributes::LOCK_WRONG_USER,
+ install_attributes_.LockDevice("test1@example.com"));
+}
+
+TEST_F(EnterpriseInstallAttributesTest, IsEnterpriseDevice) {
+ EXPECT_FALSE(install_attributes_.IsEnterpriseDevice());
+ ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
+ install_attributes_.LockDevice(kTestUser));
+ EXPECT_TRUE(install_attributes_.IsEnterpriseDevice());
+}
+
+TEST_F(EnterpriseInstallAttributesTest, GetDomain) {
+ EXPECT_EQ(std::string(), install_attributes_.GetDomain());
+ ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
+ install_attributes_.LockDevice(kTestUser));
+ EXPECT_EQ("example.com", install_attributes_.GetDomain());
+}
+
+TEST_F(EnterpriseInstallAttributesTest, GetRegistrationUser) {
+ EXPECT_EQ(std::string(), install_attributes_.GetRegistrationUser());
+ ASSERT_EQ(EnterpriseInstallAttributes::LOCK_SUCCESS,
+ install_attributes_.LockDevice(kTestUser));
+ EXPECT_EQ(kTestUser, install_attributes_.GetRegistrationUser());
+}
+
+} // namespace policy
diff --git a/chrome/browser/policy/proto/device_management_backend.proto b/chrome/browser/policy/proto/device_management_backend.proto
index 9d3923f..71bbfc1 100644
--- a/chrome/browser/policy/proto/device_management_backend.proto
+++ b/chrome/browser/policy/proto/device_management_backend.proto
@@ -106,7 +106,7 @@ message PolicyFetchRequest {
SHA1_RSA = 1;
}
optional SignatureType signature_type = 3 [default = NONE];
-
+
// The version number of the public key that is currently stored
// on the client. This should be the last number the server had
// supplied as new_public_key_version in PolicyData.
@@ -148,16 +148,16 @@ message PolicyData {
// |machine_name| in DeviceRegisterResponse but it might have
// changed since then.
optional string machine_name = 5;
-
+
// Version number of the server's current public key. (The key that
// was used to sign this response. Numbering should start at 1 and be
// increased by 1 at each key rotation.)
optional int32 public_key_version = 6;
-
+
// The user this policy is intended for. In case of device policy, the name
// of the owner (who registered the device).
optional string username = 7;
-
+
// In this field the DMServer should echo back the "deviceid" HTTP parameter
// from the request.
optional string device_id = 8;
@@ -274,4 +274,4 @@ message DeviceManagementResponse {
// Policy response.
optional DevicePolicyResponse policy_response = 5;
-} \ No newline at end of file
+}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index fcfab61..b975335 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1554,6 +1554,8 @@
'browser/policy/device_token_fetcher.h',
'browser/policy/dummy_configuration_policy_provider.cc',
'browser/policy/dummy_configuration_policy_provider.h',
+ 'browser/policy/enterprise_install_attributes.cc',
+ 'browser/policy/enterprise_install_attributes.h',
'browser/policy/file_based_policy_loader.cc',
'browser/policy/file_based_policy_loader.h',
'browser/policy/file_based_policy_provider.cc',
@@ -3433,10 +3435,14 @@
['exclude', 'browser/extensions/file_manager_util.cc'],
['exclude', 'browser/oom_priority_manager.cc'],
['exclude', 'browser/oom_priority_manager.h'],
- ['exclude', 'browser/policy/device_policy_cache\\.(h|cc)'],
+ ['exclude', 'browser/policy/device_policy_cache.cc'],
+ ['exclude', 'browser/policy/device_policy_cache.h'],
+ ['exclude', 'browser/policy/enterprise_install_attributes.cc'],
+ ['exclude', 'browser/policy/enterprise_install_attributes.h'],
['exclude', 'browser/policy/device_policy_identity_strategy.cc'],
['exclude', 'browser/policy/device_policy_identity_strategy.h'],
- ['exclude', 'browser/policy/proto/chrome_device_policy\\.pb\\.(h|cc)'],
+ ['exclude', 'browser/policy/proto/chrome_device_policy.pb.cc'],
+ ['exclude', 'browser/policy/proto/chrome_device_policy.pb.h'],
['exclude', 'browser/renderer_host/offline_resource_handler.cc'],
['exclude', 'browser/renderer_host/offline_resource_handler.h'],
['exclude', 'browser/ui/login/login_prompt_ui.cc'],
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 94767c6..3d30545 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1444,6 +1444,7 @@
'browser/policy/configuration_policy_store_interface_unittest.cc',
'browser/policy/device_policy_cache_unittest.cc',
'browser/policy/device_token_fetcher_unittest.cc',
+ 'browser/policy/enterprise_install_attributes_unittest.cc',
'browser/policy/file_based_policy_provider_unittest.cc',
'browser/policy/device_management_backend_mock.cc',
'browser/policy/device_management_backend_mock.h',
@@ -1939,6 +1940,7 @@
'sources/': [
['exclude', '^browser/chromeos/'],
['exclude', '^browser/policy/device_policy_cache_unittest.cc'],
+ ['exclude', '^browser/policy/enterprise_install_attributes_unittest.cc' ],
['exclude', '^browser/ui/webui/chromeos/login'],
],
}],