summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgfeher@chromium.org <gfeher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-01 23:01:35 +0000
committergfeher@chromium.org <gfeher@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-03-01 23:01:35 +0000
commitf38374f3cd28322208f71094ace8162299b0380d (patch)
tree0281324f99fab58bcbe109674044b0fb3334e6a4
parent9100ab1858c6ac0ab8334215f9c13ec65dca7be4 (diff)
downloadchromium_src-f38374f3cd28322208f71094ace8162299b0380d.zip
chromium_src-f38374f3cd28322208f71094ace8162299b0380d.tar.gz
chromium_src-f38374f3cd28322208f71094ace8162299b0380d.tar.bz2
Update policy backend and testserver for the latest policy protocol
BUG=chromium-os:11253, chromium-os:11254, chromium-os:11255 TEST=DeviceManagementServiceIntegrationTest.WithTestServer Review URL: http://codereview.chromium.org/6537020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@76455 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/policy/cloud_policy_cache.cc37
-rw-r--r--chrome/browser/policy/cloud_policy_cache.h4
-rw-r--r--chrome/browser/policy/cloud_policy_cache_unittest.cc51
-rw-r--r--chrome/browser/policy/cloud_policy_controller.cc76
-rw-r--r--chrome/browser/policy/cloud_policy_controller.h3
-rw-r--r--chrome/browser/policy/cloud_policy_controller_unittest.cc107
-rw-r--r--chrome/browser/policy/cloud_policy_identity_strategy.h18
-rw-r--r--chrome/browser/policy/device_management_backend.h12
-rw-r--r--chrome/browser/policy/device_management_backend_impl.cc50
-rw-r--r--chrome/browser/policy/device_management_backend_impl.h12
-rw-r--r--chrome/browser/policy/device_management_backend_mock.h1
-rw-r--r--chrome/browser/policy/device_policy_identity_strategy.cc126
-rw-r--r--chrome/browser/policy/device_policy_identity_strategy.h34
-rw-r--r--chrome/browser/policy/device_token_fetcher.cc14
-rw-r--r--chrome/browser/policy/device_token_fetcher.h9
-rw-r--r--chrome/browser/policy/device_token_fetcher_unittest.cc21
-rw-r--r--chrome/browser/policy/mock_device_management_backend.h33
-rw-r--r--chrome/browser/policy/proto/device_management_backend.proto348
-rw-r--r--chrome/browser/policy/proto/device_management_constants.cc7
-rw-r--r--chrome/browser/policy/proto/device_management_constants.h7
-rw-r--r--chrome/browser/policy/proto/device_management_local.proto13
-rw-r--r--chrome/browser/policy/user_policy_identity_strategy.cc22
-rw-r--r--chrome/browser/policy/user_policy_identity_strategy.h4
-rw-r--r--chrome/test/data/policy/device_management2
-rw-r--r--chrome/tools/build/generate_policy_source.py2
-rw-r--r--net/tools/testserver/device_management.py226
26 files changed, 716 insertions, 523 deletions
diff --git a/chrome/browser/policy/cloud_policy_cache.cc b/chrome/browser/policy/cloud_policy_cache.cc
index 445ff86..7b8a0fa 100644
--- a/chrome/browser/policy/cloud_policy_cache.cc
+++ b/chrome/browser/policy/cloud_policy_cache.cc
@@ -82,7 +82,7 @@ class CloudPolicyCache::CloudPolicyProvider
class PersistPolicyTask : public Task {
public:
PersistPolicyTask(const FilePath& path,
- const em::CloudPolicyResponse* cloud_policy_response,
+ const em::PolicyFetchResponse* cloud_policy_response,
const em::DevicePolicyResponse* device_policy_response,
const bool is_unmanaged)
: path_(path),
@@ -95,7 +95,7 @@ class PersistPolicyTask : public Task {
virtual void Run();
const FilePath path_;
- scoped_ptr<const em::CloudPolicyResponse> cloud_policy_response_;
+ scoped_ptr<const em::PolicyFetchResponse> cloud_policy_response_;
scoped_ptr<const em::DevicePolicyResponse> device_policy_response_;
const bool is_unmanaged_;
};
@@ -211,7 +211,7 @@ void CloudPolicyCache::LoadFromFile() {
observer_list_, OnUpdatePolicy());
}
-void CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) {
+void CloudPolicyCache::SetPolicy(const em::PolicyFetchResponse& policy) {
DCHECK(CalledOnValidThread());
bool initialization_was_not_complete = !initialization_complete_;
is_unmanaged_ = false;
@@ -242,7 +242,7 @@ void CloudPolicyCache::SetPolicy(const em::CloudPolicyResponse& policy) {
LOG(WARNING) << "Server returned policy with timestamp from the future, "
"not persisting to disk.";
} else {
- em::CloudPolicyResponse* policy_copy = new em::CloudPolicyResponse;
+ em::PolicyFetchResponse* policy_copy = new em::PolicyFetchResponse;
policy_copy->CopyFrom(policy);
BrowserThread::PostTask(
BrowserThread::FILE,
@@ -305,33 +305,38 @@ void CloudPolicyCache::SetUnmanaged() {
// static
bool CloudPolicyCache::DecodePolicyResponse(
- const em::CloudPolicyResponse& policy_response,
+ const em::PolicyFetchResponse& policy_response,
PolicyMap* mandatory,
PolicyMap* recommended,
base::Time* timestamp) {
- std::string data = policy_response.signed_response();
+ std::string data = policy_response.policy_data();
- if (!VerifySignature(policy_response.signature(), data,
+ if (!VerifySignature(policy_response.policy_data_signature(), data,
policy_response.certificate_chain())) {
LOG(WARNING) << "Failed to verify signature.";
return false;
}
- em::SignedCloudPolicyResponse response;
- if (!response.ParseFromArray(data.c_str(), data.size())) {
- LOG(WARNING) << "Failed to parse SignedCloudPolicyResponse protobuf.";
+ em::PolicyData policy_data;
+ if (!policy_data.ParseFromString(data)) {
+ LOG(WARNING) << "Failed to parse PolicyData protobuf.";
return false;
}
- // TODO(jkummerow): Verify response.device_token(). Needs final specification
- // which token we're actually sending / expecting to get back.
+ // TODO(jkummerow): Verify policy_data.device_token(). Needs final
+ // specification which token we're actually sending / expecting to get back.
- // TODO(jkummerow): Store response.device_name(), if we decide to transfer
+ // TODO(jkummerow): Store policy_data.device_name(), if we decide to transfer
// it from the server to the client.
- DCHECK(timestamp);
- *timestamp = base::Time::FromTimeT(response.timestamp());
- DecodePolicy(response.settings(), mandatory, recommended);
+ *timestamp = base::Time::UnixEpoch() +
+ base::TimeDelta::FromMilliseconds(policy_data.timestamp());
+ em::CloudPolicySettings policy;
+ if (!policy.ParseFromString(policy_data.policy_value())) {
+ LOG(WARNING) << "Failed to parse CloudPolicySettings protobuf.";
+ return false;
+ }
+ DecodePolicy(policy, mandatory, recommended);
return true;
}
diff --git a/chrome/browser/policy/cloud_policy_cache.h b/chrome/browser/policy/cloud_policy_cache.h
index 5e7745a..ce7965b 100644
--- a/chrome/browser/policy/cloud_policy_cache.h
+++ b/chrome/browser/policy/cloud_policy_cache.h
@@ -52,7 +52,7 @@ class CloudPolicyCache : public base::NonThreadSafe {
void LoadFromFile();
// Resets the policy information.
- void SetPolicy(const em::CloudPolicyResponse& policy);
+ void SetPolicy(const em::PolicyFetchResponse& policy);
void SetDevicePolicy(const em::DevicePolicyResponse& policy);
ConfigurationPolicyProvider* GetManagedPolicyProvider();
@@ -85,7 +85,7 @@ class CloudPolicyCache : public base::NonThreadSafe {
// maps and a timestamp. Also performs verification, returns NULL if any
// check fails.
static bool DecodePolicyResponse(
- const em::CloudPolicyResponse& policy_response,
+ const em::PolicyFetchResponse& policy_response,
PolicyMap* mandatory,
PolicyMap* recommended,
base::Time* timestamp);
diff --git a/chrome/browser/policy/cloud_policy_cache_unittest.cc b/chrome/browser/policy/cloud_policy_cache_unittest.cc
index 54e1de0..7140ccb 100644
--- a/chrome/browser/policy/cloud_policy_cache_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_cache_unittest.cc
@@ -58,36 +58,39 @@ class CloudPolicyCacheTest : public testing::Test {
loop_.RunAllPending();
}
- // Creates a (signed) CloudPolicyResponse setting the given |homepage| and
+ // Creates a (signed) PolicyFetchResponse setting the given |homepage| and
// featuring the given |timestamp| (as issued by the server).
// Mildly hacky special feature: pass an empty string as |homepage| to get
// a completely empty policy.
- em::CloudPolicyResponse* CreateHomepagePolicy(
+ em::PolicyFetchResponse* CreateHomepagePolicy(
const std::string& homepage,
const base::Time& timestamp,
const em::PolicyOptions::PolicyMode policy_mode) {
- em::SignedCloudPolicyResponse signed_response;
+ em::PolicyData signed_response;
if (homepage != "") {
- em::CloudPolicySettings* settings = signed_response.mutable_settings();
+ em::CloudPolicySettings settings;
em::HomepageLocationProto* homepagelocation_proto =
- settings->mutable_homepagelocation();
+ settings.mutable_homepagelocation();
homepagelocation_proto->set_homepagelocation(homepage);
homepagelocation_proto->mutable_policy_options()->set_mode(policy_mode);
+ EXPECT_TRUE(
+ settings.SerializeToString(signed_response.mutable_policy_value()));
}
- signed_response.set_timestamp(timestamp.ToTimeT());
+ signed_response.set_timestamp(
+ (timestamp - base::Time::UnixEpoch()).InMilliseconds());
std::string serialized_signed_response;
EXPECT_TRUE(signed_response.SerializeToString(&serialized_signed_response));
- em::CloudPolicyResponse* response = new em::CloudPolicyResponse;
- response->set_signed_response(serialized_signed_response);
+ em::PolicyFetchResponse* response = new em::PolicyFetchResponse;
+ response->set_policy_data(serialized_signed_response);
// TODO(jkummerow): Set proper certificate_chain and signature (when
// implementing support for signature verification).
- response->set_signature("TODO");
+ response->set_policy_data_signature("TODO");
response->add_certificate_chain("TODO");
return response;
}
- void WritePolicy(const em::CloudPolicyResponse& policy) {
+ void WritePolicy(const em::PolicyFetchResponse& policy) {
std::string data;
em::CachedCloudPolicyResponse cached_policy;
cached_policy.mutable_cloud_policy()->CopyFrom(policy);
@@ -98,9 +101,9 @@ class CloudPolicyCacheTest : public testing::Test {
// Takes ownership of |policy_response|.
void SetPolicy(CloudPolicyCache* cache,
- em::CloudPolicyResponse* policy_response,
+ em::PolicyFetchResponse* policy_response,
bool expect_changed_policy) {
- scoped_ptr<em::CloudPolicyResponse> policy(policy_response);
+ scoped_ptr<em::PolicyFetchResponse> policy(policy_response);
ConfigurationPolicyObserverRegistrar registrar;
registrar.Init(cache->GetManagedPolicyProvider(), &observer);
if (expect_changed_policy)
@@ -206,7 +209,7 @@ TEST_F(CloudPolicyCacheTest, LoadNoFile) {
}
TEST_F(CloudPolicyCacheTest, RejectFuture) {
- scoped_ptr<em::CloudPolicyResponse> policy_response(
+ scoped_ptr<em::PolicyFetchResponse> policy_response(
CreateHomepagePolicy("", base::Time::NowFromSystemTime() +
base::TimeDelta::FromMinutes(5),
em::PolicyOptions::MANDATORY));
@@ -219,7 +222,7 @@ TEST_F(CloudPolicyCacheTest, RejectFuture) {
}
TEST_F(CloudPolicyCacheTest, LoadWithFile) {
- scoped_ptr<em::CloudPolicyResponse> policy_response(
+ scoped_ptr<em::PolicyFetchResponse> policy_response(
CreateHomepagePolicy("", base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY));
WritePolicy(*policy_response);
@@ -232,7 +235,7 @@ TEST_F(CloudPolicyCacheTest, LoadWithFile) {
}
TEST_F(CloudPolicyCacheTest, LoadWithData) {
- scoped_ptr<em::CloudPolicyResponse> policy(
+ scoped_ptr<em::PolicyFetchResponse> policy(
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY));
@@ -247,12 +250,12 @@ TEST_F(CloudPolicyCacheTest, LoadWithData) {
TEST_F(CloudPolicyCacheTest, SetPolicy) {
CloudPolicyCache cache(test_file());
- em::CloudPolicyResponse* policy =
+ em::PolicyFetchResponse* policy =
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY);
SetPolicy(&cache, policy, true);
- em::CloudPolicyResponse* policy2 =
+ em::PolicyFetchResponse* policy2 =
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY);
@@ -264,8 +267,8 @@ TEST_F(CloudPolicyCacheTest, SetPolicy) {
EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
EXPECT_TRUE(empty.Equals(recommended_policy(cache)));
policy = CreateHomepagePolicy("http://www.example.com",
- base::Time::NowFromSystemTime(),
- em::PolicyOptions::RECOMMENDED);
+ base::Time::NowFromSystemTime(),
+ em::PolicyOptions::RECOMMENDED);
SetPolicy(&cache, policy, true);
EXPECT_TRUE(expected.Equals(recommended_policy(cache)));
EXPECT_TRUE(empty.Equals(mandatory_policy(cache)));
@@ -274,7 +277,7 @@ TEST_F(CloudPolicyCacheTest, SetPolicy) {
TEST_F(CloudPolicyCacheTest, ResetPolicy) {
CloudPolicyCache cache(test_file());
- em::CloudPolicyResponse* policy =
+ em::PolicyFetchResponse* policy =
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY);
@@ -284,7 +287,7 @@ TEST_F(CloudPolicyCacheTest, ResetPolicy) {
Value::CreateStringValue("http://www.example.com"));
EXPECT_TRUE(expected.Equals(mandatory_policy(cache)));
- em::CloudPolicyResponse* empty_policy =
+ em::PolicyFetchResponse* empty_policy =
CreateHomepagePolicy("", base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY);
SetPolicy(&cache, empty_policy, true);
@@ -295,7 +298,7 @@ TEST_F(CloudPolicyCacheTest, ResetPolicy) {
TEST_F(CloudPolicyCacheTest, PersistPolicy) {
{
CloudPolicyCache cache(test_file());
- scoped_ptr<em::CloudPolicyResponse> policy(
+ scoped_ptr<em::PolicyFetchResponse> policy(
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY));
@@ -314,14 +317,14 @@ TEST_F(CloudPolicyCacheTest, PersistPolicy) {
}
TEST_F(CloudPolicyCacheTest, FreshPolicyOverride) {
- scoped_ptr<em::CloudPolicyResponse> policy(
+ scoped_ptr<em::PolicyFetchResponse> policy(
CreateHomepagePolicy("http://www.example.com",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY));
WritePolicy(*policy);
CloudPolicyCache cache(test_file());
- em::CloudPolicyResponse* updated_policy =
+ em::PolicyFetchResponse* updated_policy =
CreateHomepagePolicy("http://www.chromium.org",
base::Time::NowFromSystemTime(),
em::PolicyOptions::MANDATORY);
diff --git a/chrome/browser/policy/cloud_policy_controller.cc b/chrome/browser/policy/cloud_policy_controller.cc
index 7ace406..e9b61f0 100644
--- a/chrome/browser/policy/cloud_policy_controller.cc
+++ b/chrome/browser/policy/cloud_policy_controller.cc
@@ -93,17 +93,18 @@ void CloudPolicyController::HandlePolicyResponse(
if (state_ == STATE_TOKEN_UNAVAILABLE)
return;
- cache_->SetDevicePolicy(response);
- SetState(STATE_POLICY_VALID);
-}
-
-void CloudPolicyController::HandleCloudPolicyResponse(
- const em::CloudPolicyResponse& response) {
- if (state_ == STATE_TOKEN_UNAVAILABLE)
- return;
-
- cache_->SetPolicy(response);
- SetState(STATE_POLICY_VALID);
+ if (response.response_size() > 0) {
+ if (response.response_size() > 1) {
+ LOG(WARNING) << "More than one policy in the response of the device "
+ << "management server, discarding.";
+ }
+ // Use the new version of the protocol
+ cache_->SetPolicy(response.response(0));
+ SetState(STATE_POLICY_VALID);
+ } else {
+ cache_->SetDevicePolicy(response);
+ SetState(STATE_POLICY_VALID);
+ }
}
void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) {
@@ -119,17 +120,7 @@ void CloudPolicyController::OnError(DeviceManagementBackend::ErrorCode code) {
DeviceManagementBackend::kErrorServiceManagementNotSupported) {
VLOG(1) << "The device is no longer managed, resetting device token.";
SetState(STATE_TOKEN_UNAVAILABLE);
- } else if (!fallback_to_old_protocol_ &&
- code == DeviceManagementBackend::kErrorRequestInvalid) {
- LOG(WARNING) << "Device manager doesn't understand new protocol, falling "
- << "back to old request.";
- fallback_to_old_protocol_ = true;
- SetState(STATE_TOKEN_VALID); // Triggers SendPolicyRequest() immediately.
} else {
- LOG(WARNING) << "Could not provide policy from the device manager (error = "
- << code << "), will retry in "
- << (effective_policy_refresh_error_delay_ms_ / 1000)
- << " seconds.";
SetState(STATE_POLICY_ERROR);
}
}
@@ -185,7 +176,6 @@ void CloudPolicyController::Initialize(
token_fetcher_ = token_fetcher;
identity_strategy_ = identity_strategy;
state_ = STATE_TOKEN_UNAVAILABLE;
- fallback_to_old_protocol_ = false;
delayed_work_task_ = NULL;
policy_refresh_rate_ms_ = policy_refresh_rate_ms;
policy_refresh_deviation_factor_percent_ =
@@ -206,31 +196,39 @@ void CloudPolicyController::FetchToken() {
std::string username;
std::string auth_token;
std::string device_id = identity_strategy_->GetDeviceID();
+ std::string machine_id = identity_strategy_->GetMachineID();
+ em::DeviceRegisterRequest_Type policy_type =
+ identity_strategy_->GetPolicyRegisterType();
if (identity_strategy_->GetCredentials(&username, &auth_token) &&
CanBeInManagedDomain(username)) {
- token_fetcher_->FetchToken(auth_token, device_id);
+ token_fetcher_->FetchToken(auth_token, device_id, policy_type, machine_id);
}
}
void CloudPolicyController::SendPolicyRequest() {
DCHECK(!identity_strategy_->GetDeviceToken().empty());
- if (!fallback_to_old_protocol_) {
- em::CloudPolicyRequest policy_request;
- policy_request.set_policy_scope(kChromePolicyScope);
- backend_->ProcessCloudPolicyRequest(identity_strategy_->GetDeviceToken(),
- identity_strategy_->GetDeviceID(),
- policy_request, this);
- } else {
- em::DevicePolicyRequest policy_request;
- policy_request.set_policy_scope(kChromePolicyScope);
- em::DevicePolicySettingRequest* setting =
- policy_request.add_setting_request();
- setting->set_key(kChromeDevicePolicySettingKey);
- setting->set_watermark("");
- backend_->ProcessPolicyRequest(identity_strategy_->GetDeviceToken(),
- identity_strategy_->GetDeviceID(),
- policy_request, this);
+ em::DevicePolicyRequest policy_request;
+ em::PolicyFetchRequest* fetch_request = policy_request.add_request();
+ fetch_request->set_signature_type(em::PolicyFetchRequest::X509);
+ fetch_request->set_policy_type(identity_strategy_->GetPolicyType());
+ if (!cache_->is_unmanaged() &&
+ !cache_->last_policy_refresh_time().is_null()) {
+ base::TimeDelta timestamp =
+ cache_->last_policy_refresh_time() - base::Time::UnixEpoch();
+ fetch_request->set_timestamp(timestamp.InMilliseconds());
}
+
+ // TODO(gfeher): Remove the following block when the server is migrated.
+ // Set fields for the old protocol.
+ policy_request.set_policy_scope(kChromePolicyScope);
+ em::DevicePolicySettingRequest* setting =
+ policy_request.add_setting_request();
+ setting->set_key(kChromeDevicePolicySettingKey);
+ setting->set_watermark("");
+
+ backend_->ProcessPolicyRequest(identity_strategy_->GetDeviceToken(),
+ identity_strategy_->GetDeviceID(),
+ policy_request, this);
}
void CloudPolicyController::DoDelayedWork() {
diff --git a/chrome/browser/policy/cloud_policy_controller.h b/chrome/browser/policy/cloud_policy_controller.h
index 3375981..42bb1eb 100644
--- a/chrome/browser/policy/cloud_policy_controller.h
+++ b/chrome/browser/policy/cloud_policy_controller.h
@@ -47,8 +47,6 @@ class CloudPolicyController
// DevicePolicyResponseDelegate implementation:
virtual void HandlePolicyResponse(
const em::DevicePolicyResponse& response);
- virtual void HandleCloudPolicyResponse(
- const em::CloudPolicyResponse& response);
virtual void OnError(DeviceManagementBackend::ErrorCode code);
// DeviceTokenFetcher::Observer implementation:
@@ -119,7 +117,6 @@ class CloudPolicyController
DeviceTokenFetcher* token_fetcher_;
ControllerState state_;
bool initial_fetch_done_;
- bool fallback_to_old_protocol_;
int64 policy_refresh_rate_ms_;
int policy_refresh_deviation_factor_percent_;
diff --git a/chrome/browser/policy/cloud_policy_controller_unittest.cc b/chrome/browser/policy/cloud_policy_controller_unittest.cc
index 64d8408..66d872d 100644
--- a/chrome/browser/policy/cloud_policy_controller_unittest.cc
+++ b/chrome/browser/policy/cloud_policy_controller_unittest.cc
@@ -7,6 +7,8 @@
#include "base/message_loop.h"
#include "base/scoped_temp_dir.h"
#include "chrome/browser/policy/cloud_policy_cache.h"
+#include "chrome/browser/policy/device_token_fetcher.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/mock_configuration_policy_store.h"
#include "chrome/browser/policy/mock_device_management_backend.h"
#include "content/browser/browser_thread.h"
@@ -18,6 +20,8 @@ const char kTestToken[] = "cloud_policy_controller_test_auth_token";
namespace policy {
+namespace em = enterprise_management;
+
using ::testing::_;
using ::testing::AtLeast;
using ::testing::InSequence;
@@ -31,6 +35,10 @@ class MockCloudPolicyIdentityStrategy : public CloudPolicyIdentityStrategy {
MOCK_METHOD0(GetDeviceToken, std::string());
MOCK_METHOD0(GetDeviceID, std::string());
+ MOCK_METHOD0(GetMachineID, std::string());
+ MOCK_METHOD0(GetPolicyType, std::string());
+ MOCK_METHOD0(GetPolicyRegisterType, em::DeviceRegisterRequest_Type());
+
MOCK_METHOD2(GetCredentials, bool(std::string*, std::string*));
virtual void OnDeviceTokenAvailable(const std::string&) {}
@@ -50,8 +58,10 @@ class MockDeviceTokenFetcher : public DeviceTokenFetcher {
: DeviceTokenFetcher(NULL, cache) {}
virtual ~MockDeviceTokenFetcher() {}
- MOCK_METHOD0(GetDeviceToken, std::string&());
- MOCK_METHOD2(FetchToken, void(const std::string&, const std::string&));
+ MOCK_METHOD0(GetDeviceToken, const std::string&());
+ MOCK_METHOD4(FetchToken,
+ void(const std::string&, const std::string&,
+ em::DeviceRegisterRequest_Type, const std::string&));
private:
DISALLOW_COPY_AND_ASSIGN(MockDeviceTokenFetcher);
@@ -104,14 +114,24 @@ class CloudPolicyControllerTest : public testing::Test {
EXPECT_TRUE(store.Get(kPolicyDisableSpdy)->Equals(&expected));
}
- void SetupIdentityStrategy(const std::string& device_token,
- const std::string& device_id,
- const std::string& user_name,
- const std::string& auth_token) {
+ void SetupIdentityStrategy(
+ const std::string& device_token,
+ const std::string& device_id,
+ const std::string& machine_id,
+ const std::string& policy_type,
+ const em::DeviceRegisterRequest_Type& policy_register_type,
+ const std::string& user_name,
+ const std::string& auth_token) {
EXPECT_CALL(identity_strategy_, GetDeviceToken()).WillRepeatedly(
Return(device_token));
EXPECT_CALL(identity_strategy_, GetDeviceID()).WillRepeatedly(
Return(device_id));
+ EXPECT_CALL(identity_strategy_, GetMachineID()).WillRepeatedly(
+ Return(machine_id));
+ EXPECT_CALL(identity_strategy_, GetPolicyType()).WillRepeatedly(
+ Return(policy_type));
+ EXPECT_CALL(identity_strategy_, GetPolicyRegisterType()).WillRepeatedly(
+ Return(policy_register_type));
if (!user_name.empty()) {
EXPECT_CALL(identity_strategy_, GetCredentials(_, _)).WillRepeatedly(
MockCloudPolicyIdentityStrategyGetCredentials(user_name, auth_token));
@@ -136,9 +156,11 @@ class CloudPolicyControllerTest : public testing::Test {
// If a device token is present when the controller starts up, it should
// fetch and apply policy.
TEST_F(CloudPolicyControllerTest, StartupWithDeviceToken) {
- SetupIdentityStrategy("fake_device_token", "device_id", "", "");
+ SetupIdentityStrategy("fake_device_token", "device_id", "machine_id",
+ "google/chromeos/user",
+ em::DeviceRegisterRequest::USER, "", "");
MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedSpdyCloudPolicy());
CreateNewController(backend);
loop_.RunAllPending();
@@ -148,8 +170,10 @@ TEST_F(CloudPolicyControllerTest, StartupWithDeviceToken) {
// If no device token is present when the controller starts up, it should
// instruct the token_fetcher_ to fetch one.
TEST_F(CloudPolicyControllerTest, StartupWithoutDeviceToken) {
- SetupIdentityStrategy("", "device_id", "a@b.com", "auth_token");
- EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ SetupIdentityStrategy("", "device_id", "machine_id", "google/chromeos/user",
+ em::DeviceRegisterRequest::USER,
+ "a@b.com", "auth_token");
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
CreateNewController(NULL);
loop_.RunAllPending();
}
@@ -157,8 +181,10 @@ TEST_F(CloudPolicyControllerTest, StartupWithoutDeviceToken) {
// If the current user belongs to a known non-managed domain, no token fetch
// should be initiated.
TEST_F(CloudPolicyControllerTest, StartupUnmanagedUser) {
- SetupIdentityStrategy("", "device_id", "DannoHelper@gmail.com", "auth_token");
- EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(0);
+ SetupIdentityStrategy("", "device_id", "machine_id", "google/chromeos/user",
+ em::DeviceRegisterRequest::USER,
+ "DannoHelper@gmail.com", "auth_token");
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(0);
CreateNewController(NULL);
loop_.RunAllPending();
}
@@ -166,10 +192,11 @@ TEST_F(CloudPolicyControllerTest, StartupUnmanagedUser) {
// After policy has been fetched successfully, a new fetch should be triggered
// after the refresh interval has timed out.
TEST_F(CloudPolicyControllerTest, RefreshAfterSuccessfulPolicy) {
- SetupIdentityStrategy("device_token", "device_id",
+ SetupIdentityStrategy("device_token", "device_id", "machine_id",
+ "google/chromeos/user", em::DeviceRegisterRequest::USER,
"DannoHelperDelegate@b.com", "auth_token");
MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedSpdyCloudPolicy()).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorRequestFailed));
@@ -180,10 +207,11 @@ TEST_F(CloudPolicyControllerTest, RefreshAfterSuccessfulPolicy) {
// If poliy fetching failed, it should be retried.
TEST_F(CloudPolicyControllerTest, RefreshAfterError) {
- SetupIdentityStrategy("device_token", "device_id",
+ SetupIdentityStrategy("device_token", "device_id", "machine_id",
+ "google/chromeos/user", em::DeviceRegisterRequest::USER,
"DannoHelperDelegateImpl@b.com", "auth_token");
MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorRequestFailed)).WillOnce(
MockDeviceManagementBackendSucceedSpdyCloudPolicy());
@@ -195,12 +223,14 @@ TEST_F(CloudPolicyControllerTest, RefreshAfterError) {
// If the backend reports that the device token was invalid, the controller
// should instruct the token fetcher to fetch a new token.
TEST_F(CloudPolicyControllerTest, InvalidToken) {
- SetupIdentityStrategy("device_token", "device_id", "standup@ten.am", "auth");
+ SetupIdentityStrategy("device_token", "device_id", "machine_id",
+ "google/chromeos/user", em::DeviceRegisterRequest::USER,
+ "standup@ten.am", "auth");
MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorServiceManagementTokenInvalid));
- EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
CreateNewController(backend);
loop_.RunAllPending();
}
@@ -208,12 +238,14 @@ TEST_F(CloudPolicyControllerTest, InvalidToken) {
// If the backend reports that the device is unknown to the server, the
// controller should instruct the token fetcher to fetch a new token.
TEST_F(CloudPolicyControllerTest, DeviceNotFound) {
- SetupIdentityStrategy("device_token", "device_id", "me@you.com", "auth");
+ SetupIdentityStrategy("device_token", "device_id", "machine_id",
+ "google/chromeos/user", em::DeviceRegisterRequest::USER,
+ "me@you.com", "auth");
MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorServiceDeviceNotFound));
- EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
CreateNewController(backend);
loop_.RunAllPending();
}
@@ -222,37 +254,16 @@ TEST_F(CloudPolicyControllerTest, DeviceNotFound) {
// shoud instruct the token fetcher to fetch a new token (which will in turn
// set and persist the correct 'unmanaged' state).
TEST_F(CloudPolicyControllerTest, NoLongerManaged) {
- SetupIdentityStrategy("device_token", "device_id", "who@what.com", "auth");
+ SetupIdentityStrategy("device_token", "device_id", "machine_id",
+ "google/chromeos/user", em::DeviceRegisterRequest::USER,
+ "who@what.com", "auth");
MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
+ EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendFailPolicy(
DeviceManagementBackend::kErrorServiceManagementNotSupported));
- EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _)).Times(1);
+ EXPECT_CALL(*token_fetcher_.get(), FetchToken(_, _, _, _)).Times(1);
CreateNewController(backend);
loop_.RunAllPending();
}
-// If the server doesn't support the new protocol, the controller should fall
-// back to the old protocol.
-TEST_F(CloudPolicyControllerTest, FallbackToOldProtocol) {
- SetupIdentityStrategy("device_token", "device_id", "a@b.com", "auth");
- MockDeviceManagementBackend* backend = new MockDeviceManagementBackend();
- // If the CloudPolicyRequest fails with kErrorRequestInvalid...
- EXPECT_CALL(*backend, ProcessCloudPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorRequestInvalid));
- // ...the client should fall back to a classic PolicyRequest,
- // and remember this fallback for any future request,
- // both after successful fetches and after errors.
- EXPECT_CALL(*backend, ProcessPolicyRequest(_, _, _, _)).WillOnce(
- MockDeviceManagementBackendSucceedBooleanPolicy(
- key::kDisableSpdy, true)).WillOnce(
- MockDeviceManagementBackendFailPolicy(
- DeviceManagementBackend::kErrorHttpStatus)).WillOnce(
- Return());
- CreateNewController(backend, 0, 0, 0, 0);
- loop_.RunAllPending();
- ExpectHasSpdyPolicy();
-}
-
} // namespace policy
diff --git a/chrome/browser/policy/cloud_policy_identity_strategy.h b/chrome/browser/policy/cloud_policy_identity_strategy.h
index 1ecf840..1b4db76 100644
--- a/chrome/browser/policy/cloud_policy_identity_strategy.h
+++ b/chrome/browser/policy/cloud_policy_identity_strategy.h
@@ -9,9 +9,12 @@
#include <string>
#include "base/observer_list.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
namespace policy {
+namespace em = enterprise_management;
+
// Manages a device management token, i.e. an identifier that represents a
// registration with the device management service, and the associated
// credentials. Responsibilities include storing and loading the token from
@@ -41,9 +44,22 @@ class CloudPolicyIdentityStrategy {
// if the device token is currently unavailable.
virtual std::string GetDeviceToken() = 0;
- // Returns the device ID for this device.
+ // Returns the device ID for this device. This is a unique identifier that is
+ // randomly generated at registration time on the client side. It always has
+ // to be sent along with the device token to the server.
virtual std::string GetDeviceID() = 0;
+ // Returns physical machine ID for this device.
+ virtual std::string GetMachineID() = 0;
+
+ // Returns the policy type to be used for registering at the device management
+ // server.
+ virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType() = 0;
+
+ // Returns the policy type to be used for requesting policies from the device
+ // management server.
+ virtual std::string GetPolicyType() = 0;
+
// Retrieves authentication credentials to use when talking to the device
// management service. Returns true if the data is available and writes the
// values to the provided pointers.
diff --git a/chrome/browser/policy/device_management_backend.h b/chrome/browser/policy/device_management_backend.h
index f2fec0d..9a02b48 100644
--- a/chrome/browser/policy/device_management_backend.h
+++ b/chrome/browser/policy/device_management_backend.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -75,12 +75,8 @@ class DeviceManagementBackend : base::NonThreadSafe {
public:
virtual ~DevicePolicyResponseDelegate() {}
- // Deprecated in favor of HandleCloudPolicyResponse. To be removed once
- // DMServer supports the new protocol.
virtual void HandlePolicyResponse(
const em::DevicePolicyResponse& response) = 0;
- virtual void HandleCloudPolicyResponse(
- const em::CloudPolicyResponse& response) = 0;
virtual void OnError(ErrorCode code) = 0;
protected:
@@ -110,12 +106,6 @@ class DeviceManagementBackend : base::NonThreadSafe {
const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* delegate) = 0;
- virtual void ProcessCloudPolicyRequest(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::CloudPolicyRequest& request,
- DevicePolicyResponseDelegate* delegate) = 0;
-
protected:
DeviceManagementBackend() {}
diff --git a/chrome/browser/policy/device_management_backend_impl.cc b/chrome/browser/policy/device_management_backend_impl.cc
index b01cbf8..a964a28 100644
--- a/chrome/browser/policy/device_management_backend_impl.cc
+++ b/chrome/browser/policy/device_management_backend_impl.cc
@@ -27,14 +27,12 @@ const char DeviceManagementBackendImpl::kValueRequestRegister[] = "register";
const char DeviceManagementBackendImpl::kValueRequestUnregister[] =
"unregister";
const char DeviceManagementBackendImpl::kValueRequestPolicy[] = "policy";
-const char DeviceManagementBackendImpl::kValueRequestCloudPolicy[] =
- "cloud_policy";
-const char DeviceManagementBackendImpl::kValueDeviceType[] = "Chrome OS";
+const char DeviceManagementBackendImpl::kValueDeviceType[] = "2";
const char DeviceManagementBackendImpl::kValueAppType[] = "Chrome";
namespace {
-const char kValueAgent[] = "%s enterprise management client version %s (%s)";
+const char kValueAgent[] = "%s enterprise management client %s (%s)";
const char kPostContentType[] = "application/protobuf";
@@ -332,41 +330,6 @@ class DeviceManagementPolicyJob : public DeviceManagementJobBase {
DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob);
};
-// Handles cloud policy request jobs.
-class CloudPolicyJob : public DeviceManagementJobBase {
- public:
- CloudPolicyJob(
- DeviceManagementBackendImpl* backend_impl,
- const std::string& device_management_token,
- const std::string& device_id,
- const em::CloudPolicyRequest& request,
- DeviceManagementBackend::DevicePolicyResponseDelegate* delegate)
- : DeviceManagementJobBase(
- backend_impl,
- DeviceManagementBackendImpl::kValueRequestCloudPolicy,
- device_id),
- delegate_(delegate) {
- SetDeviceManagementToken(device_management_token);
- em::DeviceManagementRequest request_wrapper;
- request_wrapper.mutable_cloud_policy_request()->CopyFrom(request);
- SetPayload(request_wrapper);
- }
- virtual ~CloudPolicyJob() {}
-
- private:
- // DeviceManagementJobBase overrides.
- virtual void OnError(DeviceManagementBackend::ErrorCode error) {
- delegate_->OnError(error);
- }
- virtual void OnResponse(const em::DeviceManagementResponse& response) {
- delegate_->HandleCloudPolicyResponse(response.cloud_policy_response());
- }
-
- DeviceManagementBackend::DevicePolicyResponseDelegate* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(CloudPolicyJob);
-};
-
DeviceManagementBackendImpl::DeviceManagementBackendImpl(
DeviceManagementService* service)
: service_(service) {
@@ -428,13 +391,4 @@ void DeviceManagementBackendImpl::ProcessPolicyRequest(
request, delegate));
}
-void DeviceManagementBackendImpl::ProcessCloudPolicyRequest(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::CloudPolicyRequest& request,
- DevicePolicyResponseDelegate* delegate) {
- AddJob(new CloudPolicyJob(this, device_management_token, device_id,
- request, delegate));
-}
-
} // namespace policy
diff --git a/chrome/browser/policy/device_management_backend_impl.h b/chrome/browser/policy/device_management_backend_impl.h
index 40c7e11..345bc40 100644
--- a/chrome/browser/policy/device_management_backend_impl.h
+++ b/chrome/browser/policy/device_management_backend_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -36,10 +36,7 @@ class DeviceManagementBackendImpl : public DeviceManagementBackend {
// String constants for the device and app type we report to the server.
static const char kValueRequestRegister[];
static const char kValueRequestUnregister[];
- // Deprecated in favor of kValueRequestCloudPolicy.
- // See DevicePolicyResponseDelegate::HandlePolicyResponse.
static const char kValueRequestPolicy[];
- static const char kValueRequestCloudPolicy[];
static const char kValueDeviceType[];
static const char kValueAppType[];
@@ -66,18 +63,11 @@ class DeviceManagementBackendImpl : public DeviceManagementBackend {
const std::string& device_id,
const em::DeviceUnregisterRequest& request,
DeviceUnregisterResponseDelegate* response_delegate);
- // Deprecated in favor of ProcessCloudPolicyRequest.
- // See DevicePolicyResponseDelegate::HandlePolicyResponse.
virtual void ProcessPolicyRequest(
const std::string& device_management_token,
const std::string& device_id,
const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* response_delegate);
- virtual void ProcessCloudPolicyRequest(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::CloudPolicyRequest& request,
- DevicePolicyResponseDelegate* delegate);
// Keeps track of the jobs currently in flight.
JobSet pending_jobs_;
diff --git a/chrome/browser/policy/device_management_backend_mock.h b/chrome/browser/policy/device_management_backend_mock.h
index 01ac14d..0533efc 100644
--- a/chrome/browser/policy/device_management_backend_mock.h
+++ b/chrome/browser/policy/device_management_backend_mock.h
@@ -40,7 +40,6 @@ class DevicePolicyResponseDelegateMock
virtual ~DevicePolicyResponseDelegateMock();
MOCK_METHOD1(HandlePolicyResponse, void(const em::DevicePolicyResponse&));
- MOCK_METHOD1(HandleCloudPolicyResponse, void(const em::CloudPolicyResponse&));
MOCK_METHOD1(OnError, void(DeviceManagementBackend::ErrorCode error));
};
diff --git a/chrome/browser/policy/device_policy_identity_strategy.cc b/chrome/browser/policy/device_policy_identity_strategy.cc
index 0f19945..42626a3 100644
--- a/chrome/browser/policy/device_policy_identity_strategy.cc
+++ b/chrome/browser/policy/device_policy_identity_strategy.cc
@@ -8,16 +8,79 @@
#include "chrome/browser/chromeos/login/ownership_service.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/guid.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/notification_type.h"
namespace policy {
+// Responsible for querying device ownership on the FILE thread.
+class DevicePolicyIdentityStrategy::OwnershipChecker
+ : public base::RefCountedThreadSafe<
+ DevicePolicyIdentityStrategy::OwnershipChecker> {
+ public:
+ explicit OwnershipChecker(
+ const base::WeakPtr<DevicePolicyIdentityStrategy>& strategy)
+ : strategy_(strategy) {}
+
+ // Initiates a query on the file thread to check if the currently logged in
+ // user is the owner.
+ void CheckCurrentUserIsOwner();
+
+ private:
+ void CheckOnFileThread();
+ void CallbackOnUIThread(bool current_user_is_owner);
+
+ private:
+ friend class base::RefCountedThreadSafe<OwnershipChecker>;
+
+ ~OwnershipChecker() {}
+
+ // The object to be called back with the result.
+ base::WeakPtr<DevicePolicyIdentityStrategy> strategy_;
+
+ DISALLOW_COPY_AND_ASSIGN(OwnershipChecker);
+};
+
+void DevicePolicyIdentityStrategy::OwnershipChecker::CheckCurrentUserIsOwner() {
+ if (!strategy_.get())
+ return;
+ BrowserThread::PostTask(
+ BrowserThread::FILE,
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &DevicePolicyIdentityStrategy::OwnershipChecker::CheckOnFileThread));
+}
+
+void DevicePolicyIdentityStrategy::OwnershipChecker::CheckOnFileThread() {
+ bool current_user_is_owner =
+ chromeos::OwnershipService::GetSharedInstance()->CurrentUserIsOwner();
+ BrowserThread::PostTask(
+ BrowserThread::UI,
+ FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &DevicePolicyIdentityStrategy::OwnershipChecker::CallbackOnUIThread,
+ current_user_is_owner));
+}
+
+void DevicePolicyIdentityStrategy::OwnershipChecker::CallbackOnUIThread(
+ bool current_user_is_owner) {
+ if (strategy_.get()) {
+ strategy_->OnOwnershipInformationAvailable(current_user_is_owner);
+ strategy_.reset();
+ }
+}
+
DevicePolicyIdentityStrategy::DevicePolicyIdentityStrategy()
- : should_register_(false) {
+ : current_user_is_owner_(false),
+ ownership_checker_(NULL),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
registrar_.Add(this,
NotificationType::TOKEN_AVAILABLE,
NotificationService::AllSources());
@@ -25,9 +88,6 @@ DevicePolicyIdentityStrategy::DevicePolicyIdentityStrategy()
NotificationType::LOGIN_USER_CHANGED,
NotificationService::AllSources());
registrar_.Add(this,
- NotificationType::OWNERSHIP_TAKEN,
- NotificationService::AllSources());
- registrar_.Add(this,
NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED,
NotificationService::AllSources());
@@ -35,27 +95,58 @@ DevicePolicyIdentityStrategy::DevicePolicyIdentityStrategy()
machine_id_ = "dummy-cros-machine-ID";
}
+DevicePolicyIdentityStrategy::~DevicePolicyIdentityStrategy() {
+}
+
+void DevicePolicyIdentityStrategy::OnOwnershipInformationAvailable(
+ bool current_user_is_owner) {
+ current_user_is_owner_ = current_user_is_owner;
+ CheckAndTriggerFetch();
+}
+
+void DevicePolicyIdentityStrategy::CheckOwnershipAndTriggerFetch() {
+ // TODO(gfeher): Avoid firing a new query if the answer is already known.
+
+ // Cancel any pending queries.
+ weak_ptr_factory_.InvalidateWeakPtrs();
+ // Set to false until we know that the current user is the owner.
+ current_user_is_owner_ = false;
+ // Issue a new query.
+ ownership_checker_ = new OwnershipChecker(weak_ptr_factory_.GetWeakPtr());
+ // The following will call back to CheckTriggerFetch().
+ ownership_checker_->CheckCurrentUserIsOwner();
+}
+
std::string DevicePolicyIdentityStrategy::GetDeviceToken() {
return device_token_;
}
std::string DevicePolicyIdentityStrategy::GetDeviceID() {
+ return device_id_;
+}
+
+std::string DevicePolicyIdentityStrategy::GetMachineID() {
return machine_id_;
}
+em::DeviceRegisterRequest_Type
+DevicePolicyIdentityStrategy::GetPolicyRegisterType() {
+ return em::DeviceRegisterRequest::DEVICE;
+}
+
+std::string DevicePolicyIdentityStrategy::GetPolicyType() {
+ return kChromeDevicePolicyType;
+}
+
bool DevicePolicyIdentityStrategy::GetCredentials(std::string* username,
std::string* auth_token) {
- // Only register if requested.
- if (!should_register_)
- return false;
-
// Need to know the machine id.
if (machine_id_.empty())
return false;
// Only fetch credentials (and, subsequently, token/policy) when the owner
// is logged in.
- if (!chromeos::OwnershipService::GetSharedInstance()->CurrentUserIsOwner())
+ if (!current_user_is_owner_)
return false;
// We need to know about the profile of the logged in user.
@@ -76,9 +167,6 @@ void DevicePolicyIdentityStrategy::OnDeviceTokenAvailable(
const std::string& token) {
DCHECK(!machine_id_.empty());
- // Reset registration flag, so we only attempt registration once.
- should_register_ = false;
-
device_token_ = token;
NotifyDeviceTokenChanged();
}
@@ -86,8 +174,10 @@ void DevicePolicyIdentityStrategy::OnDeviceTokenAvailable(
void DevicePolicyIdentityStrategy::CheckAndTriggerFetch() {
std::string username;
std::string auth_token;
- if (GetCredentials(&username, &auth_token))
+ if (GetCredentials(&username, &auth_token)) {
+ device_id_ = guid::GenerateGUID();
NotifyAuthChanged();
+ }
}
void DevicePolicyIdentityStrategy::Observe(NotificationType type,
@@ -97,15 +187,11 @@ void DevicePolicyIdentityStrategy::Observe(NotificationType type,
const TokenService::TokenAvailableDetails* token_details =
Details<const TokenService::TokenAvailableDetails>(details).ptr();
if (token_details->service() == GaiaConstants::kDeviceManagementService)
- CheckAndTriggerFetch();
+ CheckOwnershipAndTriggerFetch();
} else if (type == NotificationType::LOGIN_USER_CHANGED) {
- should_register_ = false;
- CheckAndTriggerFetch();
- } else if (type == NotificationType::OWNERSHIP_TAKEN) {
- should_register_ = true;
- CheckAndTriggerFetch();
+ CheckOwnershipAndTriggerFetch();
} else if (type == NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED) {
- CheckAndTriggerFetch();
+ CheckOwnershipAndTriggerFetch();
} else {
NOTREACHED();
}
diff --git a/chrome/browser/policy/device_policy_identity_strategy.h b/chrome/browser/policy/device_policy_identity_strategy.h
index 838124d..913a2a3 100644
--- a/chrome/browser/policy/device_policy_identity_strategy.h
+++ b/chrome/browser/policy/device_policy_identity_strategy.h
@@ -8,6 +8,8 @@
#include <string>
+#include "base/ref_counted.h"
+#include "base/weak_ptr.h"
#include "chrome/browser/policy/cloud_policy_identity_strategy.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
@@ -21,20 +23,32 @@ class DevicePolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
public NotificationObserver {
public:
DevicePolicyIdentityStrategy();
- virtual ~DevicePolicyIdentityStrategy() {}
+ virtual ~DevicePolicyIdentityStrategy();
+
+ // Called by DevicePolicyIdentityStrategy::OwnershipChecker:
+ virtual void OnOwnershipInformationAvailable(bool current_user_is_owner);
// CloudPolicyIdentityStrategy implementation:
virtual std::string GetDeviceToken();
virtual std::string GetDeviceID();
+ virtual std::string GetMachineID();
+ virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType();
+ virtual std::string GetPolicyType();
virtual bool GetCredentials(std::string* username,
std::string* auth_token);
virtual void OnDeviceTokenAvailable(const std::string& token);
private:
+ class OwnershipChecker;
+
// Recheck whether all parameters are available and if so, trigger a
// credentials changed notification.
void CheckAndTriggerFetch();
+ // Updates the ownership information and then passes control to
+ // |CheckAndTriggerFetch|.
+ void CheckOwnershipAndTriggerFetch();
+
// NotificationObserver method overrides:
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -43,17 +57,27 @@ class DevicePolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
// The machine identifier.
std::string machine_id_;
+ // The device identifier to be sent with requests. (This is actually more like
+ // a session identifier since it is re-generated for each registration
+ // request.)
+ std::string device_id_;
+
// Current token. Empty if not available.
std::string device_token_;
- // Whether to try and register. Device policy enrollment does not happen
- // automatically except for the case that the device gets claimed. This
- // situation is detected by listening for the OWNERSHIP_TAKEN notification.
- bool should_register_;
+ // Whether the currently logged in user is the device's owner. This variable
+ // is owned by the UI thread but updated from the FILE thread. Therefore
+ // after an owner login it will take some time before it turns to true.
+ bool current_user_is_owner_;
// Registers the provider for notification of successful Gaia logins.
NotificationRegistrar registrar_;
+ scoped_refptr<OwnershipChecker> ownership_checker_;
+
+ // Allows to construct weak ptrs.
+ base::WeakPtrFactory<DevicePolicyIdentityStrategy> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(DevicePolicyIdentityStrategy);
};
diff --git a/chrome/browser/policy/device_token_fetcher.cc b/chrome/browser/policy/device_token_fetcher.cc
index 6661d3c..a426cf4 100644
--- a/chrome/browser/policy/device_token_fetcher.cc
+++ b/chrome/browser/policy/device_token_fetcher.cc
@@ -9,6 +9,7 @@
#include "base/message_loop.h"
#include "chrome/browser/policy/cloud_policy_cache.h"
#include "chrome/browser/policy/device_management_service.h"
+#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"
namespace {
@@ -50,11 +51,16 @@ DeviceTokenFetcher::~DeviceTokenFetcher() {
CancelRetryTask();
}
-void DeviceTokenFetcher::FetchToken(const std::string& auth_token,
- const std::string& device_id) {
+void DeviceTokenFetcher::FetchToken(
+ const std::string& auth_token,
+ const std::string& device_id,
+ em::DeviceRegisterRequest_Type policy_type,
+ const std::string& machine_id) {
SetState(STATE_INACTIVE);
auth_token_ = auth_token;
device_id_ = device_id;
+ policy_type_ = policy_type;
+ machine_id_ = machine_id;
FetchTokenInternal();
}
@@ -64,6 +70,10 @@ void DeviceTokenFetcher::FetchTokenInternal() {
// Construct a new backend, which will discard any previous requests.
backend_.reset(service_->CreateBackend());
em::DeviceRegisterRequest request;
+ request.set_type(policy_type_);
+ if (!machine_id_.empty())
+ request.set_machine_id(machine_id_);
+ request.set_machine_model(kRegisterRequestMachineModel);
backend_->ProcessRegisterRequest(auth_token_, device_id_, request, this);
}
diff --git a/chrome/browser/policy/device_token_fetcher.h b/chrome/browser/policy/device_token_fetcher.h
index 0501433..7f78100 100644
--- a/chrome/browser/policy/device_token_fetcher.h
+++ b/chrome/browser/policy/device_token_fetcher.h
@@ -12,6 +12,7 @@
#include "base/scoped_ptr.h"
#include "base/task.h"
#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
namespace policy {
@@ -48,7 +49,9 @@ class DeviceTokenFetcher
// Starts fetching a token.
// Declared virtual so it can be overridden by mocks.
virtual void FetchToken(const std::string& auth_token,
- const std::string& device_id);
+ const std::string& device_id,
+ em::DeviceRegisterRequest_Type policy_type,
+ const std::string& machine_id);
// Returns the device management token or the empty string if not available.
// Declared virtual so it can be overridden by mocks.
@@ -125,6 +128,10 @@ class DeviceTokenFetcher
std::string auth_token_;
// Device identifier to send to the server.
std::string device_id_;
+ // Contains policy type to send to the server.
+ em::DeviceRegisterRequest_Type policy_type_;
+ // Contains physical machine id to send to the server.
+ std::string machine_id_;
// Task that has been scheduled to retry fetching a token.
CancelableTask* retry_task_;
diff --git a/chrome/browser/policy/device_token_fetcher_unittest.cc b/chrome/browser/policy/device_token_fetcher_unittest.cc
index d040fb4..95e4dda 100644
--- a/chrome/browser/policy/device_token_fetcher_unittest.cc
+++ b/chrome/browser/policy/device_token_fetcher_unittest.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/net/gaia/token_service.h"
#include "chrome/browser/policy/cloud_policy_cache.h"
#include "chrome/browser/policy/device_management_service.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/mock_device_management_backend.h"
#include "chrome/common/net/gaia/gaia_constants.h"
#include "chrome/test/testing_profile.h"
@@ -85,14 +86,6 @@ class ProxyDeviceManagementBackend : public DeviceManagementBackend {
backend_->ProcessPolicyRequest(device_management_token, device_id,
request, delegate);
}
- virtual void ProcessCloudPolicyRequest(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::CloudPolicyRequest& request,
- DevicePolicyResponseDelegate* delegate) {
- backend_->ProcessCloudPolicyRequest(device_management_token, device_id,
- request, delegate);
- }
private:
DeviceManagementBackend* backend_; // weak
@@ -142,7 +135,8 @@ TEST_F(DeviceTokenFetcherTest, FetchToken) {
EXPECT_CALL(observer, OnDeviceTokenAvailable());
fetcher.AddObserver(&observer);
EXPECT_EQ("", fetcher.GetDeviceToken());
- fetcher.FetchToken("fake_auth_token", "fake_device_id");
+ fetcher.FetchToken("fake_auth_token", "fake_device_id",
+ em::DeviceRegisterRequest::USER, "fake_machine_id");
loop_.RunAllPending();
Mock::VerifyAndClearExpectations(&observer);
std::string token = fetcher.GetDeviceToken();
@@ -152,7 +146,8 @@ TEST_F(DeviceTokenFetcherTest, FetchToken) {
EXPECT_CALL(backend_, ProcessRegisterRequest(_, _, _, _)).WillOnce(
MockDeviceManagementBackendSucceedRegister());
EXPECT_CALL(observer, OnDeviceTokenAvailable());
- fetcher.FetchToken("fake_auth_token", "fake_device_id");
+ fetcher.FetchToken("fake_auth_token", "fake_device_id",
+ em::DeviceRegisterRequest::USER, "fake_machine_id");
loop_.RunAllPending();
Mock::VerifyAndClearExpectations(&observer);
std::string token2 = fetcher.GetDeviceToken();
@@ -171,7 +166,8 @@ TEST_F(DeviceTokenFetcherTest, RetryOnError) {
MockTokenAvailableObserver observer;
EXPECT_CALL(observer, OnDeviceTokenAvailable());
fetcher.AddObserver(&observer);
- fetcher.FetchToken("fake_auth_token", "fake_device_id");
+ fetcher.FetchToken("fake_auth_token", "fake_device_id",
+ em::DeviceRegisterRequest::USER, "fake_machine_id");
loop_.RunAllPending();
Mock::VerifyAndClearExpectations(&observer);
EXPECT_NE("", fetcher.GetDeviceToken());
@@ -187,7 +183,8 @@ TEST_F(DeviceTokenFetcherTest, UnmanagedDevice) {
MockTokenAvailableObserver observer;
EXPECT_CALL(observer, OnDeviceTokenAvailable()).Times(0);
fetcher.AddObserver(&observer);
- fetcher.FetchToken("fake_auth_token", "fake_device_id");
+ fetcher.FetchToken("fake_auth_token", "fake_device_id",
+ em::DeviceRegisterRequest::USER, "fake_machine_id");
loop_.RunAllPending();
Mock::VerifyAndClearExpectations(&observer);
EXPECT_EQ("", fetcher.GetDeviceToken());
diff --git a/chrome/browser/policy/mock_device_management_backend.h b/chrome/browser/policy/mock_device_management_backend.h
index 54c8c8f..d360157 100644
--- a/chrome/browser/policy/mock_device_management_backend.h
+++ b/chrome/browser/policy/mock_device_management_backend.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -12,6 +12,8 @@
#include "base/time.h"
#include "base/values.h"
#include "chrome/browser/policy/device_management_backend.h"
+#include "chrome/browser/policy/proto/cloud_policy.pb.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
#include "chrome/browser/policy/proto/device_management_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -47,12 +49,6 @@ class MockDeviceManagementBackend : public DeviceManagementBackend {
const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* delegate));
- MOCK_METHOD4(ProcessCloudPolicyRequest, void(
- const std::string& device_management_token,
- const std::string& device_id,
- const em::CloudPolicyRequest& request,
- DevicePolicyResponseDelegate* delegate));
-
private:
DISALLOW_COPY_AND_ASSIGN(MockDeviceManagementBackend);
};
@@ -81,21 +77,26 @@ ACTION_P2(MockDeviceManagementBackendSucceedBooleanPolicy, name, value) {
}
ACTION(MockDeviceManagementBackendSucceedSpdyCloudPolicy) {
- em::SignedCloudPolicyResponse signed_response;
- em::CloudPolicySettings* settings = signed_response.mutable_settings();
- em::DisableSpdyProto* spdy_proto = settings->mutable_disablespdy();
+ em::PolicyData signed_response;
+ em::CloudPolicySettings settings;
+ em::DisableSpdyProto* spdy_proto = settings.mutable_disablespdy();
spdy_proto->set_disablespdy(true);
spdy_proto->mutable_policy_options()->set_mode(em::PolicyOptions::MANDATORY);
- signed_response.set_timestamp(base::Time::NowFromSystemTime().ToTimeT());
+ EXPECT_TRUE(
+ settings.SerializeToString(signed_response.mutable_policy_value()));
+ base::TimeDelta timestamp =
+ base::Time::NowFromSystemTime() - base::Time::UnixEpoch();
+ signed_response.set_timestamp(timestamp.InMilliseconds());
std::string serialized_signed_response;
EXPECT_TRUE(signed_response.SerializeToString(&serialized_signed_response));
- em::CloudPolicyResponse response;
- response.set_signed_response(serialized_signed_response);
+ em::DevicePolicyResponse response;
+ em::PolicyFetchResponse* fetch_response = response.add_response();
+ fetch_response->set_policy_data(serialized_signed_response);
// TODO(jkummerow): Set proper certificate_chain and signature (when
// implementing support for signature verification).
- response.set_signature("TODO");
- response.add_certificate_chain("TODO");
- arg3->HandleCloudPolicyResponse(response);
+ fetch_response->set_policy_data_signature("TODO");
+ fetch_response->add_certificate_chain("TODO");
+ arg3->HandlePolicyResponse(response);
}
ACTION_P(MockDeviceManagementBackendFailRegister, error) {
diff --git a/chrome/browser/policy/proto/device_management_backend.proto b/chrome/browser/policy/proto/device_management_backend.proto
index 1a857b6..a192a25 100644
--- a/chrome/browser/policy/proto/device_management_backend.proto
+++ b/chrome/browser/policy/proto/device_management_backend.proto
@@ -4,18 +4,31 @@
syntax = "proto2";
-import "cloud_policy.proto";
-
option optimize_for = LITE_RUNTIME;
package enterprise_management;
-// Protocol buffers for the obsolete protocol:
-// -------------------------------------------
-// GenericValue, GenericNamedValue, GenericSetting, DevicePolicySetting,
-// DevicePolicySettingRequest, DevicePolicyRequest, DevicePolicyResponse
-// TODO(gfeher): Remove these when both Chrome and DMServer is switched to
-// using the new protocol.
+// Meta-settings that control how a user receives regular settings
+// (CloudPolicySettings) for Chrome. The name "Initial" indicates that
+// these settings will be downloaded before Chrome starts requesting
+// regular settings.
+message ChromeInitialSettingsProto {
+ enum EnrollmentProvision {
+ // The users's device is not automatically enrolled for policies, but the
+ // user may choose to try to enroll it.
+ UNMANAGED = 0;
+ // The user must enroll its device for policies.
+ MANAGED = 1;
+ }
+ // Chrome will interpret this as UNMANAGED if unset.
+ optional EnrollmentProvision enrollment_provision = 1 [default = UNMANAGED];
+}
+
+// A setting is a set of generic name value pairs.
+// TODO(gfeher): remove this after Chrome OS TT is over.
+message GenericSetting {
+ repeated GenericNamedValue named_value = 1;
+}
// Generic value container.
message GenericValue {
@@ -51,12 +64,8 @@ message GenericNamedValue {
optional GenericValue value = 2;
}
-// A setting is a set of generic name value pairs.
-message GenericSetting {
- repeated GenericNamedValue named_value = 1;
-}
-
// Identify a single device policy setting key/value pair.
+// TODO(gfeher): remove this after Chrome OS TT is over.
message DevicePolicySetting {
// key of the policy setting
required string policy_key = 1;
@@ -66,189 +75,205 @@ message DevicePolicySetting {
optional string watermark = 3;
}
-// Request for a setting or with optional watermark on client side.
-message DevicePolicySettingRequest {
- // setting key
- required string key = 1;
- // watermark last read from server if available.
- optional string watermark = 2;
-}
-
-// Request from device to server to read device policies.
-message DevicePolicyRequest {
- // identify request scope: CrOS settings or other type of settings.
- optional string policy_scope = 1;
- // identify key to the settings: proxy etc.
- repeated DevicePolicySettingRequest setting_request = 2;
-}
-
-// Response from server to agent for reading policies.
-message DevicePolicyResponse {
- // the result of the settings.
- repeated DevicePolicySetting setting = 1;
-}
-
-// Request from device to server to register device. The response will include
-// a device token that can be used to query policies.
+// Request from device to server to register device.
message DeviceRegisterRequest {
- // reregister device without erasing server state.
- // it can be used to refresh dmtoken etc.
+ // Reregister device without erasing server state. It can be used
+ // to refresh dmtoken etc. Client MUST set this value to true if it
+ // reuses an existing device id.
optional bool reregister = 1;
+
+ // Device register type. This field does not exist for TT release.
+ // When a client requests for policies, server should verify the
+ // client has been registered properly. For example, a client must
+ // register with type DEVICE in order to retrieve device policies.
+ enum Type {
+ TT = 0; // Register for TT release.
+ USER = 1; // Register for user polices.
+ DEVICE = 2; // Register for device policies.
+ }
+ // NOTE: we also use this field to detect client version. If this
+ // field is missing, then the request comes from TT. We will remove
+ // Chrome OS TT support once it is over.
+ optional Type type = 2 [default = TT];
+
+ // Machine hardware id, such as MEID, Mac adress.
+ // This field is required if register type == DEVICE.
+ optional string machine_id = 3;
+
+ // Machine model name, such as "ZGA", "Cr-48", "Nexus One". If the
+ // model name is not available, client SHOULD send generic name like
+ // "Android", or "Chrome OS".
+ optional string machine_model = 4;
}
// Response from server to device register request.
message DeviceRegisterResponse {
- // device mangement toke for this registration.
+ // Device mangement token for this registration. This token MUST be
+ // part of HTTP Authorization header for all future requests from
+ // device to server.
required string device_management_token = 1;
-}
-// Protocol buffers for the new protocol:
-// --------------------------------------
-
-// Request from device to server to get policies for an unregistered user.
-// These are actually "meta-policies", that control the rules for the user
-// about enrolling for real policies.
-message InitialPolicyRequest {
+ // Device display name. By default, server generates the name in
+ // the format of "Machine Model - Machine Id". However, domain
+ // admin can update it using CPanel, so do NOT treat it as constant.
+ optional string machine_name = 2;
}
-message InitialPolicySettings {
- enum EnrollmentRule {
- // The user must enroll its device for policies.
- MANAGED = 1;
- // The users's device is not automatically enrolled for policies, but the
- // user may choose to try to enroll it.
- UNMANAGED = 2;
- }
-
- optional EnrollmentRule enrollment_rule = 1;
+// Request from device to server to unregister device.
+// GoogleDMToken MUST be in HTTP Authorization header.
+message DeviceUnregisterRequest {
}
-// Response from server to device containing the policies available before
-// registration.
-message InitialPolicyResponse {
- optional InitialPolicySettings settings = 1;
+// Response from server to device for unregister request.
+message DeviceUnregisterResponse {
}
-// Request from device to server to unregister device management token.
-message DeviceUnregisterRequest {
+// Request for a setting or with optional watermark on client side.
+// TODO(gfeher): remove this after Chrome OS TT is over.
+message DevicePolicySettingRequest {
+ // setting key
+ required string key = 1;
+ // watermark last read from server if available.
+ optional string watermark = 2;
}
-// Response from server to unregister request.
-message DeviceUnregisterResponse {
+message PolicyFetchRequest {
+ // This is the policy type, which maps to D3 policy type internally.
+ // By convention, we use "/" as separator to create policy namespace.
+ // The policy type names are case insensitive.
+ //
+ // Possible values for Chrome OS are:
+ // google/chromeos/device => ChromeSettingsProto
+ // google/chromeos/user => ChromeSettingsProto
+ // google/chromeos/unregistered_user => ChromeInitialSettingsProto
+ optional string policy_type = 1;
+
+ // This is the last policy timestamp that client received from server.
+ optional int64 timestamp = 2;
+
+ // Tell server what kind of security signature is required.
+ enum SignatureType {
+ NONE = 0;
+ X509 = 1;
+ }
+ optional SignatureType signature_type = 3 [default = NONE];
}
-// Request from device to server to register device. The response will include
-// a device token that can be used to query policies.
-message CloudRegisterRequest {
- enum Type {
- // Requesting token for user policies.
- USER = 1;
- // Requesting token for device policies.
- DEVICE = 2;
- }
- optional Type type = 1;
- // Unique identifier of the machine. Only set if type == DEVICE.
- // This won't be sent in later requests, the machine can be identified
- // by its device token.
- optional string machine_id = 2;
+// This message is included in serialized form in PolicyFetchResponse
+// below. It may also be signed, with the signature being created for
+// the serialized form.
+message PolicyData {
+ // See PolicyFetchRequest.policy_type.
+ optional string policy_type = 1;
+
+ // [timestamp] is milli seconds since Epoch in UTC timezone. It is
+ // included here so that the time at which the server issued this
+ // response cannot be faked (as protection against replay attacks).
+ // It is the timestamp generated by DMServer, NOT the time admin
+ // last updated the policy or anything like that.
+ optional int64 timestamp = 2;
+
+ // The DM token that was used by the client in the HTTP POST header
+ // for authenticating the request. It is included here again so that
+ // the client can verify that the response is meant for him (and not
+ // issued by a replay or man-in-the-middle attack).
+ optional string request_token = 3;
+
+ // The serialized value of the actual policy protobuf. This can be
+ // deserialized to an instance of, for example, ChromeSettingsProto
+ // or ChromeUserSettingsProto.
+ optional bytes policy_value = 4;
+
+ // The device display name assigned by the server. It is only
+ // filled if the display name is available.
+ //
+ // The display name of the machine as generated by the server or set
+ // by the Administrator in the CPanel GUI. This is the same thing as
+ // |machine_name| in DeviceRegisterResponse but it might have
+ // changed since then.
+ optional string machine_name = 5;
}
-// Response from server to device register request.
-message CloudRegisterResponse {
- // Token for this registration.
- required string device_management_token = 1;
+message PolicyFetchResponse {
+ // Since a single policy request may ask for multiple policies, we
+ // provide separate error code for each individual policy fetch.
- // The name of the requesting device, assigned by the server.
- optional string machine_name = 2;
+ // We will use standard HTTP Status Code as error code.
+ optional int32 error_code = 1;
+
+ // Human readable error message for customer support purpose.
+ optional string error_message = 2;
+
+ // This is a serialized bytes of PolicyData protobuf above.
+ optional bytes policy_data = 3;
+
+ // Signature of the policy data above.
+ optional bytes policy_data_signature = 4;
+
+ // The chain of DER-encoded X.509 certificates of the server's
+ // signing key. The first element should be the certificate whose
+ // private key was used for signing the response, and each of the
+ // following certificates signs the previous one.
+ //
+ // If this field does not exist, it means the policy_data is not
+ // signed.
+ repeated bytes certificate_chain = 5;
}
-message CloudPolicyRequest {
- // Identify request scope: chromeos/device for device policies, chromeos/user
- // for user policies. Only those policy scopes will be served, that are
- // allowed by the type choice in CloudRegisterRequest.
+// Request from device to server for reading policies.
+message DevicePolicyRequest {
+ // identify request scope: CrOS settings or other type of settings.
+ // TODO(gfeher): remove this after Chrome OS TT is over.
optional string policy_scope = 1;
+ // identify key to the settings: proxy etc.
+ // TODO(gfeher): remove this after Chrome OS TT is over.
+ repeated DevicePolicySettingRequest setting_request = 2;
- // The token used to query device policies on the device sending the request.
- // Note, that the token used for actual authentication is sent in an HTTP
- // header. These two tokens are the same if this request is for querying
- // device policies and they differ if this request is for querying user
- // policies. In the second case, the server can use device_policy_token to
- // identify the device and determine if the user is allowed to get policies
- // on the given device.
- optional string device_policy_token = 2;
+ // The policy fetch request. If this field exists, the request must
+ // comes from a non-TT client. The repeated field allows client to
+ // request multiple policies for better performance.
+ repeated PolicyFetchRequest request = 3;
}
// Response from server to device for reading policies.
-message CloudPolicyResponse {
- // Serialized SignedCloudPolicyResponse.
- optional bytes signed_response = 1;
- // RSA signature of the SHA1 hash of the above data.
- optional bytes signature = 2;
- // The chain of DER-encoded X.509 certificates of the server's signing key.
- // The first element should be the certificate whose private key was used
- // for signing the response, and each of the following certificates signs the
- // previous one.
- repeated bytes certificate_chain = 3;
-}
-message SignedCloudPolicyResponse {
- // The following two are necessary against replay attacks.
- // |timestamp| is a unix timestamp (seconds since 1970).
- optional int64 timestamp = 1;
- // The token that was used for the request.
- optional string request_token = 2;
- // The name of the device, assigned by the server.
- optional string device_name = 3;
- // CloudPolicySettings is defined in cloud_policy.proto (which is
- // auto-generated from chrome/app/policy_templates.json).
- optional CloudPolicySettings settings = 4;
+message DevicePolicyResponse {
+ // the result of the settings.
+ // TODO(gfeher): remove this after Chrome OS TT is over.
+ repeated DevicePolicySetting setting = 1;
+
+ // The policy fetch response.
+ repeated PolicyFetchResponse response = 3;
}
-// Request from the DMAgent on the device to the DMServer.
-// This is container for all requests from client.
+// Request from the DMAgent on the device to the DMServer. This is
+// container for all requests from device to server. The overall HTTP
+// request MUST be in the following format:
//
-// Http Query parameters:
-// Query parameters contain the following information in each request:
-// request: register/unregister/policy/cloud_policy/cloud_register/
-// initial_policy
-// devicetype: CrOS/Android/Iphone etc.
-// apptype: CrOS/AndroidDM etc.
-// agent: identify agent on device.
+// * HTTP method is POST
+// * Data mime type is application/x-protobuffer
+// * HTTP parameters are (all required, all case sensitive):
+// * request: MUST BE one of register/unregister/policy/ping
+// * devicetype: MUST BE "1" for Android or "2" for Chrome OS.
+// * apptype: MUST BE Android or Chrome.
+// * deviceid: MUST BE no more than 64-char in [\x20-\x7E].
+// * agent: MUST BE no more than 64-char long.
+// * HTTP Authorization header MUST be in the following formats:
+// * For register and ping requests
+// Authorization: GoogleLogin auth=<auth cookie for Mobile Sync>
//
-// Authorization:
-// 1. If request is initial_policy, client must pass in GoogleLogin
-// auth cookie in Authorization header:
-// Authorization: GoogleLogin auth=<auth cookie>
-// The response will contain settings that a user can get without
-// registration. Currently the only such setting is a flag indicating if the
-// user is in a managed domain or not. (We don't want to expose device ids of
-// users not in managed domains.)
-// 2. If request is register_request, client must pass in GoogleLogin auth
-// cookie in Authorization header:
-// Authorization: GoogleLogin auth=<auth cookie>
-// The response will contain an unique DMToken for future requests.
-// Depending on domain policy, the request may need admin approval before
-// DMToken is issued.
-// 3. For other requests, client must pass in DMToken in Authorization header:
-// Authorization: GoogleDMToken token=<google dm token>
+// * For unregister and policy requests
+// Authorization: GoogleDMToken token=<dm token from register>
//
+// * OAuth is NOT supported yet.
message DeviceManagementRequest {
- // Register request (old protocol).
+ // Register request.
optional DeviceRegisterRequest register_request = 1;
// Unregister request.
optional DeviceUnregisterRequest unregister_request = 2;
- // Data request.
+ // Policy request.
optional DevicePolicyRequest policy_request = 3;
-
- // Data request (new protocol).
- optional CloudPolicyRequest cloud_policy_request = 4;
-
- // Request for initial (before registration) policies.
- optional InitialPolicyRequest initial_policy_request = 5;
-
- // Register request (new protocol).
- optional CloudRegisterRequest cloud_register_request = 6;
}
// Response from server to device.
@@ -276,7 +301,7 @@ message DeviceManagementResponse {
// Error message.
optional string error_message = 2;
- // Register response (old protocol).
+ // Register response
optional DeviceRegisterResponse register_response = 3;
// Unregister response
@@ -284,13 +309,4 @@ message DeviceManagementResponse {
// Policy response.
optional DevicePolicyResponse policy_response = 5;
-
- // Policy response (new protocol).
- optional CloudPolicyResponse cloud_policy_response = 6;
-
- // Response to initial (before registration) policy request.
- optional InitialPolicyResponse initial_policy_response = 7;
-
- // Register response (new protocol).
- optional CloudRegisterResponse cloud_register_response = 8;
} \ No newline at end of file
diff --git a/chrome/browser/policy/proto/device_management_constants.cc b/chrome/browser/policy/proto/device_management_constants.cc
index 3912eb1..bb57c8d 100644
--- a/chrome/browser/policy/proto/device_management_constants.cc
+++ b/chrome/browser/policy/proto/device_management_constants.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -9,4 +9,9 @@ namespace policy {
const char kChromePolicyScope[] = "chromeos/device";
const char kChromeDevicePolicySettingKey[] = "chrome-policy";
+const char kChromeDevicePolicyType[] = "google/chromeos/device";
+const char kChromeUserPolicyType[] = "google/chromeos/user";
+
+const char kRegisterRequestMachineModel[] = "Chrome OS";
+
} // namespace policy
diff --git a/chrome/browser/policy/proto/device_management_constants.h b/chrome/browser/policy/proto/device_management_constants.h
index e37c514..920ff91 100644
--- a/chrome/browser/policy/proto/device_management_constants.h
+++ b/chrome/browser/policy/proto/device_management_constants.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -10,6 +10,11 @@ namespace policy {
extern const char kChromePolicyScope[];
extern const char kChromeDevicePolicySettingKey[];
+extern const char kChromeDevicePolicyType[];
+extern const char kChromeUserPolicyType[];
+
+extern const char kRegisterRequestMachineModel[];
+
} // namespace policy
#endif // CHROME_BROWSER_POLICY_PROTO_DEVICE_MANAGEMENT_CONSTANTS_H_
diff --git a/chrome/browser/policy/proto/device_management_local.proto b/chrome/browser/policy/proto/device_management_local.proto
index 45c2994..122e863 100644
--- a/chrome/browser/policy/proto/device_management_local.proto
+++ b/chrome/browser/policy/proto/device_management_local.proto
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
@@ -14,14 +14,14 @@ import "device_management_backend.proto";
message CachedCloudPolicyResponse {
// The DevicePolicyResponse wrapped by this message.
optional DevicePolicyResponse device_policy = 1;
- // Timestamp noting when the |unmanaged| flag was set. The data format is
- // a unix timestamp. When caching (deprecated) DevicePolicyResponses, this
- // timestamp also notes when the response was cached.
+ // Timestamp noting when the |unmanaged| flag was set. The meaning is
+ // milliseconds since 1970. When caching (deprecated) DevicePolicyResponses,
+ // this timestamp also notes when the response was cached.
optional uint64 timestamp = 2;
// Flag that is set to true if this device is not managed.
optional bool unmanaged = 3;
- // The CloudPolicyResponse wrapped by this message.
- optional CloudPolicyResponse cloud_policy = 4;
+ // The PolicyFetchResponse wrapped by this message.
+ optional PolicyFetchResponse cloud_policy = 4;
}
// Encapsulates a device ID and the associated device token.
@@ -29,4 +29,3 @@ message DeviceCredentials {
optional string device_id = 1;
optional string device_token = 2;
}
-
diff --git a/chrome/browser/policy/user_policy_identity_strategy.cc b/chrome/browser/policy/user_policy_identity_strategy.cc
index a49f311..e900390 100644
--- a/chrome/browser/policy/user_policy_identity_strategy.cc
+++ b/chrome/browser/policy/user_policy_identity_strategy.cc
@@ -7,6 +7,8 @@
#include "base/file_util.h"
#include "chrome/browser/browser_signin.h"
#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+#include "chrome/browser/policy/proto/device_management_constants.h"
#include "chrome/browser/policy/proto/device_management_local.pb.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/guid.h"
@@ -163,6 +165,20 @@ std::string UserPolicyIdentityStrategy::GetDeviceID() {
return device_id_;
}
+std::string UserPolicyIdentityStrategy::GetMachineID() {
+ return "";
+}
+
+em::DeviceRegisterRequest_Type
+UserPolicyIdentityStrategy::GetPolicyRegisterType() {
+ return em::DeviceRegisterRequest::USER;
+}
+
+std::string UserPolicyIdentityStrategy::GetPolicyType() {
+ return kChromeUserPolicyType;
+}
+
+
bool UserPolicyIdentityStrategy::GetCredentials(std::string* username,
std::string* auth_token) {
*username = GetCurrentUser();
@@ -221,7 +237,11 @@ void UserPolicyIdentityStrategy::Observe(NotificationType type,
const TokenService::TokenAvailableDetails* token_details =
Details<const TokenService::TokenAvailableDetails>(details).ptr();
if (token_details->service() == GaiaConstants::kDeviceManagementService)
- CheckAndTriggerFetch();
+ if (device_token_.empty()) {
+ // Request a new device management server token, but only in case we
+ // don't already have it.
+ CheckAndTriggerFetch();
+ }
}
#if defined(OS_CHROMEOS)
} else if (type == NotificationType::LOGIN_USER_CHANGED) {
diff --git a/chrome/browser/policy/user_policy_identity_strategy.h b/chrome/browser/policy/user_policy_identity_strategy.h
index bf6ca55..2ba3e43 100644
--- a/chrome/browser/policy/user_policy_identity_strategy.h
+++ b/chrome/browser/policy/user_policy_identity_strategy.h
@@ -33,6 +33,10 @@ class UserPolicyIdentityStrategy : public CloudPolicyIdentityStrategy,
// CloudPolicyIdentityStrategy implementation:
virtual std::string GetDeviceToken();
virtual std::string GetDeviceID();
+ virtual std::string GetMachineID();
+ virtual em::DeviceRegisterRequest_Type GetPolicyRegisterType();
+ virtual std::string GetPolicyType();
+
virtual bool GetCredentials(std::string* username,
std::string* auth_token);
virtual void OnDeviceTokenAvailable(const std::string& token);
diff --git a/chrome/test/data/policy/device_management b/chrome/test/data/policy/device_management
index 4cd0371..a64ce58 100644
--- a/chrome/test/data/policy/device_management
+++ b/chrome/test/data/policy/device_management
@@ -1,5 +1,5 @@
{
- "chromeos/device": {
+ "google/chromeos/user": {
"mandatory": {
"HomepageLocation" : "http://www.chromium.org"
},
diff --git a/chrome/tools/build/generate_policy_source.py b/chrome/tools/build/generate_policy_source.py
index f573484..4de4fef 100644
--- a/chrome/tools/build/generate_policy_source.py
+++ b/chrome/tools/build/generate_policy_source.py
@@ -226,7 +226,7 @@ CPP_HEAD = '''
#include "base/values.h"
#include "chrome/browser/policy/configuration_policy_provider.h"
#include "chrome/browser/policy/policy_map.h"
-#include "chrome/browser/policy/proto/device_management_backend.pb.h"
+#include "chrome/browser/policy/proto/cloud_policy.pb.h"
#include "policy/configuration_policy_type.h"
using google::protobuf::RepeatedPtrField;
diff --git a/net/tools/testserver/device_management.py b/net/tools/testserver/device_management.py
index ccf1ac8..efd6694 100644
--- a/net/tools/testserver/device_management.py
+++ b/net/tools/testserver/device_management.py
@@ -114,19 +114,25 @@ class RequestHandler(object):
rmsg = dm.DeviceManagementRequest()
rmsg.ParseFromString(self._request)
+ logging.debug('auth -> ' + self._headers.getheader('Authorization', ''))
+ logging.debug('deviceid -> ' + self.GetUniqueParam('deviceid'))
self.DumpMessage('Request', rmsg)
request_type = self.GetUniqueParam('request')
+ # Check server side requirements, as defined in
+ # device_management_backend.proto.
+ if (self.GetUniqueParam('devicetype') != '2' or
+ self.GetUniqueParam('apptype') != 'Chrome' or
+ (request_type != 'ping' and
+ len(self.GetUniqueParam('deviceid')) >= 64) or
+ len(self.GetUniqueParam('agent')) >= 64):
+ return (400, 'Invalid request parameter')
if request_type == 'register':
return self.ProcessRegister(rmsg.register_request)
elif request_type == 'unregister':
return self.ProcessUnregister(rmsg.unregister_request)
- elif request_type == 'policy':
- return self.ProcessPolicy(rmsg.policy_request)
- elif request_type == 'cloud_policy':
- return self.ProcessCloudPolicyRequest(rmsg.cloud_policy_request)
- elif request_type == 'managed_check':
- return self.ProcessManagedCheck(rmsg.managed_check_request)
+ elif request_type == 'policy' or request_type == 'ping':
+ return self.ProcessPolicy(rmsg.policy_request, request_type)
else:
return (400, 'Invalid request parameter')
@@ -140,12 +146,6 @@ class RequestHandler(object):
return None
return match.group(1)
- def GetDeviceName(self):
- """Returns the name for the currently authenticated device based on its
- device id.
- """
- return 'chromeos-' + self.GetUniqueParam('deviceid')
-
def ProcessRegister(self, msg):
"""Handles a register request.
@@ -166,13 +166,16 @@ class RequestHandler(object):
if not device_id:
return (400, 'Missing device identifier')
- # Register the device and create a token.
- dmtoken = self._server.RegisterDevice(device_id)
+ token_info = self._server.RegisterDevice(device_id,
+ msg.machine_id,
+ msg.type)
# Send back the reply.
response = dm.DeviceManagementResponse()
response.error = dm.DeviceManagementResponse.SUCCESS
- response.register_response.device_management_token = dmtoken
+ response.register_response.device_management_token = (
+ token_info['device_token'])
+ response.register_response.machine_name = token_info['machine_name']
self.DumpMessage('Response', response)
@@ -207,41 +210,50 @@ class RequestHandler(object):
return (200, response.SerializeToString())
- def ProcessManagedCheck(self, msg):
- """Handles a 'managed check' request.
+ def ProcessInitialPolicy(self, msg):
+ """Handles a 'preregister policy' request.
Queries the list of managed users and responds the client if their user
is managed or not.
Args:
- msg: The ManagedCheckRequest message received from the client.
+ msg: The PolicyFetchRequest message received from the client.
Returns:
A tuple of HTTP status code and response data to send to the client.
"""
- # Check the management token.
+ # Check the GAIA token.
auth = self.CheckGoogleLogin()
if not auth:
return (403, 'No authorization')
- managed_check_response = dm.ManagedCheckResponse()
+ chrome_initial_settings = dm.ChromeInitialSettingsProto()
if ('*' in self._server.policy['managed_users'] or
auth in self._server.policy['managed_users']):
- managed_check_response.mode = dm.ManagedCheckResponse.MANAGED;
+ chrome_initial_settings.enrollment_provision = (
+ dm.ChromeInitialSettingsProto.MANAGED);
else:
- managed_check_response.mode = dm.ManagedCheckResponse.UNMANAGED;
+ chrome_initial_settings.enrollment_provision = (
+ dm.ChromeInitialSettingsProto.UNMANAGED);
+
+ policy_data = dm.PolicyData()
+ policy_data.policy_type = msg.policy_type
+ policy_data.policy_value = chrome_initial_settings.SerializeToString()
# Prepare and send the response.
response = dm.DeviceManagementResponse()
response.error = dm.DeviceManagementResponse.SUCCESS
- response.managed_check_response.CopyFrom(managed_check_response)
+ fetch_response = response.policy_response.response.add()
+ fetch_response.policy_data = (
+ policy_data.SerializeToString())
self.DumpMessage('Response', response)
return (200, response.SerializeToString())
- def ProcessPolicy(self, msg):
- """Handles a policy request.
+ def ProcessDevicePolicy(self, msg):
+ """Handles a policy request that uses the deprecated protcol.
+ TODO(gfeher): Remove this when we certainly don't need it.
Checks for authorization, encodes the policy into protobuf representation
and constructs the response.
@@ -252,6 +264,7 @@ class RequestHandler(object):
Returns:
A tuple of HTTP status code and response data to send to the client.
"""
+
# Check the management token.
token, response = self.CheckToken()
if not token:
@@ -264,8 +277,8 @@ class RequestHandler(object):
# Respond only if the client requested policy for the cros/device scope,
# since that's where chrome policy is supposed to live in.
- if msg.policy_scope in self._server.policy:
- policy = self._server.policy[msg.policy_scope]['mandatory']
+ if msg.policy_scope == 'chromeos/device':
+ policy = self._server.policy['google/chromeos/user']['mandatory']
setting = response.policy_response.setting.add()
setting.policy_key = 'chrome-policy'
policy_value = dm.GenericSetting()
@@ -293,6 +306,35 @@ class RequestHandler(object):
return (200, response.SerializeToString())
+ def ProcessPolicy(self, msg, request_type):
+ """Handles a policy request.
+
+ Checks for authorization, encodes the policy into protobuf representation
+ and constructs the response.
+
+ Args:
+ msg: The DevicePolicyRequest message received from the client.
+
+ Returns:
+ A tuple of HTTP status code and response data to send to the client.
+ """
+
+ if msg.request:
+ for request in msg.request:
+ if request.policy_type == 'google/chromeos/unregistered_user':
+ if request_type != 'ping':
+ return (400, 'Invalid request type')
+ return self.ProcessInitialPolicy(request)
+ elif (request.policy_type in
+ ('google/chromeos/user', 'google/chromeos/device')):
+ if request_type != 'policy':
+ return (400, 'Invalid request type')
+ return self.ProcessCloudPolicy(request)
+ else:
+ return (400, 'Invalid policy_type')
+ else:
+ return self.ProcessDevicePolicy(msg)
+
def SetProtobufMessageField(self, group_message, field, field_value):
'''Sets a field in a protobuf message.
@@ -302,23 +344,22 @@ class RequestHandler(object):
group_message.DESCRIPTOR.fields.
field_value: The value to set.
'''
- if field.label == field.LABEL_REPEATED:
+ if field.type == field.TYPE_BOOL:
+ assert type(field_value) == bool
+ elif field.type == field.TYPE_STRING:
+ assert type(field_value) == str
+ elif field.type == field.TYPE_INT64:
+ assert type(field_value) == int
+ elif (field.type == field.TYPE_MESSAGE and
+ field.message_type.name == 'StringList'):
assert type(field_value) == list
- assert field.type == field.TYPE_STRING
- list_field = group_message.__getattribute__(field.name)
+ entries = group_message.__getattribute__(field.name).entries
for list_item in field_value:
- list_field.append(list_item)
+ entries.append(list_item)
+ return
else:
- # Simple cases:
- if field.type == field.TYPE_BOOL:
- assert type(field_value) == bool
- elif field.type == field.TYPE_STRING:
- assert type(field_value) == str
- elif field.type == field.TYPE_INT64:
- assert type(field_value) == int
- else:
- raise Exception('Unknown field type %s' % field.type_name)
- group_message.__setattr__(field.name, field_value)
+ raise Exception('Unknown field type %s' % field.type)
+ group_message.__setattr__(field.name, field_value)
def GatherPolicySettings(self, settings, policies):
'''Copies all the policies from a dictionary into a protobuf of type
@@ -352,7 +393,7 @@ class RequestHandler(object):
if got_fields:
settings.__getattribute__(group.name).CopyFrom(group_message)
- def ProcessCloudPolicyRequest(self, msg):
+ def ProcessCloudPolicy(self, msg):
"""Handles a cloud policy request. (New protocol for policy requests.)
Checks for authorization, encodes the policy into protobuf representation,
@@ -364,37 +405,37 @@ class RequestHandler(object):
Returns:
A tuple of HTTP status code and response data to send to the client.
"""
- token, response = self.CheckToken()
- if not token:
- return response
+
+ token_info, error = self.CheckToken()
+ if not token_info:
+ return error
settings = cp.CloudPolicySettings()
- if msg.policy_scope in self._server.policy:
- # Respond is only given if the scope is specified in the config file.
+ if (msg.policy_type in token_info['allowed_policy_types'] and
+ msg.policy_type in self._server.policy):
+ # Response is only given if the scope is specified in the config file.
# Normally 'chromeos/device' and 'chromeos/user' should be accepted.
self.GatherPolicySettings(settings,
- self._server.policy[msg.policy_scope])
-
- # Construct response
- signed_response = dm.SignedCloudPolicyResponse()
- signed_response.settings.CopyFrom(settings)
- signed_response.timestamp = int(time.time())
- signed_response.request_token = token;
- signed_response.device_name = self.GetDeviceName()
-
- cloud_response = dm.CloudPolicyResponse()
- cloud_response.signed_response = signed_response.SerializeToString()
- signed_data = cloud_response.signed_response
- cloud_response.signature = (
- self._server.private_key.hashAndSign(signed_data).tostring())
- for certificate in self._server.cert_chain:
- cloud_response.certificate_chain.append(
- certificate.writeBytes().tostring())
+ self._server.policy[msg.policy_type])
+
+ policy_data = dm.PolicyData()
+ policy_data.policy_value = settings.SerializeToString()
+ policy_data.policy_type = msg.policy_type
+ policy_data.timestamp = int(time.time() * 1000)
+ policy_data.request_token = token_info['device_token'];
+ policy_data.machine_name = token_info['machine_name']
+ signed_data = policy_data.SerializeToString()
response = dm.DeviceManagementResponse()
response.error = dm.DeviceManagementResponse.SUCCESS
- response.cloud_policy_response.CopyFrom(cloud_response)
+ fetch_response = response.policy_response.response.add()
+ fetch_response.policy_data = signed_data
+ fetch_response.policy_data_signature = (
+ self._server.private_key.hashAndSign(signed_data).tostring())
+ for certificate in self._server.cert_chain:
+ fetch_response.certificate_chain.append(
+ certificate.writeBytes().tostring())
self.DumpMessage('Response', response)
@@ -404,12 +445,13 @@ class RequestHandler(object):
"""Helper for checking whether the client supplied a valid DM token.
Extracts the token from the request and passed to the server in order to
- look up the client. Returns a pair of token and error response. If the token
- is None, the error response is a pair of status code and error message.
+ look up the client.
Returns:
- A pair of DM token and error response. If the token is None, the message
- will contain the error response to send back.
+ A pair of token information record and error response. If the first
+ element is None, then the second contains an error code to send back to
+ the client. Otherwise the first element is the same structure that is
+ returned by LookupToken().
"""
error = None
dmtoken = None
@@ -420,11 +462,14 @@ class RequestHandler(object):
dmtoken = match.group(1)
if not dmtoken:
error = dm.DeviceManagementResponse.DEVICE_MANAGEMENT_TOKEN_INVALID
- elif (not request_device_id or
- not self._server.LookupDevice(dmtoken) == request_device_id):
- error = dm.DeviceManagementResponse.DEVICE_NOT_FOUND
else:
- return (dmtoken, None)
+ token_info = self._server.LookupToken(dmtoken)
+ if (not token_info or
+ not request_device_id or
+ token_info['device_id'] != request_device_id):
+ error = dm.DeviceManagementResponse.DEVICE_NOT_FOUND
+ else:
+ return (token_info, None)
response = dm.DeviceManagementResponse()
response.error = error
@@ -448,7 +493,7 @@ class TestServer(object):
policy_cert_chain: List of paths to X.509 certificate files of the
certificate chain used for signing responses.
"""
- self._registered_devices = {}
+ self._registered_tokens = {}
self.policy = {}
if json is None:
print 'No JSON module, cannot parse policy information'
@@ -485,8 +530,8 @@ class TestServer(object):
handler = RequestHandler(self, path, headers, request)
return handler.HandleRequest()
- def RegisterDevice(self, device_id):
- """Registers a device and generate a DM token for it.
+ def RegisterDevice(self, device_id, machine_id, type):
+ """Registers a device or user and generates a DM token for it.
Args:
device_id: The device identifier provided by the client.
@@ -498,19 +543,30 @@ class TestServer(object):
while len(dmtoken_chars) < 32:
dmtoken_chars.append(random.choice('0123456789abcdef'))
dmtoken = ''.join(dmtoken_chars)
- self._registered_devices[dmtoken] = device_id
- return dmtoken
-
- def LookupDevice(self, dmtoken):
- """Looks up a device by DMToken.
+ allowed_policy_types = {
+ dm.DeviceRegisterRequest.USER: ['google/chromeos/user'],
+ dm.DeviceRegisterRequest.DEVICE: ['google/chromeos/device'],
+ dm.DeviceRegisterRequest.TT: ['google/chromeos/user'],
+ }
+ self._registered_tokens[dmtoken] = {
+ 'device_id': device_id,
+ 'device_token': dmtoken,
+ 'allowed_policy_types': allowed_policy_types[type],
+ 'machine_name': 'chromeos-' + machine_id,
+ }
+ return self._registered_tokens[dmtoken]
+
+ def LookupToken(self, dmtoken):
+ """Looks up a device or a user by DM token.
Args:
dmtoken: The device management token provided by the client.
Returns:
- The corresponding device identifier or None if not found.
+ A dictionary with information about a device or user that is registered by
+ dmtoken, or None if the token is not found.
"""
- return self._registered_devices.get(dmtoken, None)
+ return self._registered_tokens.get(dmtoken, None)
def UnregisterDevice(self, dmtoken):
"""Unregisters a device identified by the given DM token.
@@ -518,5 +574,5 @@ class TestServer(object):
Args:
dmtoken: The device management token provided by the client.
"""
- if dmtoken in self._registered_devices:
- del self._registered_devices[dmtoken]
+ if dmtoken in self._registered_tokens.keys():
+ del self._registered_tokens[dmtoken]