1 // Copyright (c) 2012 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_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
6 #define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
7 
8 #include <memory>
9 #include <string>
10 #include <vector>
11 
12 #include "base/callback.h"
13 #include "base/compiler_specific.h"
14 #include "base/containers/circular_deque.h"
15 #include "base/macros.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/observer_list.h"
18 #include "chromeos/dbus/session_manager/session_manager_client.h"
19 #include "components/ownership/owner_settings_service.h"
20 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
21 #include "components/policy/core/common/cloud/cloud_policy_validator.h"
22 #include "components/policy/proto/chrome_device_policy.pb.h"
23 #include "components/policy/proto/device_management_backend.pb.h"
24 #include "crypto/scoped_nss_types.h"
25 
26 namespace ownership {
27 class OwnerKeyUtil;
28 class PublicKey;
29 }
30 
31 namespace policy {
32 namespace off_hours {
33 class DeviceOffHoursController;
34 }  // namespace off_hours
35 }  // namespace policy
36 
37 namespace chromeos {
38 
39 class SessionManagerOperation;
40 
41 // Deals with the low-level interface to Chrome OS device settings. Device
42 // settings are stored in a protobuf that's protected by a cryptographic
43 // signature generated by a key in the device owner's possession. Key and
44 // settings are brokered by the session_manager daemon.
45 //
46 // The purpose of DeviceSettingsService is to keep track of the current key and
47 // settings blob. For reading and writing device settings, use CrosSettings
48 // instead, which provides a high-level interface that allows for manipulation
49 // of individual settings.
50 //
51 // DeviceSettingsService generates notifications for key and policy update
52 // events so interested parties can reload state as appropriate.
53 class DeviceSettingsService : public SessionManagerClient::Observer {
54  public:
55   // Indicates ownership status of the device (listed in upgrade order).
56   enum OwnershipStatus {
57     OWNERSHIP_UNKNOWN = 0,
58     // Not yet owned.
59     OWNERSHIP_NONE,
60     // Either consumer ownership, cloud management or Active Directory
61     // management.
62     OWNERSHIP_TAKEN
63   };
64 
65   typedef base::Callback<void(OwnershipStatus)> OwnershipStatusCallback;
66 
67   // Status codes for Load() and Store().
68   // These values are logged to UMA. Entries should not be renumbered and
69   // numeric values should never be reused. Please keep in sync with
70   // "DeviceSettingsStatus" in src/tools/metrics/histograms/enums.xml.
71   enum Status {
72     STORE_SUCCESS,
73     STORE_KEY_UNAVAILABLE,   // Owner key not yet configured.
74     STORE_OPERATION_FAILED,  // IPC to session_manager daemon failed.
75     STORE_NO_POLICY,         // No settings blob present.
76     STORE_INVALID_POLICY,    // Invalid settings blob (proto parse failed).
77     STORE_VALIDATION_ERROR,  // Policy validation failure.
78     kMaxValue = STORE_VALIDATION_ERROR,
79   };
80 
81   // Observer interface.
82   class Observer {
83    public:
84     virtual ~Observer();
85 
86     // Indicates device ownership status changes.  This is triggered upon every
87     // browser start since the transition from uninitialized (OWNERSHIP_UNKNOWN)
88     // to initialized (either of OWNERSHIP_{NONE,TAKEN}) also counts as an
89     // ownership change.
90     virtual void OwnershipStatusChanged();
91 
92     // Gets called after updates to the device settings.
93     virtual void DeviceSettingsUpdated();
94 
95     virtual void OnDeviceSettingsServiceShutdown();
96   };
97 
98   // Manage singleton instance.
99   static void Initialize();
100   static bool IsInitialized();
101   static void Shutdown();
102   static DeviceSettingsService* Get();
103 
104   // Returns a human-readable string describing |status|.
105   static const char* StatusToString(Status status);
106 
107   // Creates a device settings service instance. This is meant for unit tests,
108   // production code uses the singleton returned by Get() above.
109   DeviceSettingsService();
110   ~DeviceSettingsService() override;
111 
112   // To be called on startup once threads are initialized and D-Bus is ready.
113   void SetSessionManager(SessionManagerClient* session_manager_client,
114                          scoped_refptr<ownership::OwnerKeyUtil> owner_key_util);
115 
116   // Prevents the service from making further calls to session_manager_client
117   // and stops any pending operations.
118   void UnsetSessionManager();
119 
120   // Must only be used with a |device_mode| that has been read and verified by
121   // the InstallAttributes class.
122   void SetDeviceMode(policy::DeviceMode device_mode);
123 
policy_data()124   const enterprise_management::PolicyData* policy_data() const {
125     return policy_data_.get();
126   }
127 
128   // Returns the currently active device settings. Returns nullptr if the device
129   // settings have not been retrieved from session_manager yet.
130   const enterprise_management::ChromeDeviceSettingsProto*
device_settings()131       device_settings() const {
132     return device_settings_.get();
133   }
134 
135   // Returns the currently used owner key.
136   scoped_refptr<ownership::PublicKey> GetPublicKey();
137 
138   // Returns the status generated by the *last operation*.
139   // WARNING: It is not correct to take this method as an indication of whether
140   // DeviceSettingsService contains valid device settings. In order to answer
141   // that question, simply check whether device_settings() is different from
142   // nullptr.
status()143   Status status() const { return store_status_; }
144 
145   // Returns the currently device off hours controller. The returned pointer is
146   // guaranteed to be non-null.
device_off_hours_controller()147   policy::off_hours::DeviceOffHoursController* device_off_hours_controller()
148       const {
149     return device_off_hours_controller_.get();
150   }
151 
152   void SetDeviceOffHoursControllerForTesting(
153       std::unique_ptr<policy::off_hours::DeviceOffHoursController> controller);
154 
155   // Triggers an attempt to pull the public half of the owner key from disk and
156   // load the device settings.
157   void Load();
158 
159   // Synchronously pulls the public key and loads the device settings.
160   void LoadImmediately();
161 
162   // Stores a policy blob to session_manager. The result of the operation is
163   // reported through |callback|. If successful, the updated device settings are
164   // present in policy_data() and device_settings() when the callback runs.
165   void Store(std::unique_ptr<enterprise_management::PolicyFetchResponse> policy,
166              const base::Closure& callback);
167 
168   // Returns the ownership status. May return OWNERSHIP_UNKNOWN if the disk
169   // hasn't been checked yet.
170   OwnershipStatus GetOwnershipStatus();
171 
172   // Determines the ownership status and reports the result to |callback|. This
173   // is guaranteed to never return OWNERSHIP_UNKNOWN.
174   void GetOwnershipStatusAsync(const OwnershipStatusCallback& callback);
175 
176   // Checks whether we have the private owner key.
177   //
178   // DEPRECATED (ygorshenin@, crbug.com/433840): this method should
179   // not be used since private key is a profile-specific resource and
180   // should be checked and used in a profile-aware manner, through
181   // OwnerSettingsService.
182   bool HasPrivateOwnerKey();
183 
184   // Sets the identity of the user that's interacting with the service. This is
185   // relevant only for writing settings through SignAndStore().
186   //
187   // TODO (ygorshenin@, crbug.com/433840): get rid of the method when
188   // write path for device settings will be removed from
189   // DeviceSettingsProvider and all existing clients will be switched
190   // to OwnerSettingsServiceChromeOS.
191   void InitOwner(const std::string& username,
192                  const base::WeakPtr<ownership::OwnerSettingsService>&
193                      owner_settings_service);
194 
195   const std::string& GetUsername() const;
196 
197   ownership::OwnerSettingsService* GetOwnerSettingsService() const;
198 
199   // Mark that the device will establish consumer ownership. If the flag is set
200   // and ownership is not taken, policy reload will be deferred until InitOwner
201   // is called. So that the ownership status is flipped after the private part
202   // of owner is fully loaded.
203   void MarkWillEstablishConsumerOwnership();
204 
205   // Adds an observer.
206   void AddObserver(Observer* observer);
207   // Removes an observer.
208   void RemoveObserver(Observer* observer);
209 
210   // SessionManagerClient::Observer:
211   void OwnerKeySet(bool success) override;
212   void PropertyChangeComplete(bool success) override;
213 
214  private:
215   friend class OwnerSettingsServiceChromeOS;
216 
217   // Enqueues a new operation. Takes ownership of |operation| and starts it
218   // right away if there is no active operation currently.
219   void Enqueue(std::unique_ptr<SessionManagerOperation> operation);
220 
221   // Enqueues a load operation.
222   void EnqueueLoad(bool request_key_load);
223 
224   // Makes sure there's a reload operation so changes to the settings (and key,
225   // in case |request_key_load| is set) are getting picked up.
226   void EnsureReload(bool request_key_load);
227 
228   // Runs the next pending operation.
229   void StartNextOperation();
230 
231   // Updates status, policy data and owner key from a finished operation.
232   void HandleCompletedOperation(const base::Closure& callback,
233                                 SessionManagerOperation* operation,
234                                 Status status);
235 
236   // Same as HandleCompletedOperation(), but also starts the next pending
237   // operation if available.
238   void HandleCompletedAsyncOperation(const base::Closure& callback,
239                                      SessionManagerOperation* operation,
240                                      Status status);
241 
242   // Run OwnershipStatusChanged() for observers.
243   void NotifyOwnershipStatusChanged() const;
244 
245   // Run DeviceSettingsUpdated() for observers.
246   void NotifyDeviceSettingsUpdated() const;
247 
248   // Processes pending callbacks from GetOwnershipStatusAsync().
249   void RunPendingOwnershipStatusCallbacks();
250 
251   SessionManagerClient* session_manager_client_ = nullptr;
252   scoped_refptr<ownership::OwnerKeyUtil> owner_key_util_;
253 
254   Status store_status_ = STORE_SUCCESS;
255 
256   std::vector<OwnershipStatusCallback> pending_ownership_status_callbacks_;
257 
258   std::string username_;
259   scoped_refptr<ownership::PublicKey> public_key_;
260   base::WeakPtr<ownership::OwnerSettingsService> owner_settings_service_;
261   // Ownership status before the current session manager operation.
262   OwnershipStatus previous_ownership_status_ = OWNERSHIP_UNKNOWN;
263 
264   std::unique_ptr<enterprise_management::PolicyData> policy_data_;
265   std::unique_ptr<enterprise_management::ChromeDeviceSettingsProto>
266       device_settings_;
267 
268   policy::DeviceMode device_mode_ = policy::DEVICE_MODE_PENDING;
269 
270   // The queue of pending operations. The first operation on the queue is
271   // currently active; it gets removed and destroyed once it completes.
272   base::circular_deque<std::unique_ptr<SessionManagerOperation>>
273       pending_operations_;
274 
275   base::ObserverList<Observer>::Unchecked observers_;
276 
277   // Whether the device will be establishing consumer ownership.
278   bool will_establish_consumer_ownership_ = false;
279 
280   std::unique_ptr<policy::off_hours::DeviceOffHoursController>
281       device_off_hours_controller_;
282 
283   base::WeakPtrFactory<DeviceSettingsService> weak_factory_{this};
284 
285   DISALLOW_COPY_AND_ASSIGN(DeviceSettingsService);
286 };
287 
288 // Helper class for tests. Initializes the DeviceSettingsService singleton on
289 // construction and tears it down again on destruction.
290 class ScopedTestDeviceSettingsService {
291  public:
292   ScopedTestDeviceSettingsService();
293   ~ScopedTestDeviceSettingsService();
294 
295  private:
296   DISALLOW_COPY_AND_ASSIGN(ScopedTestDeviceSettingsService);
297 };
298 
299 }  // namespace chromeos
300 
301 #endif  // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
302