Skip to content
This repository has been archived by the owner on Apr 13, 2023. It is now read-only.

Commit

Permalink
Enable Initial Enrollment for official builds and detect outdated server
Browse files Browse the repository at this point in the history
This enables Initial Enrollment by default for official builds.
Also, this adds functionality to detect a server which does not support
Initial Enrollment by comparing against a maximal expected modulus
value.

Bug: 839353
Test: unit_tests --gtest_filter=AutoEnrollmentClient*
Change-Id: I1b64ab2875c7317dc92c74276173e27b1c58bbe2
Reviewed-on: https://chromium-review.googlesource.com/1073309
Reviewed-by: Maksim Ivanov <emaxx@chromium.org>
Commit-Queue: Pavol Marko <pmarko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#562143}
  • Loading branch information
Pavol Marko authored and Commit Bot committed May 27, 2018
1 parent d6afac5 commit 83a6b57
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 10 deletions.
Expand Up @@ -31,6 +31,16 @@ namespace {
// enrollment check.
const int kInitialEnrollmentModulusPowerLimit = 6;

// If the modulus requested by the server is higher or equal to
// |1<<kInitialEnrollmentModulusPowerOutdatedServer|, assume that the server
// does not know initial enrollment yet.
// This is currently set to |14|, the server was requesting |16| for FRE on
// 2018-05-25.
// TODO(pmarko): Remove this mechanism when the server version supporting
// Initial Enrollment has been in production for a while
// (https://crbug.com/846645).
const int kInitialEnrollmentModulusPowerOutdatedServer = 14;

// Maximum time to wait before forcing a decision. Note that download time for
// state key buckets can be non-negligible, especially on 2G connections.
const int kSafeguardTimeoutSeconds = 90;
Expand Down Expand Up @@ -142,7 +152,7 @@ bool AutoEnrollmentController::IsInitialEnrollmentEnabled() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();

if (!command_line->HasSwitch(switches::kEnterpriseEnableInitialEnrollment))
return false;
return IsOfficialChrome();

std::string command_line_mode = command_line->GetSwitchValueASCII(
switches::kEnterpriseEnableInitialEnrollment);
Expand Down Expand Up @@ -476,7 +486,8 @@ void AutoEnrollmentController::StartClientForInitialEnrollment() {
weak_ptr_factory_.GetWeakPtr()),
service, g_browser_process->local_state(),
g_browser_process->system_request_context(), serial_number,
rlz_brand_code, power_initial, power_limit);
rlz_brand_code, power_initial, power_limit,
kInitialEnrollmentModulusPowerOutdatedServer);

VLOG(1) << "Starting auto-enrollment client for Initial Enrollment.";
client_->Start();
Expand Down
9 changes: 8 additions & 1 deletion chrome/browser/chromeos/policy/auto_enrollment_client.h
Expand Up @@ -77,6 +77,12 @@ class AutoEnrollmentClient {
// the protocol will be cached in |local_state|. |power_initial| and
// |power_limit| are exponents of power-of-2 values which will be the
// initial modulus and the maximum modulus used by this client.
// If the modulus requested by the server is higher or equal than
// |1<<power_outdated_server_detect|, the client will assume that the server
// is outdated and that no Initial Enrollment should happen.
// TODO(pmarko): Remove |power_outdated_server_detect| when the server
// version supporting Initial Enrollment has been in production for a while
// (https://crbug.com/846645).
virtual std::unique_ptr<AutoEnrollmentClient> CreateForInitialEnrollment(
const ProgressCallback& progress_callback,
DeviceManagementService* device_management_service,
Expand All @@ -85,7 +91,8 @@ class AutoEnrollmentClient {
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit) = 0;
int power_limit,
int power_outdated_server_detect) = 0;
};

virtual ~AutoEnrollmentClient() {}
Expand Down
26 changes: 23 additions & 3 deletions chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
Expand Up @@ -348,7 +348,7 @@ AutoEnrollmentClientImpl::FactoryImpl::CreateForFRE(
std::make_unique<DeviceIdentifierProviderFRE>(server_backed_state_key),
std::make_unique<StateDownloadMessageProcessorFRE>(
server_backed_state_key),
power_initial, power_limit, kUMASuffixFRE));
power_initial, power_limit, base::nullopt, kUMASuffixFRE));
}

