| Index: chrome/browser/chromeos/attestation/attestation_policy_observer.cc
|
| diff --git a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
|
| index a3ac89007aeca71fe17e2d6794d1676fcf9b00e4..00bf832681652a02fc0ed17ed8e8e7e37440b96d 100644
|
| --- a/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
|
| +++ b/chrome/browser/chromeos/attestation/attestation_policy_observer.cc
|
| @@ -7,7 +7,11 @@
|
| #include <string>
|
|
|
| #include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/location.h"
|
| +#include "base/time.h"
|
| #include "chrome/browser/chromeos/attestation/attestation_ca_client.h"
|
| +#include "chrome/browser/chromeos/attestation/attestation_key_payload.pb.h"
|
| #include "chrome/browser/chromeos/settings/cros_settings.h"
|
| #include "chrome/browser/policy/cloud/cloud_policy_client.h"
|
| #include "chrome/browser/policy/cloud/cloud_policy_manager.h"
|
| @@ -19,9 +23,19 @@
|
| #include "chromeos/dbus/dbus_thread_manager.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_details.h"
|
| +#include "net/cert/x509_certificate.h"
|
|
|
| namespace {
|
|
|
| +const char kEnterpriseMachineKey[] = "attest-ent-machine";
|
| +
|
| +// The number of days before a certificate expires during which it is
|
| +// considered 'expiring soon' and replacement is initiated. The Chrome OS CA
|
| +// issues certificates with an expiry of at least two years. This value has
|
| +// been set large enough so that the majority of users will have gone through
|
| +// a full sign-in during the period.
|
| +const int kExpiryThresholdInDays = 30;
|
| +
|
| // A dbus callback which handles a boolean result.
|
| //
|
| // Parameters
|
| @@ -31,10 +45,14 @@ namespace {
|
| // value - The value returned by the dbus operation.
|
| void DBusBoolRedirectCallback(const base::Closure& on_true,
|
| const base::Closure& on_false,
|
| + const tracked_objects::Location& from_here,
|
| chromeos::DBusMethodCallStatus status,
|
| bool value) {
|
| - if (status != chromeos::DBUS_METHOD_CALL_SUCCESS)
|
| + if (status != chromeos::DBUS_METHOD_CALL_SUCCESS) {
|
| + LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString()
|
| + << " - " << status;
|
| return;
|
| + }
|
| const base::Closure& task = value ? on_true : on_false;
|
| if (!task.is_null())
|
| task.Run();
|
| @@ -49,11 +67,15 @@ void DBusBoolRedirectCallback(const base::Closure& on_true,
|
| // data - The data returned by the dbus operation.
|
| void DBusStringCallback(
|
| const base::Callback<void(const std::string&)> on_success,
|
| + const tracked_objects::Location& from_here,
|
| chromeos::DBusMethodCallStatus status,
|
| bool result,
|
| const std::string& data) {
|
| - if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result)
|
| + if (status != chromeos::DBUS_METHOD_CALL_SUCCESS || !result) {
|
| + LOG(ERROR) << "Cryptohome DBus method failed: " << from_here.ToString()
|
| + << " - " << status << " - " << result;
|
| return;
|
| + }
|
| on_success.Run(data);
|
| }
|
|
|
| @@ -62,9 +84,6 @@ void DBusStringCallback(
|
| namespace chromeos {
|
| namespace attestation {
|
|
|
| -const char AttestationPolicyObserver::kEnterpriseMachineKey[] =
|
| - "attest-ent-machine";
|
| -
|
| AttestationPolicyObserver::AttestationPolicyObserver(
|
| policy::CloudPolicyClient* policy_client)
|
| : cros_settings_(CrosSettings::Get()),
|
| @@ -145,7 +164,10 @@ void AttestationPolicyObserver::Start() {
|
| cryptohome_client_->TpmAttestationDoesKeyExist(
|
| KEY_DEVICE,
|
| kEnterpriseMachineKey,
|
| - base::Bind(DBusBoolRedirectCallback, on_does_exist, on_does_not_exist));
|
| + base::Bind(DBusBoolRedirectCallback,
|
| + on_does_exist,
|
| + on_does_not_exist,
|
| + FROM_HERE));
|
| }
|
|
|
| void AttestationPolicyObserver::GetNewCertificate() {
|
| @@ -156,6 +178,7 @@ void AttestationPolicyObserver::GetNewCertificate() {
|
| base::Bind(DBusStringCallback,
|
| base::Bind(&AttestationPolicyObserver::UploadCertificate,
|
| weak_factory_.GetWeakPtr()),
|
| + FROM_HERE,
|
| DBUS_METHOD_CALL_SUCCESS));
|
| }
|
|
|
| @@ -165,23 +188,87 @@ void AttestationPolicyObserver::GetExistingCertificate() {
|
| kEnterpriseMachineKey,
|
| base::Bind(DBusStringCallback,
|
| base::Bind(&AttestationPolicyObserver::CheckCertificateExpiry,
|
| - weak_factory_.GetWeakPtr())));
|
| + weak_factory_.GetWeakPtr()),
|
| + FROM_HERE));
|
| }
|
|
|
| void AttestationPolicyObserver::CheckCertificateExpiry(
|
| const std::string& certificate) {
|
| - // TODO(dkrahn): Check if the certificate will expire soon, for now assume no.
|
| - CheckIfUploaded(certificate);
|
| + scoped_refptr<net::X509Certificate> x509(
|
| + net::X509Certificate::CreateFromBytes(certificate.data(),
|
| + certificate.length()));
|
| + if (!x509.get() || x509->valid_expiry().is_null()) {
|
| + LOG(WARNING) << "Failed to parse certificate, cannot check expiry.";
|
| + } else {
|
| + const base::TimeDelta threshold =
|
| + base::TimeDelta::FromDays(kExpiryThresholdInDays);
|
| + if ((base::Time::Now() + threshold) > x509->valid_expiry()) {
|
| + // The certificate has expired or will soon, replace it.
|
| + GetNewCertificate();
|
| + return;
|
| + }
|
| + }
|
| +
|
| + // Get the payload and check if the certificate has already been uploaded.
|
| + GetKeyPayload(base::Bind(&AttestationPolicyObserver::CheckIfUploaded,
|
| + weak_factory_.GetWeakPtr(),
|
| + certificate));
|
| }
|
|
|
| void AttestationPolicyObserver::UploadCertificate(
|
| const std::string& certificate) {
|
| - // TODO(dkrahn): Upload the certificate.
|
| + policy_client_->UploadCertificate(
|
| + certificate,
|
| + base::Bind(&AttestationPolicyObserver::OnUploadComplete,
|
| + weak_factory_.GetWeakPtr()));
|
| }
|
|
|
| void AttestationPolicyObserver::CheckIfUploaded(
|
| - const std::string& certificate) {
|
| - // TODO(dkrahn): Check if we've already uploaded the certificate.
|
| + const std::string& certificate,
|
| + const std::string& key_payload) {
|
| + AttestationKeyPayload payload_pb;
|
| + if (!key_payload.empty() &&
|
| + payload_pb.ParseFromString(key_payload) &&
|
| + payload_pb.is_certificate_uploaded()) {
|
| + // Already uploaded... nothing more to do.
|
| + return;
|
| + }
|
| + UploadCertificate(certificate);
|
| +}
|
| +
|
| +void AttestationPolicyObserver::GetKeyPayload(
|
| + base::Callback<void(const std::string&)> callback) {
|
| + cryptohome_client_->TpmAttestationGetKeyPayload(
|
| + KEY_DEVICE,
|
| + kEnterpriseMachineKey,
|
| + base::Bind(DBusStringCallback, callback, FROM_HERE));
|
| +}
|
| +
|
| +void AttestationPolicyObserver::OnUploadComplete(bool status) {
|
| + if (!status)
|
| + return;
|
| + GetKeyPayload(base::Bind(&AttestationPolicyObserver::MarkAsUploaded,
|
| + weak_factory_.GetWeakPtr()));
|
| +}
|
| +
|
| +void AttestationPolicyObserver::MarkAsUploaded(const std::string& key_payload) {
|
| + AttestationKeyPayload payload_pb;
|
| + if (!key_payload.empty())
|
| + payload_pb.ParseFromString(key_payload);
|
| + payload_pb.set_is_certificate_uploaded(true);
|
| + std::string new_payload;
|
| + if (!payload_pb.SerializeToString(&new_payload)) {
|
| + LOG(WARNING) << "Failed to serialize key payload.";
|
| + return;
|
| + }
|
| + cryptohome_client_->TpmAttestationSetKeyPayload(
|
| + KEY_DEVICE,
|
| + kEnterpriseMachineKey,
|
| + new_payload,
|
| + base::Bind(DBusBoolRedirectCallback,
|
| + base::Closure(),
|
| + base::Closure(),
|
| + FROM_HERE));
|
| }
|
|
|
| } // namespace attestation
|
|
|