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" | |
11 #include "base/time.h" | |
10 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" | 12 #include "chrome/browser/chromeos/attestation/attestation_ca_client.h" |
13 #include "chrome/browser/chromeos/attestation/attestation_key_payload.pb.h" | |
11 #include "chrome/browser/chromeos/settings/cros_settings.h" | 14 #include "chrome/browser/chromeos/settings/cros_settings.h" |
12 #include "chrome/browser/policy/cloud/cloud_policy_client.h" | 15 #include "chrome/browser/policy/cloud/cloud_policy_client.h" |
13 #include "chrome/browser/policy/cloud/cloud_policy_manager.h" | 16 #include "chrome/browser/policy/cloud/cloud_policy_manager.h" |
14 #include "chrome/common/chrome_notification_types.h" | 17 #include "chrome/common/chrome_notification_types.h" |
15 #include "chromeos/attestation/attestation_flow.h" | 18 #include "chromeos/attestation/attestation_flow.h" |
16 #include "chromeos/cryptohome/async_method_caller.h" | 19 #include "chromeos/cryptohome/async_method_caller.h" |
17 #include "chromeos/dbus/cryptohome_client.h" | 20 #include "chromeos/dbus/cryptohome_client.h" |
18 #include "chromeos/dbus/dbus_method_call_status.h" | 21 #include "chromeos/dbus/dbus_method_call_status.h" |
19 #include "chromeos/dbus/dbus_thread_manager.h" | 22 #include "chromeos/dbus/dbus_thread_manager.h" |
20 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
21 #include "content/public/browser/notification_details.h" | 24 #include "content/public/browser/notification_details.h" |
25 #include "net/cert/x509_certificate.h" | |
22 | 26 |
23 namespace { | 27 namespace { |
24 | 28 |
25 // A dbus callback which handles a boolean result. | 29 // A dbus callback which handles a boolean result. |
26 // | 30 // |
27 // Parameters | 31 // Parameters |
28 // on_true - Called when status=success and value=true. | 32 // on_true - Called when status=success and value=true. |
29 // on_false - Called when status=success and value=false. | 33 // on_false - Called when status=success and value=false. |
30 // status - The dbus operation status. | 34 // status - The dbus operation status. |
31 // value - The value returned by the dbus operation. | 35 // value - The value returned by the dbus operation. |
32 void DBusBoolRedirectCallback(const base::Closure& on_true, | 36 void DBusBoolRedirectCallback(const base::Closure& on_true, |
33 const base::Closure& on_false, | 37 const base::Closure& on_false, |
38 const std::string& method_name, | |
34 chromeos::DBusMethodCallStatus status, | 39 chromeos::DBusMethodCallStatus status, |
35 bool value) { | 40 bool value) { |
36 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) | 41 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) { |
42 LOG(WARNING) << "Cryptohome DBus method failed: " << method_name; | |
Mattias Nissler (ping if slow)
2013/04/23 10:53:01
You probably want to log |status| as well.
dkrahn
2013/04/23 21:17:09
Done.
| |
37 return; | 43 return; |
44 } | |
38 const base::Closure& task = value ? on_true : on_false; | 45 const base::Closure& task = value ? on_true : on_false; |
39 if (!task.is_null()) | 46 if (!task.is_null()) |
40 task.Run(); | 47 task.Run(); |
41 } | 48 } |
42 | 49 |
43 // A dbus callback which handles a string result. | 50 // A dbus callback which handles a string result. |
44 // | 51 // |
45 // Parameters | 52 // Parameters |
46 // on_success - Called when status=success and result=true. | 53 // on_success - Called when status=success and result=true. |
47 // status - The dbus operation status. | 54 // status - The dbus operation status. |
48 // result - The result returned by the dbus operation. | 55 // result - The result returned by the dbus operation. |
49 // data - The data returned by the dbus operation. | 56 // data - The data returned by the dbus operation. |
50 void DBusStringCallback( | 57 void DBusStringCallback( |
51 const base::Callback<void(const std::string&)> on_success, | 58 const base::Callback<void(const std::string&)> on_success, |
59 const std::string& method_name, | |
52 chromeos::DBusMethodCallStatus status, | 60 chromeos::DBusMethodCallStatus status, |
53 bool result, | 61 bool result, |
54 const std::string& data) { | 62 const std::string& data) { |
55 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) | 63 if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) { |
64 LOG(WARNING) << "Cryptohome DBus method failed: " << method_name; | |
56 return; | 65 return; |
66 } | |
57 on_success.Run(data); | 67 on_success.Run(data); |
58 } | 68 } |
59 | 69 |
60 } // namespace | 70 } // namespace |
61 | 71 |
62 namespace chromeos { | 72 namespace chromeos { |
63 namespace attestation { | 73 namespace attestation { |
64 | 74 |
65 const char AttestationPolicyObserver::kEnterpriseMachineKey[] = | 75 const char AttestationPolicyObserver::kEnterpriseMachineKey[] = |
66 "attest-ent-machine"; | 76 "attest-ent-machine"; |
67 | 77 |
78 const int AttestationPolicyObserver::kExpiryThresholdInDays = 30; | |
79 | |
68 AttestationPolicyObserver::AttestationPolicyObserver( | 80 AttestationPolicyObserver::AttestationPolicyObserver( |
69 policy::CloudPolicyClient* policy_client) | 81 policy::CloudPolicyClient* policy_client) |
70 : cros_settings_(CrosSettings::Get()), | 82 : cros_settings_(CrosSettings::Get()), |
71 policy_client_(policy_client), | 83 policy_client_(policy_client), |
72 cryptohome_client_(NULL), | 84 cryptohome_client_(NULL), |
73 attestation_flow_(NULL), | 85 attestation_flow_(NULL), |
74 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 86 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
75 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 87 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
76 cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); | 88 cros_settings_->AddSettingsObserver(kDeviceAttestationEnabled, this); |
77 Start(); | 89 Start(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
138 // Start a dbus call to check if an Enterprise Machine Key already exists. | 150 // Start a dbus call to check if an Enterprise Machine Key already exists. |
139 base::Closure on_does_exist = | 151 base::Closure on_does_exist = |
140 base::Bind(&AttestationPolicyObserver::GetExistingCertificate, | 152 base::Bind(&AttestationPolicyObserver::GetExistingCertificate, |
141 weak_factory_.GetWeakPtr()); | 153 weak_factory_.GetWeakPtr()); |
142 base::Closure on_does_not_exist = | 154 base::Closure on_does_not_exist = |
143 base::Bind(&AttestationPolicyObserver::GetNewCertificate, | 155 base::Bind(&AttestationPolicyObserver::GetNewCertificate, |
144 weak_factory_.GetWeakPtr()); | 156 weak_factory_.GetWeakPtr()); |
145 cryptohome_client_->TpmAttestationDoesKeyExist( | 157 cryptohome_client_->TpmAttestationDoesKeyExist( |
146 CryptohomeClient::DEVICE_KEY, | 158 CryptohomeClient::DEVICE_KEY, |
147 kEnterpriseMachineKey, | 159 kEnterpriseMachineKey, |
148 base::Bind(DBusBoolRedirectCallback, on_does_exist, on_does_not_exist)); | 160 base::Bind(DBusBoolRedirectCallback, |
161 on_does_exist, | |
162 on_does_not_exist, | |
163 "TpmAttestationDoesKeyExist")); | |
149 } | 164 } |
150 | 165 |
151 void AttestationPolicyObserver::GetNewCertificate() { | 166 void AttestationPolicyObserver::GetNewCertificate() { |
152 // We can reuse the dbus callback handler logic. | 167 // We can reuse the dbus callback handler logic. |
153 attestation_flow_->GetCertificate( | 168 attestation_flow_->GetCertificate( |
154 kEnterpriseMachineKey, | 169 kEnterpriseMachineKey, |
155 base::Bind(DBusStringCallback, | 170 base::Bind(DBusStringCallback, |
156 base::Bind(&AttestationPolicyObserver::UploadCertificate, | 171 base::Bind(&AttestationPolicyObserver::UploadCertificate, |
157 weak_factory_.GetWeakPtr()), | 172 weak_factory_.GetWeakPtr()), |
158 DBUS_METHOD_CALL_SUCCESS)); | 173 "", DBUS_METHOD_CALL_SUCCESS)); |
Mattias Nissler (ping if slow)
2013/04/23 10:53:01
Should have a proper identifying name? FWIW, you c
dkrahn
2013/04/23 21:17:09
Good idea, changed to use FROM_HERE.
| |
159 } | 174 } |
160 | 175 |
161 void AttestationPolicyObserver::GetExistingCertificate() { | 176 void AttestationPolicyObserver::GetExistingCertificate() { |
162 cryptohome_client_->TpmAttestationGetCertificate( | 177 cryptohome_client_->TpmAttestationGetCertificate( |
163 CryptohomeClient::DEVICE_KEY, | 178 CryptohomeClient::DEVICE_KEY, |
164 kEnterpriseMachineKey, | 179 kEnterpriseMachineKey, |
165 base::Bind(DBusStringCallback, | 180 base::Bind(DBusStringCallback, |
166 base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, | 181 base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry, |
167 weak_factory_.GetWeakPtr()))); | 182 weak_factory_.GetWeakPtr()), |
183 "TpmAttestationGetCertificate")); | |
168 } | 184 } |
169 | 185 |
170 void AttestationPolicyObserver::CheckCertificateExpiry( | 186 void AttestationPolicyObserver::CheckCertificateExpiry( |
171 const std::string& certificate) { | 187 const std::string& certificate) { |
172 // TODO(dkrahn): Check if the certificate will expire soon, for now assume no. | 188 scoped_refptr<net::X509Certificate> x509( |
173 CheckIfUploaded(certificate); | 189 net::X509Certificate::CreateFromBytes(certificate.data(), |
190 certificate.length())); | |
191 if (!x509.get() || x509->valid_expiry().is_null()) { | |
192 LOG(WARNING) << "Failed to parse certificate, cannot check expiry."; | |
193 } else { | |
194 const base::TimeDelta threshold = | |
195 base::TimeDelta::FromDays(kExpiryThresholdInDays); | |
196 if ((base::Time::Now() + threshold) > x509->valid_expiry()) { | |
197 // The certificate has expired or will soon, replace it. | |
198 GetNewCertificate(); | |
199 return; | |
200 } | |
201 } | |
202 | |
203 // Get the payload and check if the certificate has already been uploaded. | |
204 GetKeyPayload(base::Bind(&AttestationPolicyObserver::CheckIfUploaded, | |
205 weak_factory_.GetWeakPtr(), | |
206 certificate)); | |
174 } | 207 } |
175 | 208 |
176 void AttestationPolicyObserver::UploadCertificate( | 209 void AttestationPolicyObserver::UploadCertificate( |
177 const std::string& certificate) { | 210 const std::string& certificate) { |
178 // TODO(dkrahn): Upload the certificate. | 211 policy_client_->UploadCertificate( |
212 certificate, | |
213 base::Bind(&AttestationPolicyObserver::OnUploadComplete, | |
214 weak_factory_.GetWeakPtr())); | |
179 } | 215 } |
180 | 216 |
181 void AttestationPolicyObserver::CheckIfUploaded( | 217 void AttestationPolicyObserver::CheckIfUploaded( |
182 const std::string& certificate) { | 218 const std::string& certificate, |
183 // TODO(dkrahn): Check if we've already uploaded the certificate. | 219 const std::string& key_payload) { |
220 AttestationKeyPayload payload_pb; | |
221 if (!key_payload.empty() && | |
222 payload_pb.ParseFromString(key_payload) && | |
223 payload_pb.is_certificate_uploaded()) { | |
224 // Already uploaded... nothing more to do. | |
225 return; | |
226 } | |
227 UploadCertificate(certificate); | |
228 } | |
229 | |
230 void AttestationPolicyObserver::GetKeyPayload( | |
231 base::Callback<void(const std::string&)> callback) { | |
232 cryptohome_client_->TpmAttestationGetKeyPayload( | |
233 CryptohomeClient::DEVICE_KEY, | |
234 kEnterpriseMachineKey, | |
235 base::Bind(DBusStringCallback, callback, "TpmAttestationGetKeyPayload")); | |
236 } | |
237 | |
238 void AttestationPolicyObserver::OnUploadComplete(bool status) { | |
239 if (!status) | |
240 return; | |
241 GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded, | |
242 weak_factory_.GetWeakPtr())); | |
243 } | |
244 | |
245 void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) { | |
246 AttestationKeyPayload payload_pb; | |
247 if (!key_payload.empty()) | |
248 payload_pb.ParseFromString(key_payload); | |
249 payload_pb.set_is_certificate_uploaded(true); | |
250 std::string new_payload; | |
251 if (!payload_pb.SerializeToString(&new_payload)) { | |
252 LOG(WARNING) << "Failed to serialize key payload."; | |
253 return; | |
254 } | |
255 cryptohome_client_->TpmAttestationSetKeyPayload( | |
256 CryptohomeClient::DEVICE_KEY, | |
257 kEnterpriseMachineKey, | |
258 new_payload, | |
259 base::Bind(DBusBoolRedirectCallback, | |
260 base::Closure(), | |
261 base::Closure(), | |
262 "TpmAttestationSetKeyPayload")); | |
184 } | 263 } |
185 | 264 |
186 } // namespace attestation | 265 } // namespace attestation |
187 } // namespace chromeos | 266 } // namespace chromeos |
OLD | NEW |