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

Side by Side Diff: chrome/browser/chromeos/attestation/attestation_policy_observer.cc

Issue 18053006: Added retry support to AttestationPolicyObserver. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 5 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 | Annotate | Revision Log
OLDNEW
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
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
139 // We expect a registered CloudPolicyClient. 152 // We expect a registered CloudPolicyClient.
140 if (!policy_client_->is_registered()) { 153 if (!policy_client_->is_registered()) {
141 LOG(ERROR) << "AttestationPolicyObserver: Invalid CloudPolicyClient."; 154 LOG(ERROR) << "AttestationPolicyObserver: Invalid CloudPolicyClient.";
155 Reschedule();
Mattias Nissler (ping if slow) 2013/07/02 08:18:07 Why is this needed?
dkrahn 2013/07/02 21:00:02 I haven't seen this fail but the idea was to resch
142 return; 156 return;
143 } 157 }
144 158
145 if (!cryptohome_client_) 159 if (!cryptohome_client_)
146 cryptohome_client_ = DBusThreadManager::Get()->GetCryptohomeClient(); 160 cryptohome_client_ = DBusThreadManager::Get()->GetCryptohomeClient();
147 161
148 if (!attestation_flow_) { 162 if (!attestation_flow_) {
149 scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient()); 163 scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient());
150 default_attestation_flow_.reset(new AttestationFlow( 164 default_attestation_flow_.reset(new AttestationFlow(
151 cryptohome::AsyncMethodCaller::GetInstance(), 165 cryptohome::AsyncMethodCaller::GetInstance(),
152 cryptohome_client_, 166 cryptohome_client_,
153 attestation_ca_client.Pass())); 167 attestation_ca_client.Pass()));
154 attestation_flow_ = default_attestation_flow_.get(); 168 attestation_flow_ = default_attestation_flow_.get();
155 } 169 }
156 170
157 // Start a dbus call to check if an Enterprise Machine Key already exists. 171 // Start a dbus call to check if an Enterprise Machine Key already exists.
158 base::Closure on_does_exist = 172 base::Closure on_does_exist =
159 base::Bind(&AttestationPolicyObserver::GetExistingCertificate, 173 base::Bind(&AttestationPolicyObserver::GetExistingCertificate,
160 weak_factory_.GetWeakPtr()); 174 weak_factory_.GetWeakPtr());
161 base::Closure on_does_not_exist = 175 base::Closure on_does_not_exist =
162 base::Bind(&AttestationPolicyObserver::GetNewCertificate, 176 base::Bind(&AttestationPolicyObserver::GetNewCertificate,
163 weak_factory_.GetWeakPtr()); 177 weak_factory_.GetWeakPtr());
164 cryptohome_client_->TpmAttestationDoesKeyExist( 178 cryptohome_client_->TpmAttestationDoesKeyExist(
165 KEY_DEVICE, 179 KEY_DEVICE,
166 kEnterpriseMachineKey, 180 kEnterpriseMachineKey,
167 base::Bind(DBusBoolRedirectCallback, 181 base::Bind(DBusBoolRedirectCallback,
168 on_does_exist, 182 on_does_exist,
169 on_does_not_exist, 183 on_does_not_exist,
184 base::Bind(&AttestationPolicyObserver::Reschedule,
185 weak_factory_.GetWeakPtr()),
170 FROM_HERE)); 186 FROM_HERE));
171 } 187 }
172 188
173 void AttestationPolicyObserver::GetNewCertificate() { 189 void AttestationPolicyObserver::GetNewCertificate() {
174 // We can reuse the dbus callback handler logic. 190 // We can reuse the dbus callback handler logic.
175 attestation_flow_->GetCertificate( 191 attestation_flow_->GetCertificate(
176 PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, 192 PROFILE_ENTERPRISE_MACHINE_CERTIFICATE,
177 true, // Force a new key to be generated. 193 true, // Force a new key to be generated.
178 base::Bind(DBusStringCallback, 194 base::Bind(DBusStringCallback,
179 base::Bind(&AttestationPolicyObserver::UploadCertificate, 195 base::Bind(&AttestationPolicyObserver::UploadCertificate,
180 weak_factory_.GetWeakPtr()), 196 weak_factory_.GetWeakPtr()),
197 base::Bind(&AttestationPolicyObserver::Reschedule,
198 weak_factory_.GetWeakPtr()),
181 FROM_HERE, 199 FROM_HERE,
182 DBUS_METHOD_CALL_SUCCESS)); 200 DBUS_METHOD_CALL_SUCCESS));
183 } 201 }
184 202
185 void AttestationPolicyObserver::GetExistingCertificate() { 203 void AttestationPolicyObserver::GetExistingCertificate() {
186 cryptohome_client_->TpmAttestationGetCertificate( 204 cryptohome_client_->TpmAttestationGetCertificate(
187 KEY_DEVICE, 205 KEY_DEVICE,
188 kEnterpriseMachineKey, 206 kEnterpriseMachineKey,
189 base::Bind(DBusStringCallback, 207 base::Bind(DBusStringCallback,
190 base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, 208 base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry,
191 weak_factory_.GetWeakPtr()), 209 weak_factory_.GetWeakPtr()),
210 base::Bind(&AttestationPolicyObserver::Reschedule,
211 weak_factory_.GetWeakPtr()),
192 FROM_HERE)); 212 FROM_HERE));
193 } 213 }
194 214
195 void AttestationPolicyObserver::CheckCertificateExpiry( 215 void AttestationPolicyObserver::CheckCertificateExpiry(
196 const std::string& certificate) { 216 const std::string& certificate) {
197 scoped_refptr<net::X509Certificate> x509( 217 scoped_refptr<net::X509Certificate> x509(
198 net::X509Certificate::CreateFromBytes(certificate.data(), 218 net::X509Certificate::CreateFromBytes(certificate.data(),
199 certificate.length())); 219 certificate.length()));
200 if (!x509.get() || x509->valid_expiry().is_null()) { 220 if (!x509.get() || x509->valid_expiry().is_null()) {
201 LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; 221 LOG(WARNING) << "Failed to parse certificate, cannot check expiry.";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 return; 254 return;
235 } 255 }
236 UploadCertificate(certificate); 256 UploadCertificate(certificate);
237 } 257 }
238 258
239 void AttestationPolicyObserver::GetKeyPayload( 259 void AttestationPolicyObserver::GetKeyPayload(
240 base::Callback<void(const std::string&)> callback) { 260 base::Callback<void(const std::string&)> callback) {
241 cryptohome_client_->TpmAttestationGetKeyPayload( 261 cryptohome_client_->TpmAttestationGetKeyPayload(
242 KEY_DEVICE, 262 KEY_DEVICE,
243 kEnterpriseMachineKey, 263 kEnterpriseMachineKey,
244 base::Bind(DBusStringCallback, callback, FROM_HERE)); 264 base::Bind(DBusStringCallback,
265 callback,
266 base::Bind(&AttestationPolicyObserver::Reschedule,
267 weak_factory_.GetWeakPtr()),
268 FROM_HERE));
245 } 269 }
246 270
247 void AttestationPolicyObserver::OnUploadComplete(bool status) { 271 void AttestationPolicyObserver::OnUploadComplete(bool status) {
248 if (!status) 272 if (!status) {
273 Reschedule();
Mattias Nissler (ping if slow) 2013/07/02 08:18:07 This is probably not a good idea. You'll hammer th
dkrahn 2013/07/02 21:00:02 You're right. This may be more work than I though
249 return; 274 return;
275 }
276 LOG(INFO) << "Enterprise Machine Certificate uploaded to DMServer.";
250 GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded, 277 GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded,
251 weak_factory_.GetWeakPtr())); 278 weak_factory_.GetWeakPtr()));
252 } 279 }
253 280
254 void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) { 281 void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) {
255 AttestationKeyPayload payload_pb; 282 AttestationKeyPayload payload_pb;
256 if (!key_payload.empty()) 283 if (!key_payload.empty())
257 payload_pb.ParseFromString(key_payload); 284 payload_pb.ParseFromString(key_payload);
258 payload_pb.set_is_certificate_uploaded(true); 285 payload_pb.set_is_certificate_uploaded(true);
259 std::string new_payload; 286 std::string new_payload;
260 if (!payload_pb.SerializeToString(&new_payload)) { 287 if (!payload_pb.SerializeToString(&new_payload)) {
261 LOG(WARNING) << "Failed to serialize key payload."; 288 LOG(WARNING) << "Failed to serialize key payload.";
262 return; 289 return;
263 } 290 }
264 cryptohome_client_->TpmAttestationSetKeyPayload( 291 cryptohome_client_->TpmAttestationSetKeyPayload(
265 KEY_DEVICE, 292 KEY_DEVICE,
266 kEnterpriseMachineKey, 293 kEnterpriseMachineKey,
267 new_payload, 294 new_payload,
268 base::Bind(DBusBoolRedirectCallback, 295 base::Bind(DBusBoolRedirectCallback,
269 base::Closure(), 296 base::Closure(),
270 base::Closure(), 297 base::Closure(),
298 base::Closure(),
271 FROM_HERE)); 299 FROM_HERE));
272 } 300 }
273 301
302 void AttestationPolicyObserver::Reschedule() {
303 if (++num_retries_ < kRetryLimit) {
304 content::BrowserThread::PostDelayedTask(
305 content::BrowserThread::UI, FROM_HERE,
306 base::Bind(&AttestationPolicyObserver::Start,
307 weak_factory_.GetWeakPtr()),
308 base::TimeDelta::FromSeconds(retry_delay_));
309 } else {
310 LOG(WARNING) << "AttestationPolicyObserver: Retry limit exceeded.";
311 }
312 }
313
274 } // namespace attestation 314 } // namespace attestation
275 } // namespace chromeos 315 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698