blob: 99e13e9ec36e7ca7d6c9c53689db7d57d2cd9f2f [file] [log] [blame]
Alex Deymoc705cc82014-02-19 11:15:00 -08001// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Alex Deymo0d11c602014-04-23 20:12:20 -07005#include "update_engine/policy_manager/chromeos_policy.h"
Alex Deymo0d11c602014-04-23 20:12:20 -07006
Gilad Arnolde1218812014-05-07 12:21:36 -07007#include <algorithm>
Gilad Arnold0adbc942014-05-12 10:35:43 -07008#include <set>
Alex Deymoc705cc82014-02-19 11:15:00 -08009#include <string>
10
Gilad Arnoldf62a4b82014-05-01 07:41:07 -070011#include <base/logging.h>
12#include <base/time/time.h>
13
14#include "update_engine/policy_manager/device_policy_provider.h"
15#include "update_engine/policy_manager/policy_utils.h"
Gilad Arnold0adbc942014-05-12 10:35:43 -070016#include "update_engine/policy_manager/shill_provider.h"
Gilad Arnoldf62a4b82014-05-01 07:41:07 -070017
Alex Deymo0d11c602014-04-23 20:12:20 -070018using base::Time;
19using base::TimeDelta;
Gilad Arnoldf62a4b82014-05-01 07:41:07 -070020using std::min;
Gilad Arnold0adbc942014-05-12 10:35:43 -070021using std::set;
Alex Deymoc705cc82014-02-19 11:15:00 -080022using std::string;
23
24namespace chromeos_policy_manager {
25
Alex Deymo0d11c602014-04-23 20:12:20 -070026EvalStatus ChromeOSPolicy::UpdateCheckAllowed(
27 EvaluationContext* ec, State* state, string* error,
28 UpdateCheckParams* result) const {
29 Time next_update_check;
30 if (NextUpdateCheckTime(ec, state, error, &next_update_check) !=
31 EvalStatus::kSucceeded) {
32 return EvalStatus::kFailed;
33 }
34
35 if (!ec->IsTimeGreaterThan(next_update_check))
36 return EvalStatus::kAskMeAgainLater;
37
38 // It is time to check for an update.
39 result->updates_enabled = true;
Alex Deymoe636c3c2014-03-11 19:02:08 -070040 return EvalStatus::kSucceeded;
Alex Deymoc705cc82014-02-19 11:15:00 -080041}
42
Gilad Arnoldf62a4b82014-05-01 07:41:07 -070043EvalStatus ChromeOSPolicy::UpdateCanStart(
44 EvaluationContext* ec,
45 State* state,
46 string* error,
47 UpdateCanStartResult* result,
48 const bool interactive,
49 const UpdateState& update_state) const {
50 // Set the default return values.
51 result->update_can_start = true;
52 result->http_allowed = true;
53 result->p2p_allowed = false;
54 result->target_channel.clear();
55 result->cannot_start_reason = UpdateCannotStartReason::kUndefined;
56 result->scatter_wait_period = kZeroInterval;
57 result->scatter_check_threshold = 0;
58
59 // Make sure that we're not due for an update check.
60 UpdateCheckParams check_result;
61 EvalStatus check_status = UpdateCheckAllowed(ec, state, error, &check_result);
62 if (check_status == EvalStatus::kFailed)
63 return EvalStatus::kFailed;
64 if (check_status == EvalStatus::kSucceeded &&
65 check_result.updates_enabled == true) {
66 result->update_can_start = false;
67 result->cannot_start_reason = UpdateCannotStartReason::kCheckDue;
68 return EvalStatus::kSucceeded;
69 }
70
71 DevicePolicyProvider* const dp_provider = state->device_policy_provider();
72
73 const bool* device_policy_is_loaded_p = ec->GetValue(
74 dp_provider->var_device_policy_is_loaded());
75 if (device_policy_is_loaded_p && *device_policy_is_loaded_p) {
76 // Ensure that update is enabled.
77 const bool* update_disabled_p = ec->GetValue(
78 dp_provider->var_update_disabled());
79 if (update_disabled_p && *update_disabled_p) {
80 result->update_can_start = false;
81 result->cannot_start_reason = UpdateCannotStartReason::kDisabledByPolicy;
82 return EvalStatus::kAskMeAgainLater;
83 }
84
85 // Check whether scattering applies to this update attempt.
86 // TODO(garnold) We should not be scattering during OOBE. We'll need to read
87 // the OOBE status (via SystemProvider) and only scatter if not enacted.
88 // TODO(garnold) Current code further suppresses scattering if a "deadline"
89 // attribute is found in the Omaha response. However, it appears that the
90 // presence of this attribute is merely indicative of an OOBE update, which
91 // we should support anyway (see above).
92 if (!interactive) {
93 UpdateScatteringResult scatter_result;
94 EvalStatus scattering_status = UpdateScattering(
95 ec, state, error, &scatter_result, update_state);
96 if (scattering_status != EvalStatus::kSucceeded ||
97 scatter_result.is_scattering) {
98 if (scattering_status != EvalStatus::kFailed) {
99 result->update_can_start = false;
100 result->cannot_start_reason = UpdateCannotStartReason::kScattering;
101 result->scatter_wait_period = scatter_result.wait_period;
102 result->scatter_check_threshold = scatter_result.check_threshold;
103 }
104 return scattering_status;
105 }
106 }
107
108 // Determine whether HTTP downloads are forbidden by policy. This only
109 // applies to official system builds; otherwise, HTTP is always enabled.
110 const bool* is_official_build_p = ec->GetValue(
111 state->system_provider()->var_is_official_build());
112 if (is_official_build_p && *is_official_build_p) {
113 const bool* policy_http_downloads_enabled_p = ec->GetValue(
114 dp_provider->var_http_downloads_enabled());
115 result->http_allowed =
116 !policy_http_downloads_enabled_p || *policy_http_downloads_enabled_p;
117 }
118
119 // Determine whether use of P2P is allowed by policy.
120 const bool* policy_au_p2p_enabled_p = ec->GetValue(
121 dp_provider->var_au_p2p_enabled());
122 result->p2p_allowed = policy_au_p2p_enabled_p && *policy_au_p2p_enabled_p;
123
124 // Determine whether a target channel is dictated by policy.
125 const bool* release_channel_delegated_p = ec->GetValue(
126 dp_provider->var_release_channel_delegated());
127 if (release_channel_delegated_p && !(*release_channel_delegated_p)) {
128 const string* release_channel_p = ec->GetValue(
129 dp_provider->var_release_channel());
130 if (release_channel_p)
131 result->target_channel = *release_channel_p;
132 }
133 }
134
135 // Enable P2P, if so mandated by the updater configuration.
136 if (!result->p2p_allowed) {
137 const bool* updater_p2p_enabled_p = ec->GetValue(
138 state->updater_provider()->var_p2p_enabled());
139 result->p2p_allowed = updater_p2p_enabled_p && *updater_p2p_enabled_p;
140 }
141
Gilad Arnoldaf2f6ae2014-04-28 14:14:52 -0700142 return EvalStatus::kSucceeded;
143}
144
Alex Deymo0d11c602014-04-23 20:12:20 -0700145EvalStatus ChromeOSPolicy::NextUpdateCheckTime(EvaluationContext* ec,
146 State* state, string* error,
147 Time* next_update_check) const {
148 // Don't check for updates too often. We limit the update checks to once every
149 // some interval. The interval is kTimeoutInitialInterval the first time and
150 // kTimeoutPeriodicInterval for the subsequent update checks. If the update
151 // check fails, we increase the interval between the update checks
152 // exponentially until kTimeoutMaxBackoffInterval. Finally, to avoid having
153 // many chromebooks running update checks at the exact same time, we add some
154 // fuzz to the interval.
155 const Time* updater_started_time =
156 ec->GetValue(state->updater_provider()->var_updater_started_time());
157 POLICY_CHECK_VALUE_AND_FAIL(updater_started_time, error);
158
159 const base::Time* last_checked_time =
160 ec->GetValue(state->updater_provider()->var_last_checked_time());
161
162 const uint64_t* seed = ec->GetValue(state->random_provider()->var_seed());
163 POLICY_CHECK_VALUE_AND_FAIL(seed, error);
164
165 PRNG prng(*seed);
166
167 if (!last_checked_time || *last_checked_time < *updater_started_time) {
168 // First attempt.
169 *next_update_check = *updater_started_time + FuzzedInterval(
170 &prng, kTimeoutInitialInterval, kTimeoutRegularFuzz);
171 return EvalStatus::kSucceeded;
172 }
173 // Check for previous failed attempts to implement the exponential backoff.
174 const unsigned int* consecutive_failed_update_checks = ec->GetValue(
175 state->updater_provider()->var_consecutive_failed_update_checks());
176 POLICY_CHECK_VALUE_AND_FAIL(consecutive_failed_update_checks, error);
177
178 int interval = kTimeoutInitialInterval;
179 for (unsigned int i = 0; i < *consecutive_failed_update_checks; ++i) {
180 interval *= 2;
181 if (interval > kTimeoutMaxBackoffInterval) {
182 interval = kTimeoutMaxBackoffInterval;
183 break;
184 }
185 }
186
187 *next_update_check = *last_checked_time + FuzzedInterval(
188 &prng, interval, kTimeoutRegularFuzz);
189 return EvalStatus::kSucceeded;
190}
191
192TimeDelta ChromeOSPolicy::FuzzedInterval(PRNG* prng, int interval, int fuzz) {
Gilad Arnolde1218812014-05-07 12:21:36 -0700193 DCHECK_GE(interval, 0);
194 DCHECK_GE(fuzz, 0);
Alex Deymo0d11c602014-04-23 20:12:20 -0700195 int half_fuzz = fuzz / 2;
Alex Deymo0d11c602014-04-23 20:12:20 -0700196 // This guarantees the output interval is non negative.
Gilad Arnolde1218812014-05-07 12:21:36 -0700197 int interval_min = std::max(interval - half_fuzz, 0);
198 int interval_max = interval + half_fuzz;
199 return TimeDelta::FromSeconds(prng->RandMinMax(interval_min, interval_max));
Alex Deymo0d11c602014-04-23 20:12:20 -0700200}
201
Gilad Arnoldf62a4b82014-05-01 07:41:07 -0700202EvalStatus ChromeOSPolicy::UpdateScattering(
203 EvaluationContext* ec,
204 State* state,
205 string* error,
206 UpdateScatteringResult* result,
207 const UpdateState& update_state) const {
208 // Preconditions. These stem from the postconditions and usage contract.
209 DCHECK(update_state.scatter_wait_period >= kZeroInterval);
210 DCHECK_GE(update_state.scatter_check_threshold, 0);
211
212 // Set default result values.
213 result->is_scattering = false;
214 result->wait_period = kZeroInterval;
215 result->check_threshold = 0;
216
217 DevicePolicyProvider* const dp_provider = state->device_policy_provider();
218
219 // Ensure that a device policy is loaded.
220 const bool* device_policy_is_loaded_p = ec->GetValue(
221 dp_provider->var_device_policy_is_loaded());
222 if (!(device_policy_is_loaded_p && *device_policy_is_loaded_p))
223 return EvalStatus::kSucceeded;
224
225 // Is scattering enabled by policy?
226 const TimeDelta* scatter_factor_p = ec->GetValue(
227 dp_provider->var_scatter_factor());
228 if (!scatter_factor_p || *scatter_factor_p == kZeroInterval)
229 return EvalStatus::kSucceeded;
230
231 // Obtain a pseudo-random number generator.
232 const uint64_t* seed = ec->GetValue(state->random_provider()->var_seed());
233 POLICY_CHECK_VALUE_AND_FAIL(seed, error);
234 PRNG prng(*seed);
235
236 // Step 1: Maintain the scattering wait period.
237 //
238 // If no wait period was previously determined, or it no longer fits in the
239 // scatter factor, then generate a new one. Otherwise, keep the one we have.
240 // TODO(garnold) Current code (UpdateAttempter::GenerateNewWaitingPeriod())
241 // always generates a non-zero value, which seems to imply that *some*
242 // scattering always happens. Yet to validate whether this is intentional.
243 TimeDelta wait_period = update_state.scatter_wait_period;
244 if (wait_period == kZeroInterval || wait_period > *scatter_factor_p) {
245 wait_period = TimeDelta::FromSeconds(
246 prng.RandMinMax(1, scatter_factor_p->InSeconds()));
247 }
248
249 // If we surpass the wait period or the max scatter period associated with
250 // the update, then no wait is needed.
251 Time wait_expires = (update_state.first_seen +
252 min(wait_period, update_state.scatter_wait_period_max));
253 if (ec->IsTimeGreaterThan(wait_expires))
254 wait_period = kZeroInterval;
255
256 // Step 2: Maintain the update check threshold count.
257 //
258 // If an update check threshold is not specified then generate a new
259 // one.
260 int check_threshold = update_state.scatter_check_threshold;
261 if (check_threshold == 0) {
262 check_threshold = prng.RandMinMax(
263 update_state.scatter_check_threshold_min,
264 update_state.scatter_check_threshold_max);
265 }
266
267 // If the update check threshold is not within allowed range then nullify it.
268 // TODO(garnold) This is compliant with current logic found in
269 // OmahaRequestAction::IsUpdateCheckCountBasedWaitingSatisfied(). We may want
270 // to change it so that it behaves similarly to the wait period case, namely
271 // if the current value exceeds the maximum, we set a new one within range.
272 if (check_threshold > update_state.scatter_check_threshold_max)
273 check_threshold = 0;
274
275 // If the update check threshold is non-zero and satisfied, then nullify it.
276 if (check_threshold > 0 && update_state.num_checks >= check_threshold)
277 check_threshold = 0;
278
279 bool is_scattering = (wait_period != kZeroInterval || check_threshold);
280 EvalStatus ret = EvalStatus::kSucceeded;
281 if (is_scattering && wait_period == update_state.scatter_wait_period &&
282 check_threshold == update_state.scatter_check_threshold)
283 ret = EvalStatus::kAskMeAgainLater;
284 result->is_scattering = is_scattering;
285 result->wait_period = wait_period;
286 result->check_threshold = check_threshold;
287 return ret;
288}
289
Gilad Arnold0adbc942014-05-12 10:35:43 -0700290// TODO(garnold) Logic in this method is based on
291// ConnectionManager::IsUpdateAllowedOver(); be sure to deprecate the latter.
292//
293// TODO(garnold) The current logic generally treats the list of allowed
294// connections coming from the device policy as a whitelist, meaning that it
295// can only be used for enabling connections, but not disable them. Further,
296// certain connection types (like Bluetooth) cannot be enabled even by policy.
297// In effect, the only thing that device policy can change is to enable
298// updates over a cellular network (disabled by default). We may want to
299// revisit this semantics, allowing greater flexibility in defining specific
300// permissions over all types of networks.
301EvalStatus ChromeOSPolicy::UpdateCurrentConnectionAllowed(
302 EvaluationContext* ec,
303 State* state,
304 string* error,
305 bool* result) const {
306 // Get the current connection type.
307 ShillProvider* const shill_provider = state->shill_provider();
308 const ConnectionType* conn_type_p = ec->GetValue(
309 shill_provider->var_conn_type());
310 POLICY_CHECK_VALUE_AND_FAIL(conn_type_p, error);
311 ConnectionType conn_type = *conn_type_p;
312
313 // If we're tethering, treat it as a cellular connection.
314 if (conn_type != ConnectionType::kCellular) {
315 const ConnectionTethering* conn_tethering_p = ec->GetValue(
316 shill_provider->var_conn_tethering());
317 POLICY_CHECK_VALUE_AND_FAIL(conn_tethering_p, error);
318 if (*conn_tethering_p == ConnectionTethering::kConfirmed)
319 conn_type = ConnectionType::kCellular;
320 }
321
322 // By default, we allow updates for all connection types, with exceptions as
323 // noted below. This also determines whether a device policy can override the
324 // default.
325 *result = true;
326 bool device_policy_can_override = false;
327 switch (conn_type) {
328 case ConnectionType::kBluetooth:
329 *result = false;
330 break;
331
332 case ConnectionType::kCellular:
333 *result = false;
334 device_policy_can_override = true;
335 break;
336
337 case ConnectionType::kUnknown:
338 if (error)
339 *error = "Unknown connection type";
340 return EvalStatus::kFailed;
341
342 default:
343 break; // Nothing to do.
344 }
345
346 // If update is allowed, we're done.
347 if (*result)
348 return EvalStatus::kSucceeded;
349
350 // Check whether the device policy specifically allows this connection.
351 bool user_settings_can_override = false;
352 if (device_policy_can_override) {
353 DevicePolicyProvider* const dp_provider = state->device_policy_provider();
354 const bool* device_policy_is_loaded_p = ec->GetValue(
355 dp_provider->var_device_policy_is_loaded());
356 if (device_policy_is_loaded_p && *device_policy_is_loaded_p) {
357 const set<ConnectionType>* allowed_conn_types_p = ec->GetValue(
358 dp_provider->var_allowed_connection_types_for_update());
359 if (allowed_conn_types_p) {
360 if (allowed_conn_types_p->count(conn_type)) {
361 *result = true;
362 return EvalStatus::kSucceeded;
363 }
364 } else {
365 user_settings_can_override = true;
366 }
367 }
368 }
369
370 // Local user settings can allow updates iff a policy was loaded but no
371 // allowed connections were specified in it. In all other cases, we either
372 // stick with the default or use the values determined by the policy.
373 if (user_settings_can_override) {
374 const bool* update_over_cellular_allowed_p = ec->GetValue(
375 state->updater_provider()->var_cellular_enabled());
376 if (update_over_cellular_allowed_p && *update_over_cellular_allowed_p)
377 *result = true;
378 }
379
380 return EvalStatus::kSucceeded;
381}
382
Alex Deymoc705cc82014-02-19 11:15:00 -0800383} // namespace chromeos_policy_manager