OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/attestation/attestation_policy_observer.h" | 5 #include "chrome/browser/chromeos/attestation/attestation_policy_observer.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 17 matching lines...) Expand all Loading... |
28 namespace { | 28 namespace { |
29 | 29 |
30 const char kEnterpriseMachineKey[] = "attest-ent-machine"; | 30 const char kEnterpriseMachineKey[] = "attest-ent-machine"; |
31 | 31 |
32 // The number of days before a certificate expires during which it is | 32 // The number of days before a certificate expires during which it is |
33 // considered 'expiring soon' and replacement is initiated. The Chrome OS CA | 33 // considered 'expiring soon' and replacement is initiated. The Chrome OS CA |
34 // issues certificates with an expiry of at least two years. This value has | 34 // issues certificates with an expiry of at least two years. This value has |
35 // been set large enough so that the majority of users will have gone through | 35 // been set large enough so that the majority of users will have gone through |
36 // a full sign-in during the period. | 36 // a full sign-in during the period. |
37 const int kExpiryThresholdInDays = 30; | 37 const int kExpiryThresholdInDays = 30; |
| 38 const int kRetryDelay = 5; // Seconds. |
| 39 const int kRetryLimit = 100; |
38 | 40 |
39 // A dbus callback which handles a boolean result. | 41 // A dbus callback which handles a boolean result. |
40 // | 42 // |
41 // Parameters | 43 // Parameters |
42 // on_true - Called when status=success and value=true. | 44 // on_true - Called when status=success and value=true. |
43 // on_false - Called when status=success and value=false. | 45 // on_false - Called when status=success and value=false. |
44 // status - The dbus operation status. | 46 // status - The dbus operation status. |
45 // value - The value returned by the dbus operation. | 47 // value - The value returned by the dbus operation. |
46 void DBusBoolRedirectCallback(const base::Closure& on_true, | 48 void DBusBoolRedirectCallback(const base::Closure& on_true, |
47 const base::Closure& on_false, | 49 const base::Closure& on_false, |
| 50 const base::Closure& on_failure, |
48 const tracked_objects::Location& from_here, | 51 const tracked_objects::Location& from_here, |
49 chromeos::DBusMethodCallStatus status, | 52 chromeos::DBusMethodCallStatus status, |
50 bool value) { | 53 bool value) { |
51 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) { | 54 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) { |
52 LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() | 55 LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() |
53 << " - " << status; | 56 << " - " << status; |
| 57 if (!on_failure.is_null()) |
| 58 on_failure.Run(); |
54 return; | 59 return; |
55 } | 60 } |
56 const base::Closure& task = value ? on_true : on_false; | 61 const base::Closure& task = value ? on_true : on_false; |
57 if (!task.is_null()) | 62 if (!task.is_null()) |
58 task.Run(); | 63 task.Run(); |
59 } | 64 } |
60 | 65 |
61 // A dbus callback which handles a string result. | 66 // A dbus callback which handles a string result. |
62 // | 67 // |
63 // Parameters | 68 // Parameters |
64 // on_success - Called when status=success and result=true. | 69 // on_success - Called when status=success and result=true. |
65 // status - The dbus operation status. | 70 // status - The dbus operation status. |
66 // result - The result returned by the dbus operation. | 71 // result - The result returned by the dbus operation. |
67 // data - The data returned by the dbus operation. | 72 // data - The data returned by the dbus operation. |
68 void DBusStringCallback( | 73 void DBusStringCallback( |
69 const base::Callback<void(const std::string&)> on_success, | 74 const base::Callback<void(const std::string&)> on_success, |
| 75 const base::Closure& on_failure, |
70 const tracked_objects::Location& from_here, | 76 const tracked_objects::Location& from_here, |
71 chromeos::DBusMethodCallStatus status, | 77 chromeos::DBusMethodCallStatus status, |
72 bool result, | 78 bool result, |
73 const std::string& data) { | 79 const std::string& data) { |
74 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { | 80 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { |
75 LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() | 81 LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString() |
76 << " - " << status << " - " << result; | 82 << " - " << status << " - " << result; |
| 83 if (!on_failure.is_null()) |
| 84 on_failure.Run(); |
77 return; | 85 return; |
78 } | 86 } |
79 on_success.Run(data); | 87 on_success.Run(data); |
80 } | 88 } |
81 | 89 |
82 } // namespace | 90 } // namespace |
83 | 91 |
84 namespace chromeos { | 92 namespace chromeos { |
85 namespace attestation { | 93 namespace attestation { |
86 | 94 |
87 AttestationPolicyObserver::AttestationPolicyObserver( | 95 AttestationPolicyObserver::AttestationPolicyObserver( |
88 policy::CloudPolicyClient* policy_client) | 96 policy::CloudPolicyClient* policy_client) |
89 : cros_settings_(CrosSettings::Get()), | 97 : cros_settings_(CrosSettings::Get()), |
90 policy_client_(policy_client), | 98 policy_client_(policy_client), |
91 cryptohome_client_(NULL), | 99 cryptohome_client_(NULL), |
92 attestation_flow_(NULL), | 100 attestation_flow_(NULL), |
| 101 num_retries_(0), |
| 102 retry_delay_(kRetryDelay), |
93 weak_factory_(this) { | 103 weak_factory_(this) { |
94 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 104 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
95 cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); | 105 cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); |
96 Start(); | 106 Start(); |
97 } | 107 } |
98 | 108 |
99 AttestationPolicyObserver::AttestationPolicyObserver( | 109 AttestationPolicyObserver::AttestationPolicyObserver( |
100 policy::CloudPolicyClient* policy_client, | 110 policy::CloudPolicyClient* policy_client, |
101 CryptohomeClient* cryptohome_client, | 111 CryptohomeClient* cryptohome_client, |
102 AttestationFlow* attestation_flow) | 112 AttestationFlow* attestation_flow) |
103 : cros_settings_(CrosSettings::Get()), | 113 : cros_settings_(CrosSettings::Get()), |
104 policy_client_(policy_client), | 114 policy_client_(policy_client), |
105 cryptohome_client_(cryptohome_client), | 115 cryptohome_client_(cryptohome_client), |
106 attestation_flow_(attestation_flow), | 116 attestation_flow_(attestation_flow), |
| 117 num_retries_(0), |
| 118 retry_delay_(kRetryDelay), |
107 weak_factory_(this) { | 119 weak_factory_(this) { |
108 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 120 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
109 cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); | 121 cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); |
110 Start(); | 122 Start(); |
111 } | 123 } |
112 | 124 |
113 AttestationPolicyObserver::~AttestationPolicyObserver() { | 125 AttestationPolicyObserver::~AttestationPolicyObserver() { |
114 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 126 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
115 cros_settings_->RemoveSettingsObserver(kDeviceAttestationEnabled, this); | 127 cros_settings_->RemoveSettingsObserver(kDeviceAttestationEnabled, this); |
116 } | 128 } |
117 | 129 |
118 void AttestationPolicyObserver::Observe( | 130 void AttestationPolicyObserver::Observe( |
119 int type, | 131 int type, |
120 const content::NotificationSource& source, | 132 const content::NotificationSource& source, |
121 const content::NotificationDetails& details) { | 133 const content::NotificationDetails& details) { |
122 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 134 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
123 std::string* path = content::Details<std::string>(details).ptr(); | 135 std::string* path = content::Details<std::string>(details).ptr(); |
124 if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED || | 136 if (type != chrome::NOTIFICATION_SYSTEM_SETTING_CHANGED || |
125 *path != kDeviceAttestationEnabled) { | 137 *path != kDeviceAttestationEnabled) { |
126 LOG(WARNING) << "AttestationPolicyObserver: Unexpected event received."; | 138 LOG(WARNING) << "AttestationPolicyObserver: Unexpected event received."; |
127 return; | 139 return; |
128 } | 140 } |
| 141 num_retries_ = 0; |
129 Start(); | 142 Start(); |
130 } | 143 } |
131 | 144 |
132 void AttestationPolicyObserver::Start() { | 145 void AttestationPolicyObserver::Start() { |
133 // If attestation is not enabled, there is nothing to do. | 146 // If attestation is not enabled, there is nothing to do. |
134 bool enabled = false; | 147 bool enabled = false; |
135 if (!cros_settings_->GetBoolean(kDeviceAttestationEnabled, &enabled) || | 148 if (!cros_settings_->GetBoolean(kDeviceAttestationEnabled, &enabled) || |
136 !enabled) | 149 !enabled) |
137 return; | 150 return; |
138 | 151 |
(...skipping 21 matching lines...) Expand all Loading... |
160 weak_factory_.GetWeakPtr()); | 173 weak_factory_.GetWeakPtr()); |
161 base::Closure on_does_not_exist = | 174 base::Closure on_does_not_exist = |
162 base::Bind(&AttestationPolicyObserver::GetNewCertificate, | 175 base::Bind(&AttestationPolicyObserver::GetNewCertificate, |
163 weak_factory_.GetWeakPtr()); | 176 weak_factory_.GetWeakPtr()); |
164 cryptohome_client_->TpmAttestationDoesKeyExist( | 177 cryptohome_client_->TpmAttestationDoesKeyExist( |
165 KEY_DEVICE, | 178 KEY_DEVICE, |
166 kEnterpriseMachineKey, | 179 kEnterpriseMachineKey, |
167 base::Bind(DBusBoolRedirectCallback, | 180 base::Bind(DBusBoolRedirectCallback, |
168 on_does_exist, | 181 on_does_exist, |
169 on_does_not_exist, | 182 on_does_not_exist, |
| 183 base::Bind(&AttestationPolicyObserver::Reschedule, |
| 184 weak_factory_.GetWeakPtr()), |
170 FROM_HERE)); | 185 FROM_HERE)); |
171 } | 186 } |
172 | 187 |
173 void AttestationPolicyObserver::GetNewCertificate() { | 188 void AttestationPolicyObserver::GetNewCertificate() { |
174 // We can reuse the dbus callback handler logic. | 189 // We can reuse the dbus callback handler logic. |
175 attestation_flow_->GetCertificate( | 190 attestation_flow_->GetCertificate( |
176 PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, | 191 PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, |
177 true, // Force a new key to be generated. | 192 true, // Force a new key to be generated. |
178 base::Bind(DBusStringCallback, | 193 base::Bind(DBusStringCallback, |
179 base::Bind(&AttestationPolicyObserver::UploadCertificate, | 194 base::Bind(&AttestationPolicyObserver::UploadCertificate, |
180 weak_factory_.GetWeakPtr()), | 195 weak_factory_.GetWeakPtr()), |
| 196 base::Bind(&AttestationPolicyObserver::Reschedule, |
| 197 weak_factory_.GetWeakPtr()), |
181 FROM_HERE, | 198 FROM_HERE, |
182 DBUS_METHOD_CALL_SUCCESS)); | 199 DBUS_METHOD_CALL_SUCCESS)); |
183 } | 200 } |
184 | 201 |
185 void AttestationPolicyObserver::GetExistingCertificate() { | 202 void AttestationPolicyObserver::GetExistingCertificate() { |
186 cryptohome_client_->TpmAttestationGetCertificate( | 203 cryptohome_client_->TpmAttestationGetCertificate( |
187 KEY_DEVICE, | 204 KEY_DEVICE, |
188 kEnterpriseMachineKey, | 205 kEnterpriseMachineKey, |
189 base::Bind(DBusStringCallback, | 206 base::Bind(DBusStringCallback, |
190 base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, | 207 base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, |
191 weak_factory_.GetWeakPtr()), | 208 weak_factory_.GetWeakPtr()), |
| 209 base::Bind(&AttestationPolicyObserver::Reschedule, |
| 210 weak_factory_.GetWeakPtr()), |
192 FROM_HERE)); | 211 FROM_HERE)); |
193 } | 212 } |
194 | 213 |
195 void AttestationPolicyObserver::CheckCertificateExpiry( | 214 void AttestationPolicyObserver::CheckCertificateExpiry( |
196 const std::string& certificate) { | 215 const std::string& certificate) { |
197 scoped_refptr<net::X509Certificate> x509( | 216 scoped_refptr<net::X509Certificate> x509( |
198 net::X509Certificate::CreateFromBytes(certificate.data(), | 217 net::X509Certificate::CreateFromBytes(certificate.data(), |
199 certificate.length())); | 218 certificate.length())); |
200 if (!x509.get() || x509->valid_expiry().is_null()) { | 219 if (!x509.get() || x509->valid_expiry().is_null()) { |
201 LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; | 220 LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 return; | 253 return; |
235 } | 254 } |
236 UploadCertificate(certificate); | 255 UploadCertificate(certificate); |
237 } | 256 } |
238 | 257 |
239 void AttestationPolicyObserver::GetKeyPayload( | 258 void AttestationPolicyObserver::GetKeyPayload( |
240 base::Callback<void(const std::string&)> callback) { | 259 base::Callback<void(const std::string&)> callback) { |
241 cryptohome_client_->TpmAttestationGetKeyPayload( | 260 cryptohome_client_->TpmAttestationGetKeyPayload( |
242 KEY_DEVICE, | 261 KEY_DEVICE, |
243 kEnterpriseMachineKey, | 262 kEnterpriseMachineKey, |
244 base::Bind(DBusStringCallback, callback, FROM_HERE)); | 263 base::Bind(DBusStringCallback, |
| 264 callback, |
| 265 base::Bind(&AttestationPolicyObserver::Reschedule, |
| 266 weak_factory_.GetWeakPtr()), |
| 267 FROM_HERE)); |
245 } | 268 } |
246 | 269 |
247 void AttestationPolicyObserver::OnUploadComplete(bool status) { | 270 void AttestationPolicyObserver::OnUploadComplete(bool status) { |
248 if (!status) | 271 if (!status) |
249 return; | 272 return; |
| 273 LOG(INFO) << "Enterprise Machine Certificate uploaded to DMServer."; |
250 GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded, | 274 GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded, |
251 weak_factory_.GetWeakPtr())); | 275 weak_factory_.GetWeakPtr())); |
252 } | 276 } |
253 | 277 |
254 void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) { | 278 void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) { |
255 AttestationKeyPayload payload_pb; | 279 AttestationKeyPayload payload_pb; |
256 if (!key_payload.empty()) | 280 if (!key_payload.empty()) |
257 payload_pb.ParseFromString(key_payload); | 281 payload_pb.ParseFromString(key_payload); |
258 payload_pb.set_is_certificate_uploaded(true); | 282 payload_pb.set_is_certificate_uploaded(true); |
259 std::string new_payload; | 283 std::string new_payload; |
260 if (!payload_pb.SerializeToString(&new_payload)) { | 284 if (!payload_pb.SerializeToString(&new_payload)) { |
261 LOG(WARNING) << "Failed to serialize key payload."; | 285 LOG(WARNING) << "Failed to serialize key payload."; |
262 return; | 286 return; |
263 } | 287 } |
264 cryptohome_client_->TpmAttestationSetKeyPayload( | 288 cryptohome_client_->TpmAttestationSetKeyPayload( |
265 KEY_DEVICE, | 289 KEY_DEVICE, |
266 kEnterpriseMachineKey, | 290 kEnterpriseMachineKey, |
267 new_payload, | 291 new_payload, |
268 base::Bind(DBusBoolRedirectCallback, | 292 base::Bind(DBusBoolRedirectCallback, |
269 base::Closure(), | 293 base::Closure(), |
270 base::Closure(), | 294 base::Closure(), |
| 295 base::Closure(), |
271 FROM_HERE)); | 296 FROM_HERE)); |
272 } | 297 } |
273 | 298 |
| 299 void AttestationPolicyObserver::Reschedule() { |
| 300 if (++num_retries_ < kRetryLimit) { |
| 301 content::BrowserThread::PostDelayedTask( |
| 302 content::BrowserThread::UI, FROM_HERE, |
| 303 base::Bind(&AttestationPolicyObserver::Start, |
| 304 weak_factory_.GetWeakPtr()), |
| 305 base::TimeDelta::FromSeconds(retry_delay_)); |
| 306 } else { |
| 307 LOG(WARNING) << "AttestationPolicyObserver: Retry limit exceeded."; |
| 308 } |
| 309 } |
| 310 |
274 } // namespace attestation | 311 } // namespace attestation |
275 } // namespace chromeos | 312 } // namespace chromeos |
OLD | NEW |