Added auto-enrollment request support to the device_management_backend.

Also extended the testserver's device_management.py handler to serve these
requests.

BUG=chromium-os:23063
TEST=unit_tests and browser_tests all pass


Review URL: http://codereview.chromium.org/8741014

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@113009 0039d316-1c4b-4281-b951-d872f2087c98
parent 42e35e53
...@@ -99,6 +99,21 @@ class DeviceManagementBackend : base::NonThreadSafe { ...@@ -99,6 +99,21 @@ class DeviceManagementBackend : base::NonThreadSafe {
DISALLOW_COPY_AND_ASSIGN(DevicePolicyResponseDelegate); DISALLOW_COPY_AND_ASSIGN(DevicePolicyResponseDelegate);
}; };
class DeviceAutoEnrollmentResponseDelegate {
public:
virtual ~DeviceAutoEnrollmentResponseDelegate() {}
virtual void HandleAutoEnrollmentResponse(
const em::DeviceAutoEnrollmentResponse& response) = 0;
virtual void OnError(ErrorCode code) = 0;
protected:
DeviceAutoEnrollmentResponseDelegate() {}
private:
DISALLOW_COPY_AND_ASSIGN(DeviceAutoEnrollmentResponseDelegate);
};
virtual ~DeviceManagementBackend() {} virtual ~DeviceManagementBackend() {}
virtual void ProcessRegisterRequest( virtual void ProcessRegisterRequest(
...@@ -121,6 +136,11 @@ class DeviceManagementBackend : base::NonThreadSafe { ...@@ -121,6 +136,11 @@ class DeviceManagementBackend : base::NonThreadSafe {
const em::DevicePolicyRequest& request, const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* delegate) = 0; DevicePolicyResponseDelegate* delegate) = 0;
virtual void ProcessAutoEnrollmentRequest(
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceAutoEnrollmentResponseDelegate* delegate) = 0;
protected: protected:
DeviceManagementBackend() {} DeviceManagementBackend() {}
......
...@@ -37,6 +37,8 @@ const char DeviceManagementBackendImpl::kParamUserAffiliation[] = ...@@ -37,6 +37,8 @@ const char DeviceManagementBackendImpl::kParamUserAffiliation[] =
// String constants for the device and app type we report to the server. // String constants for the device and app type we report to the server.
const char DeviceManagementBackendImpl::kValueAppType[] = "Chrome"; const char DeviceManagementBackendImpl::kValueAppType[] = "Chrome";
const char DeviceManagementBackendImpl::kValueDeviceType[] = "2"; const char DeviceManagementBackendImpl::kValueDeviceType[] = "2";
const char DeviceManagementBackendImpl::kValueRequestAutoEnrollment[] =
"enterprise_check";
const char DeviceManagementBackendImpl::kValueRequestPolicy[] = "policy"; const char DeviceManagementBackendImpl::kValueRequestPolicy[] = "policy";
const char DeviceManagementBackendImpl::kValueRequestRegister[] = "register"; const char DeviceManagementBackendImpl::kValueRequestRegister[] = "register";
const char DeviceManagementBackendImpl::kValueRequestUnregister[] = const char DeviceManagementBackendImpl::kValueRequestUnregister[] =
...@@ -457,6 +459,43 @@ class DeviceManagementPolicyJob : public DeviceManagementJobBase { ...@@ -457,6 +459,43 @@ class DeviceManagementPolicyJob : public DeviceManagementJobBase {
DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob); DISALLOW_COPY_AND_ASSIGN(DeviceManagementPolicyJob);
}; };
// Handles auto enrollment request jobs. These are used to determine if a new
// ChromiumOS device should automatically enter the enterprise enrollment screen
// during the OOBE flow.
class DeviceManagementAutoEnrollmentJob : public DeviceManagementJobBase {
public:
DeviceManagementAutoEnrollmentJob(
DeviceManagementBackendImpl* backend_impl,
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceManagementBackend::DeviceAutoEnrollmentResponseDelegate* delegate)
: DeviceManagementJobBase(
backend_impl,
DeviceManagementBackendImpl::kValueRequestAutoEnrollment,
device_id),
delegate_(delegate) {
em::DeviceManagementRequest request_wrapper;
request_wrapper.mutable_auto_enrollment_request()->CopyFrom(request);
SetPayload(request_wrapper);
}
virtual ~DeviceManagementAutoEnrollmentJob() {}
private:
// DeviceManagementJobBase overrides.
virtual void OnError(DeviceManagementBackend::ErrorCode error) OVERRIDE {
delegate_->OnError(error);
}
virtual void OnResponse(
const em::DeviceManagementResponse& response) OVERRIDE {
delegate_->HandleAutoEnrollmentResponse(
response.auto_enrollment_response());
}
DeviceManagementBackend::DeviceAutoEnrollmentResponseDelegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(DeviceManagementAutoEnrollmentJob);
};
DeviceManagementBackendImpl::DeviceManagementBackendImpl( DeviceManagementBackendImpl::DeviceManagementBackendImpl(
DeviceManagementService* service) DeviceManagementService* service)
: service_(service) { : service_(service) {
...@@ -571,6 +610,14 @@ void DeviceManagementBackendImpl::ProcessPolicyRequest( ...@@ -571,6 +610,14 @@ void DeviceManagementBackendImpl::ProcessPolicyRequest(
request, delegate)); request, delegate));
} }
void DeviceManagementBackendImpl::ProcessAutoEnrollmentRequest(
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceAutoEnrollmentResponseDelegate* delegate) {
AddJob(new DeviceManagementAutoEnrollmentJob(this, device_id, request,
delegate));
}
// static // static
const char* DeviceManagementBackendImpl::UserAffiliationToString( const char* DeviceManagementBackendImpl::UserAffiliationToString(
CloudPolicyDataStore::UserAffiliation affiliation) { CloudPolicyDataStore::UserAffiliation affiliation) {
......
...@@ -40,6 +40,7 @@ class DeviceManagementBackendImpl : public DeviceManagementBackend { ...@@ -40,6 +40,7 @@ class DeviceManagementBackendImpl : public DeviceManagementBackend {
// String constants for the device and app type we report to the server. // String constants for the device and app type we report to the server.
static const char kValueAppType[]; static const char kValueAppType[];
static const char kValueDeviceType[]; static const char kValueDeviceType[];
static const char kValueRequestAutoEnrollment[];
static const char kValueRequestPolicy[]; static const char kValueRequestPolicy[];
static const char kValueRequestRegister[]; static const char kValueRequestRegister[];
static const char kValueRequestUnregister[]; static const char kValueRequestUnregister[];
...@@ -76,6 +77,10 @@ class DeviceManagementBackendImpl : public DeviceManagementBackend { ...@@ -76,6 +77,10 @@ class DeviceManagementBackendImpl : public DeviceManagementBackend {
CloudPolicyDataStore::UserAffiliation affiliation, CloudPolicyDataStore::UserAffiliation affiliation,
const em::DevicePolicyRequest& request, const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* response_delegate) OVERRIDE; DevicePolicyResponseDelegate* response_delegate) OVERRIDE;
virtual void ProcessAutoEnrollmentRequest(
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceAutoEnrollmentResponseDelegate* delegate) OVERRIDE;
// Converts a user affiliation to the appropriate query parameter value. // Converts a user affiliation to the appropriate query parameter value.
static const char* UserAffiliationToString( static const char* UserAffiliationToString(
......
...@@ -18,4 +18,10 @@ DevicePolicyResponseDelegateMock::DevicePolicyResponseDelegateMock() {} ...@@ -18,4 +18,10 @@ DevicePolicyResponseDelegateMock::DevicePolicyResponseDelegateMock() {}
DevicePolicyResponseDelegateMock::~DevicePolicyResponseDelegateMock() {} DevicePolicyResponseDelegateMock::~DevicePolicyResponseDelegateMock() {}
DeviceAutoEnrollmentResponseDelegateMock::
DeviceAutoEnrollmentResponseDelegateMock() {}
DeviceAutoEnrollmentResponseDelegateMock::
~DeviceAutoEnrollmentResponseDelegateMock() {}
} // namespace policy } // namespace policy
...@@ -44,6 +44,17 @@ class DevicePolicyResponseDelegateMock ...@@ -44,6 +44,17 @@ class DevicePolicyResponseDelegateMock
MOCK_METHOD1(OnError, void(DeviceManagementBackend::ErrorCode error)); MOCK_METHOD1(OnError, void(DeviceManagementBackend::ErrorCode error));
}; };
class DeviceAutoEnrollmentResponseDelegateMock
: public DeviceManagementBackend::DeviceAutoEnrollmentResponseDelegate {
public:
DeviceAutoEnrollmentResponseDelegateMock();
virtual ~DeviceAutoEnrollmentResponseDelegateMock();
MOCK_METHOD1(HandleAutoEnrollmentResponse,
void(const em::DeviceAutoEnrollmentResponse&));
MOCK_METHOD1(OnError, void(DeviceManagementBackend::ErrorCode error));
};
} // namespace policy } // namespace policy
#endif // CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_BACKEND_MOCK_H_ #endif // CHROME_BROWSER_POLICY_DEVICE_MANAGEMENT_BACKEND_MOCK_H_
...@@ -6,8 +6,6 @@ ...@@ -6,8 +6,6 @@
#include "chrome/browser/policy/device_management_backend_mock.h" #include "chrome/browser/policy/device_management_backend_mock.h"
#include "chrome/browser/policy/device_management_service.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_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "content/public/common/url_fetcher.h" #include "content/public/common/url_fetcher.h"
#include "net/test/test_server.h" #include "net/test/test_server.h"
...@@ -39,6 +37,9 @@ const char kServiceResponsePolicy[] = ...@@ -39,6 +37,9 @@ const char kServiceResponsePolicy[] =
// Successful unregister response. // Successful unregister response.
const char kServiceResponseUnregister[] = const char kServiceResponseUnregister[] =
"\x08\x00\x22\x00"; "\x08\x00\x22\x00";
// Auto-enrollment response with no modulus and no hashes.
const char kServiceResponseAutoEnrollment[] = "\x42\x00";
#define PROTO_STRING(name) (std::string(name, arraysize(name) - 1)) #define PROTO_STRING(name) (std::string(name, arraysize(name) - 1))
...@@ -138,6 +139,20 @@ IN_PROC_BROWSER_TEST_F(DeviceManagementServiceIntegrationTest, ...@@ -138,6 +139,20 @@ IN_PROC_BROWSER_TEST_F(DeviceManagementServiceIntegrationTest,
MessageLoop::current()->Run(); MessageLoop::current()->Run();
} }
{
CannedResponseInterceptor interceptor(
GURL(kServiceUrl), PROTO_STRING(kServiceResponseAutoEnrollment));
DeviceAutoEnrollmentResponseDelegateMock delegate;
EXPECT_CALL(delegate, HandleAutoEnrollmentResponse(_))
.WillOnce(InvokeWithoutArgs(QuitMessageLoop));
em::DeviceAutoEnrollmentRequest request;
request.set_remainder(0);
request.set_modulus(1);
backend->ProcessAutoEnrollmentRequest("testid", request, &delegate);
MessageLoop::current()->Run();
}
} }
IN_PROC_BROWSER_TEST_F(DeviceManagementServiceIntegrationTest, IN_PROC_BROWSER_TEST_F(DeviceManagementServiceIntegrationTest,
...@@ -189,6 +204,18 @@ IN_PROC_BROWSER_TEST_F(DeviceManagementServiceIntegrationTest, ...@@ -189,6 +204,18 @@ IN_PROC_BROWSER_TEST_F(DeviceManagementServiceIntegrationTest,
MessageLoop::current()->Run(); MessageLoop::current()->Run();
} }
{
DeviceAutoEnrollmentResponseDelegateMock delegate;
EXPECT_CALL(delegate, HandleAutoEnrollmentResponse(_))
.WillOnce(InvokeWithoutArgs(QuitMessageLoop));
em::DeviceAutoEnrollmentRequest request;
request.set_modulus(1);
request.set_remainder(0);
backend->ProcessAutoEnrollmentRequest("testid", request, &delegate);
MessageLoop::current()->Run();
}
} }
} // namespace policy } // namespace policy
...@@ -165,6 +165,23 @@ TEST_P(DeviceManagementServiceFailedRequestTest, PolicyRequest) { ...@@ -165,6 +165,23 @@ TEST_P(DeviceManagementServiceFailedRequestTest, PolicyRequest) {
fetcher->delegate()->OnURLFetchComplete(fetcher); fetcher->delegate()->OnURLFetchComplete(fetcher);
} }
TEST_P(DeviceManagementServiceFailedRequestTest, AutoEnrollmentRequest) {
DeviceAutoEnrollmentResponseDelegateMock mock;
EXPECT_CALL(mock, OnError(GetParam().expected_error_));
em::DeviceAutoEnrollmentRequest request;
request.set_modulus(1);
request.set_remainder(0);
backend_->ProcessAutoEnrollmentRequest(kDeviceId, request, &mock);
TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
ASSERT_TRUE(fetcher);
fetcher->set_url(GURL(kServiceUrl));
fetcher->set_status(GetParam().request_status_);
fetcher->set_response_code(GetParam().http_status_);
fetcher->SetResponseString(GetParam().response_);
fetcher->delegate()->OnURLFetchComplete(fetcher);
}
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
DeviceManagementServiceFailedRequestTestInstance, DeviceManagementServiceFailedRequestTestInstance,
DeviceManagementServiceFailedRequestTest, DeviceManagementServiceFailedRequestTest,
......
...@@ -49,6 +49,11 @@ class MockDeviceManagementBackend : public DeviceManagementBackend { ...@@ -49,6 +49,11 @@ class MockDeviceManagementBackend : public DeviceManagementBackend {
const em::DevicePolicyRequest& request, const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* delegate)); DevicePolicyResponseDelegate* delegate));
MOCK_METHOD3(ProcessAutoEnrollmentRequest, void(
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceAutoEnrollmentResponseDelegate* delegate));
private: private:
DISALLOW_COPY_AND_ASSIGN(MockDeviceManagementBackend); DISALLOW_COPY_AND_ASSIGN(MockDeviceManagementBackend);
}; };
......
...@@ -41,6 +41,13 @@ void ProxyDeviceManagementBackend::ProcessPolicyRequest( ...@@ -41,6 +41,13 @@ void ProxyDeviceManagementBackend::ProcessPolicyRequest(
affiliation, request, delegate); affiliation, request, delegate);
} }
void ProxyDeviceManagementBackend::ProcessAutoEnrollmentRequest(
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceAutoEnrollmentResponseDelegate* delegate) {
backend_->ProcessAutoEnrollmentRequest(device_id, request, delegate);
}
MockDeviceManagementService::MockDeviceManagementService() MockDeviceManagementService::MockDeviceManagementService()
: DeviceManagementService("") {} : DeviceManagementService("") {}
......
...@@ -42,6 +42,10 @@ class ProxyDeviceManagementBackend : public DeviceManagementBackend { ...@@ -42,6 +42,10 @@ class ProxyDeviceManagementBackend : public DeviceManagementBackend {
CloudPolicyDataStore::UserAffiliation affiliation, CloudPolicyDataStore::UserAffiliation affiliation,
const em::DevicePolicyRequest& request, const em::DevicePolicyRequest& request,
DevicePolicyResponseDelegate* delegate) OVERRIDE; DevicePolicyResponseDelegate* delegate) OVERRIDE;
virtual void ProcessAutoEnrollmentRequest(
const std::string& device_id,
const em::DeviceAutoEnrollmentRequest& request,
DeviceAutoEnrollmentResponseDelegate* delegate) OVERRIDE;
private: private:
DeviceManagementBackend* backend_; // weak DeviceManagementBackend* backend_; // weak
......
...@@ -44,6 +44,7 @@ Example: ...@@ -44,6 +44,7 @@ Example:
""" """
import cgi import cgi
import hashlib
import logging import logging
import os import os
import random import random
...@@ -71,6 +72,9 @@ import chrome_device_policy_pb2 as dp ...@@ -71,6 +72,9 @@ import chrome_device_policy_pb2 as dp
# ASN.1 object identifier for PKCS#1/RSA. # ASN.1 object identifier for PKCS#1/RSA.
PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01' PKCS1_RSA_OID = '\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01'
# SHA256 sum of "0".
SHA256_0 = hashlib.sha256('0').digest()
class RequestHandler(object): class RequestHandler(object):
"""Decodes and handles device management requests from clients. """Decodes and handles device management requests from clients.
...@@ -144,6 +148,8 @@ class RequestHandler(object): ...@@ -144,6 +148,8 @@ class RequestHandler(object):
return self.ProcessUnregister(rmsg.unregister_request) return self.ProcessUnregister(rmsg.unregister_request)
elif request_type == 'policy' or request_type == 'ping': elif request_type == 'policy' or request_type == 'ping':
return self.ProcessPolicy(rmsg.policy_request, request_type) return self.ProcessPolicy(rmsg.policy_request, request_type)
elif request_type == 'enterprise_check':
return self.ProcessAutoEnrollment(rmsg.auto_enrollment_request)
else: else:
return (400, 'Invalid request parameter') return (400, 'Invalid request parameter')
...@@ -254,6 +260,39 @@ class RequestHandler(object): ...@@ -254,6 +260,39 @@ class RequestHandler(object):
else: else:
return (400, 'Invalid policy_type') return (400, 'Invalid policy_type')
def ProcessAutoEnrollment(self, msg):
"""Handles an auto-enrollment check request.
The reply depends on the value of the modulus:
1: replies with no new modulus and the sha256 hash of "0"
2: replies with a new modulus, 4.
4: replies with a new modulus, 2.
8: fails with error 400.
anything else: replies with no new modulus and an empty list of hashes
These allow the client to pick the testing scenario its wants to simulate.
Args:
msg: The DeviceAutoEnrollmentRequest message received from the client.
Returns:
A tuple of HTTP status code and response data to send to the client.
"""
auto_enrollment_response = dm.DeviceAutoEnrollmentResponse()
if msg.modulus == 1:
auto_enrollment_response.hashes.append(SHA256_0)
elif msg.modulus == 2:
auto_enrollment_response.modulus = 4
elif msg.modulus == 4:
auto_enrollment_response.modulus = 2
elif msg.modulus == 8:
return (400, 'Server error')
response = dm.DeviceManagementResponse()
response.auto_enrollment_response.CopyFrom(auto_enrollment_response)
return (200, response.SerializeToString())
def SetProtobufMessageField(self, group_message, field, field_value): def SetProtobufMessageField(self, group_message, field, field_value):
'''Sets a field in a protobuf message. '''Sets a field in a protobuf message.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment