blob: 7a3087cfe9d9821623718010d71caba2268b9c78 [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 Vakulenkod2779df2014-06-16 13:19:00 -0700125 return {
Chris Sosac1972482013-04-30 22:31:10 -0700126 StartsWithASCII(hwid_, string("SAMS ALEX"), true) ||
127 StartsWithASCII(hwid_, string("BUTTERFLY"), true) ||
128 StartsWithASCII(hwid_, string("LUMPY"), true) ||
129 StartsWithASCII(hwid_, string("PARROT"), true) ||
130 StartsWithASCII(hwid_, string("SPRING"), true) ||
131 StartsWithASCII(hwid_, string("SNOW"), true)
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700132 };
Chris Sosac1972482013-04-30 22:31:10 -0700133}
134
Alex Deymof329b932014-10-30 01:37:48 -0700135bool OmahaRequestParams::SetTargetChannel(const string& new_target_channel,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700136 bool is_powerwash_allowed) {
137 LOG(INFO) << "SetTargetChannel called with " << new_target_channel
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700138 << ", Is Powerwash Allowed = "
139 << utils::ToString(is_powerwash_allowed)
140 << ". Current channel = " << current_channel_
141 << ", existing target channel = " << target_channel_
142 << ", download channel = " << download_channel_;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700143 TEST_AND_RETURN_FALSE(IsValidChannel(new_target_channel));
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700144 chromeos::KeyValueStore lsb_release;
Alex Vakulenko75039d72014-03-25 12:36:28 -0700145 base::FilePath kFile(root_ + kStatefulPartition + "/etc/lsb-release");
Alex Deymoa7658442014-04-17 15:49:37 -0700146
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700147 lsb_release.Load(kFile);
Alex Deymoa7658442014-04-17 15:49:37 -0700148 lsb_release.SetString(kUpdateChannelKey, new_target_channel);
149 lsb_release.SetBoolean(kIsPowerwashAllowedKey, is_powerwash_allowed);
150
Alex Vakulenko75039d72014-03-25 12:36:28 -0700151 TEST_AND_RETURN_FALSE(base::CreateDirectory(kFile.DirName()));
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700152 TEST_AND_RETURN_FALSE(lsb_release.Save(kFile));
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700153 target_channel_ = new_target_channel;
154 is_powerwash_allowed_ = is_powerwash_allowed;
Darin Petkov49d91322010-10-25 16:34:58 -0700155 return true;
156}
157
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700158void OmahaRequestParams::SetTargetChannelFromLsbValue() {
159 string target_channel_new_value = GetLsbValue(
160 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700161 current_channel_,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700162 &chromeos_update_engine::OmahaRequestParams::IsValidChannel,
163 true); // stateful_override
164
165 if (target_channel_ != target_channel_new_value) {
166 target_channel_ = target_channel_new_value;
167 LOG(INFO) << "Target Channel set to " << target_channel_
168 << " from LSB file";
169 }
Darin Petkov49d91322010-10-25 16:34:58 -0700170}
171
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700172void OmahaRequestParams::SetCurrentChannelFromLsbValue() {
173 string current_channel_new_value = GetLsbValue(
174 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700175 current_channel_,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700176 nullptr, // No need to validate the read-only rootfs channel.
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700177 false); // stateful_override is false so we get the current channel.
178
179 if (current_channel_ != current_channel_new_value) {
180 current_channel_ = current_channel_new_value;
181 LOG(INFO) << "Current Channel set to " << current_channel_
182 << " from LSB file in rootfs";
183 }
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900184}
185
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700186void OmahaRequestParams::SetIsPowerwashAllowedFromLsbValue() {
187 string is_powerwash_allowed_str = GetLsbValue(
188 kIsPowerwashAllowedKey,
189 "false",
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700190 nullptr, // no need to validate
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700191 true); // always get it from stateful, as that's the only place it'll be
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700192 bool is_powerwash_allowed_new_value = (is_powerwash_allowed_str == "true");
193 if (is_powerwash_allowed_ != is_powerwash_allowed_new_value) {
194 is_powerwash_allowed_ = is_powerwash_allowed_new_value;
195 LOG(INFO) << "Powerwash Allowed set to "
196 << utils::ToString(is_powerwash_allowed_)
197 << " from LSB file in stateful";
198 }
199}
200
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700201void OmahaRequestParams::UpdateDownloadChannel() {
202 if (download_channel_ != target_channel_) {
203 download_channel_ = target_channel_;
204 LOG(INFO) << "Download channel for this attempt = " << download_channel_;
205 }
206}
207
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700208void OmahaRequestParams::InitFromLsbValue() {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700209 SetCurrentChannelFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700210 SetTargetChannelFromLsbValue();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700211 SetIsPowerwashAllowedFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700212 UpdateDownloadChannel();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700213}
214
215string OmahaRequestParams::GetLsbValue(const string& key,
216 const string& default_value,
217 ValueValidator validator,
218 bool stateful_override) const {
Darin Petkova3df55b2010-11-15 13:33:55 -0800219 vector<string> files;
220 if (stateful_override) {
Chris Sosabe45bef2013-04-09 18:25:12 -0700221 files.push_back(string(kStatefulPartition) + "/etc/lsb-release");
Darin Petkova3df55b2010-11-15 13:33:55 -0800222 }
223 files.push_back("/etc/lsb-release");
224 for (vector<string>::const_iterator it = files.begin();
225 it != files.end(); ++it) {
226 // TODO(adlr): make sure files checked are owned as root (and all their
227 // parents are recursively, too).
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700228 chromeos::KeyValueStore data;
229 if (!data.Load(base::FilePath(root_ + *it)))
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700230 continue;
231
Alex Deymoa7658442014-04-17 15:49:37 -0700232 string value;
233 if (data.GetString(key, &value)) {
Darin Petkov49d91322010-10-25 16:34:58 -0700234 if (validator && !CALL_MEMBER_FN(*this, validator)(value)) {
235 continue;
236 }
237 return value;
238 }
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700239 }
240 // not found
241 return default_value;
242}
243
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700244string OmahaRequestParams::GetMachineType() const {
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700245 struct utsname buf;
246 string ret;
247 if (uname(&buf) == 0)
248 ret = buf.machine;
249 return ret;
250}
251
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700252bool OmahaRequestParams::ShouldLockDown() const {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800253 if (force_lock_down_) {
254 return forced_lock_down_;
255 }
J. Richard Barnette056b0ab2013-10-29 15:24:56 -0700256 return system_state_->hardware()->IsOfficialBuild() &&
257 system_state_->hardware()->IsNormalBootMode();
Darin Petkov49d91322010-10-25 16:34:58 -0700258}
259
Alex Deymof329b932014-10-30 01:37:48 -0700260bool OmahaRequestParams::IsValidChannel(const string& channel) const {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700261 return GetChannelIndex(channel) >= 0;
Darin Petkov49d91322010-10-25 16:34:58 -0700262}
263
Alex Deymof329b932014-10-30 01:37:48 -0700264void OmahaRequestParams::set_root(const string& root) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700265 root_ = root;
266 InitFromLsbValue();
267}
268
269void OmahaRequestParams::SetLockDown(bool lock) {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800270 force_lock_down_ = true;
271 forced_lock_down_ = lock;
Darin Petkov49d91322010-10-25 16:34:58 -0700272}
273
Alex Deymof329b932014-10-30 01:37:48 -0700274int OmahaRequestParams::GetChannelIndex(const string& channel) const {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700275 for (size_t t = 0; t < arraysize(kChannelsByStability); ++t)
276 if (channel == kChannelsByStability[t])
277 return t;
278
279 return -1;
280}
281
282bool OmahaRequestParams::to_more_stable_channel() const {
283 int current_channel_index = GetChannelIndex(current_channel_);
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700284 int download_channel_index = GetChannelIndex(download_channel_);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700285
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700286 return download_channel_index > current_channel_index;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700287}
288
Jay Srinivasandb0acdf2013-04-02 14:47:45 -0700289string OmahaRequestParams::GetAppId() const {
290 return download_channel_ == "canary-channel" ? canary_app_id_ : board_app_id_;
291}
292
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700293} // namespace chromeos_update_engine