blob: 6e8d636dacc522a5faeabf72213e5245237f71df [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2011 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Darin Petkova4a8a8c2010-07-15 22:21:12 -070016
17#include "update_engine/omaha_request_params.h"
18
19#include <errno.h>
20#include <fcntl.h>
21#include <sys/utsname.h>
22
23#include <map>
24#include <string>
Darin Petkova3df55b2010-11-15 13:33:55 -080025#include <vector>
Darin Petkova4a8a8c2010-07-15 22:21:12 -070026
Ben Chan06c76a42014-09-05 08:21:06 -070027#include <base/files/file_util.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070028#include <base/strings/string_util.h>
Alex Deymo2b4e2a52014-09-23 12:05:56 -070029#include <chromeos/key_value_store.h>
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020030#include <policy/device_policy.h>
Darin Petkov49d91322010-10-25 16:34:58 -070031
Chris Sosabe45bef2013-04-09 18:25:12 -070032#include "update_engine/constants.h"
J. Richard Barnette522d36f2013-10-28 17:22:12 -070033#include "update_engine/hardware_interface.h"
Jay Srinivasanae4697c2013-03-18 17:08:08 -070034#include "update_engine/system_state.h"
Darin Petkova4a8a8c2010-07-15 22:21:12 -070035#include "update_engine/utils.h"
36
Darin Petkov49d91322010-10-25 16:34:58 -070037#define CALL_MEMBER_FN(object, member) ((object).*(member))
38
Darin Petkova4a8a8c2010-07-15 22:21:12 -070039using std::map;
40using std::string;
Darin Petkova3df55b2010-11-15 13:33:55 -080041using std::vector;
Darin Petkova4a8a8c2010-07-15 22:21:12 -070042
Darin Petkova4a8a8c2010-07-15 22:21:12 -070043namespace chromeos_update_engine {
44
David Pursell02c18642014-11-06 11:26:11 -080045const char kProductionOmahaUrl[] =
46 "https://tools.google.com/service/update2";
47const char kAUTestOmahaUrl[] =
48 "https://omaha.sandbox.google.com/service/update2";
Darin Petkov5a7f5652010-07-22 21:40:09 -070049
David Pursell02c18642014-11-06 11:26:11 -080050const char OmahaRequestParams::kAppId[] =
51 "{87efface-864d-49a5-9bb3-4b050a7c227a}";
52const char OmahaRequestParams::kOsPlatform[] = "Chrome OS";
53const char OmahaRequestParams::kOsVersion[] = "Indy";
54const char OmahaRequestParams::kUpdateChannelKey[] = "CHROMEOS_RELEASE_TRACK";
55const char OmahaRequestParams::kIsPowerwashAllowedKey[] =
56 "CHROMEOS_IS_POWERWASH_ALLOWED";
57const char OmahaRequestParams::kAutoUpdateServerKey[] = "CHROMEOS_AUSERVER";
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +020058
Jay Srinivasanae4697c2013-03-18 17:08:08 -070059const char* kChannelsByStability[] = {
60 // This list has to be sorted from least stable to most stable channel.
61 "canary-channel",
62 "dev-channel",
63 "beta-channel",
64 "stable-channel",
65};
Darin Petkov49d91322010-10-25 16:34:58 -070066
Alex Deymof329b932014-10-30 01:37:48 -070067bool OmahaRequestParams::Init(const string& in_app_version,
68 const string& in_update_url,
Jay Srinivasanae4697c2013-03-18 17:08:08 -070069 bool in_interactive) {
Jay Srinivasan1c0fe792013-03-28 16:45:25 -070070 LOG(INFO) << "Initializing parameters for this update attempt";
Jay Srinivasanae4697c2013-03-18 17:08:08 -070071 InitFromLsbValue();
Darin Petkov10d02dd2011-01-10 14:57:39 -080072 bool stateful_override = !ShouldLockDown();
Jay Srinivasanae4697c2013-03-18 17:08:08 -070073 os_platform_ = OmahaRequestParams::kOsPlatform;
74 os_version_ = OmahaRequestParams::kOsVersion;
75 app_version_ = in_app_version.empty() ?
Alex Vakulenko88b591f2014-08-28 16:48:57 -070076 GetLsbValue("CHROMEOS_RELEASE_VERSION", "", nullptr, stateful_override) :
Darin Petkov10d02dd2011-01-10 14:57:39 -080077 in_app_version;
Jay Srinivasanae4697c2013-03-18 17:08:08 -070078 os_sp_ = app_version_ + "_" + GetMachineType();
79 os_board_ = GetLsbValue("CHROMEOS_RELEASE_BOARD",
80 "",
Alex Vakulenko88b591f2014-08-28 16:48:57 -070081 nullptr,
Jay Srinivasanae4697c2013-03-18 17:08:08 -070082 stateful_override);
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070083 string release_app_id = GetLsbValue("CHROMEOS_RELEASE_APPID",
84 OmahaRequestParams::kAppId,
Alex Vakulenko88b591f2014-08-28 16:48:57 -070085 nullptr,
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070086 stateful_override);
Jay Srinivasanae4697c2013-03-18 17:08:08 -070087 board_app_id_ = GetLsbValue("CHROMEOS_BOARD_APPID",
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070088 release_app_id,
Alex Vakulenko88b591f2014-08-28 16:48:57 -070089 nullptr,
Jay Srinivasanae4697c2013-03-18 17:08:08 -070090 stateful_override);
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070091 canary_app_id_ = GetLsbValue("CHROMEOS_CANARY_APPID",
92 release_app_id,
Alex Vakulenko88b591f2014-08-28 16:48:57 -070093 nullptr,
Jay Srinivasandb0acdf2013-04-02 14:47:45 -070094 stateful_override);
Jay Srinivasanae4697c2013-03-18 17:08:08 -070095 app_lang_ = "en-US";
J. Richard Barnette522d36f2013-10-28 17:22:12 -070096 hwid_ = system_state_->hardware()->GetHardwareClass();
Chris Sosac1972482013-04-30 22:31:10 -070097 if (CollectECFWVersions()) {
J. Richard Barnette522d36f2013-10-28 17:22:12 -070098 fw_version_ = system_state_->hardware()->GetFirmwareVersion();
99 ec_version_ = system_state_->hardware()->GetECVersion();
Chris Sosac1972482013-04-30 22:31:10 -0700100 }
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +0200101
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700102 if (current_channel_ == target_channel_) {
103 // deltas are only okay if the /.nodelta file does not exist. if we don't
104 // know (i.e. stat() returns some unexpected error), then err on the side of
105 // caution and say deltas are not okay.
106 struct stat stbuf;
107 delta_okay_ = (stat((root_ + "/.nodelta").c_str(), &stbuf) < 0) &&
108 (errno == ENOENT);
109
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +0200110 } else {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700111 LOG(INFO) << "Disabling deltas as a channel change is pending";
112 // For now, disable delta updates if the current channel is different from
113 // the channel that we're sending to the update server because such updates
114 // are destined to fail -- the current rootfs hash will be different than
115 // the expected hash due to the different channel in /etc/lsb-release.
116 delta_okay_ = false;
Patrick Dubroy7fbbe8a2011-08-01 17:28:22 +0200117 }
118
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700119 if (in_update_url.empty())
David Pursell02c18642014-11-06 11:26:11 -0800120 update_url_ = GetLsbValue(kAutoUpdateServerKey, kProductionOmahaUrl,
121 nullptr, stateful_override);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700122 else
123 update_url_ = in_update_url;
Gilad Arnoldbbdd4902013-01-10 16:06:30 -0800124
125 // Set the interactive flag accordingly.
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700126 interactive_ = in_interactive;
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700127 return true;
128}
129
David Pursell02c18642014-11-06 11:26:11 -0800130bool OmahaRequestParams::IsUpdateUrlOfficial() const {
131 return (update_url_ == kAUTestOmahaUrl ||
132 update_url_ == GetLsbValue(kAutoUpdateServerKey, kProductionOmahaUrl,
133 nullptr, !ShouldLockDown()));
134}
135
Chris Sosac1972482013-04-30 22:31:10 -0700136bool OmahaRequestParams::CollectECFWVersions() const {
Alex Vakulenko6a9d3492015-06-15 12:53:22 -0700137 return base::StartsWithASCII(hwid_, string("SAMS ALEX"), true) ||
138 base::StartsWithASCII(hwid_, string("BUTTERFLY"), true) ||
139 base::StartsWithASCII(hwid_, string("LUMPY"), true) ||
140 base::StartsWithASCII(hwid_, string("PARROT"), true) ||
141 base::StartsWithASCII(hwid_, string("SPRING"), true) ||
142 base::StartsWithASCII(hwid_, string("SNOW"), true);
Chris Sosac1972482013-04-30 22:31:10 -0700143}
144
Alex Deymof329b932014-10-30 01:37:48 -0700145bool OmahaRequestParams::SetTargetChannel(const string& new_target_channel,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700146 bool is_powerwash_allowed) {
147 LOG(INFO) << "SetTargetChannel called with " << new_target_channel
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700148 << ", Is Powerwash Allowed = "
149 << utils::ToString(is_powerwash_allowed)
150 << ". Current channel = " << current_channel_
151 << ", existing target channel = " << target_channel_
152 << ", download channel = " << download_channel_;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700153 TEST_AND_RETURN_FALSE(IsValidChannel(new_target_channel));
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700154 chromeos::KeyValueStore lsb_release;
Alex Vakulenko75039d72014-03-25 12:36:28 -0700155 base::FilePath kFile(root_ + kStatefulPartition + "/etc/lsb-release");
Alex Deymoa7658442014-04-17 15:49:37 -0700156
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700157 lsb_release.Load(kFile);
Alex Deymoa7658442014-04-17 15:49:37 -0700158 lsb_release.SetString(kUpdateChannelKey, new_target_channel);
159 lsb_release.SetBoolean(kIsPowerwashAllowedKey, is_powerwash_allowed);
160
Alex Vakulenko75039d72014-03-25 12:36:28 -0700161 TEST_AND_RETURN_FALSE(base::CreateDirectory(kFile.DirName()));
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700162 TEST_AND_RETURN_FALSE(lsb_release.Save(kFile));
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700163 target_channel_ = new_target_channel;
164 is_powerwash_allowed_ = is_powerwash_allowed;
Darin Petkov49d91322010-10-25 16:34:58 -0700165 return true;
166}
167
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700168void OmahaRequestParams::SetTargetChannelFromLsbValue() {
169 string target_channel_new_value = GetLsbValue(
170 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700171 current_channel_,
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700172 &chromeos_update_engine::OmahaRequestParams::IsValidChannel,
173 true); // stateful_override
174
175 if (target_channel_ != target_channel_new_value) {
176 target_channel_ = target_channel_new_value;
177 LOG(INFO) << "Target Channel set to " << target_channel_
178 << " from LSB file";
179 }
Darin Petkov49d91322010-10-25 16:34:58 -0700180}
181
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700182void OmahaRequestParams::SetCurrentChannelFromLsbValue() {
183 string current_channel_new_value = GetLsbValue(
184 kUpdateChannelKey,
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700185 current_channel_,
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700186 nullptr, // No need to validate the read-only rootfs channel.
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700187 false); // stateful_override is false so we get the current channel.
188
189 if (current_channel_ != current_channel_new_value) {
190 current_channel_ = current_channel_new_value;
191 LOG(INFO) << "Current Channel set to " << current_channel_
192 << " from LSB file in rootfs";
193 }
Satoru Takabayashi583667b2010-10-27 13:09:57 +0900194}
195
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700196void OmahaRequestParams::SetIsPowerwashAllowedFromLsbValue() {
197 string is_powerwash_allowed_str = GetLsbValue(
198 kIsPowerwashAllowedKey,
199 "false",
Alex Vakulenko88b591f2014-08-28 16:48:57 -0700200 nullptr, // no need to validate
Alex Vakulenkod2779df2014-06-16 13:19:00 -0700201 true); // always get it from stateful, as that's the only place it'll be
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700202 bool is_powerwash_allowed_new_value = (is_powerwash_allowed_str == "true");
203 if (is_powerwash_allowed_ != is_powerwash_allowed_new_value) {
204 is_powerwash_allowed_ = is_powerwash_allowed_new_value;
205 LOG(INFO) << "Powerwash Allowed set to "
206 << utils::ToString(is_powerwash_allowed_)
207 << " from LSB file in stateful";
208 }
209}
210
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700211void OmahaRequestParams::UpdateDownloadChannel() {
212 if (download_channel_ != target_channel_) {
213 download_channel_ = target_channel_;
214 LOG(INFO) << "Download channel for this attempt = " << download_channel_;
215 }
216}
217
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700218void OmahaRequestParams::InitFromLsbValue() {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700219 SetCurrentChannelFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700220 SetTargetChannelFromLsbValue();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700221 SetIsPowerwashAllowedFromLsbValue();
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700222 UpdateDownloadChannel();
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700223}
224
225string OmahaRequestParams::GetLsbValue(const string& key,
226 const string& default_value,
227 ValueValidator validator,
228 bool stateful_override) const {
Darin Petkova3df55b2010-11-15 13:33:55 -0800229 vector<string> files;
230 if (stateful_override) {
Chris Sosabe45bef2013-04-09 18:25:12 -0700231 files.push_back(string(kStatefulPartition) + "/etc/lsb-release");
Darin Petkova3df55b2010-11-15 13:33:55 -0800232 }
233 files.push_back("/etc/lsb-release");
234 for (vector<string>::const_iterator it = files.begin();
235 it != files.end(); ++it) {
236 // TODO(adlr): make sure files checked are owned as root (and all their
237 // parents are recursively, too).
Alex Deymo2b4e2a52014-09-23 12:05:56 -0700238 chromeos::KeyValueStore data;
239 if (!data.Load(base::FilePath(root_ + *it)))
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700240 continue;
241
Alex Deymoa7658442014-04-17 15:49:37 -0700242 string value;
243 if (data.GetString(key, &value)) {
Darin Petkov49d91322010-10-25 16:34:58 -0700244 if (validator && !CALL_MEMBER_FN(*this, validator)(value)) {
245 continue;
246 }
247 return value;
248 }
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700249 }
250 // not found
251 return default_value;
252}
253
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700254string OmahaRequestParams::GetMachineType() const {
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700255 struct utsname buf;
256 string ret;
257 if (uname(&buf) == 0)
258 ret = buf.machine;
259 return ret;
260}
261
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700262bool OmahaRequestParams::ShouldLockDown() const {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800263 if (force_lock_down_) {
264 return forced_lock_down_;
265 }
J. Richard Barnette056b0ab2013-10-29 15:24:56 -0700266 return system_state_->hardware()->IsOfficialBuild() &&
267 system_state_->hardware()->IsNormalBootMode();
Darin Petkov49d91322010-10-25 16:34:58 -0700268}
269
Alex Deymof329b932014-10-30 01:37:48 -0700270bool OmahaRequestParams::IsValidChannel(const string& channel) const {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700271 return GetChannelIndex(channel) >= 0;
Darin Petkov49d91322010-10-25 16:34:58 -0700272}
273
Alex Deymof329b932014-10-30 01:37:48 -0700274void OmahaRequestParams::set_root(const string& root) {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700275 root_ = root;
276 InitFromLsbValue();
277}
278
279void OmahaRequestParams::SetLockDown(bool lock) {
Darin Petkov10d02dd2011-01-10 14:57:39 -0800280 force_lock_down_ = true;
281 forced_lock_down_ = lock;
Darin Petkov49d91322010-10-25 16:34:58 -0700282}
283
Alex Deymof329b932014-10-30 01:37:48 -0700284int OmahaRequestParams::GetChannelIndex(const string& channel) const {
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700285 for (size_t t = 0; t < arraysize(kChannelsByStability); ++t)
286 if (channel == kChannelsByStability[t])
287 return t;
288
289 return -1;
290}
291
292bool OmahaRequestParams::to_more_stable_channel() const {
293 int current_channel_index = GetChannelIndex(current_channel_);
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700294 int download_channel_index = GetChannelIndex(download_channel_);
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700295
Jay Srinivasan1c0fe792013-03-28 16:45:25 -0700296 return download_channel_index > current_channel_index;
Jay Srinivasanae4697c2013-03-18 17:08:08 -0700297}
298
Jay Srinivasandb0acdf2013-04-02 14:47:45 -0700299string OmahaRequestParams::GetAppId() const {
300 return download_channel_ == "canary-channel" ? canary_app_id_ : board_app_id_;
301}
302
Darin Petkova4a8a8c2010-07-15 22:21:12 -0700303} // namespace chromeos_update_engine