1 //
2 // Copyright (C) 2019 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_BUILDER_XML_H_
18 #define UPDATE_ENGINE_OMAHA_REQUEST_BUILDER_XML_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_params.h"
37 #include "update_engine/omaha_response.h"
38 #include "update_engine/system_state.h"
39 
40 namespace chromeos_update_engine {
41 
42 extern const char kNoVersion[];
43 extern const int kPingNeverPinged;
44 extern const int kPingUnknownValue;
45 extern const int kPingActiveValue;
46 extern const int kPingInactiveValue;
47 
48 // This struct encapsulates the Omaha event information. For a
49 // complete list of defined event types and results, see
50 // http://code.google.com/p/omaha/wiki/ServerProtocol#event
51 struct OmahaEvent {
52   // The Type values correspond to EVENT_TYPE values of Omaha.
53   enum Type {
54     kTypeUnknown = 0,
55     kTypeDownloadComplete = 1,
56     kTypeInstallComplete = 2,
57     kTypeUpdateComplete = 3,
58     kTypeUpdateDownloadStarted = 13,
59     kTypeUpdateDownloadFinished = 14,
60     // Chromium OS reserved type sent after the first reboot following an update
61     // completed.
62     kTypeRebootedAfterUpdate = 54,
63   };
64 
65   // The Result values correspond to EVENT_RESULT values of Omaha.
66   enum Result {
67     kResultError = 0,
68     kResultSuccess = 1,
69     kResultUpdateDeferred = 9,  // When we ignore/defer updates due to policy.
70   };
71 
OmahaEventOmahaEvent72   OmahaEvent()
73       : type(kTypeUnknown),
74         result(kResultError),
75         error_code(ErrorCode::kError) {}
OmahaEventOmahaEvent76   explicit OmahaEvent(Type in_type)
77       : type(in_type),
78         result(kResultSuccess),
79         error_code(ErrorCode::kSuccess) {}
OmahaEventOmahaEvent80   OmahaEvent(Type in_type, Result in_result, ErrorCode in_error_code)
81       : type(in_type), result(in_result), error_code(in_error_code) {}
82 
83   Type type;
84   Result result;
85   ErrorCode error_code;
86 };
87 
88 struct OmahaAppData {
89   std::string id;
90   std::string version;
91   std::string product_components;
92   bool skip_update;
93   bool is_dlc;
94   OmahaRequestParams::AppParams app_params;
95 };
96 
97 // Encodes XML entities in a given string. Input must be ASCII-7 valid. If
98 // the input is invalid, the default value is used instead.
99 std::string XmlEncodeWithDefault(const std::string& input,
100                                  const std::string& default_value = "");
101 
102 // Escapes text so it can be included as character data and attribute
103 // values. The |input| string must be valid ASCII-7, no UTF-8 supported.
104 // Returns whether the |input| was valid and escaped properly in |output|.
105 bool XmlEncode(const std::string& input, std::string* output);
106 
107 // Returns a boolean based on examining each character on whether it's a valid
108 // component (meaning all characters are an alphanum excluding '-', '_', '.').
109 bool IsValidComponentID(const std::string& id);
110 
111 class OmahaRequestBuilder {
112  public:
113   OmahaRequestBuilder() = default;
114   virtual ~OmahaRequestBuilder() = default;
115 
116   virtual std::string GetRequest() const = 0;
117 
118  private:
119   DISALLOW_COPY_AND_ASSIGN(OmahaRequestBuilder);
120 };
121 
122 class OmahaRequestBuilderXml : OmahaRequestBuilder {
123  public:
OmahaRequestBuilderXml(const OmahaEvent * event,OmahaRequestParams * params,bool ping_only,bool include_ping,int ping_active_days,int ping_roll_call_days,int install_date_in_days,PrefsInterface * prefs,const std::string & session_id)124   OmahaRequestBuilderXml(const OmahaEvent* event,
125                          OmahaRequestParams* params,
126                          bool ping_only,
127                          bool include_ping,
128                          int ping_active_days,
129                          int ping_roll_call_days,
130                          int install_date_in_days,
131                          PrefsInterface* prefs,
132                          const std::string& session_id)
133       : event_(event),
134         params_(params),
135         ping_only_(ping_only),
136         include_ping_(include_ping),
137         ping_active_days_(ping_active_days),
138         ping_roll_call_days_(ping_roll_call_days),
139         install_date_in_days_(install_date_in_days),
140         prefs_(prefs),
141         session_id_(session_id) {}
142 
143   ~OmahaRequestBuilderXml() override = default;
144 
145   // Returns an XML that corresponds to the entire Omaha request.
146   std::string GetRequest() const override;
147 
148  private:
149   FRIEND_TEST(OmahaRequestBuilderXmlTest, PlatformGetAppTest);
150   FRIEND_TEST(OmahaRequestBuilderXmlTest, DlcGetAppTest);
151 
152   // Returns an XML that corresponds to the entire <os> node of the Omaha
153   // request based on the member variables.
154   std::string GetOs() const;
155 
156   // Returns an XML that corresponds to all <app> nodes of the Omaha
157   // request based on the given parameters.
158   std::string GetApps() const;
159 
160   // Returns an XML that corresponds to the single <app> node of the Omaha
161   // request based on the given parameters.
162   std::string GetApp(const OmahaAppData& app_data) const;
163 
164   // Returns an XML that goes into the body of the <app> element of the Omaha
165   // request based on the given parameters.
166   std::string GetAppBody(const OmahaAppData& app_data) const;
167 
168   // Returns the cohort* argument to include in the <app> tag for the passed
169   // |arg_name| and |prefs_key|, if any. The return value is suitable to
170   // concatenate to the list of arguments and includes a space at the end.
171   std::string GetCohortArg(const std::string arg_name,
172                            const std::string prefs_key,
173                            const std::string override_value = "") const;
174 
175   // Returns an XML ping element if any of the elapsed days need to be
176   // sent, or an empty string otherwise.
177   std::string GetPing() const;
178 
179   // Returns an XML ping element if any of the elapsed days need to be
180   // sent, or an empty string otherwise.
181   std::string GetPingDateBased(
182       const OmahaRequestParams::AppParams& app_params) const;
183 
184   const OmahaEvent* event_;
185   OmahaRequestParams* params_;
186   bool ping_only_;
187   bool include_ping_;
188   int ping_active_days_;
189   int ping_roll_call_days_;
190   int install_date_in_days_;
191   PrefsInterface* prefs_;
192   std::string session_id_;
193 
194   DISALLOW_COPY_AND_ASSIGN(OmahaRequestBuilderXml);
195 };
196 
197 }  // namespace chromeos_update_engine
198 
199 #endif  // UPDATE_ENGINE_OMAHA_REQUEST_BUILDER_XML_H_
200