Download via HTTP only if enterprise policy allows.
In order to rollout HTTP-downloads for AU to stable channel, we want to
be a bit more conservative to preseve the defense in depth we have now
with HTTPS. So, we're introduced a new enterprise policy which should be
explicitly enabled in order for the payloads to be downloaded via HTTP.
This CL adds the support for honoring such a policy in update engine.
BUG=chromium:235562
TEST=New unit tests added, existing ones updated and they all pass.
TEST=Tested on ZGB with and without policy and it works as expected.
Change-Id: I356efbe237b10031161a57c70cb851c521915a76
Reviewed-on: https://gerrit.chromium.org/gerrit/55805
Reviewed-by: Chris Sosa <[email protected]>
Tested-by: Jay Srinivasan <[email protected]>
Commit-Queue: Jay Srinivasan <[email protected]>
diff --git a/payload_state.cc b/payload_state.cc
index 5ab6028..3de9e04 100644
--- a/payload_state.cc
+++ b/payload_state.cc
@@ -67,6 +67,12 @@
// Always store the latest response.
response_ = omaha_response;
+ // Compute the candidate URLs first as they are used to calculate the
+ // response signature so that a change in enterprise policy for
+ // HTTP downloads being enabled or not could be honored as soon as the
+ // next update check happens.
+ ComputeCandidateUrls();
+
// Check if the "signature" of this response (i.e. the fields we care about)
// has changed.
string new_response_signature = CalculateResponseSignature();
@@ -85,7 +91,7 @@
// we loaded from the persisted state is a valid value. If the response
// hasn't changed but the URL index is invalid, it's indicative of some
// tampering of the persisted state.
- if (url_index_ >= GetNumUrls()) {
+ if (static_cast<uint32_t>(url_index_) >= candidate_urls_.size()) {
LOG(INFO) << "Resetting all payload state as the url index seems to have "
"been tampered with";
ResetPersistedState();
@@ -152,8 +158,9 @@
LOG(INFO) << "Updating payload state for error code: " << base_error
<< " (" << utils::CodeToString(base_error) << ")";
- if (GetNumUrls() == 0) {
- // This means we got this error even before we got a valid Omaha response.
+ if (candidate_urls_.size() == 0) {
+ // This means we got this error even before we got a valid Omaha response
+ // or don't have any valid candidates in the Omaha response.
// So we should not advance the url_index_ in such cases.
LOG(INFO) << "Ignoring failures until we get a valid Omaha response.";
return;
@@ -307,18 +314,19 @@
void PayloadState::IncrementUrlIndex() {
uint32_t next_url_index = GetUrlIndex() + 1;
- if (next_url_index < GetNumUrls()) {
+ if (next_url_index < candidate_urls_.size()) {
LOG(INFO) << "Incrementing the URL index for next attempt";
SetUrlIndex(next_url_index);
} else {
LOG(INFO) << "Resetting the current URL index (" << GetUrlIndex() << ") to "
- << "0 as we only have " << GetNumUrls() << " URL(s)";
+ << "0 as we only have " << candidate_urls_.size()
+ << " candidate URL(s)";
SetUrlIndex(0);
IncrementPayloadAttemptNumber();
}
// If we have multiple URLs, record that we just switched to another one
- if (GetNumUrls() > 1)
+ if (candidate_urls_.size() > 1)
SetUrlSwitchCount(url_switch_count_ + 1);
// Whenever we update the URL index, we should also clear the URL failure
@@ -377,8 +385,8 @@
void PayloadState::UpdateCurrentDownloadSource() {
current_download_source_ = kNumDownloadSources;
- if (GetUrlIndex() < response_.payload_urls.size()) {
- string current_url = response_.payload_urls[GetUrlIndex()];
+ if (GetUrlIndex() < candidate_urls_.size()) {
+ string current_url = candidate_urls_[GetUrlIndex()];
if (StartsWithASCII(current_url, "https://", false))
current_download_source_ = kDownloadSourceHttpsServer;
else if (StartsWithASCII(current_url, "http://", false))
@@ -552,11 +560,11 @@
string PayloadState::CalculateResponseSignature() {
string response_sign = StringPrintf("NumURLs = %d\n",
- response_.payload_urls.size());
+ candidate_urls_.size());
- for (size_t i = 0; i < response_.payload_urls.size(); i++)
- response_sign += StringPrintf("Url%d = %s\n",
- i, response_.payload_urls[i].c_str());
+ for (size_t i = 0; i < candidate_urls_.size(); i++)
+ response_sign += StringPrintf("Candidate Url%d = %s\n",
+ i, candidate_urls_[i].c_str());
response_sign += StringPrintf("Payload Size = %llu\n"
"Payload Sha256 Hash = %s\n"
@@ -875,4 +883,31 @@
<< GetTotalBytesDownloaded(source);
}
+void PayloadState::ComputeCandidateUrls() {
+ bool http_url_ok = false;
+
+ if (system_state_->IsOfficialBuild()) {
+ const policy::DevicePolicy* policy = system_state_->device_policy();
+ if (!(policy && policy->GetHttpDownloadsEnabled(&http_url_ok) &&
+ http_url_ok))
+ LOG(INFO) << "Downloads via HTTP Url are not enabled by device policy";
+ } else {
+ LOG(INFO) << "Allowing HTTP downloads for unofficial builds";
+ http_url_ok = true;
+ }
+
+ candidate_urls_.clear();
+ for (size_t i = 0; i < response_.payload_urls.size(); i++) {
+ string candidate_url = response_.payload_urls[i];
+ if (StartsWithASCII(candidate_url, "http://", false) && !http_url_ok)
+ continue;
+ candidate_urls_.push_back(candidate_url);
+ LOG(INFO) << "Candidate Url" << (candidate_urls_.size() - 1)
+ << ": " << candidate_url;
+ }
+
+ LOG(INFO) << "Found " << candidate_urls_.size() << " candidate URLs "
+ << "out of " << response_.payload_urls.size() << " URLs supplied";
+}
+
} // namespace chromeos_update_engine