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