Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: chrome/browser/chromeos/policy/enterprise_install_attributes.cc

Issue 1189203003: Add UMA for consistency between TPM and install attributes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master3
Patch Set: Applied more comments, prevent concurrent TPM locking through multiple LockDevice() calls. Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h" 5 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/histogram_base.h"
15 #include "base/metrics/histogram_macros.h"
16 #include "base/time/time.h"
14 #include "chrome/browser/chromeos/policy/proto/install_attributes.pb.h" 17 #include "chrome/browser/chromeos/policy/proto/install_attributes.pb.h"
15 #include "chromeos/cryptohome/cryptohome_util.h" 18 #include "chromeos/cryptohome/cryptohome_util.h"
16 #include "chromeos/dbus/dbus_thread_manager.h" 19 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "google_apis/gaia/gaia_auth_util.h" 20 #include "google_apis/gaia/gaia_auth_util.h"
18 21
19 namespace policy { 22 namespace policy {
20 23
21 namespace cryptohome_util = chromeos::cryptohome_util; 24 namespace cryptohome_util = chromeos::cryptohome_util;
22 25
23 namespace { 26 namespace {
24 27
28 // Retry interval for consistency check against TPM lock state.
29 int kDbusRetryIntervalInSeconds = 5;
30
31 // Total time during which of TPM lock state queries are retried.
32 int kDbusRetryDurationInSeconds = 60;
33
25 bool ReadMapKey(const std::map<std::string, std::string>& map, 34 bool ReadMapKey(const std::map<std::string, std::string>& map,
26 const std::string& key, 35 const std::string& key,
27 std::string* value) { 36 std::string* value) {
28 std::map<std::string, std::string>::const_iterator entry = map.find(key); 37 std::map<std::string, std::string>::const_iterator entry = map.find(key);
29 if (entry == map.end()) 38 if (entry == map.end())
30 return false; 39 return false;
31 40
32 *value = entry->second; 41 *value = entry->second;
33 return true; 42 return true;
34 } 43 }
(...skipping 14 matching lines...) Expand all
49 attribute = install_attrs_proto.add_attributes(); 58 attribute = install_attrs_proto.add_attributes();
50 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser); 59 attribute->set_name(EnterpriseInstallAttributes::kAttrEnterpriseUser);
51 attribute->set_value(user_name); 60 attribute->set_value(user_name);
52 61
53 return install_attrs_proto.SerializeAsString(); 62 return install_attrs_proto.SerializeAsString();
54 } 63 }
55 64
56 EnterpriseInstallAttributes::EnterpriseInstallAttributes( 65 EnterpriseInstallAttributes::EnterpriseInstallAttributes(
57 chromeos::CryptohomeClient* cryptohome_client) 66 chromeos::CryptohomeClient* cryptohome_client)
58 : device_locked_(false), 67 : device_locked_(false),
68 consistency_check_running_(false),
69 registration_running_(false),
59 registration_mode_(DEVICE_MODE_PENDING), 70 registration_mode_(DEVICE_MODE_PENDING),
60 cryptohome_client_(cryptohome_client), 71 cryptohome_client_(cryptohome_client),
61 weak_ptr_factory_(this) { 72 weak_ptr_factory_(this) {
62 } 73 }
63 74
64 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {} 75 EnterpriseInstallAttributes::~EnterpriseInstallAttributes() {}
65 76
66 void EnterpriseInstallAttributes::ReadCacheFile( 77 void EnterpriseInstallAttributes::Init(const base::FilePath& cache_file) {
67 const base::FilePath& cache_file) { 78 DCHECK_EQ(false, device_locked_);
68 if (device_locked_ || !base::PathExists(cache_file)) 79
80 // The actual check happens asynchronously, thus it is ok to trigger it before
81 // Init() has completed.
82 TriggerConsistencyCheck(
83 kDbusRetryDurationInSeconds / kDbusRetryIntervalInSeconds);
84
85 if (!base::PathExists(cache_file))
69 return; 86 return;
70 87
71 device_locked_ = true; 88 device_locked_ = true;
72 89
73 char buf[16384]; 90 char buf[16384];
74 int len = base::ReadFile(cache_file, buf, sizeof(buf)); 91 int len = base::ReadFile(cache_file, buf, sizeof(buf));
75 if (len == -1 || len >= static_cast<int>(sizeof(buf))) { 92 if (len == -1 || len >= static_cast<int>(sizeof(buf))) {
76 PLOG(ERROR) << "Failed to read " << cache_file.value(); 93 PLOG(ERROR) << "Failed to read " << cache_file.value();
77 return; 94 return;
78 } 95 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 } 159 }
143 callback.Run(); 160 callback.Run();
144 } 161 }
145 162
146 void EnterpriseInstallAttributes::LockDevice( 163 void EnterpriseInstallAttributes::LockDevice(
147 const std::string& user, 164 const std::string& user,
148 DeviceMode device_mode, 165 DeviceMode device_mode,
149 const std::string& device_id, 166 const std::string& device_id,
150 const LockResultCallback& callback) { 167 const LockResultCallback& callback) {
151 DCHECK(!callback.is_null()); 168 DCHECK(!callback.is_null());
169 DCHECK_EQ(registration_running_, false);
Mattias Nissler (ping if slow) 2015/06/24 11:55:03 Let's make this a CHECK_EQ so we fail fast if this
Thiemo Nagel 2015/06/24 12:49:52 Done.
152 CHECK_NE(device_mode, DEVICE_MODE_PENDING); 170 CHECK_NE(device_mode, DEVICE_MODE_PENDING);
153 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET); 171 CHECK_NE(device_mode, DEVICE_MODE_NOT_SET);
154 172
155 // Check for existing lock first. 173 // Check for existing lock first.
156 if (device_locked_) { 174 if (device_locked_) {
157 if (device_mode != registration_mode_) { 175 if (device_mode != registration_mode_) {
158 callback.Run(LOCK_WRONG_MODE); 176 callback.Run(LOCK_WRONG_MODE);
159 return; 177 return;
160 } 178 }
161 179
(...skipping 17 matching lines...) Expand all
179 case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH: 197 case DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH:
180 // The user parameter is ignored for consumer devices. 198 // The user parameter is ignored for consumer devices.
181 break; 199 break;
182 } 200 }
183 201
184 // Already locked in the right mode, signal success. 202 // Already locked in the right mode, signal success.
185 callback.Run(LOCK_SUCCESS); 203 callback.Run(LOCK_SUCCESS);
186 return; 204 return;
187 } 205 }
188 206
207 registration_running_ = true;
208
209 // In case the consistency check is still running, postpone the device locking
210 // until it has finished. This should not introduce additional delay since
211 // device locking must wait for TPM initialization anyways.
212 if (consistency_check_running_) {
213 post_check_action_ = base::Bind(&EnterpriseInstallAttributes::LockDevice,
214 weak_ptr_factory_.GetWeakPtr(),
215 user,
216 device_mode,
217 device_id,
218 callback);
219 return;
220 }
221
189 cryptohome_client_->InstallAttributesIsReady( 222 cryptohome_client_->InstallAttributesIsReady(
190 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady, 223 base::Bind(&EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady,
191 weak_ptr_factory_.GetWeakPtr(), 224 weak_ptr_factory_.GetWeakPtr(),
192 user, 225 user,
193 device_mode, 226 device_mode,
194 device_id, 227 device_id,
195 callback)); 228 callback));
196 } 229 }
197 230
198 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady( 231 void EnterpriseInstallAttributes::LockDeviceIfAttributesIsReady(
199 const std::string& user, 232 const std::string& user,
200 DeviceMode device_mode, 233 DeviceMode device_mode,
201 const std::string& device_id, 234 const std::string& device_id,
202 const LockResultCallback& callback, 235 const LockResultCallback& callback,
203 chromeos::DBusMethodCallStatus call_status, 236 chromeos::DBusMethodCallStatus call_status,
204 bool result) { 237 bool result) {
205 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { 238 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
239 registration_running_ = false;
206 callback.Run(LOCK_NOT_READY); 240 callback.Run(LOCK_NOT_READY);
207 return; 241 return;
208 } 242 }
209 243
210 // Clearing the TPM password seems to be always a good deal. 244 // Clearing the TPM password seems to be always a good deal.
211 if (cryptohome_util::TpmIsEnabled() && 245 if (cryptohome_util::TpmIsEnabled() &&
212 !cryptohome_util::TpmIsBeingOwned() && 246 !cryptohome_util::TpmIsBeingOwned() &&
213 cryptohome_util::TpmIsOwned()) { 247 cryptohome_util::TpmIsOwned()) {
214 cryptohome_client_->CallTpmClearStoredPasswordAndBlock(); 248 cryptohome_client_->CallTpmClearStoredPasswordAndBlock();
215 } 249 }
216 250
217 // Make sure we really have a working InstallAttrs. 251 // Make sure we really have a working InstallAttrs.
218 if (cryptohome_util::InstallAttributesIsInvalid()) { 252 if (cryptohome_util::InstallAttributesIsInvalid()) {
219 LOG(ERROR) << "Install attributes invalid."; 253 LOG(ERROR) << "Install attributes invalid.";
254 registration_running_ = false;
220 callback.Run(LOCK_BACKEND_INVALID); 255 callback.Run(LOCK_BACKEND_INVALID);
221 return; 256 return;
222 } 257 }
223 258
224 if (!cryptohome_util::InstallAttributesIsFirstInstall()) { 259 if (!cryptohome_util::InstallAttributesIsFirstInstall()) {
225 LOG(ERROR) << "Install attributes already installed."; 260 LOG(ERROR) << "Install attributes already installed.";
261 registration_running_ = false;
226 callback.Run(LOCK_ALREADY_LOCKED); 262 callback.Run(LOCK_ALREADY_LOCKED);
227 return; 263 return;
228 } 264 }
229 265
230 std::string mode = GetDeviceModeString(device_mode); 266 std::string mode = GetDeviceModeString(device_mode);
231 std::string registration_user; 267 std::string registration_user;
232 if (!user.empty()) 268 if (!user.empty())
233 registration_user = gaia::CanonicalizeEmail(user); 269 registration_user = gaia::CanonicalizeEmail(user);
234 270
235 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) { 271 if (device_mode == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH) {
236 // Set values in the InstallAttrs and lock it. 272 // Set values in the InstallAttrs and lock it.
237 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled, 273 if (!cryptohome_util::InstallAttributesSet(kAttrConsumerKioskEnabled,
238 "true")) { 274 "true")) {
239 LOG(ERROR) << "Failed writing attributes."; 275 LOG(ERROR) << "Failed writing attributes.";
276 registration_running_ = false;
240 callback.Run(LOCK_SET_ERROR); 277 callback.Run(LOCK_SET_ERROR);
241 return; 278 return;
242 } 279 }
243 } else { 280 } else {
244 std::string domain = gaia::ExtractDomainName(registration_user); 281 std::string domain = gaia::ExtractDomainName(registration_user);
245 // Set values in the InstallAttrs and lock it. 282 // Set values in the InstallAttrs and lock it.
246 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned, "true") || 283 if (!cryptohome_util::InstallAttributesSet(kAttrEnterpriseOwned, "true") ||
247 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser, 284 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseUser,
248 registration_user) || 285 registration_user) ||
249 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain, 286 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDomain,
250 domain) || 287 domain) ||
251 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) || 288 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseMode, mode) ||
252 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId, 289 !cryptohome_util::InstallAttributesSet(kAttrEnterpriseDeviceId,
253 device_id)) { 290 device_id)) {
254 LOG(ERROR) << "Failed writing attributes."; 291 LOG(ERROR) << "Failed writing attributes.";
292 registration_running_ = false;
255 callback.Run(LOCK_SET_ERROR); 293 callback.Run(LOCK_SET_ERROR);
256 return; 294 return;
257 } 295 }
258 } 296 }
259 297
260 if (!cryptohome_util::InstallAttributesFinalize() || 298 if (!cryptohome_util::InstallAttributesFinalize() ||
261 cryptohome_util::InstallAttributesIsFirstInstall()) { 299 cryptohome_util::InstallAttributesIsFirstInstall()) {
262 LOG(ERROR) << "Failed locking."; 300 LOG(ERROR) << "Failed locking.";
301 registration_running_ = false;
263 callback.Run(LOCK_FINALIZE_ERROR); 302 callback.Run(LOCK_FINALIZE_ERROR);
264 return; 303 return;
265 } 304 }
266 305
267 ReadImmutableAttributes( 306 ReadImmutableAttributes(
268 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes, 307 base::Bind(&EnterpriseInstallAttributes::OnReadImmutableAttributes,
269 weak_ptr_factory_.GetWeakPtr(), 308 weak_ptr_factory_.GetWeakPtr(),
270 registration_user, 309 registration_user,
271 callback)); 310 callback));
272 } 311 }
273 312
274 void EnterpriseInstallAttributes::OnReadImmutableAttributes( 313 void EnterpriseInstallAttributes::OnReadImmutableAttributes(
275 const std::string& registration_user, 314 const std::string& registration_user,
276 const LockResultCallback& callback) { 315 const LockResultCallback& callback) {
277 316
278 if (GetRegistrationUser() != registration_user) { 317 if (GetRegistrationUser() != registration_user) {
279 LOG(ERROR) << "Locked data doesn't match."; 318 LOG(ERROR) << "Locked data doesn't match.";
319 registration_running_ = false;
280 callback.Run(LOCK_READBACK_ERROR); 320 callback.Run(LOCK_READBACK_ERROR);
281 return; 321 return;
282 } 322 }
283 323
324 registration_running_ = false;
284 callback.Run(LOCK_SUCCESS); 325 callback.Run(LOCK_SUCCESS);
285 } 326 }
286 327
287 bool EnterpriseInstallAttributes::IsEnterpriseDevice() { 328 bool EnterpriseInstallAttributes::IsEnterpriseDevice() {
288 return device_locked_ && !registration_user_.empty(); 329 return device_locked_ && !registration_user_.empty();
289 } 330 }
290 331
291 bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() { 332 bool EnterpriseInstallAttributes::IsConsumerKioskDeviceWithAutoLaunch() {
292 return device_locked_ && 333 return device_locked_ &&
293 registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH; 334 registration_mode_ == DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
(...skipping 17 matching lines...) Expand all
311 if (!IsEnterpriseDevice()) 352 if (!IsEnterpriseDevice())
312 return std::string(); 353 return std::string();
313 354
314 return registration_device_id_; 355 return registration_device_id_;
315 } 356 }
316 357
317 DeviceMode EnterpriseInstallAttributes::GetMode() { 358 DeviceMode EnterpriseInstallAttributes::GetMode() {
318 return registration_mode_; 359 return registration_mode_;
319 } 360 }
320 361
362 void EnterpriseInstallAttributes::TriggerConsistencyCheck(
363 int dbus_tries_remaining) {
364 consistency_check_running_ = true;
365 cryptohome_client_->TpmIsOwned(base::Bind(
366 &EnterpriseInstallAttributes::OnTpmOwnerCheckCompleted,
367 weak_ptr_factory_.GetWeakPtr(),
368 dbus_tries_remaining));
369 }
370
371 void EnterpriseInstallAttributes::OnTpmOwnerCheckCompleted(
372 int dbus_tries_remaining,
373 chromeos::DBusMethodCallStatus call_status,
374 bool result) {
375 if (call_status != chromeos::DBUS_METHOD_CALL_SUCCESS &&
376 dbus_tries_remaining) {
377 base::MessageLoop::current()->PostDelayedTask(
378 FROM_HERE,
379 base::Bind(&EnterpriseInstallAttributes::TriggerConsistencyCheck,
380 weak_ptr_factory_.GetWeakPtr(),
381 dbus_tries_remaining - 1),
382 base::TimeDelta::FromSeconds(kDbusRetryIntervalInSeconds));
383 return;
384 }
385
386 base::HistogramBase::Sample state = device_locked_;
387 state |= 0x2 * (registration_mode_ == DEVICE_MODE_ENTERPRISE);
388 if (call_status == chromeos::DBUS_METHOD_CALL_SUCCESS)
389 state |= 0x4 * result;
390 else
391 state |= 0x8;
392 UMA_HISTOGRAM_ENUMERATION("Enterprise.AttributesTPMConsistency", state, 12);
393
394 // Run any action (LockDevice call) that might have queued behind the
395 // consistency check.
396 consistency_check_running_ = false;
397 if (!post_check_action_.is_null())
398 post_check_action_.Run();
399 }
400
321 // Warning: The values for these keys (but not the keys themselves) are stored 401 // Warning: The values for these keys (but not the keys themselves) are stored
322 // in the protobuf with a trailing zero. Also note that some of these constants 402 // in the protobuf with a trailing zero. Also note that some of these constants
323 // have been copied to login_manager/device_policy_service.cc. Please make sure 403 // have been copied to login_manager/device_policy_service.cc. Please make sure
324 // that all changes to the constants are reflected there as well. 404 // that all changes to the constants are reflected there as well.
325 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer"; 405 const char EnterpriseInstallAttributes::kConsumerDeviceMode[] = "consumer";
326 const char EnterpriseInstallAttributes::kEnterpriseDeviceMode[] = "enterprise"; 406 const char EnterpriseInstallAttributes::kEnterpriseDeviceMode[] = "enterprise";
327 const char EnterpriseInstallAttributes::kLegacyRetailDeviceMode[] = "kiosk"; 407 const char EnterpriseInstallAttributes::kLegacyRetailDeviceMode[] = "kiosk";
328 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] = 408 const char EnterpriseInstallAttributes::kConsumerKioskDeviceMode[] =
329 "consumer_kiosk"; 409 "consumer_kiosk";
330 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown"; 410 const char EnterpriseInstallAttributes::kUnknownDeviceMode[] = "unknown";
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 &consumer_kiosk_enabled) && 488 &consumer_kiosk_enabled) &&
409 consumer_kiosk_enabled == "true") { 489 consumer_kiosk_enabled == "true") {
410 registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH; 490 registration_mode_ = DEVICE_MODE_CONSUMER_KIOSK_AUTOLAUNCH;
411 } else if (enterprise_user.empty() && enterprise_owned != "true") { 491 } else if (enterprise_user.empty() && enterprise_owned != "true") {
412 // |registration_user_| is empty on consumer devices. 492 // |registration_user_| is empty on consumer devices.
413 registration_mode_ = DEVICE_MODE_CONSUMER; 493 registration_mode_ = DEVICE_MODE_CONSUMER;
414 } 494 }
415 } 495 }
416 496
417 } // namespace policy 497 } // namespace policy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698