omaha_request_params.cc revision ac41a82e4be1be43913292d13d58b5eb2c572f53
1// 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// 16 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> 25#include <vector> 26 27#include <base/files/file_util.h> 28#include <base/strings/string_util.h> 29#include <chromeos/key_value_store.h> 30#include <policy/device_policy.h> 31 32#include "update_engine/constants.h" 33#include "update_engine/hardware_interface.h" 34#include "update_engine/platform_constants.h" 35#include "update_engine/system_state.h" 36#include "update_engine/utils.h" 37 38#define CALL_MEMBER_FN(object, member) ((object).*(member)) 39 40using std::map; 41using std::string; 42using std::vector; 43 44namespace chromeos_update_engine { 45 46const char OmahaRequestParams::kAppId[] = 47 "{87efface-864d-49a5-9bb3-4b050a7c227a}"; 48const char OmahaRequestParams::kOsVersion[] = "Indy"; 49const char OmahaRequestParams::kUpdateChannelKey[] = "CHROMEOS_RELEASE_TRACK"; 50const char OmahaRequestParams::kIsPowerwashAllowedKey[] = 51 "CHROMEOS_IS_POWERWASH_ALLOWED"; 52const char OmahaRequestParams::kAutoUpdateServerKey[] = "CHROMEOS_AUSERVER"; 53 54const char* kChannelsByStability[] = { 55 // This list has to be sorted from least stable to most stable channel. 56 "canary-channel", 57 "dev-channel", 58 "beta-channel", 59 "stable-channel", 60}; 61 62bool OmahaRequestParams::Init(const string& in_app_version, 63 const string& in_update_url, 64 bool in_interactive) { 65 LOG(INFO) << "Initializing parameters for this update attempt"; 66 InitFromLsbValue(); 67 bool stateful_override = !ShouldLockDown(); 68 os_platform_ = constants::kOmahaPlatformName; 69 os_version_ = OmahaRequestParams::kOsVersion; 70 app_version_ = in_app_version.empty() ? 71 GetLsbValue("CHROMEOS_RELEASE_VERSION", "", nullptr, stateful_override) : 72 in_app_version; 73 os_sp_ = app_version_ + "_" + GetMachineType(); 74 os_board_ = GetLsbValue("CHROMEOS_RELEASE_BOARD", 75 "", 76 nullptr, 77 stateful_override); 78 string release_app_id = GetLsbValue("CHROMEOS_RELEASE_APPID", 79 OmahaRequestParams::kAppId, 80 nullptr, 81 stateful_override); 82 board_app_id_ = GetLsbValue("CHROMEOS_BOARD_APPID", 83 release_app_id, 84 nullptr, 85 stateful_override); 86 canary_app_id_ = GetLsbValue("CHROMEOS_CANARY_APPID", 87 release_app_id, 88 nullptr, 89 stateful_override); 90 app_lang_ = "en-US"; 91 hwid_ = system_state_->hardware()->GetHardwareClass(); 92 if (CollectECFWVersions()) { 93 fw_version_ = system_state_->hardware()->GetFirmwareVersion(); 94 ec_version_ = system_state_->hardware()->GetECVersion(); 95 } 96 97 if (current_channel_ == target_channel_) { 98 // deltas are only okay if the /.nodelta file does not exist. if we don't 99 // know (i.e. stat() returns some unexpected error), then err on the side of 100 // caution and say deltas are not okay. 101 struct stat stbuf; 102 delta_okay_ = (stat((root_ + "/.nodelta").c_str(), &stbuf) < 0) && 103 (errno == ENOENT); 104 105 } else { 106 LOG(INFO) << "Disabling deltas as a channel change is pending"; 107 // For now, disable delta updates if the current channel is different from 108 // the channel that we're sending to the update server because such updates 109 // are destined to fail -- the current rootfs hash will be different than 110 // the expected hash due to the different channel in /etc/lsb-release. 111 delta_okay_ = false; 112 } 113 114 if (in_update_url.empty()) 115 update_url_ = GetLsbValue(kAutoUpdateServerKey, 116 constants::kOmahaDefaultProductionURL, 117 nullptr, stateful_override); 118 else 119 update_url_ = in_update_url; 120 121 // Set the interactive flag accordingly. 122 interactive_ = in_interactive; 123 return true; 124} 125 126bool OmahaRequestParams::IsUpdateUrlOfficial() const { 127 return (update_url_ == constants::kOmahaDefaultAUTestURL || 128 update_url_ == GetLsbValue(kAutoUpdateServerKey, 129 constants::kOmahaDefaultProductionURL, 130 nullptr, !ShouldLockDown())); 131} 132 133bool OmahaRequestParams::CollectECFWVersions() const { 134 return base::StartsWithASCII(hwid_, string("SAMS ALEX"), true) || 135 base::StartsWithASCII(hwid_, string("BUTTERFLY"), true) || 136 base::StartsWithASCII(hwid_, string("LUMPY"), true) || 137 base::StartsWithASCII(hwid_, string("PARROT"), true) || 138 base::StartsWithASCII(hwid_, string("SPRING"), true) || 139 base::StartsWithASCII(hwid_, string("SNOW"), true); 140} 141 142bool OmahaRequestParams::SetTargetChannel(const string& new_target_channel, 143 bool is_powerwash_allowed) { 144 LOG(INFO) << "SetTargetChannel called with " << new_target_channel 145 << ", Is Powerwash Allowed = " 146 << utils::ToString(is_powerwash_allowed) 147 << ". Current channel = " << current_channel_ 148 << ", existing target channel = " << target_channel_ 149 << ", download channel = " << download_channel_; 150 TEST_AND_RETURN_FALSE(IsValidChannel(new_target_channel)); 151 chromeos::KeyValueStore lsb_release; 152 base::FilePath kFile(root_ + kStatefulPartition + "/etc/lsb-release"); 153 154 lsb_release.Load(kFile); 155 lsb_release.SetString(kUpdateChannelKey, new_target_channel); 156 lsb_release.SetBoolean(kIsPowerwashAllowedKey, is_powerwash_allowed); 157 158 TEST_AND_RETURN_FALSE(base::CreateDirectory(kFile.DirName())); 159 TEST_AND_RETURN_FALSE(lsb_release.Save(kFile)); 160 target_channel_ = new_target_channel; 161 is_powerwash_allowed_ = is_powerwash_allowed; 162 return true; 163} 164 165void OmahaRequestParams::SetTargetChannelFromLsbValue() { 166 string target_channel_new_value = GetLsbValue( 167 kUpdateChannelKey, 168 current_channel_, 169 &chromeos_update_engine::OmahaRequestParams::IsValidChannel, 170 true); // stateful_override 171 172 if (target_channel_ != target_channel_new_value) { 173 target_channel_ = target_channel_new_value; 174 LOG(INFO) << "Target Channel set to " << target_channel_ 175 << " from LSB file"; 176 } 177} 178 179void OmahaRequestParams::SetCurrentChannelFromLsbValue() { 180 string current_channel_new_value = GetLsbValue( 181 kUpdateChannelKey, 182 current_channel_, 183 nullptr, // No need to validate the read-only rootfs channel. 184 false); // stateful_override is false so we get the current channel. 185 186 if (current_channel_ != current_channel_new_value) { 187 current_channel_ = current_channel_new_value; 188 LOG(INFO) << "Current Channel set to " << current_channel_ 189 << " from LSB file in rootfs"; 190 } 191} 192 193void OmahaRequestParams::SetIsPowerwashAllowedFromLsbValue() { 194 string is_powerwash_allowed_str = GetLsbValue( 195 kIsPowerwashAllowedKey, 196 "false", 197 nullptr, // no need to validate 198 true); // always get it from stateful, as that's the only place it'll be 199 bool is_powerwash_allowed_new_value = (is_powerwash_allowed_str == "true"); 200 if (is_powerwash_allowed_ != is_powerwash_allowed_new_value) { 201 is_powerwash_allowed_ = is_powerwash_allowed_new_value; 202 LOG(INFO) << "Powerwash Allowed set to " 203 << utils::ToString(is_powerwash_allowed_) 204 << " from LSB file in stateful"; 205 } 206} 207 208void OmahaRequestParams::UpdateDownloadChannel() { 209 if (download_channel_ != target_channel_) { 210 download_channel_ = target_channel_; 211 LOG(INFO) << "Download channel for this attempt = " << download_channel_; 212 } 213} 214 215void OmahaRequestParams::InitFromLsbValue() { 216 SetCurrentChannelFromLsbValue(); 217 SetTargetChannelFromLsbValue(); 218 SetIsPowerwashAllowedFromLsbValue(); 219 UpdateDownloadChannel(); 220} 221 222string OmahaRequestParams::GetLsbValue(const string& key, 223 const string& default_value, 224 ValueValidator validator, 225 bool stateful_override) const { 226 vector<string> files; 227 if (stateful_override) { 228 files.push_back(string(kStatefulPartition) + "/etc/lsb-release"); 229 } 230 files.push_back("/etc/lsb-release"); 231 for (vector<string>::const_iterator it = files.begin(); 232 it != files.end(); ++it) { 233 // TODO(adlr): make sure files checked are owned as root (and all their 234 // parents are recursively, too). 235 chromeos::KeyValueStore data; 236 if (!data.Load(base::FilePath(root_ + *it))) 237 continue; 238 239 string value; 240 if (data.GetString(key, &value)) { 241 if (validator && !CALL_MEMBER_FN(*this, validator)(value)) { 242 continue; 243 } 244 return value; 245 } 246 } 247 // not found 248 return default_value; 249} 250 251string OmahaRequestParams::GetMachineType() const { 252 struct utsname buf; 253 string ret; 254 if (uname(&buf) == 0) 255 ret = buf.machine; 256 return ret; 257} 258 259bool OmahaRequestParams::ShouldLockDown() const { 260 if (force_lock_down_) { 261 return forced_lock_down_; 262 } 263 return system_state_->hardware()->IsOfficialBuild() && 264 system_state_->hardware()->IsNormalBootMode(); 265} 266 267bool OmahaRequestParams::IsValidChannel(const string& channel) const { 268 return GetChannelIndex(channel) >= 0; 269} 270 271void OmahaRequestParams::set_root(const string& root) { 272 root_ = root; 273 InitFromLsbValue(); 274} 275 276void OmahaRequestParams::SetLockDown(bool lock) { 277 force_lock_down_ = true; 278 forced_lock_down_ = lock; 279} 280 281int OmahaRequestParams::GetChannelIndex(const string& channel) const { 282 for (size_t t = 0; t < arraysize(kChannelsByStability); ++t) 283 if (channel == kChannelsByStability[t]) 284 return t; 285 286 return -1; 287} 288 289bool OmahaRequestParams::to_more_stable_channel() const { 290 int current_channel_index = GetChannelIndex(current_channel_); 291 int download_channel_index = GetChannelIndex(download_channel_); 292 293 return download_channel_index > current_channel_index; 294} 295 296string OmahaRequestParams::GetAppId() const { 297 return download_channel_ == "canary-channel" ? canary_app_id_ : board_app_id_; 298} 299 300} // namespace chromeos_update_engine 301