omaha_request_action.cc 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997
  1. //
  2. // Copyright (C) 2012 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. #include "update_engine/omaha_request_action.h"
  17. #include <inttypes.h>
  18. #include <limits>
  19. #include <map>
  20. #include <sstream>
  21. #include <string>
  22. #include <utility>
  23. #include <vector>
  24. #include <base/bind.h>
  25. #include <base/logging.h>
  26. #include <base/rand_util.h>
  27. #include <base/strings/string_number_conversions.h>
  28. #include <base/strings/string_split.h>
  29. #include <base/strings/string_util.h>
  30. #include <base/strings/stringprintf.h>
  31. #include <base/time/time.h>
  32. #include <brillo/key_value_store.h>
  33. #include <expat.h>
  34. #include <metrics/metrics_library.h>
  35. #include <policy/libpolicy.h>
  36. #include "update_engine/common/action_pipe.h"
  37. #include "update_engine/common/constants.h"
  38. #include "update_engine/common/hardware_interface.h"
  39. #include "update_engine/common/hash_calculator.h"
  40. #include "update_engine/common/platform_constants.h"
  41. #include "update_engine/common/prefs_interface.h"
  42. #include "update_engine/common/utils.h"
  43. #include "update_engine/connection_manager_interface.h"
  44. #include "update_engine/metrics_reporter_interface.h"
  45. #include "update_engine/metrics_utils.h"
  46. #include "update_engine/omaha_request_params.h"
  47. #include "update_engine/p2p_manager.h"
  48. #include "update_engine/payload_state_interface.h"
  49. using base::Time;
  50. using base::TimeDelta;
  51. using chromeos_update_manager::kRollforwardInfinity;
  52. using std::map;
  53. using std::numeric_limits;
  54. using std::string;
  55. using std::vector;
  56. namespace chromeos_update_engine {
  57. // List of custom attributes that we interpret in the Omaha response:
  58. constexpr char kAttrDeadline[] = "deadline";
  59. constexpr char kAttrDisableP2PForDownloading[] = "DisableP2PForDownloading";
  60. constexpr char kAttrDisableP2PForSharing[] = "DisableP2PForSharing";
  61. constexpr char kAttrDisablePayloadBackoff[] = "DisablePayloadBackoff";
  62. constexpr char kAttrVersion[] = "version";
  63. // Deprecated: "IsDelta"
  64. constexpr char kAttrIsDeltaPayload[] = "IsDeltaPayload";
  65. constexpr char kAttrMaxFailureCountPerUrl[] = "MaxFailureCountPerUrl";
  66. constexpr char kAttrMaxDaysToScatter[] = "MaxDaysToScatter";
  67. // Deprecated: "ManifestSignatureRsa"
  68. // Deprecated: "ManifestSize"
  69. constexpr char kAttrMetadataSignatureRsa[] = "MetadataSignatureRsa";
  70. constexpr char kAttrMetadataSize[] = "MetadataSize";
  71. constexpr char kAttrMoreInfo[] = "MoreInfo";
  72. constexpr char kAttrNoUpdate[] = "noupdate";
  73. // Deprecated: "NeedsAdmin"
  74. constexpr char kAttrPollInterval[] = "PollInterval";
  75. constexpr char kAttrPowerwash[] = "Powerwash";
  76. constexpr char kAttrPrompt[] = "Prompt";
  77. constexpr char kAttrPublicKeyRsa[] = "PublicKeyRsa";
  78. // List of attributes that we interpret in the Omaha response:
  79. constexpr char kAttrAppId[] = "appid";
  80. constexpr char kAttrCodeBase[] = "codebase";
  81. constexpr char kAttrCohort[] = "cohort";
  82. constexpr char kAttrCohortHint[] = "cohorthint";
  83. constexpr char kAttrCohortName[] = "cohortname";
  84. constexpr char kAttrElapsedDays[] = "elapsed_days";
  85. constexpr char kAttrElapsedSeconds[] = "elapsed_seconds";
  86. constexpr char kAttrEvent[] = "event";
  87. constexpr char kAttrHashSha256[] = "hash_sha256";
  88. // Deprecated: "hash"; Although we still need to pass it from the server for
  89. // backward compatibility.
  90. constexpr char kAttrName[] = "name";
  91. // Deprecated: "sha256"; Although we still need to pass it from the server for
  92. // backward compatibility.
  93. constexpr char kAttrSize[] = "size";
  94. constexpr char kAttrStatus[] = "status";
  95. // List of values that we interpret in the Omaha response:
  96. constexpr char kValPostInstall[] = "postinstall";
  97. constexpr char kValNoUpdate[] = "noupdate";
  98. constexpr char kOmahaUpdaterVersion[] = "0.1.0.0";
  99. // X-Goog-Update headers.
  100. constexpr char kXGoogleUpdateInteractivity[] = "X-Goog-Update-Interactivity";
  101. constexpr char kXGoogleUpdateAppId[] = "X-Goog-Update-AppId";
  102. constexpr char kXGoogleUpdateUpdater[] = "X-Goog-Update-Updater";
  103. // updatecheck attributes (without the underscore prefix).
  104. constexpr char kAttrEol[] = "eol";
  105. constexpr char kAttrRollback[] = "rollback";
  106. constexpr char kAttrFirmwareVersion[] = "firmware_version";
  107. constexpr char kAttrKernelVersion[] = "kernel_version";
  108. namespace {
  109. // Returns an XML ping element attribute assignment with attribute
  110. // |name| and value |ping_days| if |ping_days| has a value that needs
  111. // to be sent, or an empty string otherwise.
  112. string GetPingAttribute(const string& name, int ping_days) {
  113. if (ping_days > 0 || ping_days == OmahaRequestAction::kNeverPinged)
  114. return base::StringPrintf(" %s=\"%d\"", name.c_str(), ping_days);
  115. return "";
  116. }
  117. // Returns an XML ping element if any of the elapsed days need to be
  118. // sent, or an empty string otherwise.
  119. string GetPingXml(int ping_active_days, int ping_roll_call_days) {
  120. string ping_active = GetPingAttribute("a", ping_active_days);
  121. string ping_roll_call = GetPingAttribute("r", ping_roll_call_days);
  122. if (!ping_active.empty() || !ping_roll_call.empty()) {
  123. return base::StringPrintf(" <ping active=\"1\"%s%s></ping>\n",
  124. ping_active.c_str(),
  125. ping_roll_call.c_str());
  126. }
  127. return "";
  128. }
  129. // Returns an XML that goes into the body of the <app> element of the Omaha
  130. // request based on the given parameters.
  131. string GetAppBody(const OmahaEvent* event,
  132. OmahaRequestParams* params,
  133. bool ping_only,
  134. bool include_ping,
  135. bool skip_updatecheck,
  136. int ping_active_days,
  137. int ping_roll_call_days,
  138. PrefsInterface* prefs) {
  139. string app_body;
  140. if (event == nullptr) {
  141. if (include_ping)
  142. app_body = GetPingXml(ping_active_days, ping_roll_call_days);
  143. if (!ping_only) {
  144. if (!skip_updatecheck) {
  145. app_body += " <updatecheck";
  146. if (!params->target_version_prefix().empty()) {
  147. app_body += base::StringPrintf(
  148. " targetversionprefix=\"%s\"",
  149. XmlEncodeWithDefault(params->target_version_prefix(), "")
  150. .c_str());
  151. // Rollback requires target_version_prefix set.
  152. if (params->rollback_allowed()) {
  153. app_body += " rollback_allowed=\"true\"";
  154. }
  155. }
  156. app_body += "></updatecheck>\n";
  157. }
  158. // If this is the first update check after a reboot following a previous
  159. // update, generate an event containing the previous version number. If
  160. // the previous version preference file doesn't exist the event is still
  161. // generated with a previous version of 0.0.0.0 -- this is relevant for
  162. // older clients or new installs. The previous version event is not sent
  163. // for ping-only requests because they come before the client has
  164. // rebooted. The previous version event is also not sent if it was already
  165. // sent for this new version with a previous updatecheck.
  166. string prev_version;
  167. if (!prefs->GetString(kPrefsPreviousVersion, &prev_version)) {
  168. prev_version = "0.0.0.0";
  169. }
  170. // We only store a non-empty previous version value after a successful
  171. // update in the previous boot. After reporting it back to the server,
  172. // we clear the previous version value so it doesn't get reported again.
  173. if (!prev_version.empty()) {
  174. app_body += base::StringPrintf(
  175. " <event eventtype=\"%d\" eventresult=\"%d\" "
  176. "previousversion=\"%s\"></event>\n",
  177. OmahaEvent::kTypeRebootedAfterUpdate,
  178. OmahaEvent::kResultSuccess,
  179. XmlEncodeWithDefault(prev_version, "0.0.0.0").c_str());
  180. LOG_IF(WARNING, !prefs->SetString(kPrefsPreviousVersion, ""))
  181. << "Unable to reset the previous version.";
  182. }
  183. }
  184. } else {
  185. // The error code is an optional attribute so append it only if the result
  186. // is not success.
  187. string error_code;
  188. if (event->result != OmahaEvent::kResultSuccess) {
  189. error_code = base::StringPrintf(" errorcode=\"%d\"",
  190. static_cast<int>(event->error_code));
  191. }
  192. app_body = base::StringPrintf(
  193. " <event eventtype=\"%d\" eventresult=\"%d\"%s></event>\n",
  194. event->type,
  195. event->result,
  196. error_code.c_str());
  197. }
  198. return app_body;
  199. }
  200. // Returns the cohort* argument to include in the <app> tag for the passed
  201. // |arg_name| and |prefs_key|, if any. The return value is suitable to
  202. // concatenate to the list of arguments and includes a space at the end.
  203. string GetCohortArgXml(PrefsInterface* prefs,
  204. const string arg_name,
  205. const string prefs_key) {
  206. // There's nothing wrong with not having a given cohort setting, so we check
  207. // existence first to avoid the warning log message.
  208. if (!prefs->Exists(prefs_key))
  209. return "";
  210. string cohort_value;
  211. if (!prefs->GetString(prefs_key, &cohort_value) || cohort_value.empty())
  212. return "";
  213. // This is a sanity check to avoid sending a huge XML file back to Ohama due
  214. // to a compromised stateful partition making the update check fail in low
  215. // network environments envent after a reboot.
  216. if (cohort_value.size() > 1024) {
  217. LOG(WARNING) << "The omaha cohort setting " << arg_name
  218. << " has a too big value, which must be an error or an "
  219. "attacker trying to inhibit updates.";
  220. return "";
  221. }
  222. string escaped_xml_value;
  223. if (!XmlEncode(cohort_value, &escaped_xml_value)) {
  224. LOG(WARNING) << "The omaha cohort setting " << arg_name
  225. << " is ASCII-7 invalid, ignoring it.";
  226. return "";
  227. }
  228. return base::StringPrintf(
  229. "%s=\"%s\" ", arg_name.c_str(), escaped_xml_value.c_str());
  230. }
  231. struct OmahaAppData {
  232. string id;
  233. string version;
  234. string product_components;
  235. };
  236. bool IsValidComponentID(const string& id) {
  237. for (char c : id) {
  238. if (!isalnum(c) && c != '-' && c != '_' && c != '.')
  239. return false;
  240. }
  241. return true;
  242. }
  243. // Returns an XML that corresponds to the entire <app> node of the Omaha
  244. // request based on the given parameters.
  245. string GetAppXml(const OmahaEvent* event,
  246. OmahaRequestParams* params,
  247. const OmahaAppData& app_data,
  248. bool ping_only,
  249. bool include_ping,
  250. bool skip_updatecheck,
  251. int ping_active_days,
  252. int ping_roll_call_days,
  253. int install_date_in_days,
  254. SystemState* system_state) {
  255. string app_body = GetAppBody(event,
  256. params,
  257. ping_only,
  258. include_ping,
  259. skip_updatecheck,
  260. ping_active_days,
  261. ping_roll_call_days,
  262. system_state->prefs());
  263. string app_versions;
  264. // If we are downgrading to a more stable channel and we are allowed to do
  265. // powerwash, then pass 0.0.0.0 as the version. This is needed to get the
  266. // highest-versioned payload on the destination channel.
  267. if (params->ShouldPowerwash()) {
  268. LOG(INFO) << "Passing OS version as 0.0.0.0 as we are set to powerwash "
  269. << "on downgrading to the version in the more stable channel";
  270. app_versions = "version=\"0.0.0.0\" from_version=\"" +
  271. XmlEncodeWithDefault(app_data.version, "0.0.0.0") + "\" ";
  272. } else {
  273. app_versions = "version=\"" +
  274. XmlEncodeWithDefault(app_data.version, "0.0.0.0") + "\" ";
  275. }
  276. string download_channel = params->download_channel();
  277. string app_channels =
  278. "track=\"" + XmlEncodeWithDefault(download_channel, "") + "\" ";
  279. if (params->current_channel() != download_channel) {
  280. app_channels += "from_track=\"" +
  281. XmlEncodeWithDefault(params->current_channel(), "") + "\" ";
  282. }
  283. string delta_okay_str = params->delta_okay() ? "true" : "false";
  284. // If install_date_days is not set (e.g. its value is -1 ), don't
  285. // include the attribute.
  286. string install_date_in_days_str = "";
  287. if (install_date_in_days >= 0) {
  288. install_date_in_days_str =
  289. base::StringPrintf("installdate=\"%d\" ", install_date_in_days);
  290. }
  291. string app_cohort_args;
  292. app_cohort_args +=
  293. GetCohortArgXml(system_state->prefs(), "cohort", kPrefsOmahaCohort);
  294. app_cohort_args += GetCohortArgXml(
  295. system_state->prefs(), "cohorthint", kPrefsOmahaCohortHint);
  296. app_cohort_args += GetCohortArgXml(
  297. system_state->prefs(), "cohortname", kPrefsOmahaCohortName);
  298. string fingerprint_arg;
  299. if (!params->os_build_fingerprint().empty()) {
  300. fingerprint_arg = "fingerprint=\"" +
  301. XmlEncodeWithDefault(params->os_build_fingerprint(), "") +
  302. "\" ";
  303. }
  304. string buildtype_arg;
  305. if (!params->os_build_type().empty()) {
  306. buildtype_arg = "os_build_type=\"" +
  307. XmlEncodeWithDefault(params->os_build_type(), "") + "\" ";
  308. }
  309. string product_components_args;
  310. if (!params->ShouldPowerwash() && !app_data.product_components.empty()) {
  311. brillo::KeyValueStore store;
  312. if (store.LoadFromString(app_data.product_components)) {
  313. for (const string& key : store.GetKeys()) {
  314. if (!IsValidComponentID(key)) {
  315. LOG(ERROR) << "Invalid component id: " << key;
  316. continue;
  317. }
  318. string version;
  319. if (!store.GetString(key, &version)) {
  320. LOG(ERROR) << "Failed to get version for " << key
  321. << " in product_components.";
  322. continue;
  323. }
  324. product_components_args +=
  325. base::StringPrintf("_%s.version=\"%s\" ",
  326. key.c_str(),
  327. XmlEncodeWithDefault(version, "").c_str());
  328. }
  329. } else {
  330. LOG(ERROR) << "Failed to parse product_components:\n"
  331. << app_data.product_components;
  332. }
  333. }
  334. // clang-format off
  335. string app_xml = " <app "
  336. "appid=\"" + XmlEncodeWithDefault(app_data.id, "") + "\" " +
  337. app_cohort_args +
  338. app_versions +
  339. app_channels +
  340. product_components_args +
  341. fingerprint_arg +
  342. buildtype_arg +
  343. "lang=\"" + XmlEncodeWithDefault(params->app_lang(), "en-US") + "\" " +
  344. "board=\"" + XmlEncodeWithDefault(params->os_board(), "") + "\" " +
  345. "hardware_class=\"" + XmlEncodeWithDefault(params->hwid(), "") + "\" " +
  346. "delta_okay=\"" + delta_okay_str + "\" "
  347. "fw_version=\"" + XmlEncodeWithDefault(params->fw_version(), "") + "\" " +
  348. "ec_version=\"" + XmlEncodeWithDefault(params->ec_version(), "") + "\" " +
  349. install_date_in_days_str +
  350. ">\n" +
  351. app_body +
  352. " </app>\n";
  353. // clang-format on
  354. return app_xml;
  355. }
  356. // Returns an XML that corresponds to the entire <os> node of the Omaha
  357. // request based on the given parameters.
  358. string GetOsXml(OmahaRequestParams* params) {
  359. string os_xml =
  360. " <os "
  361. "version=\"" +
  362. XmlEncodeWithDefault(params->os_version(), "") + "\" " + "platform=\"" +
  363. XmlEncodeWithDefault(params->os_platform(), "") + "\" " + "sp=\"" +
  364. XmlEncodeWithDefault(params->os_sp(), "") +
  365. "\">"
  366. "</os>\n";
  367. return os_xml;
  368. }
  369. // Returns an XML that corresponds to the entire Omaha request based on the
  370. // given parameters.
  371. string GetRequestXml(const OmahaEvent* event,
  372. OmahaRequestParams* params,
  373. bool ping_only,
  374. bool include_ping,
  375. int ping_active_days,
  376. int ping_roll_call_days,
  377. int install_date_in_days,
  378. SystemState* system_state) {
  379. string os_xml = GetOsXml(params);
  380. OmahaAppData product_app = {
  381. .id = params->GetAppId(),
  382. .version = params->app_version(),
  383. .product_components = params->product_components()};
  384. // Skips updatecheck for platform app in case of an install operation.
  385. string app_xml = GetAppXml(event,
  386. params,
  387. product_app,
  388. ping_only,
  389. include_ping,
  390. params->is_install(), /* skip_updatecheck */
  391. ping_active_days,
  392. ping_roll_call_days,
  393. install_date_in_days,
  394. system_state);
  395. if (!params->system_app_id().empty()) {
  396. OmahaAppData system_app = {.id = params->system_app_id(),
  397. .version = params->system_version()};
  398. app_xml += GetAppXml(event,
  399. params,
  400. system_app,
  401. ping_only,
  402. include_ping,
  403. false, /* skip_updatecheck */
  404. ping_active_days,
  405. ping_roll_call_days,
  406. install_date_in_days,
  407. system_state);
  408. }
  409. // Create APP ID according to |dlc_module_id| (sticking the current AppID to
  410. // the DLC module ID with an underscode).
  411. for (const auto& dlc_module_id : params->dlc_module_ids()) {
  412. OmahaAppData dlc_module_app = {
  413. .id = params->GetAppId() + "_" + dlc_module_id,
  414. .version = params->app_version()};
  415. app_xml += GetAppXml(event,
  416. params,
  417. dlc_module_app,
  418. ping_only,
  419. include_ping,
  420. false, /* skip_updatecheck */
  421. ping_active_days,
  422. ping_roll_call_days,
  423. install_date_in_days,
  424. system_state);
  425. }
  426. string install_source = base::StringPrintf(
  427. "installsource=\"%s\" ",
  428. (params->interactive() ? "ondemandupdate" : "scheduler"));
  429. string updater_version = XmlEncodeWithDefault(
  430. base::StringPrintf(
  431. "%s-%s", constants::kOmahaUpdaterID, kOmahaUpdaterVersion),
  432. "");
  433. string request_xml =
  434. "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  435. "<request protocol=\"3.0\" " +
  436. ("version=\"" + updater_version +
  437. "\" "
  438. "updaterversion=\"" +
  439. updater_version + "\" " + install_source + "ismachine=\"1\">\n") +
  440. os_xml + app_xml + "</request>\n";
  441. return request_xml;
  442. }
  443. } // namespace
  444. // Struct used for holding data obtained when parsing the XML.
  445. struct OmahaParserData {
  446. explicit OmahaParserData(XML_Parser _xml_parser) : xml_parser(_xml_parser) {}
  447. // Pointer to the expat XML_Parser object.
  448. XML_Parser xml_parser;
  449. // This is the state of the parser as it's processing the XML.
  450. bool failed = false;
  451. bool entity_decl = false;
  452. string current_path;
  453. // These are the values extracted from the XML.
  454. string updatecheck_poll_interval;
  455. map<string, string> updatecheck_attrs;
  456. string daystart_elapsed_days;
  457. string daystart_elapsed_seconds;
  458. struct App {
  459. string id;
  460. vector<string> url_codebase;
  461. string manifest_version;
  462. map<string, string> action_postinstall_attrs;
  463. string updatecheck_status;
  464. string cohort;
  465. string cohorthint;
  466. string cohortname;
  467. bool cohort_set = false;
  468. bool cohorthint_set = false;
  469. bool cohortname_set = false;
  470. struct Package {
  471. string name;
  472. string size;
  473. string hash;
  474. };
  475. vector<Package> packages;
  476. };
  477. vector<App> apps;
  478. };
  479. namespace {
  480. // Callback function invoked by expat.
  481. void ParserHandlerStart(void* user_data,
  482. const XML_Char* element,
  483. const XML_Char** attr) {
  484. OmahaParserData* data = reinterpret_cast<OmahaParserData*>(user_data);
  485. if (data->failed)
  486. return;
  487. data->current_path += string("/") + element;
  488. map<string, string> attrs;
  489. if (attr != nullptr) {
  490. for (int n = 0; attr[n] != nullptr && attr[n + 1] != nullptr; n += 2) {
  491. string key = attr[n];
  492. string value = attr[n + 1];
  493. attrs[key] = value;
  494. }
  495. }
  496. if (data->current_path == "/response/app") {
  497. OmahaParserData::App app;
  498. if (attrs.find(kAttrAppId) != attrs.end()) {
  499. app.id = attrs[kAttrAppId];
  500. }
  501. if (attrs.find(kAttrCohort) != attrs.end()) {
  502. app.cohort_set = true;
  503. app.cohort = attrs[kAttrCohort];
  504. }
  505. if (attrs.find(kAttrCohortHint) != attrs.end()) {
  506. app.cohorthint_set = true;
  507. app.cohorthint = attrs[kAttrCohortHint];
  508. }
  509. if (attrs.find(kAttrCohortName) != attrs.end()) {
  510. app.cohortname_set = true;
  511. app.cohortname = attrs[kAttrCohortName];
  512. }
  513. data->apps.push_back(std::move(app));
  514. } else if (data->current_path == "/response/app/updatecheck") {
  515. if (!data->apps.empty())
  516. data->apps.back().updatecheck_status = attrs[kAttrStatus];
  517. if (data->updatecheck_poll_interval.empty())
  518. data->updatecheck_poll_interval = attrs[kAttrPollInterval];
  519. // Omaha sends arbitrary key-value pairs as extra attributes starting with
  520. // an underscore.
  521. for (const auto& attr : attrs) {
  522. if (!attr.first.empty() && attr.first[0] == '_')
  523. data->updatecheck_attrs[attr.first.substr(1)] = attr.second;
  524. }
  525. } else if (data->current_path == "/response/daystart") {
  526. // Get the install-date.
  527. data->daystart_elapsed_days = attrs[kAttrElapsedDays];
  528. data->daystart_elapsed_seconds = attrs[kAttrElapsedSeconds];
  529. } else if (data->current_path == "/response/app/updatecheck/urls/url") {
  530. // Look at all <url> elements.
  531. if (!data->apps.empty())
  532. data->apps.back().url_codebase.push_back(attrs[kAttrCodeBase]);
  533. } else if (data->current_path ==
  534. "/response/app/updatecheck/manifest/packages/package") {
  535. // Look at all <package> elements.
  536. if (!data->apps.empty())
  537. data->apps.back().packages.push_back({.name = attrs[kAttrName],
  538. .size = attrs[kAttrSize],
  539. .hash = attrs[kAttrHashSha256]});
  540. } else if (data->current_path == "/response/app/updatecheck/manifest") {
  541. // Get the version.
  542. if (!data->apps.empty())
  543. data->apps.back().manifest_version = attrs[kAttrVersion];
  544. } else if (data->current_path ==
  545. "/response/app/updatecheck/manifest/actions/action") {
  546. // We only care about the postinstall action.
  547. if (attrs[kAttrEvent] == kValPostInstall && !data->apps.empty()) {
  548. data->apps.back().action_postinstall_attrs = std::move(attrs);
  549. }
  550. }
  551. }
  552. // Callback function invoked by expat.
  553. void ParserHandlerEnd(void* user_data, const XML_Char* element) {
  554. OmahaParserData* data = reinterpret_cast<OmahaParserData*>(user_data);
  555. if (data->failed)
  556. return;
  557. const string path_suffix = string("/") + element;
  558. if (!base::EndsWith(
  559. data->current_path, path_suffix, base::CompareCase::SENSITIVE)) {
  560. LOG(ERROR) << "Unexpected end element '" << element
  561. << "' with current_path='" << data->current_path << "'";
  562. data->failed = true;
  563. return;
  564. }
  565. data->current_path.resize(data->current_path.size() - path_suffix.size());
  566. }
  567. // Callback function invoked by expat.
  568. //
  569. // This is called for entity declarations. Since Omaha is guaranteed
  570. // to never return any XML with entities our course of action is to
  571. // just stop parsing. This avoids potential resource exhaustion
  572. // problems AKA the "billion laughs". CVE-2013-0340.
  573. void ParserHandlerEntityDecl(void* user_data,
  574. const XML_Char* entity_name,
  575. int is_parameter_entity,
  576. const XML_Char* value,
  577. int value_length,
  578. const XML_Char* base,
  579. const XML_Char* system_id,
  580. const XML_Char* public_id,
  581. const XML_Char* notation_name) {
  582. OmahaParserData* data = reinterpret_cast<OmahaParserData*>(user_data);
  583. LOG(ERROR) << "XML entities are not supported. Aborting parsing.";
  584. data->failed = true;
  585. data->entity_decl = true;
  586. XML_StopParser(data->xml_parser, false);
  587. }
  588. } // namespace
  589. bool XmlEncode(const string& input, string* output) {
  590. if (std::find_if(input.begin(), input.end(), [](const char c) {
  591. return c & 0x80;
  592. }) != input.end()) {
  593. LOG(WARNING) << "Invalid ASCII-7 string passed to the XML encoder:";
  594. utils::HexDumpString(input);
  595. return false;
  596. }
  597. output->clear();
  598. // We need at least input.size() space in the output, but the code below will
  599. // handle it if we need more.
  600. output->reserve(input.size());
  601. for (char c : input) {
  602. switch (c) {
  603. case '\"':
  604. output->append("&quot;");
  605. break;
  606. case '\'':
  607. output->append("&apos;");
  608. break;
  609. case '&':
  610. output->append("&amp;");
  611. break;
  612. case '<':
  613. output->append("&lt;");
  614. break;
  615. case '>':
  616. output->append("&gt;");
  617. break;
  618. default:
  619. output->push_back(c);
  620. }
  621. }
  622. return true;
  623. }
  624. string XmlEncodeWithDefault(const string& input, const string& default_value) {
  625. string output;
  626. if (XmlEncode(input, &output))
  627. return output;
  628. return default_value;
  629. }
  630. OmahaRequestAction::OmahaRequestAction(
  631. SystemState* system_state,
  632. OmahaEvent* event,
  633. std::unique_ptr<HttpFetcher> http_fetcher,
  634. bool ping_only)
  635. : system_state_(system_state),
  636. params_(system_state->request_params()),
  637. event_(event),
  638. http_fetcher_(std::move(http_fetcher)),
  639. policy_provider_(std::make_unique<policy::PolicyProvider>()),
  640. ping_only_(ping_only),
  641. ping_active_days_(0),
  642. ping_roll_call_days_(0) {
  643. policy_provider_->Reload();
  644. }
  645. OmahaRequestAction::~OmahaRequestAction() {}
  646. // Calculates the value to use for the ping days parameter.
  647. int OmahaRequestAction::CalculatePingDays(const string& key) {
  648. int days = kNeverPinged;
  649. int64_t last_ping = 0;
  650. if (system_state_->prefs()->GetInt64(key, &last_ping) && last_ping >= 0) {
  651. days = (Time::Now() - Time::FromInternalValue(last_ping)).InDays();
  652. if (days < 0) {
  653. // If |days| is negative, then the system clock must have jumped
  654. // back in time since the ping was sent. Mark the value so that
  655. // it doesn't get sent to the server but we still update the
  656. // last ping daystart preference. This way the next ping time
  657. // will be correct, hopefully.
  658. days = kPingTimeJump;
  659. LOG(WARNING)
  660. << "System clock jumped back in time. Resetting ping daystarts.";
  661. }
  662. }
  663. return days;
  664. }
  665. void OmahaRequestAction::InitPingDays() {
  666. // We send pings only along with update checks, not with events.
  667. if (IsEvent()) {
  668. return;
  669. }
  670. // TODO(petkov): Figure a way to distinguish active use pings
  671. // vs. roll call pings. Currently, the two pings are identical. A
  672. // fix needs to change this code as well as UpdateLastPingDays and ShouldPing.
  673. ping_active_days_ = CalculatePingDays(kPrefsLastActivePingDay);
  674. ping_roll_call_days_ = CalculatePingDays(kPrefsLastRollCallPingDay);
  675. }
  676. bool OmahaRequestAction::ShouldPing() const {
  677. if (ping_active_days_ == OmahaRequestAction::kNeverPinged &&
  678. ping_roll_call_days_ == OmahaRequestAction::kNeverPinged) {
  679. int powerwash_count = system_state_->hardware()->GetPowerwashCount();
  680. if (powerwash_count > 0) {
  681. LOG(INFO) << "Not sending ping with a=-1 r=-1 to omaha because "
  682. << "powerwash_count is " << powerwash_count;
  683. return false;
  684. }
  685. if (system_state_->hardware()->GetFirstActiveOmahaPingSent()) {
  686. LOG(INFO) << "Not sending ping with a=-1 r=-1 to omaha because "
  687. << "the first_active_omaha_ping_sent is true";
  688. return false;
  689. }
  690. return true;
  691. }
  692. return ping_active_days_ > 0 || ping_roll_call_days_ > 0;
  693. }
  694. // static
  695. int OmahaRequestAction::GetInstallDate(SystemState* system_state) {
  696. PrefsInterface* prefs = system_state->prefs();
  697. if (prefs == nullptr)
  698. return -1;
  699. // If we have the value stored on disk, just return it.
  700. int64_t stored_value;
  701. if (prefs->GetInt64(kPrefsInstallDateDays, &stored_value)) {
  702. // Convert and sanity-check.
  703. int install_date_days = static_cast<int>(stored_value);
  704. if (install_date_days >= 0)
  705. return install_date_days;
  706. LOG(ERROR) << "Dropping stored Omaha InstallData since its value num_days="
  707. << install_date_days << " looks suspicious.";
  708. prefs->Delete(kPrefsInstallDateDays);
  709. }
  710. // Otherwise, if OOBE is not complete then do nothing and wait for
  711. // ParseResponse() to call ParseInstallDate() and then
  712. // PersistInstallDate() to set the kPrefsInstallDateDays state
  713. // variable. Once that is done, we'll then report back in future
  714. // Omaha requests. This works exactly because OOBE triggers an
  715. // update check.
  716. //
  717. // However, if OOBE is complete and the kPrefsInstallDateDays state
  718. // variable is not set, there are two possibilities
  719. //
  720. // 1. The update check in OOBE failed so we never got a response
  721. // from Omaha (no network etc.); or
  722. //
  723. // 2. OOBE was done on an older version that didn't write to the
  724. // kPrefsInstallDateDays state variable.
  725. //
  726. // In both cases, we approximate the install date by simply
  727. // inspecting the timestamp of when OOBE happened.
  728. Time time_of_oobe;
  729. if (!system_state->hardware()->IsOOBEEnabled() ||
  730. !system_state->hardware()->IsOOBEComplete(&time_of_oobe)) {
  731. LOG(INFO) << "Not generating Omaha InstallData as we have "
  732. << "no prefs file and OOBE is not complete or not enabled.";
  733. return -1;
  734. }
  735. int num_days;
  736. if (!utils::ConvertToOmahaInstallDate(time_of_oobe, &num_days)) {
  737. LOG(ERROR) << "Not generating Omaha InstallData from time of OOBE "
  738. << "as its value '" << utils::ToString(time_of_oobe)
  739. << "' looks suspicious.";
  740. return -1;
  741. }
  742. // Persist this to disk, for future use.
  743. if (!OmahaRequestAction::PersistInstallDate(
  744. system_state, num_days, kProvisionedFromOOBEMarker))
  745. return -1;
  746. LOG(INFO) << "Set the Omaha InstallDate from OOBE time-stamp to " << num_days
  747. << " days";
  748. return num_days;
  749. }
  750. void OmahaRequestAction::PerformAction() {
  751. http_fetcher_->set_delegate(this);
  752. InitPingDays();
  753. if (ping_only_ && !ShouldPing()) {
  754. processor_->ActionComplete(this, ErrorCode::kSuccess);
  755. return;
  756. }
  757. string request_post(GetRequestXml(event_.get(),
  758. params_,
  759. ping_only_,
  760. ShouldPing(), // include_ping
  761. ping_active_days_,
  762. ping_roll_call_days_,
  763. GetInstallDate(system_state_),
  764. system_state_));
  765. // Set X-Goog-Update headers.
  766. http_fetcher_->SetHeader(kXGoogleUpdateInteractivity,
  767. params_->interactive() ? "fg" : "bg");
  768. http_fetcher_->SetHeader(kXGoogleUpdateAppId, params_->GetAppId());
  769. http_fetcher_->SetHeader(
  770. kXGoogleUpdateUpdater,
  771. base::StringPrintf(
  772. "%s-%s", constants::kOmahaUpdaterID, kOmahaUpdaterVersion));
  773. http_fetcher_->SetPostData(
  774. request_post.data(), request_post.size(), kHttpContentTypeTextXml);
  775. LOG(INFO) << "Posting an Omaha request to " << params_->update_url();
  776. LOG(INFO) << "Request: " << request_post;
  777. http_fetcher_->BeginTransfer(params_->update_url());
  778. }
  779. void OmahaRequestAction::TerminateProcessing() {
  780. http_fetcher_->TerminateTransfer();
  781. }
  782. // We just store the response in the buffer. Once we've received all bytes,
  783. // we'll look in the buffer and decide what to do.
  784. bool OmahaRequestAction::ReceivedBytes(HttpFetcher* fetcher,
  785. const void* bytes,
  786. size_t length) {
  787. const uint8_t* byte_ptr = reinterpret_cast<const uint8_t*>(bytes);
  788. response_buffer_.insert(response_buffer_.end(), byte_ptr, byte_ptr + length);
  789. return true;
  790. }
  791. namespace {
  792. // Parses a 64 bit base-10 int from a string and returns it. Returns 0
  793. // on error. If the string contains "0", that's indistinguishable from
  794. // error.
  795. off_t ParseInt(const string& str) {
  796. off_t ret = 0;
  797. int rc = sscanf(str.c_str(), "%" PRIi64, &ret); // NOLINT(runtime/printf)
  798. if (rc < 1) {
  799. // failure
  800. return 0;
  801. }
  802. return ret;
  803. }
  804. // Parses |str| and returns |true| if, and only if, its value is "true".
  805. bool ParseBool(const string& str) {
  806. return str == "true";
  807. }
  808. // Update the last ping day preferences based on the server daystart
  809. // response. Returns true on success, false otherwise.
  810. bool UpdateLastPingDays(OmahaParserData* parser_data, PrefsInterface* prefs) {
  811. int64_t elapsed_seconds = 0;
  812. TEST_AND_RETURN_FALSE(base::StringToInt64(
  813. parser_data->daystart_elapsed_seconds, &elapsed_seconds));
  814. TEST_AND_RETURN_FALSE(elapsed_seconds >= 0);
  815. // Remember the local time that matches the server's last midnight
  816. // time.
  817. Time daystart = Time::Now() - TimeDelta::FromSeconds(elapsed_seconds);
  818. prefs->SetInt64(kPrefsLastActivePingDay, daystart.ToInternalValue());
  819. prefs->SetInt64(kPrefsLastRollCallPingDay, daystart.ToInternalValue());
  820. return true;
  821. }
  822. // Parses the package node in the given XML document and populates
  823. // |output_object| if valid. Returns true if we should continue the parsing.
  824. // False otherwise, in which case it sets any error code using |completer|.
  825. bool ParsePackage(OmahaParserData::App* app,
  826. OmahaResponse* output_object,
  827. ScopedActionCompleter* completer) {
  828. if (app->updatecheck_status.empty() ||
  829. app->updatecheck_status == kValNoUpdate) {
  830. if (!app->packages.empty()) {
  831. LOG(ERROR) << "No update in this <app> but <package> is not empty.";
  832. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  833. return false;
  834. }
  835. return true;
  836. }
  837. if (app->packages.empty()) {
  838. LOG(ERROR) << "Omaha Response has no packages";
  839. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  840. return false;
  841. }
  842. if (app->url_codebase.empty()) {
  843. LOG(ERROR) << "No Omaha Response URLs";
  844. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  845. return false;
  846. }
  847. LOG(INFO) << "Found " << app->url_codebase.size() << " url(s)";
  848. vector<string> metadata_sizes =
  849. base::SplitString(app->action_postinstall_attrs[kAttrMetadataSize],
  850. ":",
  851. base::TRIM_WHITESPACE,
  852. base::SPLIT_WANT_ALL);
  853. vector<string> metadata_signatures = base::SplitString(
  854. app->action_postinstall_attrs[kAttrMetadataSignatureRsa],
  855. ":",
  856. base::TRIM_WHITESPACE,
  857. base::SPLIT_WANT_ALL);
  858. vector<string> is_delta_payloads =
  859. base::SplitString(app->action_postinstall_attrs[kAttrIsDeltaPayload],
  860. ":",
  861. base::TRIM_WHITESPACE,
  862. base::SPLIT_WANT_ALL);
  863. for (size_t i = 0; i < app->packages.size(); i++) {
  864. const auto& package = app->packages[i];
  865. if (package.name.empty()) {
  866. LOG(ERROR) << "Omaha Response has empty package name";
  867. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  868. return false;
  869. }
  870. LOG(INFO) << "Found package " << package.name;
  871. OmahaResponse::Package out_package;
  872. for (const string& codebase : app->url_codebase) {
  873. if (codebase.empty()) {
  874. LOG(ERROR) << "Omaha Response URL has empty codebase";
  875. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  876. return false;
  877. }
  878. out_package.payload_urls.push_back(codebase + package.name);
  879. }
  880. // Parse the payload size.
  881. base::StringToUint64(package.size, &out_package.size);
  882. if (out_package.size <= 0) {
  883. LOG(ERROR) << "Omaha Response has invalid payload size: " << package.size;
  884. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  885. return false;
  886. }
  887. LOG(INFO) << "Payload size = " << out_package.size << " bytes";
  888. if (i < metadata_sizes.size())
  889. base::StringToUint64(metadata_sizes[i], &out_package.metadata_size);
  890. LOG(INFO) << "Payload metadata size = " << out_package.metadata_size
  891. << " bytes";
  892. if (i < metadata_signatures.size())
  893. out_package.metadata_signature = metadata_signatures[i];
  894. LOG(INFO) << "Payload metadata signature = "
  895. << out_package.metadata_signature;
  896. out_package.hash = package.hash;
  897. if (out_package.hash.empty()) {
  898. LOG(ERROR) << "Omaha Response has empty hash_sha256 value";
  899. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  900. return false;
  901. }
  902. LOG(INFO) << "Payload hash = " << out_package.hash;
  903. if (i < is_delta_payloads.size())
  904. out_package.is_delta = ParseBool(is_delta_payloads[i]);
  905. LOG(INFO) << "Payload is delta = " << utils::ToString(out_package.is_delta);
  906. output_object->packages.push_back(std::move(out_package));
  907. }
  908. return true;
  909. }
  910. // Parses the 2 key version strings kernel_version and firmware_version. If the
  911. // field is not present, or cannot be parsed the values default to 0xffff.
  912. void ParseRollbackVersions(OmahaParserData* parser_data,
  913. OmahaResponse* output_object) {
  914. utils::ParseRollbackKeyVersion(
  915. parser_data->updatecheck_attrs[kAttrFirmwareVersion],
  916. &output_object->rollback_key_version.firmware_key,
  917. &output_object->rollback_key_version.firmware);
  918. utils::ParseRollbackKeyVersion(
  919. parser_data->updatecheck_attrs[kAttrKernelVersion],
  920. &output_object->rollback_key_version.kernel_key,
  921. &output_object->rollback_key_version.kernel);
  922. }
  923. } // namespace
  924. bool OmahaRequestAction::ParseResponse(OmahaParserData* parser_data,
  925. OmahaResponse* output_object,
  926. ScopedActionCompleter* completer) {
  927. if (parser_data->apps.empty()) {
  928. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  929. return false;
  930. }
  931. LOG(INFO) << "Found " << parser_data->apps.size() << " <app>.";
  932. // chromium-os:37289: The PollInterval is not supported by Omaha server
  933. // currently. But still keeping this existing code in case we ever decide to
  934. // slow down the request rate from the server-side. Note that the PollInterval
  935. // is not persisted, so it has to be sent by the server on every response to
  936. // guarantee that the scheduler uses this value (otherwise, if the device got
  937. // rebooted after the last server-indicated value, it'll revert to the default
  938. // value). Also kDefaultMaxUpdateChecks value for the scattering logic is
  939. // based on the assumption that we perform an update check every hour so that
  940. // the max value of 8 will roughly be equivalent to one work day. If we decide
  941. // to use PollInterval permanently, we should update the
  942. // max_update_checks_allowed to take PollInterval into account. Note: The
  943. // parsing for PollInterval happens even before parsing of the status because
  944. // we may want to specify the PollInterval even when there's no update.
  945. base::StringToInt(parser_data->updatecheck_poll_interval,
  946. &output_object->poll_interval);
  947. // Check for the "elapsed_days" attribute in the "daystart"
  948. // element. This is the number of days since Jan 1 2007, 0:00
  949. // PST. If we don't have a persisted value of the Omaha InstallDate,
  950. // we'll use it to calculate it and then persist it.
  951. if (ParseInstallDate(parser_data, output_object) &&
  952. !HasInstallDate(system_state_)) {
  953. // Since output_object->install_date_days is never negative, the
  954. // elapsed_days -> install-date calculation is reduced to simply
  955. // rounding down to the nearest number divisible by 7.
  956. int remainder = output_object->install_date_days % 7;
  957. int install_date_days_rounded =
  958. output_object->install_date_days - remainder;
  959. if (PersistInstallDate(system_state_,
  960. install_date_days_rounded,
  961. kProvisionedFromOmahaResponse)) {
  962. LOG(INFO) << "Set the Omaha InstallDate from Omaha Response to "
  963. << install_date_days_rounded << " days";
  964. }
  965. }
  966. // We persist the cohorts sent by omaha even if the status is "noupdate".
  967. for (const auto& app : parser_data->apps) {
  968. if (app.id == params_->GetAppId()) {
  969. if (app.cohort_set)
  970. PersistCohortData(kPrefsOmahaCohort, app.cohort);
  971. if (app.cohorthint_set)
  972. PersistCohortData(kPrefsOmahaCohortHint, app.cohorthint);
  973. if (app.cohortname_set)
  974. PersistCohortData(kPrefsOmahaCohortName, app.cohortname);
  975. break;
  976. }
  977. }
  978. // Parse the updatecheck attributes.
  979. PersistEolStatus(parser_data->updatecheck_attrs);
  980. // Rollback-related updatecheck attributes.
  981. // Defaults to false if attribute is not present.
  982. output_object->is_rollback =
  983. ParseBool(parser_data->updatecheck_attrs[kAttrRollback]);
  984. // Parses the rollback versions of the current image. If the fields do not
  985. // exist they default to 0xffff for the 4 key versions.
  986. ParseRollbackVersions(parser_data, output_object);
  987. if (!ParseStatus(parser_data, output_object, completer))
  988. return false;
  989. if (!ParseParams(parser_data, output_object, completer))
  990. return false;
  991. // Package has to be parsed after Params now because ParseParams need to make
  992. // sure that postinstall action exists.
  993. for (auto& app : parser_data->apps)
  994. if (!ParsePackage(&app, output_object, completer))
  995. return false;
  996. return true;
  997. }
  998. bool OmahaRequestAction::ParseStatus(OmahaParserData* parser_data,
  999. OmahaResponse* output_object,
  1000. ScopedActionCompleter* completer) {
  1001. output_object->update_exists = false;
  1002. for (const auto& app : parser_data->apps) {
  1003. const string& status = app.updatecheck_status;
  1004. if (status == kValNoUpdate) {
  1005. // Don't update if any app has status="noupdate".
  1006. LOG(INFO) << "No update for <app> " << app.id;
  1007. output_object->update_exists = false;
  1008. break;
  1009. } else if (status == "ok") {
  1010. auto const& attr_no_update =
  1011. app.action_postinstall_attrs.find(kAttrNoUpdate);
  1012. if (attr_no_update != app.action_postinstall_attrs.end() &&
  1013. attr_no_update->second == "true") {
  1014. // noupdate="true" in postinstall attributes means it's an update to
  1015. // self, only update if there's at least one app really have update.
  1016. LOG(INFO) << "Update to self for <app> " << app.id;
  1017. } else {
  1018. LOG(INFO) << "Update for <app> " << app.id;
  1019. output_object->update_exists = true;
  1020. }
  1021. } else if (status.empty() && params_->is_install() &&
  1022. params_->GetAppId() == app.id) {
  1023. // Skips the platform app for install operation.
  1024. LOG(INFO) << "No payload (and ignore) for <app> " << app.id;
  1025. } else {
  1026. LOG(ERROR) << "Unknown Omaha response status: " << status;
  1027. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  1028. return false;
  1029. }
  1030. }
  1031. if (!output_object->update_exists) {
  1032. SetOutputObject(*output_object);
  1033. completer->set_code(ErrorCode::kSuccess);
  1034. }
  1035. return output_object->update_exists;
  1036. }
  1037. bool OmahaRequestAction::ParseParams(OmahaParserData* parser_data,
  1038. OmahaResponse* output_object,
  1039. ScopedActionCompleter* completer) {
  1040. map<string, string> attrs;
  1041. for (auto& app : parser_data->apps) {
  1042. if (app.id == params_->GetAppId()) {
  1043. // this is the app (potentially the only app)
  1044. output_object->version = app.manifest_version;
  1045. } else if (!params_->system_app_id().empty() &&
  1046. app.id == params_->system_app_id()) {
  1047. // this is the system app (this check is intentionally skipped if there is
  1048. // no system_app_id set)
  1049. output_object->system_version = app.manifest_version;
  1050. } else if (params_->is_install() &&
  1051. app.manifest_version != params_->app_version()) {
  1052. LOG(WARNING) << "An app has a different version (" << app.manifest_version
  1053. << ") that is different than platform app version ("
  1054. << params_->app_version() << ")";
  1055. }
  1056. if (!app.action_postinstall_attrs.empty() && attrs.empty()) {
  1057. attrs = app.action_postinstall_attrs;
  1058. }
  1059. }
  1060. if (params_->is_install()) {
  1061. LOG(INFO) << "Use request version for Install operation.";
  1062. output_object->version = params_->app_version();
  1063. }
  1064. if (output_object->version.empty()) {
  1065. LOG(ERROR) << "Omaha Response does not have version in manifest!";
  1066. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  1067. return false;
  1068. }
  1069. LOG(INFO) << "Received omaha response to update to version "
  1070. << output_object->version;
  1071. if (attrs.empty()) {
  1072. LOG(ERROR) << "Omaha Response has no postinstall event action";
  1073. completer->set_code(ErrorCode::kOmahaResponseInvalid);
  1074. return false;
  1075. }
  1076. // Get the optional properties one by one.
  1077. output_object->more_info_url = attrs[kAttrMoreInfo];
  1078. output_object->prompt = ParseBool(attrs[kAttrPrompt]);
  1079. output_object->deadline = attrs[kAttrDeadline];
  1080. output_object->max_days_to_scatter = ParseInt(attrs[kAttrMaxDaysToScatter]);
  1081. output_object->disable_p2p_for_downloading =
  1082. ParseBool(attrs[kAttrDisableP2PForDownloading]);
  1083. output_object->disable_p2p_for_sharing =
  1084. ParseBool(attrs[kAttrDisableP2PForSharing]);
  1085. output_object->public_key_rsa = attrs[kAttrPublicKeyRsa];
  1086. string max = attrs[kAttrMaxFailureCountPerUrl];
  1087. if (!base::StringToUint(max, &output_object->max_failure_count_per_url))
  1088. output_object->max_failure_count_per_url = kDefaultMaxFailureCountPerUrl;
  1089. output_object->disable_payload_backoff =
  1090. ParseBool(attrs[kAttrDisablePayloadBackoff]);
  1091. output_object->powerwash_required = ParseBool(attrs[kAttrPowerwash]);
  1092. return true;
  1093. }
  1094. // If the transfer was successful, this uses expat to parse the response
  1095. // and fill in the appropriate fields of the output object. Also, notifies
  1096. // the processor that we're done.
  1097. void OmahaRequestAction::TransferComplete(HttpFetcher* fetcher,
  1098. bool successful) {
  1099. ScopedActionCompleter completer(processor_, this);
  1100. string current_response(response_buffer_.begin(), response_buffer_.end());
  1101. LOG(INFO) << "Omaha request response: " << current_response;
  1102. PayloadStateInterface* const payload_state = system_state_->payload_state();
  1103. // Set the max kernel key version based on whether rollback is allowed.
  1104. SetMaxKernelKeyVersionForRollback();
  1105. // Events are best effort transactions -- assume they always succeed.
  1106. if (IsEvent()) {
  1107. CHECK(!HasOutputPipe()) << "No output pipe allowed for event requests.";
  1108. completer.set_code(ErrorCode::kSuccess);
  1109. return;
  1110. }
  1111. if (!successful) {
  1112. LOG(ERROR) << "Omaha request network transfer failed.";
  1113. int code = GetHTTPResponseCode();
  1114. // Makes sure we send sane error values.
  1115. if (code < 0 || code >= 1000) {
  1116. code = 999;
  1117. }
  1118. completer.set_code(static_cast<ErrorCode>(
  1119. static_cast<int>(ErrorCode::kOmahaRequestHTTPResponseBase) + code));
  1120. return;
  1121. }
  1122. XML_Parser parser = XML_ParserCreate(nullptr);
  1123. OmahaParserData parser_data(parser);
  1124. XML_SetUserData(parser, &parser_data);
  1125. XML_SetElementHandler(parser, ParserHandlerStart, ParserHandlerEnd);
  1126. XML_SetEntityDeclHandler(parser, ParserHandlerEntityDecl);
  1127. XML_Status res =
  1128. XML_Parse(parser,
  1129. reinterpret_cast<const char*>(response_buffer_.data()),
  1130. response_buffer_.size(),
  1131. XML_TRUE);
  1132. if (res != XML_STATUS_OK || parser_data.failed) {
  1133. LOG(ERROR) << "Omaha response not valid XML: "
  1134. << XML_ErrorString(XML_GetErrorCode(parser)) << " at line "
  1135. << XML_GetCurrentLineNumber(parser) << " col "
  1136. << XML_GetCurrentColumnNumber(parser);
  1137. XML_ParserFree(parser);
  1138. ErrorCode error_code = ErrorCode::kOmahaRequestXMLParseError;
  1139. if (response_buffer_.empty()) {
  1140. error_code = ErrorCode::kOmahaRequestEmptyResponseError;
  1141. } else if (parser_data.entity_decl) {
  1142. error_code = ErrorCode::kOmahaRequestXMLHasEntityDecl;
  1143. }
  1144. completer.set_code(error_code);
  1145. return;
  1146. }
  1147. XML_ParserFree(parser);
  1148. // Update the last ping day preferences based on the server daystart response
  1149. // even if we didn't send a ping. Omaha always includes the daystart in the
  1150. // response, but log the error if it didn't.
  1151. LOG_IF(ERROR, !UpdateLastPingDays(&parser_data, system_state_->prefs()))
  1152. << "Failed to update the last ping day preferences!";
  1153. // Sets first_active_omaha_ping_sent to true (vpd in CrOS). We only do this if
  1154. // we have got a response from omaha and if its value has never been set to
  1155. // true before. Failure of this function should be ignored. There should be no
  1156. // need to check if a=-1 has been sent because older devices have already sent
  1157. // their a=-1 in the past and we have to set first_active_omaha_ping_sent for
  1158. // future checks.
  1159. if (!system_state_->hardware()->GetFirstActiveOmahaPingSent()) {
  1160. if (!system_state_->hardware()->SetFirstActiveOmahaPingSent()) {
  1161. system_state_->metrics_reporter()->ReportInternalErrorCode(
  1162. ErrorCode::kFirstActiveOmahaPingSentPersistenceError);
  1163. }
  1164. }
  1165. if (!HasOutputPipe()) {
  1166. // Just set success to whether or not the http transfer succeeded,
  1167. // which must be true at this point in the code.
  1168. completer.set_code(ErrorCode::kSuccess);
  1169. return;
  1170. }
  1171. OmahaResponse output_object;
  1172. if (!ParseResponse(&parser_data, &output_object, &completer))
  1173. return;
  1174. output_object.update_exists = true;
  1175. SetOutputObject(output_object);
  1176. LoadOrPersistUpdateFirstSeenAtPref();
  1177. ErrorCode error = ErrorCode::kSuccess;
  1178. if (ShouldIgnoreUpdate(output_object, &error)) {
  1179. // No need to change output_object.update_exists here, since the value
  1180. // has been output to the pipe.
  1181. completer.set_code(error);
  1182. return;
  1183. }
  1184. // If Omaha says to disable p2p, respect that
  1185. if (output_object.disable_p2p_for_downloading) {
  1186. LOG(INFO) << "Forcibly disabling use of p2p for downloading as "
  1187. << "requested by Omaha.";
  1188. payload_state->SetUsingP2PForDownloading(false);
  1189. }
  1190. if (output_object.disable_p2p_for_sharing) {
  1191. LOG(INFO) << "Forcibly disabling use of p2p for sharing as "
  1192. << "requested by Omaha.";
  1193. payload_state->SetUsingP2PForSharing(false);
  1194. }
  1195. // Update the payload state with the current response. The payload state
  1196. // will automatically reset all stale state if this response is different
  1197. // from what's stored already. We are updating the payload state as late
  1198. // as possible in this method so that if a new release gets pushed and then
  1199. // got pulled back due to some issues, we don't want to clear our internal
  1200. // state unnecessarily.
  1201. payload_state->SetResponse(output_object);
  1202. // It could be we've already exceeded the deadline for when p2p is
  1203. // allowed or that we've tried too many times with p2p. Check that.
  1204. if (payload_state->GetUsingP2PForDownloading()) {
  1205. payload_state->P2PNewAttempt();
  1206. if (!payload_state->P2PAttemptAllowed()) {
  1207. LOG(INFO) << "Forcibly disabling use of p2p for downloading because "
  1208. << "of previous failures when using p2p.";
  1209. payload_state->SetUsingP2PForDownloading(false);
  1210. }
  1211. }
  1212. // From here on, we'll complete stuff in CompleteProcessing() so
  1213. // disable |completer| since we'll create a new one in that
  1214. // function.
  1215. completer.set_should_complete(false);
  1216. // If we're allowed to use p2p for downloading we do not pay
  1217. // attention to wall-clock-based waiting if the URL is indeed
  1218. // available via p2p. Therefore, check if the file is available via
  1219. // p2p before deferring...
  1220. if (payload_state->GetUsingP2PForDownloading()) {
  1221. LookupPayloadViaP2P(output_object);
  1222. } else {
  1223. CompleteProcessing();
  1224. }
  1225. }
  1226. void OmahaRequestAction::CompleteProcessing() {
  1227. ScopedActionCompleter completer(processor_, this);
  1228. OmahaResponse& output_object = const_cast<OmahaResponse&>(GetOutputObject());
  1229. PayloadStateInterface* payload_state = system_state_->payload_state();
  1230. if (ShouldDeferDownload(&output_object)) {
  1231. output_object.update_exists = false;
  1232. LOG(INFO) << "Ignoring Omaha updates as updates are deferred by policy.";
  1233. completer.set_code(ErrorCode::kOmahaUpdateDeferredPerPolicy);
  1234. return;
  1235. }
  1236. if (payload_state->ShouldBackoffDownload()) {
  1237. output_object.update_exists = false;
  1238. LOG(INFO) << "Ignoring Omaha updates in order to backoff our retry "
  1239. << "attempts";
  1240. completer.set_code(ErrorCode::kOmahaUpdateDeferredForBackoff);
  1241. return;
  1242. }
  1243. completer.set_code(ErrorCode::kSuccess);
  1244. }
  1245. void OmahaRequestAction::OnLookupPayloadViaP2PCompleted(const string& url) {
  1246. LOG(INFO) << "Lookup complete, p2p-client returned URL '" << url << "'";
  1247. if (!url.empty()) {
  1248. system_state_->payload_state()->SetP2PUrl(url);
  1249. } else {
  1250. LOG(INFO) << "Forcibly disabling use of p2p for downloading "
  1251. << "because no suitable peer could be found.";
  1252. system_state_->payload_state()->SetUsingP2PForDownloading(false);
  1253. }
  1254. CompleteProcessing();
  1255. }
  1256. void OmahaRequestAction::LookupPayloadViaP2P(const OmahaResponse& response) {
  1257. // If the device is in the middle of an update, the state variables
  1258. // kPrefsUpdateStateNextDataOffset, kPrefsUpdateStateNextDataLength
  1259. // tracks the offset and length of the operation currently in
  1260. // progress. The offset is based from the end of the manifest which
  1261. // is kPrefsManifestMetadataSize bytes long.
  1262. //
  1263. // To make forward progress and avoid deadlocks, we need to find a
  1264. // peer that has at least the entire operation we're currently
  1265. // working on. Otherwise we may end up in a situation where two
  1266. // devices bounce back and forth downloading from each other,
  1267. // neither making any forward progress until one of them decides to
  1268. // stop using p2p (via kMaxP2PAttempts and kMaxP2PAttemptTimeSeconds
  1269. // safe-guards). See http://crbug.com/297170 for an example)
  1270. size_t minimum_size = 0;
  1271. int64_t manifest_metadata_size = 0;
  1272. int64_t manifest_signature_size = 0;
  1273. int64_t next_data_offset = 0;
  1274. int64_t next_data_length = 0;
  1275. if (system_state_ &&
  1276. system_state_->prefs()->GetInt64(kPrefsManifestMetadataSize,
  1277. &manifest_metadata_size) &&
  1278. manifest_metadata_size != -1 &&
  1279. system_state_->prefs()->GetInt64(kPrefsManifestSignatureSize,
  1280. &manifest_signature_size) &&
  1281. manifest_signature_size != -1 &&
  1282. system_state_->prefs()->GetInt64(kPrefsUpdateStateNextDataOffset,
  1283. &next_data_offset) &&
  1284. next_data_offset != -1 &&
  1285. system_state_->prefs()->GetInt64(kPrefsUpdateStateNextDataLength,
  1286. &next_data_length)) {
  1287. minimum_size = manifest_metadata_size + manifest_signature_size +
  1288. next_data_offset + next_data_length;
  1289. }
  1290. // TODO(senj): Fix P2P for multiple package.
  1291. brillo::Blob raw_hash;
  1292. if (!base::HexStringToBytes(response.packages[0].hash, &raw_hash))
  1293. return;
  1294. string file_id =
  1295. utils::CalculateP2PFileId(raw_hash, response.packages[0].size);
  1296. if (system_state_->p2p_manager()) {
  1297. LOG(INFO) << "Checking if payload is available via p2p, file_id=" << file_id
  1298. << " minimum_size=" << minimum_size;
  1299. system_state_->p2p_manager()->LookupUrlForFile(
  1300. file_id,
  1301. minimum_size,
  1302. TimeDelta::FromSeconds(kMaxP2PNetworkWaitTimeSeconds),
  1303. base::Bind(&OmahaRequestAction::OnLookupPayloadViaP2PCompleted,
  1304. base::Unretained(this)));
  1305. }
  1306. }
  1307. bool OmahaRequestAction::ShouldDeferDownload(OmahaResponse* output_object) {
  1308. if (params_->interactive()) {
  1309. LOG(INFO) << "Not deferring download because update is interactive.";
  1310. return false;
  1311. }
  1312. // If we're using p2p to download _and_ we have a p2p URL, we never
  1313. // defer the download. This is because the download will always
  1314. // happen from a peer on the LAN and we've been waiting in line for
  1315. // our turn.
  1316. const PayloadStateInterface* payload_state = system_state_->payload_state();
  1317. if (payload_state->GetUsingP2PForDownloading() &&
  1318. !payload_state->GetP2PUrl().empty()) {
  1319. LOG(INFO) << "Download not deferred because download "
  1320. << "will happen from a local peer (via p2p).";
  1321. return false;
  1322. }
  1323. // We should defer the downloads only if we've first satisfied the
  1324. // wall-clock-based-waiting period and then the update-check-based waiting
  1325. // period, if required.
  1326. if (!params_->wall_clock_based_wait_enabled()) {
  1327. LOG(INFO) << "Wall-clock-based waiting period is not enabled,"
  1328. << " so no deferring needed.";
  1329. return false;
  1330. }
  1331. switch (IsWallClockBasedWaitingSatisfied(output_object)) {
  1332. case kWallClockWaitNotSatisfied:
  1333. // We haven't even satisfied the first condition, passing the
  1334. // wall-clock-based waiting period, so we should defer the downloads
  1335. // until that happens.
  1336. LOG(INFO) << "wall-clock-based-wait not satisfied.";
  1337. return true;
  1338. case kWallClockWaitDoneButUpdateCheckWaitRequired:
  1339. LOG(INFO) << "wall-clock-based-wait satisfied and "
  1340. << "update-check-based-wait required.";
  1341. return !IsUpdateCheckCountBasedWaitingSatisfied();
  1342. case kWallClockWaitDoneAndUpdateCheckWaitNotRequired:
  1343. // Wall-clock-based waiting period is satisfied, and it's determined
  1344. // that we do not need the update-check-based wait. so no need to
  1345. // defer downloads.
  1346. LOG(INFO) << "wall-clock-based-wait satisfied and "
  1347. << "update-check-based-wait is not required.";
  1348. return false;
  1349. default:
  1350. // Returning false for this default case so we err on the
  1351. // side of downloading updates than deferring in case of any bugs.
  1352. NOTREACHED();
  1353. return false;
  1354. }
  1355. }
  1356. OmahaRequestAction::WallClockWaitResult
  1357. OmahaRequestAction::IsWallClockBasedWaitingSatisfied(
  1358. OmahaResponse* output_object) {
  1359. Time update_first_seen_at = LoadOrPersistUpdateFirstSeenAtPref();
  1360. if (update_first_seen_at == base::Time()) {
  1361. LOG(INFO) << "Not scattering as UpdateFirstSeenAt value cannot be read or "
  1362. "persisted";
  1363. return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
  1364. }
  1365. TimeDelta elapsed_time =
  1366. system_state_->clock()->GetWallclockTime() - update_first_seen_at;
  1367. TimeDelta max_scatter_period =
  1368. TimeDelta::FromDays(output_object->max_days_to_scatter);
  1369. int64_t staging_wait_time_in_days = 0;
  1370. // Use staging and its default max value if staging is on.
  1371. if (system_state_->prefs()->GetInt64(kPrefsWallClockStagingWaitPeriod,
  1372. &staging_wait_time_in_days) &&
  1373. staging_wait_time_in_days > 0)
  1374. max_scatter_period = TimeDelta::FromDays(kMaxWaitTimeStagingInDays);
  1375. LOG(INFO) << "Waiting Period = "
  1376. << utils::FormatSecs(params_->waiting_period().InSeconds())
  1377. << ", Time Elapsed = "
  1378. << utils::FormatSecs(elapsed_time.InSeconds())
  1379. << ", MaxDaysToScatter = " << max_scatter_period.InDays();
  1380. if (!output_object->deadline.empty()) {
  1381. // The deadline is set for all rules which serve a delta update from a
  1382. // previous FSI, which means this update will be applied mostly in OOBE
  1383. // cases. For these cases, we shouldn't scatter so as to finish the OOBE
  1384. // quickly.
  1385. LOG(INFO) << "Not scattering as deadline flag is set";
  1386. return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
  1387. }
  1388. if (max_scatter_period.InDays() == 0) {
  1389. // This means the Omaha rule creator decides that this rule
  1390. // should not be scattered irrespective of the policy.
  1391. LOG(INFO) << "Not scattering as MaxDaysToScatter in rule is 0.";
  1392. return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
  1393. }
  1394. if (elapsed_time > max_scatter_period) {
  1395. // This means we've waited more than the upperbound wait in the rule
  1396. // from the time we first saw a valid update available to us.
  1397. // This will prevent update starvation.
  1398. LOG(INFO) << "Not scattering as we're past the MaxDaysToScatter limit.";
  1399. return kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
  1400. }
  1401. // This means we are required to participate in scattering.
  1402. // See if our turn has arrived now.
  1403. TimeDelta remaining_wait_time = params_->waiting_period() - elapsed_time;
  1404. if (remaining_wait_time.InSeconds() <= 0) {
  1405. // Yes, it's our turn now.
  1406. LOG(INFO) << "Successfully passed the wall-clock-based-wait.";
  1407. // But we can't download until the update-check-count-based wait is also
  1408. // satisfied, so mark it as required now if update checks are enabled.
  1409. return params_->update_check_count_wait_enabled()
  1410. ? kWallClockWaitDoneButUpdateCheckWaitRequired
  1411. : kWallClockWaitDoneAndUpdateCheckWaitNotRequired;
  1412. }
  1413. // Not our turn yet, so we have to wait until our turn to
  1414. // help scatter the downloads across all clients of the enterprise.
  1415. LOG(INFO) << "Update deferred for another "
  1416. << utils::FormatSecs(remaining_wait_time.InSeconds())
  1417. << " per policy.";
  1418. return kWallClockWaitNotSatisfied;
  1419. }
  1420. bool OmahaRequestAction::IsUpdateCheckCountBasedWaitingSatisfied() {
  1421. int64_t update_check_count_value;
  1422. if (system_state_->prefs()->Exists(kPrefsUpdateCheckCount)) {
  1423. if (!system_state_->prefs()->GetInt64(kPrefsUpdateCheckCount,
  1424. &update_check_count_value)) {
  1425. // We are unable to read the update check count from file for some reason.
  1426. // So let's proceed anyway so as to not stall the update.
  1427. LOG(ERROR) << "Unable to read update check count. "
  1428. << "Skipping update-check-count-based-wait.";
  1429. return true;
  1430. }
  1431. } else {
  1432. // This file does not exist. This means we haven't started our update
  1433. // check count down yet, so this is the right time to start the count down.
  1434. update_check_count_value =
  1435. base::RandInt(params_->min_update_checks_needed(),
  1436. params_->max_update_checks_allowed());
  1437. LOG(INFO) << "Randomly picked update check count value = "
  1438. << update_check_count_value;
  1439. // Write out the initial value of update_check_count_value.
  1440. if (!system_state_->prefs()->SetInt64(kPrefsUpdateCheckCount,
  1441. update_check_count_value)) {
  1442. // We weren't able to write the update check count file for some reason.
  1443. // So let's proceed anyway so as to not stall the update.
  1444. LOG(ERROR) << "Unable to write update check count. "
  1445. << "Skipping update-check-count-based-wait.";
  1446. return true;
  1447. }
  1448. }
  1449. if (update_check_count_value == 0) {
  1450. LOG(INFO) << "Successfully passed the update-check-based-wait.";
  1451. return true;
  1452. }
  1453. if (update_check_count_value < 0 ||
  1454. update_check_count_value > params_->max_update_checks_allowed()) {
  1455. // We err on the side of skipping scattering logic instead of stalling
  1456. // a machine from receiving any updates in case of any unexpected state.
  1457. LOG(ERROR) << "Invalid value for update check count detected. "
  1458. << "Skipping update-check-count-based-wait.";
  1459. return true;
  1460. }
  1461. // Legal value, we need to wait for more update checks to happen
  1462. // until this becomes 0.
  1463. LOG(INFO) << "Deferring Omaha updates for another "
  1464. << update_check_count_value << " update checks per policy";
  1465. return false;
  1466. }
  1467. // static
  1468. bool OmahaRequestAction::ParseInstallDate(OmahaParserData* parser_data,
  1469. OmahaResponse* output_object) {
  1470. int64_t elapsed_days = 0;
  1471. if (!base::StringToInt64(parser_data->daystart_elapsed_days, &elapsed_days))
  1472. return false;
  1473. if (elapsed_days < 0)
  1474. return false;
  1475. output_object->install_date_days = elapsed_days;
  1476. return true;
  1477. }
  1478. // static
  1479. bool OmahaRequestAction::HasInstallDate(SystemState* system_state) {
  1480. PrefsInterface* prefs = system_state->prefs();
  1481. if (prefs == nullptr)
  1482. return false;
  1483. return prefs->Exists(kPrefsInstallDateDays);
  1484. }
  1485. // static
  1486. bool OmahaRequestAction::PersistInstallDate(
  1487. SystemState* system_state,
  1488. int install_date_days,
  1489. InstallDateProvisioningSource source) {
  1490. TEST_AND_RETURN_FALSE(install_date_days >= 0);
  1491. PrefsInterface* prefs = system_state->prefs();
  1492. if (prefs == nullptr)
  1493. return false;
  1494. if (!prefs->SetInt64(kPrefsInstallDateDays, install_date_days))
  1495. return false;
  1496. system_state->metrics_reporter()->ReportInstallDateProvisioningSource(
  1497. static_cast<int>(source), // Sample.
  1498. kProvisionedMax); // Maximum.
  1499. return true;
  1500. }
  1501. bool OmahaRequestAction::PersistCohortData(const string& prefs_key,
  1502. const string& new_value) {
  1503. if (new_value.empty() && system_state_->prefs()->Exists(prefs_key)) {
  1504. LOG(INFO) << "Removing stored " << prefs_key << " value.";
  1505. return system_state_->prefs()->Delete(prefs_key);
  1506. } else if (!new_value.empty()) {
  1507. LOG(INFO) << "Storing new setting " << prefs_key << " as " << new_value;
  1508. return system_state_->prefs()->SetString(prefs_key, new_value);
  1509. }
  1510. return true;
  1511. }
  1512. bool OmahaRequestAction::PersistEolStatus(const map<string, string>& attrs) {
  1513. auto eol_attr = attrs.find(kAttrEol);
  1514. if (eol_attr != attrs.end()) {
  1515. return system_state_->prefs()->SetString(kPrefsOmahaEolStatus,
  1516. eol_attr->second);
  1517. } else if (system_state_->prefs()->Exists(kPrefsOmahaEolStatus)) {
  1518. return system_state_->prefs()->Delete(kPrefsOmahaEolStatus);
  1519. }
  1520. return true;
  1521. }
  1522. void OmahaRequestAction::ActionCompleted(ErrorCode code) {
  1523. // We only want to report this on "update check".
  1524. if (ping_only_ || event_ != nullptr)
  1525. return;
  1526. metrics::CheckResult result = metrics::CheckResult::kUnset;
  1527. metrics::CheckReaction reaction = metrics::CheckReaction::kUnset;
  1528. metrics::DownloadErrorCode download_error_code =
  1529. metrics::DownloadErrorCode::kUnset;
  1530. // Regular update attempt.
  1531. switch (code) {
  1532. case ErrorCode::kSuccess:
  1533. // OK, we parsed the response successfully but that does
  1534. // necessarily mean that an update is available.
  1535. if (HasOutputPipe()) {
  1536. const OmahaResponse& response = GetOutputObject();
  1537. if (response.update_exists) {
  1538. result = metrics::CheckResult::kUpdateAvailable;
  1539. reaction = metrics::CheckReaction::kUpdating;
  1540. } else {
  1541. result = metrics::CheckResult::kNoUpdateAvailable;
  1542. }
  1543. } else {
  1544. result = metrics::CheckResult::kNoUpdateAvailable;
  1545. }
  1546. break;
  1547. case ErrorCode::kOmahaUpdateIgnoredPerPolicy:
  1548. case ErrorCode::kOmahaUpdateIgnoredOverCellular:
  1549. result = metrics::CheckResult::kUpdateAvailable;
  1550. reaction = metrics::CheckReaction::kIgnored;
  1551. break;
  1552. case ErrorCode::kOmahaUpdateDeferredPerPolicy:
  1553. result = metrics::CheckResult::kUpdateAvailable;
  1554. reaction = metrics::CheckReaction::kDeferring;
  1555. break;
  1556. case ErrorCode::kOmahaUpdateDeferredForBackoff:
  1557. result = metrics::CheckResult::kUpdateAvailable;
  1558. reaction = metrics::CheckReaction::kBackingOff;
  1559. break;
  1560. default:
  1561. // We report two flavors of errors, "Download errors" and "Parsing
  1562. // error". Try to convert to the former and if that doesn't work
  1563. // we know it's the latter.
  1564. metrics::DownloadErrorCode tmp_error =
  1565. metrics_utils::GetDownloadErrorCode(code);
  1566. if (tmp_error != metrics::DownloadErrorCode::kInputMalformed) {
  1567. result = metrics::CheckResult::kDownloadError;
  1568. download_error_code = tmp_error;
  1569. } else {
  1570. result = metrics::CheckResult::kParsingError;
  1571. }
  1572. break;
  1573. }
  1574. system_state_->metrics_reporter()->ReportUpdateCheckMetrics(
  1575. system_state_, result, reaction, download_error_code);
  1576. }
  1577. bool OmahaRequestAction::ShouldIgnoreUpdate(const OmahaResponse& response,
  1578. ErrorCode* error) const {
  1579. // Note: policy decision to not update to a version we rolled back from.
  1580. string rollback_version =
  1581. system_state_->payload_state()->GetRollbackVersion();
  1582. if (!rollback_version.empty()) {
  1583. LOG(INFO) << "Detected previous rollback from version " << rollback_version;
  1584. if (rollback_version == response.version) {
  1585. LOG(INFO) << "Received version that we rolled back from. Ignoring.";
  1586. *error = ErrorCode::kOmahaUpdateIgnoredPerPolicy;
  1587. return true;
  1588. }
  1589. }
  1590. if (system_state_->hardware()->IsOOBEEnabled() &&
  1591. !system_state_->hardware()->IsOOBEComplete(nullptr) &&
  1592. (response.deadline.empty() ||
  1593. system_state_->payload_state()->GetRollbackHappened()) &&
  1594. params_->app_version() != "ForcedUpdate") {
  1595. LOG(INFO) << "Ignoring a non-critical Omaha update before OOBE completion.";
  1596. *error = ErrorCode::kNonCriticalUpdateInOOBE;
  1597. return true;
  1598. }
  1599. if (!IsUpdateAllowedOverCurrentConnection(error, response)) {
  1600. LOG(INFO) << "Update is not allowed over current connection.";
  1601. return true;
  1602. }
  1603. // Note: We could technically delete the UpdateFirstSeenAt state when we
  1604. // return true. If we do, it'll mean a device has to restart the
  1605. // UpdateFirstSeenAt and thus help scattering take effect when the AU is
  1606. // turned on again. On the other hand, it also increases the chance of update
  1607. // starvation if an admin turns AU on/off more frequently. We choose to err on
  1608. // the side of preventing starvation at the cost of not applying scattering in
  1609. // those cases.
  1610. return false;
  1611. }
  1612. bool OmahaRequestAction::IsUpdateAllowedOverCellularByPrefs(
  1613. const OmahaResponse& response) const {
  1614. PrefsInterface* prefs = system_state_->prefs();
  1615. if (!prefs) {
  1616. LOG(INFO) << "Disabling updates over cellular as the preferences are "
  1617. "not available.";
  1618. return false;
  1619. }
  1620. bool is_allowed;
  1621. if (prefs->Exists(kPrefsUpdateOverCellularPermission) &&
  1622. prefs->GetBoolean(kPrefsUpdateOverCellularPermission, &is_allowed) &&
  1623. is_allowed) {
  1624. LOG(INFO) << "Allowing updates over cellular as permission preference is "
  1625. "set to true.";
  1626. return true;
  1627. }
  1628. if (!prefs->Exists(kPrefsUpdateOverCellularTargetVersion) ||
  1629. !prefs->Exists(kPrefsUpdateOverCellularTargetSize)) {
  1630. LOG(INFO) << "Disabling updates over cellular as permission preference is "
  1631. "set to false or does not exist while target does not exist.";
  1632. return false;
  1633. }
  1634. std::string target_version;
  1635. int64_t target_size;
  1636. if (!prefs->GetString(kPrefsUpdateOverCellularTargetVersion,
  1637. &target_version) ||
  1638. !prefs->GetInt64(kPrefsUpdateOverCellularTargetSize, &target_size)) {
  1639. LOG(INFO) << "Disabling updates over cellular as the target version or "
  1640. "size is not accessible.";
  1641. return false;
  1642. }
  1643. uint64_t total_packages_size = 0;
  1644. for (const auto& package : response.packages) {
  1645. total_packages_size += package.size;
  1646. }
  1647. if (target_version == response.version &&
  1648. static_cast<uint64_t>(target_size) == total_packages_size) {
  1649. LOG(INFO) << "Allowing updates over cellular as the target matches the"
  1650. "omaha response.";
  1651. return true;
  1652. } else {
  1653. LOG(INFO) << "Disabling updates over cellular as the target does not"
  1654. "match the omaha response.";
  1655. return false;
  1656. }
  1657. }
  1658. bool OmahaRequestAction::IsUpdateAllowedOverCurrentConnection(
  1659. ErrorCode* error, const OmahaResponse& response) const {
  1660. ConnectionType type;
  1661. ConnectionTethering tethering;
  1662. ConnectionManagerInterface* connection_manager =
  1663. system_state_->connection_manager();
  1664. if (!connection_manager->GetConnectionProperties(&type, &tethering)) {
  1665. LOG(INFO) << "We could not determine our connection type. "
  1666. << "Defaulting to allow updates.";
  1667. return true;
  1668. }
  1669. bool is_allowed = connection_manager->IsUpdateAllowedOver(type, tethering);
  1670. bool is_device_policy_set =
  1671. connection_manager->IsAllowedConnectionTypesForUpdateSet();
  1672. // Treats tethered connection as if it is cellular connection.
  1673. bool is_over_cellular = type == ConnectionType::kCellular ||
  1674. tethering == ConnectionTethering::kConfirmed;
  1675. if (!is_over_cellular) {
  1676. // There's no need to further check user preferences as we are not over
  1677. // cellular connection.
  1678. if (!is_allowed)
  1679. *error = ErrorCode::kOmahaUpdateIgnoredPerPolicy;
  1680. } else if (is_device_policy_set) {
  1681. // There's no need to further check user preferences as the device policy
  1682. // is set regarding updates over cellular.
  1683. if (!is_allowed)
  1684. *error = ErrorCode::kOmahaUpdateIgnoredPerPolicy;
  1685. } else {
  1686. // Deivce policy is not set, so user preferences overwrite whether to
  1687. // allow updates over cellular.
  1688. is_allowed = IsUpdateAllowedOverCellularByPrefs(response);
  1689. if (!is_allowed)
  1690. *error = ErrorCode::kOmahaUpdateIgnoredOverCellular;
  1691. }
  1692. LOG(INFO) << "We are connected via "
  1693. << connection_utils::StringForConnectionType(type)
  1694. << ", Updates allowed: " << (is_allowed ? "Yes" : "No");
  1695. return is_allowed;
  1696. }
  1697. bool OmahaRequestAction::IsRollbackEnabled() const {
  1698. if (policy_provider_->IsConsumerDevice()) {
  1699. LOG(INFO) << "Rollback is not enabled for consumer devices.";
  1700. return false;
  1701. }
  1702. if (!policy_provider_->device_policy_is_loaded()) {
  1703. LOG(INFO) << "No device policy is loaded. Assuming rollback enabled.";
  1704. return true;
  1705. }
  1706. int allowed_milestones;
  1707. if (!policy_provider_->GetDevicePolicy().GetRollbackAllowedMilestones(
  1708. &allowed_milestones)) {
  1709. LOG(INFO) << "RollbackAllowedMilestones policy can't be read. "
  1710. "Defaulting to rollback enabled.";
  1711. return true;
  1712. }
  1713. LOG(INFO) << "Rollback allows " << allowed_milestones << " milestones.";
  1714. return allowed_milestones > 0;
  1715. }
  1716. void OmahaRequestAction::SetMaxKernelKeyVersionForRollback() const {
  1717. int max_kernel_rollforward;
  1718. int min_kernel_version = system_state_->hardware()->GetMinKernelKeyVersion();
  1719. if (IsRollbackEnabled()) {
  1720. // If rollback is enabled, set the max kernel key version to the current
  1721. // kernel key version. This has the effect of freezing kernel key roll
  1722. // forwards.
  1723. //
  1724. // TODO(zentaro): This behavior is temporary, and ensures that no kernel
  1725. // key roll forward happens until the server side components of rollback
  1726. // are implemented. Future changes will allow the Omaha server to return
  1727. // the kernel key version from max_rollback_versions in the past. At that
  1728. // point the max kernel key version will be set to that value, creating a
  1729. // sliding window of versions that can be rolled back to.
  1730. LOG(INFO) << "Rollback is enabled. Setting kernel_max_rollforward to "
  1731. << min_kernel_version;
  1732. max_kernel_rollforward = min_kernel_version;
  1733. } else {
  1734. // For devices that are not rollback enabled (ie. consumer devices), the
  1735. // max kernel key version is set to 0xfffffffe, which is logically
  1736. // infinity. This maintains the previous behavior that that kernel key
  1737. // versions roll forward each time they are incremented.
  1738. LOG(INFO) << "Rollback is disabled. Setting kernel_max_rollforward to "
  1739. << kRollforwardInfinity;
  1740. max_kernel_rollforward = kRollforwardInfinity;
  1741. }
  1742. bool max_rollforward_set =
  1743. system_state_->hardware()->SetMaxKernelKeyRollforward(
  1744. max_kernel_rollforward);
  1745. if (!max_rollforward_set) {
  1746. LOG(ERROR) << "Failed to set kernel_max_rollforward";
  1747. }
  1748. // Report metrics
  1749. system_state_->metrics_reporter()->ReportKeyVersionMetrics(
  1750. min_kernel_version, max_kernel_rollforward, max_rollforward_set);
  1751. }
  1752. base::Time OmahaRequestAction::LoadOrPersistUpdateFirstSeenAtPref() const {
  1753. Time update_first_seen_at;
  1754. int64_t update_first_seen_at_int;
  1755. if (system_state_->prefs()->Exists(kPrefsUpdateFirstSeenAt)) {
  1756. if (system_state_->prefs()->GetInt64(kPrefsUpdateFirstSeenAt,
  1757. &update_first_seen_at_int)) {
  1758. // Note: This timestamp could be that of ANY update we saw in the past
  1759. // (not necessarily this particular update we're considering to apply)
  1760. // but never got to apply because of some reason (e.g. stop AU policy,
  1761. // updates being pulled out from Omaha, changes in target version prefix,
  1762. // new update being rolled out, etc.). But for the purposes of scattering
  1763. // it doesn't matter which update the timestamp corresponds to. i.e.
  1764. // the clock starts ticking the first time we see an update and we're
  1765. // ready to apply when the random wait period is satisfied relative to
  1766. // that first seen timestamp.
  1767. update_first_seen_at = Time::FromInternalValue(update_first_seen_at_int);
  1768. LOG(INFO) << "Using persisted value of UpdateFirstSeenAt: "
  1769. << utils::ToString(update_first_seen_at);
  1770. } else {
  1771. // This seems like an unexpected error where the persisted value exists
  1772. // but it's not readable for some reason.
  1773. LOG(INFO) << "UpdateFirstSeenAt value cannot be read";
  1774. return base::Time();
  1775. }
  1776. } else {
  1777. update_first_seen_at = system_state_->clock()->GetWallclockTime();
  1778. update_first_seen_at_int = update_first_seen_at.ToInternalValue();
  1779. if (system_state_->prefs()->SetInt64(kPrefsUpdateFirstSeenAt,
  1780. update_first_seen_at_int)) {
  1781. LOG(INFO) << "Persisted the new value for UpdateFirstSeenAt: "
  1782. << utils::ToString(update_first_seen_at);
  1783. } else {
  1784. // This seems like an unexpected error where the value cannot be
  1785. // persisted for some reason.
  1786. LOG(INFO) << "UpdateFirstSeenAt value "
  1787. << utils::ToString(update_first_seen_at)
  1788. << " cannot be persisted";
  1789. return base::Time();
  1790. }
  1791. }
  1792. return update_first_seen_at;
  1793. }
  1794. } // namespace chromeos_update_engine