std::unique_ptr<AutoEnrollmentClient>
Expand All @@ -360,15 +360,18 @@ AutoEnrollmentClientImpl::FactoryImpl::CreateForInitialEnrollment(
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit) {
int power_limit,
int power_outdated_server_detect) {
return base::WrapUnique(new AutoEnrollmentClientImpl(
progress_callback, device_management_service, local_state,
system_request_context,
std::make_unique<DeviceIdentifierProviderInitialEnrollment>(
device_serial_number, device_brand_code),
std::make_unique<StateDownloadMessageProcessorInitialEnrollment>(
device_serial_number, device_brand_code),
power_initial, power_limit, kUMASuffixInitialEnrollment));
power_initial, power_limit,
base::make_optional(power_outdated_server_detect),
kUMASuffixInitialEnrollment));
}

AutoEnrollmentClientImpl::~AutoEnrollmentClientImpl() {
Expand Down Expand Up @@ -440,6 +443,7 @@ AutoEnrollmentClientImpl::AutoEnrollmentClientImpl(
state_download_message_processor,
int power_initial,
int power_limit,
base::Optional<int> power_outdated_server_detect,
std::string uma_suffix)
: progress_callback_(callback),
state_(AUTO_ENROLLMENT_STATE_IDLE),
Expand All @@ -448,6 +452,7 @@ AutoEnrollmentClientImpl::AutoEnrollmentClientImpl(
device_id_(base::GenerateGUID()),
current_power_(power_initial),
power_limit_(power_limit),
power_outdated_server_detect_(power_outdated_server_detect),
modulus_updates_received_(0),
device_management_service_(service),
local_state_(local_state),
Expand Down Expand Up @@ -641,6 +646,21 @@ bool AutoEnrollmentClientImpl::OnBucketDownloadRequestCompletion(
LOG(ERROR) << "Auto enrollment error: already retried with an updated "
<< "modulus but the server asked for a new one again: "
<< power;
} else if (power_outdated_server_detect_.has_value() &&
power >= power_outdated_server_detect_.value()) {
LOG(ERROR) << "Skipping auto enrollment: The server was detected as "
<< "outdated (power=" << power
<< ", power_outdated_server_detect="
<< power_outdated_server_detect_.value() << ").";
has_server_state_ = false;
// Cache the decision in local_state, so that it is reused in case
// the device reboots before completing OOBE. Note that this does not
// disable Forced Re-Enrollment for this device, because local state will
// be empty after the device is wiped.
local_state_->SetBoolean(prefs::kShouldAutoEnroll, false);
local_state_->SetInteger(prefs::kAutoEnrollmentPowerLimit, power_limit_);
local_state_->CommitPendingWrite();
return true;
} else if (power > power_limit_) {
LOG(ERROR) << "Auto enrollment error: the server asked for a larger "
<< "modulus than the client accepts (" << power << " vs "
Expand Down
10 changes: 9 additions & 1 deletion chrome/browser/chromeos/policy/auto_enrollment_client_impl.h
Expand Up @@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
Expand Down Expand Up @@ -71,7 +72,8 @@ class AutoEnrollmentClientImpl
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit) override;
int power_limit,
int power_outdated_server_detect) override;

private:
DISALLOW_COPY_AND_ASSIGN(FactoryImpl);
Expand Down Expand Up @@ -108,6 +110,7 @@ class AutoEnrollmentClientImpl
state_download_message_processor,
int power_initial,
int power_limit,
base::Optional<int> power_outdated_server_detect,
std::string uma_suffix);

// Tries to load the result of a previous execution of the protocol from
Expand Down Expand Up @@ -183,6 +186,11 @@ class AutoEnrollmentClientImpl
// a retry response from the server.
int power_limit_;

// If set and the modulus requested by the server is higher than
// |1<<power_outdated_server_detect|, this client will assume that the server
// is outdated.
base::Optional<int> power_outdated_server_detect_;

