summaryrefslogtreecommitdiffstats
path: root/chromeos
diff options
context:
space:
mode:
authorjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 21:53:56 +0000
committerjoaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-01 21:53:56 +0000
commit63ebbf2296e2ae5437f7c50892cb514d6590ba5c (patch)
tree6737fb175dc1b3c5433a3f92a8b7b5e70c6bb597 /chromeos
parent8f471efe17352dd8d4831f97f5f5c03812b6f082 (diff)
downloadchromium_src-63ebbf2296e2ae5437f7c50892cb514d6590ba5c.zip
chromium_src-63ebbf2296e2ae5437f7c50892cb514d6590ba5c.tar.gz
chromium_src-63ebbf2296e2ae5437f7c50892cb514d6590ba5c.tar.bz2
Enable Enterprise enrollment on desktop builds.
This change implements some of the DBus stub methods so that enterprise enrollment works on desktop builds. That will make development of features that depend on enrollment faster for developers that use this workflow (e.g. for kiosk enterprise apps, public accounts, testing some device policies, etc). - Override some of the directories and files involved with the enrollment state - Simple stub implementation of the DBus calls involved - Write a persistent cache of the install attributes - Cleaned up the stub for user cloud policy and made them persistent too - Updated some tests This change doesn't affect production code. TBR=jochen@chromium.org BUG=240269, 367674 Review URL: https://codereview.chromium.org/258743005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@267640 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos')
-rw-r--r--chromeos/DEPS2
-rw-r--r--chromeos/chromeos.gyp2
-rw-r--r--chromeos/chromeos_paths.cc24
-rw-r--r--chromeos/chromeos_paths.h9
-rw-r--r--chromeos/dbus/fake_cryptohome_client.cc75
-rw-r--r--chromeos/dbus/fake_session_manager_client.cc1
-rw-r--r--chromeos/dbus/fake_session_manager_client.h1
-rw-r--r--chromeos/dbus/mock_session_manager_client.h3
-rw-r--r--chromeos/dbus/session_manager_client.cc139
-rw-r--r--chromeos/dbus/session_manager_client.h3
-rw-r--r--chromeos/system/statistics_provider.cc7
11 files changed, 216 insertions, 50 deletions
diff --git a/chromeos/DEPS b/chromeos/DEPS
index 63bcc90..ea93903 100644
--- a/chromeos/DEPS
+++ b/chromeos/DEPS
@@ -1,8 +1,10 @@
include_rules = [
"+crypto",
"+net",
+ "+policy/proto",
"+third_party/cros_system_api",
"+third_party/libxml",
+ "+third_party/protobuf",
"+ui/gfx/geometry",
"+ui/gfx/x"
]
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index d6cf1bb..8ab802a 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -16,6 +16,7 @@
'dependencies': [
'../base/base.gyp:base',
'../base/base.gyp:base_prefs',
+ '../components/components.gyp:cloud_policy_proto',
'../components/components.gyp:onc_component',
'../crypto/crypto.gyp:crypto',
'../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
@@ -25,6 +26,7 @@
'../net/net.gyp:net',
'../third_party/icu/icu.gyp:icui18n',
'../third_party/libxml/libxml.gyp:libxml',
+ '../third_party/protobuf/protobuf.gyp:protobuf_lite',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../url/url.gyp:url_lib',
'cryptohome_proto',
diff --git a/chromeos/chromeos_paths.cc b/chromeos/chromeos_paths.cc
index 25174d45..a9963af 100644
--- a/chromeos/chromeos_paths.cc
+++ b/chromeos/chromeos_paths.cc
@@ -4,8 +4,10 @@
#include "chromeos/chromeos_paths.h"
+#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/path_service.h"
+#include "base/sys_info.h"
namespace chromeos {
@@ -77,4 +79,26 @@ void RegisterPathProvider() {
PathService::RegisterProvider(PathProvider, PATH_START, PATH_END);
}
+void RegisterStubPathOverrides(const base::FilePath& stubs_dir) {
+ CHECK(!base::SysInfo::IsRunningOnChromeOS());
+ // Override these paths on the desktop, so that enrollment and cloud
+ // policy work and can be tested.
+ base::FilePath parent = base::MakeAbsoluteFilePath(stubs_dir);
+ PathService::Override(
+ DIR_USER_POLICY_KEYS,
+ parent.AppendASCII("stub_user_policy"));
+ const bool is_absolute = true;
+ const bool create = false;
+ PathService::OverrideAndCreateIfNeeded(
+ FILE_OWNER_KEY,
+ parent.AppendASCII("stub_owner.key"),
+ is_absolute,
+ create);
+ PathService::OverrideAndCreateIfNeeded(
+ FILE_INSTALL_ATTRIBUTES,
+ parent.AppendASCII("stub_install_attributes.pb"),
+ is_absolute,
+ create);
+}
+
} // namespace chromeos
diff --git a/chromeos/chromeos_paths.h b/chromeos/chromeos_paths.h
index d25ac43..fe9be13 100644
--- a/chromeos/chromeos_paths.h
+++ b/chromeos/chromeos_paths.h
@@ -7,6 +7,10 @@
#include "chromeos/chromeos_export.h"
+namespace base {
+class FilePath;
+}
+
// This file declares path keys for the chromeos module. These can be used with
// the PathService to access various special directories and files.
@@ -40,6 +44,11 @@ enum {
// Call once to register the provider for the path keys defined above.
CHROMEOS_EXPORT void RegisterPathProvider();
+// Overrides some of the paths listed above so that those files can be used
+// when not running on ChromeOS. The stubs files will be relative to
+// |stubs_dir|. It is not valid to call this when running on ChromeOS.
+CHROMEOS_EXPORT void RegisterStubPathOverrides(const base::FilePath& stubs_dir);
+
} // namespace chromeos
#endif // CHROMEOS_CHROMEOS_PATHS_H_
diff --git a/chromeos/dbus/fake_cryptohome_client.cc b/chromeos/dbus/fake_cryptohome_client.cc
index 0a54ff0..1796e04 100644
--- a/chromeos/dbus/fake_cryptohome_client.cc
+++ b/chromeos/dbus/fake_cryptohome_client.cc
@@ -5,12 +5,28 @@
#include "chromeos/dbus/fake_cryptohome_client.h"
#include "base/bind.h"
+#include "base/file_util.h"
#include "base/location.h"
#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
+#include "base/threading/worker_pool.h"
+#include "chromeos/chromeos_paths.h"
#include "chromeos/dbus/cryptohome/key.pb.h"
#include "chromeos/dbus/cryptohome/rpc.pb.h"
#include "crypto/nss_util.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
+#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h"
+#include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
+
+namespace {
+
+// Helper to asynchronously write a file in the WorkerPool.
+void PersistFile(const base::FilePath& path, const std::string& content) {
+ base::WriteFile(path, content.data(), content.size());
+}
+
+} // namespace
namespace chromeos {
@@ -20,8 +36,11 @@ FakeCryptohomeClient::FakeCryptohomeClient()
tpm_is_ready_counter_(0),
unmount_result_(true),
system_salt_(GetStubSystemSalt()),
- locked_(false),
- weak_ptr_factory_(this) {}
+ weak_ptr_factory_(this) {
+ base::FilePath cache_path;
+ locked_ = PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES, &cache_path) &&
+ base::PathExists(cache_path);
+}
FakeCryptohomeClient::~FakeCryptohomeClient() {}
@@ -246,6 +265,58 @@ bool FakeCryptohomeClient::InstallAttributesSet(
bool FakeCryptohomeClient::InstallAttributesFinalize(bool* successful) {
locked_ = true;
*successful = true;
+
+ // Persist the install attributes so that they can be reloaded if the
+ // browser is restarted. This is used for ease of development when device
+ // enrollment is required.
+ // The cryptohome::SerializedInstallAttributes protobuf lives in
+ // chrome/browser/chromeos, so it can't be used directly here; use the
+ // low-level protobuf API instead to just write the name-value pairs.
+ // The cache file is read by EnterpriseInstallAttributes::ReadCacheFile.
+ base::FilePath cache_path;
+ if (!PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES, &cache_path))
+ return false;
+
+ std::string result;
+ {
+ // |result| can be used only after the StringOutputStream goes out of
+ // scope.
+ google::protobuf::io::StringOutputStream result_stream(&result);
+ google::protobuf::io::CodedOutputStream result_output(&result_stream);
+
+ // These tags encode a variable-length value on the wire, which can be
+ // used to encode strings, bytes and messages. We only needs constants
+ // for tag numbers 1 and 2 (see install_attributes.proto).
+ const int kVarLengthTag1 = (1 << 3) | 0x2;
+ const int kVarLengthTag2 = (2 << 3) | 0x2;
+
+ typedef std::map<std::string, std::vector<uint8> >::const_iterator Iter;
+ for (Iter it = install_attrs_.begin(); it != install_attrs_.end(); ++it) {
+ std::string attr;
+ {
+ google::protobuf::io::StringOutputStream attr_stream(&attr);
+ google::protobuf::io::CodedOutputStream attr_output(&attr_stream);
+
+ attr_output.WriteVarint32(kVarLengthTag1);
+ attr_output.WriteVarint32(it->first.size());
+ attr_output.WriteString(it->first);
+ attr_output.WriteVarint32(kVarLengthTag2);
+ attr_output.WriteVarint32(it->second.size());
+ attr_output.WriteRaw(it->second.data(), it->second.size());
+ }
+
+ // Two CodedOutputStreams are needed because inner messages must be
+ // prefixed by their total length, which can't be easily computed before
+ // writing their tags and values.
+ result_output.WriteVarint32(kVarLengthTag2);
+ result_output.WriteVarint32(attr.size());
+ result_output.WriteRaw(attr.data(), attr.size());
+ }
+ }
+
+ base::WorkerPool::PostTask(
+ FROM_HERE, base::Bind(&PersistFile, cache_path, result), false);
+
return true;
}
diff --git a/chromeos/dbus/fake_session_manager_client.cc b/chromeos/dbus/fake_session_manager_client.cc
index 21f50c6..ade94f52 100644
--- a/chromeos/dbus/fake_session_manager_client.cc
+++ b/chromeos/dbus/fake_session_manager_client.cc
@@ -117,7 +117,6 @@ void FakeSessionManagerClient::StoreDevicePolicy(
void FakeSessionManagerClient::StorePolicyForUser(
const std::string& username,
const std::string& policy_blob,
- const std::string& policy_key,
const StorePolicyCallback& callback) {
user_policies_[username] = policy_blob;
base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, true));
diff --git a/chromeos/dbus/fake_session_manager_client.h b/chromeos/dbus/fake_session_manager_client.h
index e0cabce..1be814a 100644
--- a/chromeos/dbus/fake_session_manager_client.h
+++ b/chromeos/dbus/fake_session_manager_client.h
@@ -53,7 +53,6 @@ class FakeSessionManagerClient : public SessionManagerClient {
const StorePolicyCallback& callback) OVERRIDE;
virtual void StorePolicyForUser(const std::string& username,
const std::string& policy_blob,
- const std::string& policy_key,
const StorePolicyCallback& callback) OVERRIDE;
virtual void StoreDeviceLocalAccountPolicy(
const std::string& account_id,
diff --git a/chromeos/dbus/mock_session_manager_client.h b/chromeos/dbus/mock_session_manager_client.h
index aa7e271..7d679b8 100644
--- a/chromeos/dbus/mock_session_manager_client.h
+++ b/chromeos/dbus/mock_session_manager_client.h
@@ -43,10 +43,9 @@ class MockSessionManagerClient : public SessionManagerClient {
MOCK_METHOD2(StoreDevicePolicy,
void(const std::string&,
const StorePolicyCallback&));
- MOCK_METHOD4(StorePolicyForUser,
+ MOCK_METHOD3(StorePolicyForUser,
void(const std::string&,
const std::string&,
- const std::string&,
const StorePolicyCallback&));
MOCK_METHOD3(StoreDeviceLocalAccountPolicy,
void(const std::string&,
diff --git a/chromeos/dbus/session_manager_client.cc b/chromeos/dbus/session_manager_client.cc
index 486ce59..44d1e0c 100644
--- a/chromeos/dbus/session_manager_client.cc
+++ b/chromeos/dbus/session_manager_client.cc
@@ -4,8 +4,6 @@
#include "chromeos/dbus/session_manager_client.h"
-#include <map>
-
#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
@@ -13,6 +11,7 @@
#include "base/location.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
+#include "base/task_runner_util.h"
#include "base/threading/worker_pool.h"
#include "chromeos/chromeos_paths.h"
#include "chromeos/dbus/blocking_method_caller.h"
@@ -21,10 +20,45 @@
#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"
+#include "policy/proto/device_management_backend.pb.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
+namespace {
+
+// Returns a location for |file| that is specific to the given |username|.
+// These paths will be relative to DIR_USER_POLICY_KEYS, and can be used only
+// to store stub files.
+base::FilePath GetUserFilePath(const std::string& username, const char* file) {
+ base::FilePath keys_path;
+ if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &keys_path))
+ return base::FilePath();
+ const std::string sanitized =
+ CryptohomeClient::GetStubSanitizedUsername(username);
+ return keys_path.AppendASCII(sanitized).AppendASCII(file);
+}
+
+// Helper to asynchronously retrieve a file's content.
+std::string GetFileContent(const base::FilePath& path) {
+ std::string result;
+ if (!path.empty())
+ base::ReadFileToString(path, &result);
+ return result;
+}
+
+// Helper to write a file in a background thread.
+void StoreFile(const base::FilePath& path, const std::string& data) {
+ const int size = static_cast<int>(data.size());
+ if (path.empty() ||
+ !base::CreateDirectory(path.DirName()) ||
+ base::WriteFile(path, data.data(), size) != size) {
+ LOG(WARNING) << "Failed to write to " << path.value();
+ }
+}
+
+} // namespace
+
// The SessionManagerClient implementation used in production.
class SessionManagerClientImpl : public SessionManagerClient {
public:
@@ -204,7 +238,6 @@ class SessionManagerClientImpl : public SessionManagerClient {
virtual void StorePolicyForUser(
const std::string& username,
const std::string& policy_blob,
- const std::string& ignored_policy_key,
const StorePolicyCallback& callback) OVERRIDE {
CallStorePolicyByUsername(login_manager::kSessionManagerStorePolicyForUser,
username,
@@ -548,58 +581,94 @@ class SessionManagerClientStubImpl : public SessionManagerClient {
const ActiveSessionsCallback& callback) OVERRIDE {}
virtual void RetrieveDevicePolicy(
const RetrievePolicyCallback& callback) OVERRIDE {
- callback.Run(device_policy_);
+ base::FilePath owner_key_path;
+ if (!PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
+ callback.Run("");
+ return;
+ }
+ base::FilePath device_policy_path =
+ owner_key_path.DirName().AppendASCII("stub_device_policy");
+ base::PostTaskAndReplyWithResult(
+ base::WorkerPool::GetTaskRunner(false),
+ FROM_HERE,
+ base::Bind(&GetFileContent, device_policy_path),
+ callback);
}
virtual void RetrievePolicyForUser(
const std::string& username,
const RetrievePolicyCallback& callback) OVERRIDE {
- callback.Run(user_policies_[username]);
+ base::PostTaskAndReplyWithResult(
+ base::WorkerPool::GetTaskRunner(false),
+ FROM_HERE,
+ base::Bind(&GetFileContent, GetUserFilePath(username, "stub_policy")),
+ callback);
}
virtual std::string BlockingRetrievePolicyForUser(
const std::string& username) OVERRIDE {
- return user_policies_[username];
+ return GetFileContent(GetUserFilePath(username, "stub_policy"));
}
virtual void RetrieveDeviceLocalAccountPolicy(
const std::string& account_name,
const RetrievePolicyCallback& callback) OVERRIDE {
- callback.Run(user_policies_[account_name]);
+ RetrievePolicyForUser(account_name, callback);
}
virtual void StoreDevicePolicy(const std::string& policy_blob,
const StorePolicyCallback& callback) OVERRIDE {
- device_policy_ = policy_blob;
- callback.Run(true);
+ enterprise_management::PolicyFetchResponse response;
+ base::FilePath owner_key_path;
+ if (!response.ParseFromString(policy_blob) ||
+ !PathService::Get(chromeos::FILE_OWNER_KEY, &owner_key_path)) {
+ callback.Run(false);
+ return;
+ }
+
+ if (response.has_new_public_key()) {
+ base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&StoreFile, owner_key_path, response.new_public_key()),
+ false);
+ }
+
+ // Chrome will attempt to retrieve the device policy right after storing
+ // during enrollment, so make sure it's written before signaling
+ // completion.
+ // Note also that the owner key will be written before the device policy,
+ // if it was present in the blob.
+ base::FilePath device_policy_path =
+ owner_key_path.DirName().AppendASCII("stub_device_policy");
+ base::WorkerPool::PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&StoreFile, device_policy_path, policy_blob),
+ base::Bind(callback, true),
+ false);
}
virtual void StorePolicyForUser(
const std::string& username,
const std::string& policy_blob,
- const std::string& policy_key,
const StorePolicyCallback& callback) OVERRIDE {
- if (policy_key.empty()) {
- user_policies_[username] = policy_blob;
- callback.Run(true);
- return;
- }
// The session manager writes the user policy key to a well-known
// location. Do the same with the stub impl, so that user policy works and
// can be tested on desktop builds.
- // TODO(joaodasilva): parse the PolicyFetchResponse in |policy_blob| to get
- // the policy key directly, after moving the policy protobufs to a top-level
- // directory. The |policy_key| argument to this method can then be removed.
- // http://crbug.com/240269
- base::FilePath key_path;
- if (!PathService::Get(chromeos::DIR_USER_POLICY_KEYS, &key_path)) {
+ enterprise_management::PolicyFetchResponse response;
+ if (!response.ParseFromString(policy_blob)) {
callback.Run(false);
return;
}
- const std::string sanitized =
- CryptohomeClient::GetStubSanitizedUsername(username);
- key_path = key_path.AppendASCII(sanitized).AppendASCII("policy.pub");
- // Assume that the key write is successful.
- user_policies_[username] = policy_blob;
+
+ if (response.has_new_public_key()) {
+ base::FilePath key_path = GetUserFilePath(username, "policy.pub");
+ base::WorkerPool::PostTask(
+ FROM_HERE,
+ base::Bind(&StoreFile, key_path, response.new_public_key()),
+ false);
+ }
+
+ // This file isn't read directly by Chrome, but is used by this class to
+ // reload the user policy across restarts.
+ base::FilePath stub_policy_path = GetUserFilePath(username, "stub_policy");
base::WorkerPool::PostTaskAndReply(
FROM_HERE,
- base::Bind(&SessionManagerClientStubImpl::StoreFileInBackground,
- key_path, policy_key),
+ base::Bind(&StoreFile, stub_policy_path, policy_blob),
base::Bind(callback, true),
false);
}
@@ -607,27 +676,15 @@ class SessionManagerClientStubImpl : public SessionManagerClient {
const std::string& account_name,
const std::string& policy_blob,
const StorePolicyCallback& callback) OVERRIDE {
- user_policies_[account_name] = policy_blob;
- callback.Run(true);
+ StorePolicyForUser(account_name, policy_blob, callback);
}
virtual void SetFlagsForUser(const std::string& username,
const std::vector<std::string>& flags) OVERRIDE {
}
-
- static void StoreFileInBackground(const base::FilePath& path,
- const std::string& data) {
- const int size = static_cast<int>(data.size());
- if (!base::CreateDirectory(path.DirName()) ||
- base::WriteFile(path, data.data(), size) != size) {
- LOG(WARNING) << "Failed to write policy key to " << path.value();
- }
- }
-
private:
StubDelegate* delegate_; // Weak pointer; may be NULL.
ObserverList<Observer> observers_;
std::string device_policy_;
- std::map<std::string, std::string> user_policies_;
DISALLOW_COPY_AND_ASSIGN(SessionManagerClientStubImpl);
};
diff --git a/chromeos/dbus/session_manager_client.h b/chromeos/dbus/session_manager_client.h
index 9e3ca89..2a5792d 100644
--- a/chromeos/dbus/session_manager_client.h
+++ b/chromeos/dbus/session_manager_client.h
@@ -156,11 +156,8 @@ class CHROMEOS_EXPORT SessionManagerClient : public DBusClient {
// Attempts to asynchronously store |policy_blob| as user policy for the given
// |username|. Upon completion of the store attempt, we will call callback.
- // The |policy_key| argument is not sent to the session manager, but is used
- // by the stub implementation to enable policy validation on desktop builds.
virtual void StorePolicyForUser(const std::string& username,
const std::string& policy_blob,
- const std::string& policy_key,
const StorePolicyCallback& callback) = 0;
// Sends a request to store a policy blob for the specified device-local
diff --git a/chromeos/system/statistics_provider.cc b/chromeos/system/statistics_provider.cc
index 93557b9..cc33756 100644
--- a/chromeos/system/statistics_provider.cc
+++ b/chromeos/system/statistics_provider.cc
@@ -37,6 +37,7 @@ const char kCrosSystemUnknownValue[] = "(error)";
const char kHardwareClassCrosSystemKey[] = "hwid";
const char kUnknownHardwareClass[] = "unknown";
+const char kSerialNumber[] = "sn";
// File to get machine hardware info from, and key/value delimiters of
// the file.
@@ -269,6 +270,12 @@ void StatisticsProviderImpl::LoadMachineStatistics(bool load_oem_manifest) {
oem_manifest_loaded_ = true;
}
+ if (!base::SysInfo::IsRunningOnChromeOS() &&
+ machine_info_.find(kSerialNumber) == machine_info_.end()) {
+ // Set stub value for testing.
+ machine_info_[kSerialNumber] = "stub_serial_number";
+ }
+
// Finished loading the statistics.
on_statistics_loaded_.Signal();
VLOG(1) << "Finished loading statistics.";