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 17 #ifndef UPDATE_ENGINE_OMAHA_REQUEST_ACTION_H_ 18 #define UPDATE_ENGINE_OMAHA_REQUEST_ACTION_H_ 19 20 #include <fcntl.h> 21 #include <sys/stat.h> 22 #include <sys/types.h> 23 24 #include <map> 25 #include <memory> 26 #include <string> 27 #include <vector> 28 29 #include <gtest/gtest_prod.h> // for FRIEND_TEST 30 31 #include <brillo/secure_blob.h> 32 #include <curl/curl.h> 33 34 #include "update_engine/common/action.h" 35 #include "update_engine/common/http_fetcher.h" 36 #include "update_engine/omaha_request_builder_xml.h" 37 #include "update_engine/omaha_response.h" 38 #include "update_engine/system_state.h" 39 40 // The Omaha Request action makes a request to Omaha and can output 41 // the response on the output ActionPipe. 42 43 namespace policy { 44 class PolicyProvider; 45 } 46 47 namespace chromeos_update_engine { 48 49 class NoneType; 50 class OmahaRequestAction; 51 class OmahaRequestParams; 52 class PrefsInterface; 53 54 // This struct is declared in the .cc file. 55 struct OmahaParserData; 56 57 template <> 58 class ActionTraits<OmahaRequestAction> { 59 public: 60 // Takes parameters on the input pipe. 61 typedef NoneType InputObjectType; 62 // On UpdateCheck success, puts the Omaha response on output. Event 63 // requests do not have an output pipe. 64 typedef OmahaResponse OutputObjectType; 65 }; 66 67 class OmahaRequestAction : public Action<OmahaRequestAction>, 68 public HttpFetcherDelegate { 69 public: 70 static const int kPingTimeJump = -2; 71 // We choose this value of 3 as a heuristic for a work day in trying 72 // each URL, assuming we check roughly every 45 mins. This is a good time to 73 // wait so we don't give up the preferred URLs, but allow using the URL that 74 // appears earlier in list for every payload before resorting to the fallback 75 // URLs in the candiate URL list. 76 static const int kDefaultMaxFailureCountPerUrl = 3; 77 78 // If staging is enabled, set the maximum wait time to 28 days, since that is 79 // the predetermined wait time for staging. 80 static const int kMaxWaitTimeStagingInDays = 28; 81 82 // These are the possible outcome upon checking whether we satisfied 83 // the wall-clock-based-wait. 84 enum WallClockWaitResult { 85 kWallClockWaitNotSatisfied, 86 kWallClockWaitDoneButUpdateCheckWaitRequired, 87 kWallClockWaitDoneAndUpdateCheckWaitNotRequired, 88 }; 89 90 // The ctor takes in all the parameters that will be used for making 91 // the request to Omaha. For some of them we have constants that 92 // should be used. 93 // 94 // Takes ownership of the passed in HttpFetcher. Useful for testing. 95 // 96 // Takes ownership of the passed in OmahaEvent. If |event| is null, 97 // this is an UpdateCheck request, otherwise it's an Event request. 98 // Event requests always succeed. 99 // 100 // A good calling pattern is: 101 // OmahaRequestAction(..., new OmahaEvent(...), new WhateverHttpFetcher); 102 // or 103 // OmahaRequestAction(..., nullptr, new WhateverHttpFetcher); 104 OmahaRequestAction(SystemState* system_state, 105 OmahaEvent* event, 106 std::unique_ptr<HttpFetcher> http_fetcher, 107 bool ping_only, 108 const std::string& session_id); 109 ~OmahaRequestAction() override; 110 typedef ActionTraits<OmahaRequestAction>::InputObjectType InputObjectType; 111 typedef ActionTraits<OmahaRequestAction>::OutputObjectType OutputObjectType; 112 void PerformAction() override; 113 void TerminateProcessing() override; 114 void ActionCompleted(ErrorCode code) override; 115 GetHTTPResponseCode()116 int GetHTTPResponseCode() { return http_fetcher_->http_response_code(); } 117 118 // Debugging/logging StaticType()119 static std::string StaticType() { return "OmahaRequestAction"; } Type()120 std::string Type() const override { return StaticType(); } 121 122 // Delegate methods (see http_fetcher.h) 123 bool ReceivedBytes(HttpFetcher* fetcher, 124 const void* bytes, 125 size_t length) override; 126 127 void TransferComplete(HttpFetcher* fetcher, bool successful) override; 128 129 // Returns true if this is an Event request, false if it's an UpdateCheck. IsEvent()130 bool IsEvent() const { return event_.get() != nullptr; } 131 132 private: 133 friend class OmahaRequestActionTest; 134 friend class OmahaRequestActionTestProcessorDelegate; 135 FRIEND_TEST(OmahaRequestActionTest, GetInstallDateWhenNoPrefsNorOOBE); 136 FRIEND_TEST(OmahaRequestActionTest, 137 GetInstallDateWhenOOBECompletedWithInvalidDate); 138 FRIEND_TEST(OmahaRequestActionTest, 139 GetInstallDateWhenOOBECompletedWithValidDate); 140 FRIEND_TEST(OmahaRequestActionTest, 141 GetInstallDateWhenOOBECompletedDateChanges); 142 friend class UpdateAttempterTest; 143 FRIEND_TEST(UpdateAttempterTest, SessionIdTestEnforceEmptyStrPingOmaha); 144 FRIEND_TEST(UpdateAttempterTest, SessionIdTestConsistencyInUpdateFlow); 145 146 // Enumeration used in PersistInstallDate(). 147 enum InstallDateProvisioningSource { 148 kProvisionedFromOmahaResponse, 149 kProvisionedFromOOBEMarker, 150 151 // kProvisionedMax is the count of the number of enums above. Add 152 // any new enums above this line only. 153 kProvisionedMax 154 }; 155 156 // Gets the install date, expressed as the number of PST8PDT 157 // calendar weeks since January 1st 2007, times seven. Returns -1 if 158 // unknown. See http://crbug.com/336838 for details about this value. 159 static int GetInstallDate(SystemState* system_state); 160 161 // Parses the Omaha Response in |doc| and sets the 162 // |install_date_days| field of |output_object| to the value of the 163 // elapsed_days attribute of the daystart element. Returns True if 164 // the value was set, False if it wasn't found. 165 static bool ParseInstallDate(OmahaParserData* parser_data, 166 OmahaResponse* output_object); 167 168 // Returns True if the kPrefsInstallDateDays state variable is set, 169 // False otherwise. 170 static bool HasInstallDate(SystemState* system_state); 171 172 // Writes |install_date_days| into the kPrefsInstallDateDays state 173 // variable and emits an UMA stat for the |source| used. Returns 174 // True if the value was written, False if an error occurred. 175 static bool PersistInstallDate(SystemState* system_state, 176 int install_date_days, 177 InstallDateProvisioningSource source); 178 179 // Persist the new cohort* value received in the XML file in the |prefs_key| 180 // preference file. If the |new_value| is empty, the currently stored value 181 // will be deleted. Don't call this function with an empty |new_value| if the 182 // value was not set in the XML, since that would delete the stored value. 183 bool PersistCohortData(const std::string& prefs_key, 184 const std::string& new_value); 185 186 // Parses and persists the end-of-life date flag sent back in the updatecheck 187 // tag attributes. The flags will be validated and stored in the Prefs. 188 bool PersistEolInfo(const std::map<std::string, std::string>& attrs); 189 190 // If this is an update check request, initializes 191 // |ping_active_days_| and |ping_roll_call_days_| to values that may 192 // be sent as pings to Omaha. 193 void InitPingDays(); 194 195 // Based on the persistent preference store values, calculates the 196 // number of days since the last ping sent for |key|. 197 int CalculatePingDays(const std::string& key); 198 199 // Returns whether we have "active_days" or "roll_call_days" ping values to 200 // send to Omaha and thus we should include them in the response. 201 bool ShouldPing() const; 202 203 // Process Omaha's response to a ping request and store the results in the DLC 204 // metadata directory. 205 void StorePingReply(const OmahaParserData& parser_data) const; 206 207 // Returns true if the download of a new update should be deferred. 208 // False if the update can be downloaded. 209 bool ShouldDeferDownload(OmahaResponse* output_object); 210 211 // Returns true if the basic wall-clock-based waiting period has been 212 // satisfied based on the scattering policy setting. False otherwise. 213 // If true, it also indicates whether the additional update-check-count-based 214 // waiting period also needs to be satisfied before the download can begin. 215 WallClockWaitResult IsWallClockBasedWaitingSatisfied( 216 OmahaResponse* output_object); 217 218 // Returns true if the update-check-count-based waiting period has been 219 // satisfied. False otherwise. 220 bool IsUpdateCheckCountBasedWaitingSatisfied(); 221 222 // Parses the response from Omaha that's available in |doc| using the other 223 // helper methods below and populates the |output_object| with the relevant 224 // values. Returns true if we should continue the parsing. False otherwise, 225 // in which case it sets any error code using |completer|. 226 bool ParseResponse(OmahaParserData* parser_data, 227 OmahaResponse* output_object, 228 ScopedActionCompleter* completer); 229 230 // Parses the status property in the given update_check_node and populates 231 // |output_object| if valid. Returns true if we should continue the parsing. 232 // False otherwise, in which case it sets any error code using |completer|. 233 bool ParseStatus(OmahaParserData* parser_data, 234 OmahaResponse* output_object, 235 ScopedActionCompleter* completer); 236 237 // Parses the URL nodes in the given XML document and populates 238 // |output_object| if valid. Returns true if we should continue the parsing. 239 // False otherwise, in which case it sets any error code using |completer|. 240 bool ParseUrls(OmahaParserData* parser_data, 241 OmahaResponse* output_object, 242 ScopedActionCompleter* completer); 243 244 // Parses the other parameters in the given XML document and populates 245 // |output_object| if valid. Returns true if we should continue the parsing. 246 // False otherwise, in which case it sets any error code using |completer|. 247 bool ParseParams(OmahaParserData* parser_data, 248 OmahaResponse* output_object, 249 ScopedActionCompleter* completer); 250 251 // Called by TransferComplete() to complete processing, either 252 // asynchronously after looking up resources via p2p or directly. 253 void CompleteProcessing(); 254 255 // Helper to asynchronously look up payload on the LAN. 256 void LookupPayloadViaP2P(const OmahaResponse& response); 257 258 // Callback used by LookupPayloadViaP2P(). 259 void OnLookupPayloadViaP2PCompleted(const std::string& url); 260 261 // Returns true if the current update should be ignored. 262 bool ShouldIgnoreUpdate(const OmahaResponse& response, 263 ErrorCode* error) const; 264 265 // Return true if updates are allowed by user preferences. 266 bool IsUpdateAllowedOverCellularByPrefs(const OmahaResponse& response) const; 267 268 // Returns true if updates are allowed over the current type of connection. 269 // False otherwise. 270 bool IsUpdateAllowedOverCurrentConnection( 271 ErrorCode* error, const OmahaResponse& response) const; 272 273 // Returns true if rollback is enabled. Always returns false for consumer 274 // devices. 275 bool IsRollbackEnabled() const; 276 277 // Sets the appropriate max kernel key version based on whether rollback is 278 // enabled. 279 void SetMaxKernelKeyVersionForRollback() const; 280 281 // Reads and returns the kPrefsUpdateFirstSeenAt pref if the pref currently 282 // exists. Otherwise saves the current wallclock time to the 283 // kPrefsUpdateFirstSeenAt pref and returns it as a base::Time object. 284 base::Time LoadOrPersistUpdateFirstSeenAtPref() const; 285 286 // Global system context. 287 SystemState* system_state_; 288 289 // Contains state that is relevant in the processing of the Omaha request. 290 OmahaRequestParams* params_; 291 292 // Pointer to the OmahaEvent info. This is an UpdateCheck request if null. 293 std::unique_ptr<OmahaEvent> event_; 294 295 // pointer to the HttpFetcher that does the http work 296 std::unique_ptr<HttpFetcher> http_fetcher_; 297 298 // Used for fetching information about the device policy. 299 std::unique_ptr<policy::PolicyProvider> policy_provider_; 300 301 // If true, only include the <ping> element in the request. 302 bool ping_only_; 303 304 // Stores the response from the omaha server 305 brillo::Blob response_buffer_; 306 307 // Initialized by InitPingDays to values that may be sent to Omaha 308 // as part of a ping message. Note that only positive values and -1 309 // are sent to Omaha. 310 int ping_active_days_; 311 int ping_roll_call_days_; 312 313 std::string session_id_; 314 315 DISALLOW_COPY_AND_ASSIGN(OmahaRequestAction); 316 }; 317 318 } // namespace chromeos_update_engine 319 320 #endif // UPDATE_ENGINE_OMAHA_REQUEST_ACTION_H_ 321