blob: a181542c3f1ff328308ef635f36e3faedb51d90a [file] [log] [blame]
Darin Petkov7ed561b2011-10-04 02:59:03 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
adlr@google.com3defe6a2009-12-04 20:57:17 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "update_engine/omaha_response_handler_action.h"
Darin Petkov73058b42010-10-06 16:32:19 -07006
adlr@google.com3defe6a2009-12-04 20:57:17 +00007#include <string>
Darin Petkov73058b42010-10-06 16:32:19 -07008
9#include <base/logging.h>
Jay Srinivasan738fdf32012-12-07 17:40:54 -080010#include "base/string_util.h"
Darin Petkov73058b42010-10-06 16:32:19 -070011
Darin Petkov0406e402010-10-06 21:33:11 -070012#include "update_engine/delta_performer.h"
Darin Petkov73058b42010-10-06 16:32:19 -070013#include "update_engine/prefs_interface.h"
adlr@google.com3defe6a2009-12-04 20:57:17 +000014#include "update_engine/utils.h"
15
16using std::string;
17
18namespace chromeos_update_engine {
19
Darin Petkov6c118642010-10-21 12:06:30 -070020const char OmahaResponseHandlerAction::kDeadlineFile[] =
21 "/tmp/update-check-response-deadline";
22
Darin Petkovabc7bc02011-02-23 14:39:43 -080023OmahaResponseHandlerAction::OmahaResponseHandlerAction(PrefsInterface* prefs)
24 : prefs_(prefs),
25 got_no_update_response_(false),
26 key_path_(DeltaPerformer::kUpdatePayloadPublicKeyPath) {}
27
adlr@google.com3defe6a2009-12-04 20:57:17 +000028void OmahaResponseHandlerAction::PerformAction() {
29 CHECK(HasInputObject());
30 ScopedActionCompleter completer(processor_, this);
Darin Petkov6a5b3222010-07-13 14:55:28 -070031 const OmahaResponse& response = GetInputObject();
adlr@google.com3defe6a2009-12-04 20:57:17 +000032 if (!response.update_exists) {
Andrew de los Reyes4fe15d02009-12-10 19:01:36 -080033 got_no_update_response_ = true;
adlr@google.com3defe6a2009-12-04 20:57:17 +000034 LOG(INFO) << "There are no updates. Aborting.";
35 return;
36 }
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070037 install_plan_.download_url = response.codebase;
Jay Srinivasan51dcf262012-09-13 17:24:32 -070038 install_plan_.payload_size = response.size;
39 install_plan_.payload_hash = response.hash;
Jay Srinivasanf4318702012-09-24 11:56:24 -070040 install_plan_.metadata_size = response.metadata_size;
41 install_plan_.metadata_signature = response.metadata_signature;
Jay Srinivasan738fdf32012-12-07 17:40:54 -080042 install_plan_.hash_checks_mandatory = AreHashChecksMandatory(response);
Darin Petkov0406e402010-10-06 21:33:11 -070043 install_plan_.is_resume =
44 DeltaPerformer::CanResumeUpdate(prefs_, response.hash);
45 if (!install_plan_.is_resume) {
Darin Petkov9b230572010-10-08 10:20:09 -070046 LOG_IF(WARNING, !DeltaPerformer::ResetUpdateProgress(prefs_, false))
Darin Petkov0406e402010-10-06 21:33:11 -070047 << "Unable to reset the update progress.";
48 LOG_IF(WARNING, !prefs_->SetString(kPrefsUpdateCheckResponseHash,
49 response.hash))
50 << "Unable to save the update check response hash.";
51 }
52
adlr@google.com3defe6a2009-12-04 20:57:17 +000053 TEST_AND_RETURN(GetInstallDev(
54 (!boot_device_.empty() ? boot_device_ : utils::BootDevice()),
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070055 &install_plan_.install_path));
56 install_plan_.kernel_install_path =
57 utils::BootKernelDevice(install_plan_.install_path);
adlr@google.com3defe6a2009-12-04 20:57:17 +000058
Andrew de los Reyesf98bff82010-05-06 13:33:25 -070059 TEST_AND_RETURN(HasOutputPipe());
adlr@google.com3defe6a2009-12-04 20:57:17 +000060 if (HasOutputPipe())
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070061 SetOutputObject(install_plan_);
adlr@google.com3defe6a2009-12-04 20:57:17 +000062 LOG(INFO) << "Using this install plan:";
Andrew de los Reyes63b96d72010-05-10 13:08:54 -070063 install_plan_.Dump();
Darin Petkov6a5b3222010-07-13 14:55:28 -070064
Darin Petkov6c118642010-10-21 12:06:30 -070065 // Send the deadline data (if any) to Chrome through a file. This is a pretty
66 // hacky solution but should be OK for now.
67 //
68 // TODO(petkov): Rearchitect this to avoid communication through a
69 // file. Ideallly, we would include this information in D-Bus's GetStatus
70 // method and UpdateStatus signal. A potential issue is that update_engine may
71 // be unresponsive during an update download.
72 utils::WriteFile(kDeadlineFile,
73 response.deadline.data(),
74 response.deadline.size());
75 chmod(kDeadlineFile, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
76
Darin Petkovc1a8b422010-07-19 11:34:49 -070077 completer.set_code(kActionCodeSuccess);
adlr@google.com3defe6a2009-12-04 20:57:17 +000078}
79
80bool OmahaResponseHandlerAction::GetInstallDev(const std::string& boot_dev,
81 std::string* install_dev) {
Andrew de los Reyesf98bff82010-05-06 13:33:25 -070082 TEST_AND_RETURN_FALSE(utils::StringHasPrefix(boot_dev, "/dev/"));
adlr@google.com3defe6a2009-12-04 20:57:17 +000083 string ret(boot_dev);
Andrew de los Reyesf98bff82010-05-06 13:33:25 -070084 string::reverse_iterator it = ret.rbegin(); // last character in string
85 // Right now, we just switch '3' and '5' partition numbers.
86 TEST_AND_RETURN_FALSE((*it == '3') || (*it == '5'));
87 *it = (*it == '3') ? '5' : '3';
adlr@google.com3defe6a2009-12-04 20:57:17 +000088 *install_dev = ret;
89 return true;
90}
91
Jay Srinivasan738fdf32012-12-07 17:40:54 -080092bool OmahaResponseHandlerAction::AreHashChecksMandatory(
93 const OmahaResponse& response) {
94 // All our internal testing uses dev server which doesn't generate metadata
95 // signatures yet. So, in order not to break image_to_live or other AU tools,
96 // we should waive the hash checks for those cases. Since all internal
97 // testing is done using a dev_image or test_image, we can use that as a
98 // criteria for waiving. This criteria reduces the attack surface as
99 // opposed to waiving the checks when we're in dev mode, because we do want
100 // to enforce the hash checks when our end customers run in dev mode if they
101 // are using an official build, so that they are protected more.
102 if (!utils::IsOfficialBuild()) {
103 LOG(INFO) << "Waiving payload hash checks for unofficial builds";
104 return false;
105 }
106
107 // TODO(jaysri): VALIDATION: For official builds, we currently waive hash
108 // checks for HTTPS until we have rolled out at least once and are confident
109 // nothing breaks. chromium-os:37082 tracks turning this on for HTTPS
110 // eventually.
111 if (StartsWithASCII(response.codebase, "https://", false)) {
112 LOG(INFO) << "Waiving payload hash checks since Omaha response "
113 << "only has HTTPS URL(s)";
114 return false;
115 }
116
117 // No exceptions apply. So hash checks are mandatory, by default.
118 LOG(INFO) << "Mandating payload hash checks since Omaha response "
119 << "contains HTTP URL(s)";
120 return true;
121}
122
adlr@google.com3defe6a2009-12-04 20:57:17 +0000123} // namespace chromeos_update_engine