1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_CHROMEOS_ATTESTATION_MACHINE_CERTIFICATE_UPLOADER_IMPL_H_
6 #define CHROME_BROWSER_CHROMEOS_ATTESTATION_MACHINE_CERTIFICATE_UPLOADER_IMPL_H_
7 
8 #include <string>
9 
10 #include "base/callback.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/optional.h"
13 #include "chrome/browser/chromeos/attestation/machine_certificate_uploader.h"
14 #include "chromeos/dbus/attestation/interface.pb.h"
15 #include "chromeos/dbus/constants/attestation_constants.h"
16 
17 namespace policy {
18 class CloudPolicyClient;
19 }
20 
21 namespace chromeos {
22 
23 namespace attestation {
24 
25 class AttestationFlow;
26 
27 // A class which uploads enterprise machine certificates.
28 class MachineCertificateUploaderImpl : public MachineCertificateUploader {
29  public:
30   explicit MachineCertificateUploaderImpl(
31       policy::CloudPolicyClient* policy_client);
32 
33   // A constructor which allows custom AttestationFlow implementations. Useful
34   // for testing.
35   MachineCertificateUploaderImpl(policy::CloudPolicyClient* policy_client,
36                                  AttestationFlow* attestation_flow);
37 
38   ~MachineCertificateUploaderImpl() override;
39 
40   // Sets the retry limit in number of tries; useful in testing.
set_retry_limit(int limit)41   void set_retry_limit(int limit) { retry_limit_ = limit; }
42   // Sets the retry delay in seconds; useful in testing.
set_retry_delay(int retry_delay)43   void set_retry_delay(int retry_delay) { retry_delay_ = retry_delay; }
44 
45   using UploadCallback =
46       base::OnceCallback<void(bool /*certificate_uploaded*/)>;
47 
48   // Checks if the machine certificate has been uploaded, and if not, do so.
49   // A certificate will be obtained if needed.
50   void UploadCertificateIfNeeded(UploadCallback callback) override;
51 
52   // Refreshes a fresh machine certificate and uploads it.
53   void RefreshAndUploadCertificate(UploadCallback callback) override;
54 
55   // Non-blocking wait for a certificate to be uploaded. Calls the |callback|
56   // immediately if the certificate was already uploaded or wait for the next
57   // attempt to do so.
58   void WaitForUploadComplete(UploadCallback callback) override;
59 
60  private:
61   // Starts certificate obtention and upload.
62   void Start();
63 
64   // Gets a new certificate for the Enterprise Machine Key (EMK).
65   void GetNewCertificate();
66 
67   // Called when `GetKeyInfo()` returned to check the existing certificate.
68   // There are 3 cases by the status replied from attestation service:
69   //     1. If the existing EMK is found, calls `CheckCertificateExpiry()`.
70   //     2. If the key does not exist, calls `GetNewCertificate()`.
71   //     3. Otherwise, there is an error and `Reschedule()` is called to retry.
72   void OnGetExistingCertificate(const ::attestation::GetKeyInfoReply& reply);
73 
74   // Checks if any certificate in the given `reply` is expired and, if so, gets
75   // a new one. If not renewing, calls `CheckIfUploaded()`.
76   void CheckCertificateExpiry(const ::attestation::GetKeyInfoReply& reply);
77 
78   // Uploads a machine certificate to the policy server.
79   void UploadCertificate(const std::string& pem_certificate_chain);
80 
81   // Checks if a certificate in `reply` has already been uploaded and, if not,
82   // upload.
83   void CheckIfUploaded(const ::attestation::GetKeyInfoReply& reply);
84 
85   // Called when a certificate upload operation completes.  On success, |status|
86   // will be true.
87   void OnUploadComplete(bool status);
88 
89   // Marks a key as uploaded in the payload proto.
90   void MarkAsUploaded(const ::attestation::GetKeyInfoReply& reply);
91 
92   // Handles failure of getting a certificate.
93   void HandleGetCertificateFailure(AttestationStatus status);
94 
95   // Reschedules a policy check (i.e. a call to Start) for a later time.
96   // TODO(dkrahn): A better solution would be to wait for a dbus signal which
97   // indicates the system is ready to process this task. See crbug.com/256845.
98   void Reschedule();
99 
100   void RunCallbacks(bool status);
101 
102   policy::CloudPolicyClient* policy_client_ = nullptr;
103   AttestationFlow* attestation_flow_ = nullptr;
104   std::unique_ptr<AttestationFlow> default_attestation_flow_;
105   bool refresh_certificate_ = false;
106   std::vector<UploadCallback> callbacks_;
107   int num_retries_ = {};
108   int retry_limit_ = {};
109   int retry_delay_ = {};
110   base::Optional<bool> certificate_uploaded_;
111 
112   // Note: This should remain the last member so it'll be destroyed and
113   // invalidate the weak pointers before any other members are destroyed.
114   base::WeakPtrFactory<MachineCertificateUploaderImpl> weak_factory_{this};
115 
116   DISALLOW_COPY_AND_ASSIGN(MachineCertificateUploaderImpl);
117 };
118 
119 }  // namespace attestation
120 }  // namespace chromeos
121 
122 #endif  // CHROME_BROWSER_CHROMEOS_ATTESTATION_MACHINE_CERTIFICATE_UPLOADER_IMPL_H_
123