blob: abbd0120a6dc934f9a3f2f70d8c7efd7e612a5c7 [file] [log] [blame]
Darin Petkovf2065b42011-05-17 16:36:27 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Darin Petkova4a8a8c2010-07-15 22:21:12 -07002// 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_request_params.h"
6
7#include <errno.h>
8#include <fcntl.h>
9#include <sys/utsname.h>
10
11#include <map>
12#include <string>
Darin Petkova3df55b2010-11-15 13:33:55 -080013#include <vector>
Darin Petkova4a8a8c2010-07-15 22:21:12 -070014
Ben Chan06c76a42014-09-05 08:21:06 -070015#include <base/files/file_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070016#include <base/strings/string_util.h>
Alex Deymo2b4e2a52014-09-23 12:05:56 -070017#include <chromeos/key_value_store.h>
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020018#include <policy/device_policy.h>
Darin Petkov49d91322010-10-25 16:34:58 -070019
Chris Sosabe45bef2013-04-09 18:25:12 -070020#include "update_engine/constants.h"
J. Richard Barnette522d36f2013-10-28 17:22:12 -070021#include "update_engine/hardware_interface.h"
Jay Srinivasanae4697c2013-03-18 17:08:08 -070022#include "update_engine/system_state.h"
Darin Petkova4a8a8c2010-07-15 22:21:12 -070023#include "update_engine/utils.h"
24
Darin Petkov49d91322010-10-25 16:34:58 -070025#define CALL_MEMBER_FN(object, member) ((object).*(member))
26
Darin Petkova4a8a8c2010-07-15 22:21:12 -070027using std::map;
28using std::string;
Darin Petkova3df55b2010-11-15 13:33:55 -080029using std::vector;
Darin Petkova4a8a8c2010-07-15 22:21:12 -070030
Darin Petkova4a8a8c2010-07-15 22:21:12 -070031namespace chromeos_update_engine {
32
David Pursell02c18642014-11-06 11:26:11 -080033const char kProductionOmahaUrl[] =
34 "https://tools.google.com/service/update2";
35const char kAUTestOmahaUrl[] =
36 "https://omaha.sandbox.google.com/service/update2";
Darin Petkov5a7f5652010-07-22 21:40:09 -070037
David Pursell02c18642014-11-06 11:26:11 -080038const char OmahaRequestParams::kAppId[] =
39 "{87efface-864d-49a5-9bb3-4b050a7c227a}";
40const char OmahaRequestParams::kOsPlatform[] = "Chrome OS";
41const char OmahaRequestParams::kOsVersion[] = "Indy";
42const char OmahaRequestParams::kUpdateChannelKey[] = "CHROMEOS_RELEASE_TRACK";
43const char OmahaRequestParams::kIsPowerwashAllowedKey[] =
44 "CHROMEOS_IS_POWERWASH_ALLOWED";
45const char OmahaRequestParams::kAutoUpdateServerKey[] = "CHROMEOS_AUSERVER";
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020046
Jay Srinivasanae4697c2013-03-18 17:08:08 -070047const char* kChannelsByStability[] = {
48 // This list has to be sorted from least stable to most stable channel.
49 "canary-channel",
50 "dev-channel",
51 "beta-channel",
52 "stable-channel",
53};
Darin Petkov49d91322010-10-25 16:34:58 -070054
Alex Deymof329b932014-10-30 01:37:48 -070055bool OmahaRequestParams::Init(const string& in_app_version,
56 const string& in_update_url,
Jay Srinivasanae4697c2013-03-18 17:08:08 -070057 bool in_interactive) {
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070058 LOG(INFO) << "Initializing parameters for this update attempt";
Jay Srinivasanae4697c2013-03-18 17:08:08 -070059 InitFromLsbValue();
Darin Petkov10d02dd2011-01-10 14:57:39 -080060 bool stateful_override = !ShouldLockDown();
Jay Srinivasanae4697c2013-03-18 17:08:08 -070061 os_platform_ = OmahaRequestParams::kOsPlatform;
62 os_version_ = OmahaRequestParams::kOsVersion;
63 app_version_ = in_app_version.empty() ?
Alex Vakulenko88b591f2014-08-28 16:48:57 -070064 GetLsbValue("CHROMEOS_RELEASE_VERSION", "", nullptr, stateful_override) :
Darin Petkov10d02dd2011-01-10 14:57:39 -080065 in_app_version;
Jay Srinivasanae4697c2013-03-18 17:08:08 -070066 os_sp_ = app_version_ + "_" + GetMachineType();
67 os_board_ = GetLsbValue("CHROMEOS_RELEASE_BOARD",
68 "",
Alex Vakulenko88b591f2014-08-28 16:48:57 -070069 nullptr,
Jay Srinivasanae4697c2013-03-18 17:08:08 -070070 stateful_override);
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070071 string release_app_id = GetLsbValue("CHROMEOS_RELEASE_APPID",
72 OmahaRequestParams::kAppId,
Alex Vakulenko88b591f2014-08-28 16:48:57 -070073 nullptr,
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070074 stateful_override);
Jay Srinivasanae4697c2013-03-18 17:08:08 -070075 board_app_id_ = GetLsbValue("CHROMEOS_BOARD_APPID",
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070076 release_app_id,
Alex Vakulenko88b591f2014-08-28 16:48:57 -070077 nullptr,
Jay Srinivasanae4697c2013-03-18 17:08:08 -070078 stateful_override);
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070079 canary_app_id_ = GetLsbValue("CHROMEOS_CANARY_APPID",
80 release_app_id,
Alex Vakulenko88b591f2014-08-28 16:48:57 -070081 nullptr,
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070082 stateful_override);
Jay Srinivasanae4697c2013-03-18 17:08:08 -070083 app_lang_ = "en-US";
J. Richard Barnette522d36f2013-10-28 17:22:12 -070084 hwid_ = system_state_->hardware()->GetHardwareClass();
Chris Sosac1972482013-04-30 22:31:10 -070085 if (CollectECFWVersions()) {
J. Richard Barnette522d36f2013-10-28 17:22:12 -070086 fw_version_ = system_state_->hardware()->GetFirmwareVersion();
87 ec_version_ = system_state_->hardware()->GetECVersion();
Chris Sosac1972482013-04-30 22:31:10 -070088 }
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020089
Jay Srinivasanae4697c2013-03-18 17:08:08 -070090 if (current_channel_ == target_channel_) {
91 // deltas are only okay if the /.nodelta file does not exist. if we don't
92 // know (i.e. stat() returns some unexpected error), then err on the side of
93 // caution and say deltas are not okay.
94 struct stat stbuf;
95 delta_okay_ = (stat((root_ + "/.nodelta").c_str(), &stbuf) < 0) &&
96 (errno == ENOENT);
97
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020098 } else {
Jay Srinivasanae4697c2013-03-18 17:08:08 -070099 LOG(INFO) << "Disabling deltas as a channel change is pending";
100 // For now, disable delta updates if the current channel is different from
101 // the channel that we're sending to the update server because such updates
102 // are destined to fail -- the current rootfs hash will be different than
103 // the expected hash due to the different channel in /etc/lsb-release.
104 delta_okay_ = false;
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +0200105 }
106
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700107 if (in_update_url.empty())
David Pursell02c18642014-11-06 11:26:11 -0800108 update_url_ = GetLsbValue(kAutoUpdateServerKey, kProductionOmahaUrl,
109 nullptr, stateful_override);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700110 else
111 update_url_ = in_update_url;
Gilad Arnoldbbdd4902013-01-10 16:06:30 -0800112
113 // Set the interactive flag accordingly.
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700114 interactive_ = in_interactive;
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700115 return true;
116}
117
David Pursell02c18642014-11-06 11:26:11 -0800118bool OmahaRequestParams::IsUpdateUrlOfficial() const {
119 return (update_url_ == kAUTestOmahaUrl ||
120 update_url_ == GetLsbValue(kAutoUpdateServerKey, kProductionOmahaUrl,
121 nullptr, !ShouldLockDown()));
122}
123
Chris Sosac1972482013-04-30 22:31:10 -0700124bool OmahaRequestParams::CollectECFWVersions() const {
Alex Vakulenko6a9d3492015-06-15 12:53:22 -0700125 return base::StartsWithASCII(hwid_, string("SAMS ALEX"), true) ||
126 base::StartsWithASCII(hwid_, string("BUTTERFLY"), true) ||
127 base::StartsWithASCII(hwid_, string("LUMPY"), true) ||
128 base::StartsWithASCII(hwid_, string("PARROT"), true) ||
129 base::StartsWithASCII(hwid_, string("SPRING"), true) ||
130 base::StartsWithASCII(hwid_, string("SNOW"), true);
Chris Sosac1972482013-04-30 22:31:10 -0700131}
132
Alex Deymof329b932014-10-30 01:37:48 -0700133bool OmahaRequestParams::SetTargetChannel(const string& new_target_channel,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700134 bool is_powerwash_allowed) {
135 LOG(INFO) << "SetTargetChannel called with " << new_target_channel
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700136 << ", Is Powerwash Allowed = "
137 << utils::ToString(is_powerwash_allowed)
138 << ". Current channel = " << current_channel_
139 << ", existing target channel = " << target_channel_
140 << ", download channel = " << download_channel_;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700141 TEST_AND_RETURN_FALSE(IsValidChannel(new_target_channel));
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700142 chromeos::KeyValueStore lsb_release;
Alex Vakulenko75039d72014-03-25 12:36:28 -0700143 base::FilePath kFile(root_ + kStatefulPartition + "/etc/lsb-release");
Alex Deymoa7658442014-04-17 15:49:37 -0700144
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700145 lsb_release.Load(kFile);
Alex Deymoa7658442014-04-17 15:49:37 -0700146 lsb_release.SetString(kUpdateChannelKey, new_target_channel);
147 lsb_release.SetBoolean(kIsPowerwashAllowedKey, is_powerwash_allowed);
148
Alex Vakulenko75039d72014-03-25 12:36:28 -0700149 TEST_AND_RETURN_FALSE(base::CreateDirectory(kFile.DirName()));
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700150 TEST_AND_RETURN_FALSE(lsb_release.Save(kFile));
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700151 target_channel_ = new_target_channel;
152 is_powerwash_allowed_ = is_powerwash_allowed;
Darin Petkov49d91322010-10-25 16:34:58 -0700153 return true;
154}
155
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700156void OmahaRequestParams::SetTargetChannelFromLsbValue() {
157 string target_channel_new_value = GetLsbValue(
158 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700159 current_channel_,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700160 &chromeos_update_engine::OmahaRequestParams::IsValidChannel,
161 true); // stateful_override
162
163 if (target_channel_ != target_channel_new_value) {
164 target_channel_ = target_channel_new_value;
165 LOG(INFO) << "Target Channel set to " << target_channel_
166 << " from LSB file";
167 }
Darin Petkov49d91322010-10-25 16:34:58 -0700168}
169
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700170void OmahaRequestParams::SetCurrentChannelFromLsbValue() {
171 string current_channel_new_value = GetLsbValue(
172 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700173 current_channel_,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700174 nullptr, // No need to validate the read-only rootfs channel.
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700175 false); // stateful_override is false so we get the current channel.
176
177 if (current_channel_ != current_channel_new_value) {
178 current_channel_ = current_channel_new_value;
179 LOG(INFO) << "Current Channel set to " << current_channel_
180 << " from LSB file in rootfs";
181 }
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900182}
183
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700184void OmahaRequestParams::SetIsPowerwashAllowedFromLsbValue() {
185 string is_powerwash_allowed_str = GetLsbValue(
186 kIsPowerwashAllowedKey,
187 "false",
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700188 nullptr, // no need to validate
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700189 true); // always get it from stateful, as that's the only place it'll be
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700190 bool is_powerwash_allowed_new_value = (is_powerwash_allowed_str == "true");
191 if (is_powerwash_allowed_ != is_powerwash_allowed_new_value) {
192 is_powerwash_allowed_ = is_powerwash_allowed_new_value;
193 LOG(INFO) << "Powerwash Allowed set to "
194 << utils::ToString(is_powerwash_allowed_)
195 << " from LSB file in stateful";
196 }
197}
198
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700199void OmahaRequestParams::UpdateDownloadChannel() {
200 if (download_channel_ != target_channel_) {
201 download_channel_ = target_channel_;
202 LOG(INFO) << "Download channel for this attempt = " << download_channel_;
203 }
204}
205
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700206void OmahaRequestParams::InitFromLsbValue() {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700207 SetCurrentChannelFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700208 SetTargetChannelFromLsbValue();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700209 SetIsPowerwashAllowedFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700210 UpdateDownloadChannel();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700211}
212
213string OmahaRequestParams::GetLsbValue(const string& key,
214 const string& default_value,
215 ValueValidator validator,
216 bool stateful_override) const {
Darin Petkova3df55b2010-11-15 13:33:55 -0800217 vector<string> files;
218 if (stateful_override) {
Chris Sosabe45bef2013-04-09 18:25:12 -0700219 files.push_back(string(kStatefulPartition) + "/etc/lsb-release");
Darin Petkova3df55b2010-11-15 13:33:55 -0800220 }
221 files.push_back("/etc/lsb-release");
222 for (vector<string>::const_iterator it = files.begin();
223 it != files.end(); ++it) {
224 // TODO(adlr): make sure files checked are owned as root (and all their
225 // parents are recursively, too).
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700226 chromeos::KeyValueStore data;
227 if (!data.Load(base::FilePath(root_ + *it)))
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700228 continue;
229
Alex Deymoa7658442014-04-17 15:49:37 -0700230 string value;
231 if (data.GetString(key, &value)) {
Darin Petkov49d91322010-10-25 16:34:58 -0700232 if (validator && !CALL_MEMBER_FN(*this, validator)(value)) {
233 continue;
234 }
235 return value;
236 }
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700237 }
238 // not found
239 return default_value;
240}
241
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700242string OmahaRequestParams::GetMachineType() const {
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700243 struct utsname buf;
244 string ret;
245 if (uname(&buf) == 0)
246 ret = buf.machine;
247 return ret;
248}
249
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700250bool OmahaRequestParams::ShouldLockDown() const {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800251 if (force_lock_down_) {
252 return forced_lock_down_;
253 }
J. Richard Barnette056b0ab2013-10-29 15:24:56 -0700254 return system_state_->hardware()->IsOfficialBuild() &&
255 system_state_->hardware()->IsNormalBootMode();
Darin Petkov49d91322010-10-25 16:34:58 -0700256}
257
Alex Deymof329b932014-10-30 01:37:48 -0700258bool OmahaRequestParams::IsValidChannel(const string& channel) const {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700259 return GetChannelIndex(channel) >= 0;
Darin Petkov49d91322010-10-25 16:34:58 -0700260}
261
Alex Deymof329b932014-10-30 01:37:48 -0700262void OmahaRequestParams::set_root(const string& root) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700263 root_ = root;
264 InitFromLsbValue();
265}
266
267void OmahaRequestParams::SetLockDown(bool lock) {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800268 force_lock_down_ = true;
269 forced_lock_down_ = lock;
Darin Petkov49d91322010-10-25 16:34:58 -0700270}
271
Alex Deymof329b932014-10-30 01:37:48 -0700272int OmahaRequestParams::GetChannelIndex(const string& channel) const {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700273 for (size_t t = 0; t < arraysize(kChannelsByStability); ++t)
274 if (channel == kChannelsByStability[t])
275 return t;
276
277 return -1;
278}
279
280bool OmahaRequestParams::to_more_stable_channel() const {
281 int current_channel_index = GetChannelIndex(current_channel_);
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700282 int download_channel_index = GetChannelIndex(download_channel_);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700283
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700284 return download_channel_index > current_channel_index;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700285}
286
Jay Srinivasandb0acdf2013-04-02 14:47:45 -0700287string OmahaRequestParams::GetAppId() const {
288 return download_channel_ == "canary-channel" ? canary_app_id_ : board_app_id_;
289}
290
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700291} // namespace chromeos_update_engine