// Number of requests for a different modulus received from the server.
// Used to determine if the server keeps asking for different moduli.
int modulus_updates_received_;
Expand Down
Expand Up @@ -47,6 +47,11 @@ const char kInitialEnrollmentIdHash[] = "\x30\x18\xb7\x0f\x76\x09\xc5\xc7";

const int kInitialEnrollmentIdHashLength = 8;

// This is modulus power value used in initial enrollment to detect that the
// server is outdated and does not support initial enrollment. See the
// |DetectOutdatedServer| test case.
const int kInitialEnrollmentModulusPowerOutdatedServer = 14;

using ::testing::InSequence;
using ::testing::Mock;
using ::testing::SaveArg;
Expand Down Expand Up @@ -93,7 +98,8 @@ class AutoEnrollmentClientImplTest
AutoEnrollmentClientImpl::FactoryImpl().CreateForInitialEnrollment(
progress_callback, service_.get(), local_state_,
url_request_context_getter, kSerialNumber, kBrandCode,
power_initial, power_limit);
power_initial, power_limit,
kInitialEnrollmentModulusPowerOutdatedServer);
}
}

Expand Down Expand Up @@ -398,6 +404,31 @@ TEST_P(AutoEnrollmentClientImplTest, AskForTooMuch) {
EXPECT_FALSE(HasServerBackedState());
}

TEST_P(AutoEnrollmentClientImplTest, DetectOutdatedServer) {
CreateClient(0, kInitialEnrollmentModulusPowerOutdatedServer + 1);
InSequence sequence;
ServerWillReply(1 << kInitialEnrollmentModulusPowerOutdatedServer, false,
false);

if (GetParam() == AutoEnrollmentProtocol::kInitialEnrollment) {
// For initial enrollment, a modulus power higher or equal to
// |kInitialEnrollmentModulusPowerOutdatedServer| means that the client will
// detect the server as outdated and will skip enrollment.
client()->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
EXPECT_TRUE(HasCachedDecision());
EXPECT_FALSE(HasServerBackedState());
} else {
// For FRE, such a detection does not exist. The client will do the second
// round and upload bits of its device identifier hash.
ServerWillReply(-1, false, false);
client()->Start();
EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
EXPECT_TRUE(HasCachedDecision());
EXPECT_FALSE(HasServerBackedState());
}
}

TEST_P(AutoEnrollmentClientImplTest, AskNonPowerOf2) {
InSequence sequence;
ServerWillReply(100, false, false);
Expand Down Expand Up @@ -540,6 +571,12 @@ TEST_P(AutoEnrollmentClientImplTest, ManyBitsUploaded) {
}

TEST_P(AutoEnrollmentClientImplTest, MoreThan32BitsUploaded) {
// Skip for initial enrollment, because the outdated server detection would
// kick in when more than |kInitialEnrollmentModulusPowerOutdatedServer| bits
// are requested.
if (GetParam() == AutoEnrollmentProtocol::kInitialEnrollment)
return;

CreateClient(10, 37);
InSequence sequence;
ServerWillReply(INT64_C(1) << 37, false, false);
Expand Down
Expand Up @@ -37,7 +37,8 @@ FakeAutoEnrollmentClient::FactoryImpl::CreateForInitialEnrollment(
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit) {
int power_limit,
int power_outdated_server_detect) {
std::unique_ptr<FakeAutoEnrollmentClient> fake_client =
std::make_unique<FakeAutoEnrollmentClient>(progress_callback);
fake_client_created_callback_.Run(fake_client.get());
Expand Down
3 changes: 2 additions & 1 deletion chrome/browser/chromeos/policy/fake_auto_enrollment_client.h
Expand Up @@ -51,7 +51,8 @@ class FakeAutoEnrollmentClient : public AutoEnrollmentClient {
const std::string& device_serial_number,
const std::string& device_brand_code,
int power_initial,
int power_limit) override;
int power_limit,
int power_outdated_server_detect) override;

private:
base::RepeatingCallback<void(FakeAutoEnrollmentClient*)>
Expand Down

0 comments on commit 83a6b57

Please sign in to comment.