Commit eb4b8c64 authored by Xiaoling Bao's avatar Xiaoling Bao Committed by Commit Bot

Add DM device registration function.

Bug: 1068797
Change-Id: I93e9d0915abc26c89b2690122199002a0b55404f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2311041
Commit-Queue: Xiaoling Bao <xiaolingbao@chromium.org>
Reviewed-by: default avatarSorin Jianu <sorin@chromium.org>
Reviewed-by: default avatarS. Ganesh <ganesh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791350}
parent 60c5967d
...@@ -95,6 +95,8 @@ if (is_win || is_mac) { ...@@ -95,6 +95,8 @@ if (is_win || is_mac) {
"control_service_in_process.h", "control_service_in_process.h",
"dm_cached_policy_info.cc", "dm_cached_policy_info.cc",
"dm_cached_policy_info.h", "dm_cached_policy_info.h",
"dm_client.cc",
"dm_client.h",
"dm_message.cc", "dm_message.cc",
"dm_message.h", "dm_message.h",
"dm_policy_manager.cc", "dm_policy_manager.cc",
...@@ -237,6 +239,7 @@ if (is_win || is_mac) { ...@@ -237,6 +239,7 @@ if (is_win || is_mac) {
sources = [ sources = [
"app/app_server_unittest.cc", "app/app_server_unittest.cc",
"dm_client_unittest.cc",
"dm_message_unittest.cc", "dm_message_unittest.cc",
"dm_policy_builder_for_testing.cc", "dm_policy_builder_for_testing.cc",
"dm_policy_builder_for_testing.h", "dm_policy_builder_for_testing.h",
...@@ -271,6 +274,7 @@ if (is_win || is_mac) { ...@@ -271,6 +274,7 @@ if (is_win || is_mac) {
"//components/prefs:test_support", "//components/prefs:test_support",
"//components/update_client", "//components/update_client",
"//crypto", "//crypto",
"//net:test_support",
"//testing/gtest", "//testing/gtest",
"//url", "//url",
] ]
...@@ -285,6 +289,7 @@ if (is_win || is_mac) { ...@@ -285,6 +289,7 @@ if (is_win || is_mac) {
deps += [ deps += [
"//chrome/updater/win:constants", "//chrome/updater/win:constants",
"//chrome/updater/win:lib",
"//chrome/updater/win:updater_tests", "//chrome/updater/win:updater_tests",
] ]
...@@ -307,6 +312,7 @@ if (is_win || is_mac) { ...@@ -307,6 +312,7 @@ if (is_win || is_mac) {
"//chrome/common/mac:launchd", "//chrome/common/mac:launchd",
"//chrome/updater/app/server/mac:protocol", "//chrome/updater/app/server/mac:protocol",
"//chrome/updater/mac:enterprise_tests", "//chrome/updater/mac:enterprise_tests",
"//chrome/updater/mac:network_fetcher_sources",
"//chrome/updater/mac:updater_bundle", "//chrome/updater/mac:updater_bundle",
"//chrome/updater/mac:updater_setup_tests", "//chrome/updater/mac:updater_setup_tests",
"//chrome/updater/mac:updater_tests", "//chrome/updater/mac:updater_tests",
......
...@@ -32,12 +32,14 @@ const char kWakeSwitch[] = "wake"; ...@@ -32,12 +32,14 @@ const char kWakeSwitch[] = "wake";
const char kInstallFromOutDir[] = "install-from-out-dir"; const char kInstallFromOutDir[] = "install-from-out-dir";
#endif // OS_WIN #endif // OS_WIN
// URLs. // TODO(crbug/1108975): brand the URLs below.
const char kUpdaterJSONDefaultUrl[] = const char kUpdaterJSONDefaultUrl[] =
"https://update.googleapis.com/service/update2/json"; "https://update.googleapis.com/service/update2/json";
const char kCrashUploadURL[] = "https://clients2.google.com/cr/report"; const char kCrashUploadURL[] = "https://clients2.google.com/cr/report";
const char kCrashStagingUploadURL[] = const char kCrashStagingUploadURL[] =
"https://clients2.google.com/cr/staging_report"; "https://clients2.google.com/cr/staging_report";
const char kDeviceManagementServerURL[] =
"https://m.google.com/devicemanagement/data/api";
// Path names. // Path names.
const char kAppsDir[] = "apps"; const char kAppsDir[] = "apps";
......
...@@ -108,6 +108,9 @@ extern const char kUpdaterJSONDefaultUrl[]; ...@@ -108,6 +108,9 @@ extern const char kUpdaterJSONDefaultUrl[];
extern const char kCrashUploadURL[]; extern const char kCrashUploadURL[];
extern const char kCrashStagingUploadURL[]; extern const char kCrashStagingUploadURL[];
// DM server end point.
extern const char kDeviceManagementServerURL[];
// File system paths. // File system paths.
// //
// The directory name where CRX apps get installed. This is provided for demo // The directory name where CRX apps get installed. This is provided for demo
......
// Copyright 2020 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/updater/dm_client.h"
#include <utility>
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/dm_storage.h"
#include "chrome/updater/updater_version.h"
#include "chrome/updater/util.h"
#include "components/policy/core/common/cloud/cloud_policy_util.h"
#include "components/update_client/network.h"
#include "url/gurl.h"
#if defined(OS_WIN)
#include "chrome/updater/win/net/network.h"
#elif defined(OS_MACOSX)
#include "chrome/updater/mac/net/network.h"
#endif
namespace updater {
namespace {
// Content-type of DM requests.
constexpr char kDMContentType[] = "application/x-protobuf";
// String constants for the device and app type we report to the server.
constexpr char kParamAgent[] = "agent";
constexpr char kParamRequest[] = "request";
constexpr char kParamPlatform[] = "platform";
constexpr char kParamDeviceID[] = "deviceid";
constexpr char kParamAppType[] = "apptype";
constexpr char kValueAppType[] = "Chrome";
constexpr char kAuthorizationHeader[] = "Authorization";
// Constants for device management enrollment requests.
constexpr char kRegistrationRequestType[] = "register_policy_agent";
constexpr char kRegistrationTokenType[] = "GoogleEnrollmentToken";
constexpr int kHTTPStatusOK = 200;
constexpr int kHTTPStatusGone = 410;
class DefaultConfigurator : public DMClient::Configurator {
public:
DefaultConfigurator();
~DefaultConfigurator() override = default;
std::string GetDMServerUrl() const override {
return kDeviceManagementServerURL;
}
std::string GetAgentParameter() const override {
return "Updater-" UPDATER_VERSION_STRING;
}
std::string GetPlatformParameter() const override;
std::unique_ptr<update_client::NetworkFetcher> CreateNetworkFetcher()
const override {
return network_fetcher_factory_->Create();
}
private:
scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_;
};
DefaultConfigurator::DefaultConfigurator()
: network_fetcher_factory_(base::MakeRefCounted<NetworkFetcherFactory>()) {}
std::string DefaultConfigurator::GetPlatformParameter() const {
std::string os_name = base::SysInfo::OperatingSystemName();
std::string os_hardware = base::SysInfo::OperatingSystemArchitecture();
int32_t os_major_version = 0;
int32_t os_minor_version = 0;
int32_t os_bugfix_version = 0;
base::SysInfo::OperatingSystemVersionNumbers(
&os_major_version, &os_minor_version, &os_bugfix_version);
std::string os_version = base::StringPrintf(
"%d.%d.%d", os_major_version, os_minor_version, os_bugfix_version);
return base::StringPrintf("%s|%s|%s", os_name.c_str(), os_hardware.c_str(),
os_version.c_str());
}
} // namespace
DMClient::DMClient()
: DMClient(std::make_unique<DefaultConfigurator>(), GetDefaultDMStorage()) {
}
DMClient::DMClient(std::unique_ptr<Configurator> config,
scoped_refptr<DMStorage> storage)
: config_(std::move(config)),
storage_(std::move(storage)),
http_status_code_(-1) {}
DMClient::~DMClient() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
GURL DMClient::BuildURL(const std::string& request_type) const {
GURL url(config_->GetDMServerUrl());
url = AppendQueryParameter(url, kParamRequest, request_type);
url = AppendQueryParameter(url, kParamAppType, kValueAppType);
url = AppendQueryParameter(url, kParamAgent, config_->GetAgentParameter());
url = AppendQueryParameter(url, kParamPlatform,
config_->GetPlatformParameter());
return AppendQueryParameter(url, kParamDeviceID, storage_->GetDeviceID());
}
scoped_refptr<DMStorage> DMClient::GetStorage() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return storage_;
}
void DMClient::PostRegisterRequest(DMRequestCallback request_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
RequestResult result = RequestResult::kSuccess;
const std::string enrollment_token = storage_->GetEnrollmentToken();
network_fetcher_ = config_->CreateNetworkFetcher();
request_callback_ = std::move(request_callback);
if (storage_->IsDeviceDeregistered()) {
result = RequestResult::kDeregistered;
} else if (!storage_->GetDmToken().empty()) {
result = RequestResult::kAleadyRegistered;
} else if (enrollment_token.empty()) {
result = RequestResult::kNotManaged;
} else if (storage_->GetDeviceID().empty()) {
result = RequestResult::kNoDeviceID;
} else if (!network_fetcher_) {
result = RequestResult::kFetcherError;
}
if (result != RequestResult::kSuccess) {
LOG(ERROR) << "Device registration skipped with DM error: "
<< static_cast<int>(result);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(request_callback_), result));
return;
}
const std::string data = GetRegisterBrowserRequestData(
policy::GetMachineName(), policy::GetOSPlatform(),
policy::GetOSVersion());
// Authorization token is the enrollment token for device registration.
base::flat_map<std::string, std::string> additional_headers;
additional_headers.emplace(
kAuthorizationHeader,
base::StringPrintf("%s token=%s", kRegistrationTokenType,
enrollment_token.c_str()));
network_fetcher_->PostRequest(
BuildURL(kRegistrationRequestType), data, kDMContentType,
additional_headers,
base::BindOnce(&DMClient::OnRequestStarted, base::Unretained(this)),
base::BindRepeating(&DMClient::OnRequestProgress, base::Unretained(this)),
base::BindOnce(&DMClient::OnRequestComplete, base::Unretained(this)));
}
void DMClient::OnRequestStarted(int response_code, int64_t content_length) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
VLOG(1) << "POST request is sent to DM server, status: " << response_code
<< ". Content length: " << content_length << ".";
http_status_code_ = response_code;
}
void DMClient::OnRequestProgress(int64_t current) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
VLOG(1) << "POST request progess made, current bytes: " << current;
}
void DMClient::OnRequestComplete(std::unique_ptr<std::string> response_body,
int net_error,
const std::string& header_etag,
const std::string& header_x_cup_server_proof,
int64_t xheader_retry_after_sec) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
RequestResult request_result = RequestResult::kSuccess;
if (net_error != 0) {
LOG(ERROR) << "DM register failed due to net error: " << net_error;
request_result = RequestResult::kNetworkError;
} else if (http_status_code_ == kHTTPStatusGone) {
VLOG(1) << "Device is now de-registered.";
storage_->DeregisterDevice();
} else if (http_status_code_ != kHTTPStatusOK) {
LOG(ERROR) << "DM device registration failed due to http error: "
<< http_status_code_;
request_result = RequestResult::kHttpError;
} else {
const std::string dm_token =
ParseDeviceRegistrationResponse(*response_body);
if (dm_token.empty()) {
LOG(ERROR) << "Failed to parse DM token from registration response.";
request_result = RequestResult::kUnexpectedResponse;
} else {
VLOG(1) << "Register request completed, got DM token: " << dm_token;
storage_->StoreDmToken(dm_token);
}
}
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(request_callback_), request_result));
}
} // namespace updater
// Copyright 2020 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_UPDATER_DM_CLIENT_H_
#define CHROME_UPDATER_DM_CLIENT_H_
#include <stdint.h>
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequence_checker.h"
class GURL;
namespace update_client {
class NetworkFetcher;
}
namespace updater {
class DMStorage;
// This class is responsible for everything related to communication with the
// device management server.
// The class maintains the intermediate state of a network request, thus it
// cannot handle multiple requests in parallel.
class DMClient {
public:
class Configurator {
public:
virtual ~Configurator() = default;
// URL at which to contact the DM server.
virtual std::string GetDMServerUrl() const = 0;
// Agent reported in the "agent" query parameter.
virtual std::string GetAgentParameter() const = 0;
// The platform reported in the "platform" query parameter.
virtual std::string GetPlatformParameter() const = 0;
virtual std::unique_ptr<update_client::NetworkFetcher>
CreateNetworkFetcher() const = 0;
};
enum class RequestResult {
// DM request is completed successfully.
kSuccess = 0,
// Request is not sent because there's no device ID.
kNoDeviceID,
// Register request is not sent since the device is already registered.
kAleadyRegistered,
// Request is not sent because the device is not managed.
kNotManaged,
// Request is not sent because the device is de-registered.
kDeregistered,
// Request is not sent because network fetcher fails to create.
kFetcherError,
// Request failed with network error.
kNetworkError,
// Request failed with an HTTP error from server.
kHttpError,
// Got an unexpected response for the request.
kUnexpectedResponse,
};
using DMRequestCallback = base::OnceCallback<void(RequestResult)>;
DMClient();
DMClient(std::unique_ptr<Configurator> config,
scoped_refptr<DMStorage> storage);
DMClient(const DMClient&) = delete;
DMClient& operator=(const DMClient&) = delete;
~DMClient();
// Returns the storage where this client saves the data from DM server.
scoped_refptr<DMStorage> GetStorage() const;
// Posts a device register request to the server. Upon success, a new DM
// token is saved into the storage before |request_callback| is called.
void PostRegisterRequest(DMRequestCallback request_callback);
private:
// Gets the full request URL to DM server for the given request type.
// Additional device specific values, such as device ID, platform etc. will
// be appended to the URL as query parameters.
GURL BuildURL(const std::string& request_type) const;
// Callback functions for the URLFetcher.
void OnRequestStarted(int response_code, int64_t content_length);
void OnRequestProgress(int64_t current);
void OnRequestComplete(std::unique_ptr<std::string> response_body,
int net_error,
const std::string& header_etag,
const std::string& header_x_cup_server_proof,
int64_t xheader_retry_after_sec);
std::unique_ptr<Configurator> config_;
scoped_refptr<DMStorage> storage_;
std::unique_ptr<update_client::NetworkFetcher> network_fetcher_;
DMRequestCallback request_callback_;
int http_status_code_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace updater
#endif // CHROME_UPDATER_DM_CLIENT_H_
This diff is collapsed.
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "chrome/updater/dm_cached_policy_info.h" #include "chrome/updater/dm_cached_policy_info.h"
#include "chrome/updater/dm_policy_manager.h" #include "chrome/updater/dm_policy_manager.h"
#include "chrome/updater/updater_version.h"
#include "chrome/updater/util.h"
#include "components/policy/proto/device_management_backend.pb.h" #include "components/policy/proto/device_management_backend.pb.h"
namespace updater { namespace updater {
...@@ -39,6 +41,9 @@ constexpr char kPolicyFileName[] = "PolicyFetchResponse"; ...@@ -39,6 +41,9 @@ constexpr char kPolicyFileName[] = "PolicyFetchResponse";
// The policy type for Omaha policy settings. // The policy type for Omaha policy settings.
constexpr char kGoogleUpdatePolicyType[] = "google/machine-level-omaha"; constexpr char kGoogleUpdatePolicyType[] = "google/machine-level-omaha";
// Policy subfolder in the updater installation path.
constexpr char kPolicyCacheSubfolder[] = "Policies";
// Deletes the child directories in cache root if they do not appear in // Deletes the child directories in cache root if they do not appear in
// set |policy_types_base64|. // set |policy_types_base64|.
bool DeleteObsoletePolicies(const base::FilePath& cache_root, bool DeleteObsoletePolicies(const base::FilePath& cache_root,
...@@ -70,19 +75,30 @@ DMStorage::DMStorage(const base::FilePath& policy_cache_root, ...@@ -70,19 +75,30 @@ DMStorage::DMStorage(const base::FilePath& policy_cache_root,
DCHECK(token_service_); DCHECK(token_service_);
} }
DMStorage::~DMStorage() = default; DMStorage::~DMStorage() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
bool DMStorage::DeregisterDevice() { bool DMStorage::DeregisterDevice() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return token_service_->StoreDmToken(kInvalidTokenValue); return token_service_->StoreDmToken(kInvalidTokenValue);
} }
bool DMStorage::IsValidDMToken() { bool DMStorage::IsValidDMToken() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
std::string dm_token = GetDmToken(); std::string dm_token = GetDmToken();
return !dm_token.empty() && dm_token != kInvalidTokenValue; return !dm_token.empty() && dm_token != kInvalidTokenValue;
} }
bool DMStorage::IsDeviceDeregistered() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return GetDmToken() == kInvalidTokenValue;
}
bool DMStorage::PersistPolicies(const std::string& policy_info_data, bool DMStorage::PersistPolicies(const std::string& policy_info_data,
const DMPolicyMap& policy_map) const { const DMPolicyMap& policy_map) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Persists policy cached info // Persists policy cached info
base::FilePath policy_info_file = base::FilePath policy_info_file =
policy_cache_root_.AppendASCII(kPolicyInfoFileName); policy_cache_root_.AppendASCII(kPolicyInfoFileName);
...@@ -118,6 +134,8 @@ bool DMStorage::PersistPolicies(const std::string& policy_info_data, ...@@ -118,6 +134,8 @@ bool DMStorage::PersistPolicies(const std::string& policy_info_data,
} }
std::unique_ptr<CachedPolicyInfo> DMStorage::GetCachedPolicyInfo() { std::unique_ptr<CachedPolicyInfo> DMStorage::GetCachedPolicyInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!IsValidDMToken()) if (!IsValidDMToken())
return nullptr; return nullptr;
...@@ -135,6 +153,8 @@ std::unique_ptr<CachedPolicyInfo> DMStorage::GetCachedPolicyInfo() { ...@@ -135,6 +153,8 @@ std::unique_ptr<CachedPolicyInfo> DMStorage::GetCachedPolicyInfo() {
} }
std::unique_ptr<PolicyManagerInterface> DMStorage::GetOmahaPolicyManager() { std::unique_ptr<PolicyManagerInterface> DMStorage::GetOmahaPolicyManager() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!IsValidDMToken()) if (!IsValidDMToken())
return nullptr; return nullptr;
...@@ -161,4 +181,15 @@ std::unique_ptr<PolicyManagerInterface> DMStorage::GetOmahaPolicyManager() { ...@@ -161,4 +181,15 @@ std::unique_ptr<PolicyManagerInterface> DMStorage::GetOmahaPolicyManager() {
return std::make_unique<DMPolicyManager>(omaha_settings); return std::make_unique<DMPolicyManager>(omaha_settings);
} }
scoped_refptr<DMStorage> GetDefaultDMStorage() {
base::FilePath updater_versioned_path;
if (!GetVersionedDirectory(&updater_versioned_path))
return nullptr;
base::FilePath policy_cache_folder =
updater_versioned_path.AppendASCII(kPolicyCacheSubfolder);
return base::MakeRefCounted<DMStorage>(policy_cache_folder);
}
} // namespace updater } // namespace updater
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <string> #include <string>
#include "base/containers/flat_map.h" #include "base/containers/flat_map.h"
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/sequence_checker.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/updater/dm_message.h" #include "chrome/updater/dm_message.h"
...@@ -23,38 +25,37 @@ class TokenServiceInterface { ...@@ -23,38 +25,37 @@ class TokenServiceInterface {
virtual ~TokenServiceInterface() = default; virtual ~TokenServiceInterface() = default;
// ID of the device that the tokens target to. // ID of the device that the tokens target to.
virtual std::string GetDeviceID() = 0; virtual std::string GetDeviceID() const = 0;
// Writes |enrollment_token| to storage. // Writes |enrollment_token| to storage.
virtual bool StoreEnrollmentToken(const std::string& enrollment_token) = 0; virtual bool StoreEnrollmentToken(const std::string& enrollment_token) = 0;
// Reads the enrollment token from sources as-needed to find one. // Reads the enrollment token from sources as-needed to find one.
// Returns an empty string if no enrollment token is found. // Returns an empty string if no enrollment token is found.
virtual std::string GetEnrollmentToken() = 0; virtual std::string GetEnrollmentToken() const = 0;
// Writes |dm_token| into storage. // Writes |dm_token| into storage.
virtual bool StoreDmToken(const std::string& dm_token) = 0; virtual bool StoreDmToken(const std::string& dm_token) = 0;
// Returns the device management token from storage, or returns an empty // Returns the device management token from storage, or returns an empty
// string if no device management token is found. // string if no device management token is found.
virtual std::string GetDmToken() = 0; virtual std::string GetDmToken() const = 0;
}; };
// The DMStorage is responsible for serialization of: // The DMStorage is responsible for serialization of:
// 1) DM enrollment token. // 1) DM enrollment token.
// 2) DM token. // 2) DM token.
// 3) DM policies. // 3) DM policies.
class DMStorage { class DMStorage : public base::RefCountedThreadSafe<DMStorage> {
public: public:
explicit DMStorage(const base::FilePath& policy_cache_root); explicit DMStorage(const base::FilePath& policy_cache_root);
DMStorage(const base::FilePath& policy_cache_root, DMStorage(const base::FilePath& policy_cache_root,
std::unique_ptr<TokenServiceInterface> token_service); std::unique_ptr<TokenServiceInterface> token_service);
DMStorage(const DMStorage&) = delete; DMStorage(const DMStorage&) = delete;
DMStorage& operator=(const DMStorage&) = delete; DMStorage& operator=(const DMStorage&) = delete;
virtual ~DMStorage();
// Forwards to token service to get device ID // Forwards to token service to get device ID
std::string GetDeviceID() { return token_service_->GetDeviceID(); } std::string GetDeviceID() const { return token_service_->GetDeviceID(); }
// Forwards to token service to save enrollment token. // Forwards to token service to save enrollment token.
bool StoreEnrollmentToken(const std::string& enrollment_token) { bool StoreEnrollmentToken(const std::string& enrollment_token) {
...@@ -62,7 +63,7 @@ class DMStorage { ...@@ -62,7 +63,7 @@ class DMStorage {
} }
// Forwards to token service to get enrollment token. // Forwards to token service to get enrollment token.
std::string GetEnrollmentToken() { std::string GetEnrollmentToken() const {
return token_service_->GetEnrollmentToken(); return token_service_->GetEnrollmentToken();
} }
...@@ -72,7 +73,7 @@ class DMStorage { ...@@ -72,7 +73,7 @@ class DMStorage {
} }
// Forwards to token service to get DM token. // Forwards to token service to get DM token.
std::string GetDmToken() { return token_service_->GetDmToken(); } std::string GetDmToken() const { return token_service_->GetDmToken(); }
// Writes a special DM token to storage to mark current device as // Writes a special DM token to storage to mark current device as
// deregistered. // deregistered.
...@@ -80,7 +81,10 @@ class DMStorage { ...@@ -80,7 +81,10 @@ class DMStorage {
// Returns true if the DM token is valid, where valid is defined as non-blank // Returns true if the DM token is valid, where valid is defined as non-blank
// and not de-registered. // and not de-registered.
bool IsValidDMToken(); bool IsValidDMToken() const;
// Returns true if the device is de-registered.
bool IsDeviceDeregistered() const;
// Persists DM policies. // Persists DM policies.
// //
...@@ -122,10 +126,17 @@ class DMStorage { ...@@ -122,10 +126,17 @@ class DMStorage {
std::unique_ptr<PolicyManagerInterface> GetOmahaPolicyManager(); std::unique_ptr<PolicyManagerInterface> GetOmahaPolicyManager();
private: private:
friend class base::RefCountedThreadSafe<DMStorage>;
~DMStorage();
const base::FilePath policy_cache_root_; const base::FilePath policy_cache_root_;
std::unique_ptr<TokenServiceInterface> token_service_; std::unique_ptr<TokenServiceInterface> token_service_;
SEQUENCE_CHECKER(sequence_checker_);
}; };
scoped_refptr<DMStorage> GetDefaultDMStorage();
} // namespace updater } // namespace updater
#endif // CHROME_UPDATER_DM_STORAGE_H_ #endif // CHROME_UPDATER_DM_STORAGE_H_
...@@ -85,15 +85,15 @@ bool LoadTokenFromFile(const base::FilePath& token_file_path, ...@@ -85,15 +85,15 @@ bool LoadTokenFromFile(const base::FilePath& token_file_path,
class TokenService : public TokenServiceInterface { class TokenService : public TokenServiceInterface {
public: public:
TokenService() = default; TokenService();
~TokenService() override = default; ~TokenService() override = default;
// Overrides for TokenServiceInterface. // Overrides for TokenServiceInterface.
std::string GetDeviceID() override; std::string GetDeviceID() const override { return device_id_; }
bool StoreEnrollmentToken(const std::string& enrollment_token) override; bool StoreEnrollmentToken(const std::string& enrollment_token) override;
std::string GetEnrollmentToken() override; std::string GetEnrollmentToken() const override { return enrollment_token_; }
bool StoreDmToken(const std::string& dm_token) override; bool StoreDmToken(const std::string& dm_token) override;
std::string GetDmToken() override; std::string GetDmToken() const override { return dm_token_; }
private: private:
// Cached values in memory. // Cached values in memory.
...@@ -102,10 +102,18 @@ class TokenService : public TokenServiceInterface { ...@@ -102,10 +102,18 @@ class TokenService : public TokenServiceInterface {
std::string dm_token_; std::string dm_token_;
}; };
std::string TokenService::GetDeviceID() { TokenService::TokenService() {
if (device_id_.empty()) device_id_ = base::mac::GetPlatformSerialNumber();
device_id_ = base::mac::GetPlatformSerialNumber(); std::string enrollment_token;
return device_id_; if (LoadEnrollmentTokenFromPolicy(&enrollment_token) ||
LoadTokenFromFile(GetEnrollmentTokenFilePath(), &enrollment_token)) {
enrollment_token_ = enrollment_token;
}
std::string dm_token;
if (LoadTokenFromFile(GetDmTokenFilePath(), &dm_token)) {
dm_token_ = dm_token;
}
} }
bool TokenService::StoreEnrollmentToken(const std::string& enrollment_token) { bool TokenService::StoreEnrollmentToken(const std::string& enrollment_token) {
...@@ -120,15 +128,6 @@ bool TokenService::StoreEnrollmentToken(const std::string& enrollment_token) { ...@@ -120,15 +128,6 @@ bool TokenService::StoreEnrollmentToken(const std::string& enrollment_token) {
return true; return true;
} }
std::string TokenService::GetEnrollmentToken() {
if (enrollment_token_.empty() &&
!LoadEnrollmentTokenFromPolicy(&enrollment_token_) &&
!LoadTokenFromFile(GetEnrollmentTokenFilePath(), &enrollment_token_)) {
enrollment_token_.clear(); // Safeguard in case it has incomplete value.
}
return enrollment_token_;
}
bool TokenService::StoreDmToken(const std::string& token) { bool TokenService::StoreDmToken(const std::string& token) {
const base::FilePath dm_token_path = GetDmTokenFilePath(); const base::FilePath dm_token_path = GetDmTokenFilePath();
if (dm_token_path.empty() || if (dm_token_path.empty() ||
...@@ -139,15 +138,6 @@ bool TokenService::StoreDmToken(const std::string& token) { ...@@ -139,15 +138,6 @@ bool TokenService::StoreDmToken(const std::string& token) {
return true; return true;
} }
std::string TokenService::GetDmToken() {
if (dm_token_.empty() &&
!LoadTokenFromFile(GetDmTokenFilePath(), &dm_token_)) {
dm_token_.clear(); // Safeguard in case it has incomplete value.
}
return dm_token_;
}
} // namespace } // namespace
DMStorage::DMStorage(const base::FilePath& policy_cache_root) DMStorage::DMStorage(const base::FilePath& policy_cache_root)
......
...@@ -26,20 +26,20 @@ class TestTokenService : public TokenServiceInterface { ...@@ -26,20 +26,20 @@ class TestTokenService : public TokenServiceInterface {
~TestTokenService() override = default; ~TestTokenService() override = default;
// Overrides for TokenServiceInterface. // Overrides for TokenServiceInterface.
std::string GetDeviceID() override { return "TestDeviceID"; } std::string GetDeviceID() const override { return "TestDeviceID"; }
bool StoreEnrollmentToken(const std::string& enrollment_token) override { bool StoreEnrollmentToken(const std::string& enrollment_token) override {
enrollment_token_ = enrollment_token; enrollment_token_ = enrollment_token;
return true; return true;
} }
std::string GetEnrollmentToken() override { return enrollment_token_; } std::string GetEnrollmentToken() const override { return enrollment_token_; }
bool StoreDmToken(const std::string& dm_token) override { bool StoreDmToken(const std::string& dm_token) override {
dm_token_ = dm_token; dm_token_ = dm_token;
return true; return true;
} }
std::string GetDmToken() override { return dm_token_; } std::string GetDmToken() const override { return dm_token_; }
private: private:
std::string enrollment_token_; std::string enrollment_token_;
...@@ -89,8 +89,9 @@ std::string CannedOmahaPolicyFetchResponse() { ...@@ -89,8 +89,9 @@ std::string CannedOmahaPolicyFetchResponse() {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
TEST(DMStorage, LoadDeviceID) { TEST(DMStorage, LoadDeviceID) {
DMStorage storage(base::FilePath(FILE_PATH_LITERAL("/TestPolicyCacheRoot"))); auto storage = base::MakeRefCounted<DMStorage>(
EXPECT_FALSE(storage.GetDeviceID().empty()); base::FilePath(FILE_PATH_LITERAL("/TestPolicyCacheRoot")));
EXPECT_FALSE(storage->GetDeviceID().empty());
} }
#endif // OS_MACOSX #endif // OS_MACOSX
...@@ -109,8 +110,8 @@ TEST(DMStorage, PersistPolicies) { ...@@ -109,8 +110,8 @@ TEST(DMStorage, PersistPolicies) {
EXPECT_TRUE(base::CreateDirectory(stale_poliy)); EXPECT_TRUE(base::CreateDirectory(stale_poliy));
EXPECT_TRUE(base::DirectoryExists(stale_poliy)); EXPECT_TRUE(base::DirectoryExists(stale_poliy));
DMStorage storage(cache_root.GetPath()); auto storage = base::MakeRefCounted<DMStorage>(cache_root.GetPath());
EXPECT_TRUE(storage.PersistPolicies("policy-meta-data", policies)); EXPECT_TRUE(storage->PersistPolicies("policy-meta-data", policies));
base::FilePath policy_info_file = base::FilePath policy_info_file =
cache_root.GetPath().AppendASCII("CachedPolicyInfo"); cache_root.GetPath().AppendASCII("CachedPolicyInfo");
EXPECT_TRUE(base::PathExists(policy_info_file)); EXPECT_TRUE(base::PathExists(policy_info_file));
...@@ -161,11 +162,12 @@ TEST(DMStorage, GetCachedPolicyInfo) { ...@@ -161,11 +162,12 @@ TEST(DMStorage, GetCachedPolicyInfo) {
base::ScopedTempDir cache_root; base::ScopedTempDir cache_root;
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); ASSERT_TRUE(cache_root.CreateUniqueTempDir());
DMStorage storage(cache_root.GetPath(), std::make_unique<TestTokenService>()); auto storage = base::MakeRefCounted<DMStorage>(
EXPECT_TRUE(storage.PersistPolicies(response.SerializeAsString(), cache_root.GetPath(), std::make_unique<TestTokenService>());
/* policies map */ {})); EXPECT_TRUE(storage->PersistPolicies(response.SerializeAsString(),
/* policies map */ {}));
auto policy_info = storage.GetCachedPolicyInfo(); auto policy_info = storage->GetCachedPolicyInfo();
ASSERT_NE(policy_info, nullptr); ASSERT_NE(policy_info, nullptr);
EXPECT_EQ(policy_info->public_key(), "SampleNewPublicKeyData"); EXPECT_EQ(policy_info->public_key(), "SampleNewPublicKeyData");
EXPECT_TRUE(policy_info->has_key_version()); EXPECT_TRUE(policy_info->has_key_version());
...@@ -182,10 +184,11 @@ TEST(DMStorage, ReadCachedOmahaPolicy) { ...@@ -182,10 +184,11 @@ TEST(DMStorage, ReadCachedOmahaPolicy) {
}); });
base::ScopedTempDir cache_root; base::ScopedTempDir cache_root;
ASSERT_TRUE(cache_root.CreateUniqueTempDir()); ASSERT_TRUE(cache_root.CreateUniqueTempDir());
DMStorage storage(cache_root.GetPath(), std::make_unique<TestTokenService>()); auto storage = base::MakeRefCounted<DMStorage>(
EXPECT_TRUE(storage.PersistPolicies(omaha_policy_data, policies)); cache_root.GetPath(), std::make_unique<TestTokenService>());
EXPECT_TRUE(storage->PersistPolicies(omaha_policy_data, policies));
auto policy_manager = storage.GetOmahaPolicyManager(); auto policy_manager = storage->GetOmahaPolicyManager();
ASSERT_NE(policy_manager, nullptr); ASSERT_NE(policy_manager, nullptr);
int check_interval = 0; int check_interval = 0;
...@@ -261,9 +264,9 @@ TEST(DMStorage, ReadCachedOmahaPolicy) { ...@@ -261,9 +264,9 @@ TEST(DMStorage, ReadCachedOmahaPolicy) {
non_exist_appid, &app_rollback_allowed)); non_exist_appid, &app_rollback_allowed));
// Verify no policy manager once device is deregistered. // Verify no policy manager once device is deregistered.
EXPECT_TRUE(storage.DeregisterDevice()); EXPECT_TRUE(storage->DeregisterDevice());
EXPECT_FALSE(storage.IsValidDMToken()); EXPECT_FALSE(storage->IsValidDMToken());
ASSERT_EQ(storage.GetOmahaPolicyManager(), nullptr); ASSERT_EQ(storage->GetOmahaPolicyManager(), nullptr);
} }
} // namespace updater } // namespace updater
...@@ -34,14 +34,14 @@ class TokenService : public TokenServiceInterface { ...@@ -34,14 +34,14 @@ class TokenService : public TokenServiceInterface {
~TokenService() override = default; ~TokenService() override = default;
// Overrides for TokenServiceInterface. // Overrides for TokenServiceInterface.
std::string GetDeviceID() override; std::string GetDeviceID() const override;
bool StoreEnrollmentToken(const std::string& enrollment_token) override; bool StoreEnrollmentToken(const std::string& enrollment_token) override;
std::string GetEnrollmentToken() override; std::string GetEnrollmentToken() const override;
bool StoreDmToken(const std::string& dm_token) override; bool StoreDmToken(const std::string& dm_token) override;
std::string GetDmToken() override; std::string GetDmToken() const override;
}; };
std::string TokenService::GetDeviceID() { std::string TokenService::GetDeviceID() const {
base::string16 device_id; base::string16 device_id;
base::win::RegKey key; base::win::RegKey key;
key.Open(HKEY_LOCAL_MACHINE, kRegKeyCryptographyKey, key.Open(HKEY_LOCAL_MACHINE, kRegKeyCryptographyKey,
...@@ -59,7 +59,7 @@ bool TokenService::StoreEnrollmentToken(const std::string& token) { ...@@ -59,7 +59,7 @@ bool TokenService::StoreEnrollmentToken(const std::string& token) {
base::SysUTF8ToWide(token).c_str()) == ERROR_SUCCESS; base::SysUTF8ToWide(token).c_str()) == ERROR_SUCCESS;
} }
std::string TokenService::GetEnrollmentToken() { std::string TokenService::GetEnrollmentToken() const {
base::string16 token; base::string16 token;
base::win::RegKey key; base::win::RegKey key;
key.Open(HKEY_LOCAL_MACHINE, kRegKeyCompanyCloudManagement, KEY_READ); key.Open(HKEY_LOCAL_MACHINE, kRegKeyCompanyCloudManagement, KEY_READ);
...@@ -76,7 +76,7 @@ bool TokenService::StoreDmToken(const std::string& token) { ...@@ -76,7 +76,7 @@ bool TokenService::StoreDmToken(const std::string& token) {
ERROR_SUCCESS; ERROR_SUCCESS;
} }
std::string TokenService::GetDmToken() { std::string TokenService::GetDmToken() const {
base::string16 token; base::string16 token;
base::win::RegKey key; base::win::RegKey key;
key.Open(HKEY_LOCAL_MACHINE, kRegKeyCompanyEnrollment, KEY_READ); key.Open(HKEY_LOCAL_MACHINE, kRegKeyCompanyEnrollment, KEY_READ);
......
...@@ -8,11 +8,75 @@ ...@@ -8,11 +8,75 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/string_util.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/updater/updater_version.h" #include "chrome/updater/updater_version.h"
#include "url/gurl.h"
namespace updater { namespace updater {
namespace {
const char kHexString[] = "0123456789ABCDEF";
inline char IntToHex(int i) {
DCHECK_GE(i, 0) << i << " not a hex value";
DCHECK_LE(i, 15) << i << " not a hex value";
return kHexString[i];
}
// A fast bit-vector map for ascii characters.
//
// Internally stores 256 bits in an array of 8 ints.
// Does quick bit-flicking to lookup needed characters.
struct Charmap {
bool Contains(unsigned char c) const {
return ((map[c >> 5] & (1 << (c & 31))) != 0);
}
uint32_t map[8];
};
// Everything except alphanumerics and !'()*-._~
// See RFC 2396 for the list of reserved characters.
static const Charmap kQueryCharmap = {{0xffffffffL, 0xfc00987dL, 0x78000001L,
0xb8000001L, 0xffffffffL, 0xffffffffL,
0xffffffffL, 0xffffffffL}};
// Given text to escape and a Charmap defining which values to escape,
// return an escaped string. If use_plus is true, spaces are converted
// to +, otherwise, if spaces are in the charmap, they are converted to
// %20. And if keep_escaped is true, %XX will be kept as it is, otherwise, if
// '%' is in the charmap, it is converted to %25.
std::string Escape(base::StringPiece text,
const Charmap& charmap,
bool use_plus,
bool keep_escaped = false) {
std::string escaped;
escaped.reserve(text.length() * 3);
for (unsigned int i = 0; i < text.length(); ++i) {
unsigned char c = static_cast<unsigned char>(text[i]);
if (use_plus && ' ' == c) {
escaped.push_back('+');
} else if (keep_escaped && '%' == c && i + 2 < text.length() &&
base::IsHexDigit(text[i + 1]) && base::IsHexDigit(text[i + 2])) {
escaped.push_back('%');
} else if (charmap.Contains(c)) {
escaped.push_back('%');
escaped.push_back(IntToHex(c >> 4));
escaped.push_back(IntToHex(c & 0xf));
} else {
escaped.push_back(c);
}
}
return escaped;
}
std::string EscapeQueryParamValue(base::StringPiece text, bool use_plus) {
return Escape(text, kQueryCharmap, use_plus);
}
} // namespace
bool GetBaseDirectory(base::FilePath* path) { bool GetBaseDirectory(base::FilePath* path) {
constexpr int kPathKey = constexpr int kPathKey =
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -72,4 +136,21 @@ void InitLogging(const base::FilePath::StringType& filename) { ...@@ -72,4 +136,21 @@ void InitLogging(const base::FilePath::StringType& filename) {
VLOG(1) << "Log file: " << settings.log_file_path; VLOG(1) << "Log file: " << settings.log_file_path;
} }
// This function and the helper functions are copied from net/base/url_util.cc
// to avoid the dependency on //net.
GURL AppendQueryParameter(const GURL& url,
const std::string& name,
const std::string& value) {
std::string query(url.query());
if (!query.empty())
query += "&";
query += (EscapeQueryParamValue(name, true) + "=" +
EscapeQueryParamValue(value, true));
GURL::Replacements replacements;
replacements.SetQueryStr(query);
return url.ReplaceComponents(replacements);
}
} // namespace updater } // namespace updater
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
class GURL;
namespace updater { namespace updater {
// Returns the base directory common to all versions of the updater. For // Returns the base directory common to all versions of the updater. For
...@@ -35,6 +37,20 @@ struct CaseInsensitiveASCIICompare { ...@@ -35,6 +37,20 @@ struct CaseInsensitiveASCIICompare {
} }
}; };
// Returns a new GURL by appending the given query parameter name and the
// value. Unsafe characters in the name and the value are escaped like
// %XX%XX. The original query component is preserved if it's present.
//
// Examples:
//
// AppendQueryParameter(GURL("http://example.com"), "name", "value").spec()
// => "http://example.com?name=value"
// AppendQueryParameter(GURL("http://example.com?x=y"), "name", "value").spec()
// => "http://example.com?x=y&name=value"
GURL AppendQueryParameter(const GURL& url,
const std::string& name,
const std::string& value);
} // namespace updater } // namespace updater
#endif // CHROME_UPDATER_UTIL_H_ #endif // CHROME_UPDATER_UTIL_H_
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