blob: 1d665693d216274102c57557ee8f558adb06fcc6 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_
#include <deque>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "chromeos/cert_loader.h"
#include "chromeos/dbus/session_manager_client.h"
#include "components/policy/core/common/cloud/cloud_policy_validator.h"
namespace crypto {
class RSAPrivateKey;
}
namespace enterprise_management {
class ChromeDeviceSettingsProto;
class PolicyData;
class PolicyFetchResponse;
}
namespace chromeos {
class OwnerKeyUtil;
class SessionManagerOperation;
// Keeps the public and private halves of the owner key. Both may be missing,
// but if the private key is present, the public half will be as well. This
// class is immutable and refcounted in order to allow safe access from any
// thread.
class OwnerKey : public base::RefCountedThreadSafe<OwnerKey> {
public:
OwnerKey(scoped_ptr<std::vector<uint8> > public_key,
scoped_ptr<crypto::RSAPrivateKey> private_key);
const std::vector<uint8>* public_key() {
return public_key_.get();
}
crypto::RSAPrivateKey* private_key() {
return private_key_.get();
}
private:
friend class base::RefCountedThreadSafe<OwnerKey>;
~OwnerKey();
scoped_ptr<std::vector<uint8> > public_key_;
scoped_ptr<crypto::RSAPrivateKey> private_key_;
DISALLOW_COPY_AND_ASSIGN(OwnerKey);
};
// Deals with the low-level interface to Chromium OS device settings. Device
// settings are stored in a protobuf that's protected by a cryptographic
// signature generated by a key in the device owner's possession. Key and
// settings are brokered by the session_manager daemon.
//
// The purpose of DeviceSettingsService is to keep track of the current key and
// settings blob. For reading and writing device settings, use CrosSettings
// instead, which provides a high-level interface that allows for manipulation
// of individual settings.
//
// DeviceSettingsService generates notifications for key and policy update
// events so interested parties can reload state as appropriate.
class DeviceSettingsService : public SessionManagerClient::Observer,
public CertLoader::Observer {
public:
// Indicates ownership status of the device.
enum OwnershipStatus {
// Listed in upgrade order.
OWNERSHIP_UNKNOWN = 0,
OWNERSHIP_NONE,
OWNERSHIP_TAKEN
};
typedef base::Callback<void(OwnershipStatus)> OwnershipStatusCallback;
typedef base::Callback<void(bool)> IsCurrentUserOwnerCallback;
// Status codes for Store().
enum Status {
STORE_SUCCESS,
STORE_KEY_UNAVAILABLE, // Owner key not yet configured.
STORE_POLICY_ERROR, // Failure constructing the settings blob.
STORE_OPERATION_FAILED, // IPC to session_manager daemon failed.
STORE_NO_POLICY, // No settings blob present.
STORE_INVALID_POLICY, // Invalid settings blob.
STORE_VALIDATION_ERROR, // Unrecoverable policy validation failure.
STORE_TEMP_VALIDATION_ERROR, // Temporary policy validation failure.
};
// Observer interface.
class Observer {
public:
virtual ~Observer();
// Indicates device ownership status changes.
virtual void OwnershipStatusChanged() = 0;
// Gets call after updates to the device settings.
virtual void DeviceSettingsUpdated() = 0;
};
// Manage singleton instance.
static void Initialize();
static bool IsInitialized();
static void Shutdown();
static DeviceSettingsService* Get();
// Creates a device settings service instance. This is meant for unit tests,
// production code uses the singleton returned by Get() above.
DeviceSettingsService();
virtual ~DeviceSettingsService();
// To be called on startup once threads are initialized and DBus is ready.
void SetSessionManager(SessionManagerClient* session_manager_client,
scoped_refptr<OwnerKeyUtil> owner_key_util);
// Prevents the service from making further calls to session_manager_client
// and stops any pending operations.
void UnsetSessionManager();
// Returns the currently active device settings. Returns NULL if the device
// settings have not been retrieved from session_manager yet.
const enterprise_management::PolicyData* policy_data() {
return policy_data_.get();
}
const enterprise_management::ChromeDeviceSettingsProto*
device_settings() const {
return device_settings_.get();
}
// Returns the currently used owner key.
scoped_refptr<OwnerKey> GetOwnerKey();
// Returns the status generated by the last operation.
Status status() {
return store_status_;
}
// Triggers an attempt to pull the public half of the owner key from disk and
// load the device settings.
void Load();
// Signs |settings| with the private half of the owner key and sends the
// resulting policy blob to session manager for storage. The result of the
// operation is reported through |callback|. If successful, the updated device
// settings are present in policy_data() and device_settings() when the
// callback runs.
void SignAndStore(
scoped_ptr<enterprise_management::ChromeDeviceSettingsProto> new_settings,
const base::Closure& callback);
// Stores a policy blob to session_manager. The result of the operation is
// reported through |callback|. If successful, the updated device settings are
// present in policy_data() and device_settings() when the callback runs.
void Store(scoped_ptr<enterprise_management::PolicyFetchResponse> policy,
const base::Closure& callback);
// Returns the ownership status. May return OWNERSHIP_UNKNOWN if the disk
// hasn't been checked yet.
OwnershipStatus GetOwnershipStatus();
// Determines the ownership status and reports the result to |callback|. This
// is guaranteed to never return OWNERSHIP_UNKNOWN.
void GetOwnershipStatusAsync(const OwnershipStatusCallback& callback);
// Checks whether we have the private owner key.
bool HasPrivateOwnerKey();
// Determines whether the current user is the owner. The callback is
// guaranteed not to be called before it is possible to determine if the
// current user is the owner (by testing existence of the private owner key).
void IsCurrentUserOwnerAsync(const IsCurrentUserOwnerCallback& callback);
// Sets the identity of the user that's interacting with the service. This is
// relevant only for writing settings through SignAndStore().
void SetUsername(const std::string& username);
const std::string& GetUsername() const;
// Adds an observer.
void AddObserver(Observer* observer);
// Removes an observer.
void RemoveObserver(Observer* observer);
// SessionManagerClient::Observer:
virtual void OwnerKeySet(bool success) OVERRIDE;
virtual void PropertyChangeComplete(bool success) OVERRIDE;
// CertLoader::Observer:
virtual void OnCertificatesLoaded(const net::CertificateList& cert_list,
bool initial_load) OVERRIDE;
private:
// Enqueues a new operation. Takes ownership of |operation| and starts it
// right away if there is no active operation currently.
void Enqueue(SessionManagerOperation* operation);
// Enqueues a load operation.
void EnqueueLoad(bool force_key_load);
// Makes sure there's a reload operation so changes to the settings (and key,
// in case force_key_load is set) are getting picked up.
void EnsureReload(bool force_key_load);
// Runs the next pending operation.
void StartNextOperation();
// Updates status, policy data and owner key from a finished operation.
// Starts the next pending operation if available.
void HandleCompletedOperation(const base::Closure& callback,
SessionManagerOperation* operation,
Status status);
SessionManagerClient* session_manager_client_;
scoped_refptr<OwnerKeyUtil> owner_key_util_;
base::WeakPtrFactory<DeviceSettingsService> weak_factory_;
Status store_status_;
std::vector<OwnershipStatusCallback> pending_ownership_status_callbacks_;
std::vector<IsCurrentUserOwnerCallback>
pending_is_current_user_owner_callbacks_;
std::string username_;
scoped_refptr<OwnerKey> owner_key_;
// Whether certificates have been loaded by CertLoader.
bool certificates_loaded_;
// Whether certificates were loaded when the current owner key was set.
// Implies that the current user is owner iff the private owner key is set.
bool owner_key_loaded_with_certificates_;
scoped_ptr<enterprise_management::PolicyData> policy_data_;
scoped_ptr<enterprise_management::ChromeDeviceSettingsProto> device_settings_;
// The queue of pending operations. The first operation on the queue is
// currently active; it gets removed and destroyed once it completes.
std::deque<SessionManagerOperation*> pending_operations_;
ObserverList<Observer, true> observers_;
// For recoverable load errors how many retries are left before we give up.
int load_retries_left_;
DISALLOW_COPY_AND_ASSIGN(DeviceSettingsService);
};
// Helper class for tests. Initializes the DeviceSettingsService singleton on
// construction and tears it down again on destruction.
class ScopedTestDeviceSettingsService {
public:
ScopedTestDeviceSettingsService();
~ScopedTestDeviceSettingsService();
private:
DISALLOW_COPY_AND_ASSIGN(ScopedTestDeviceSettingsService);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_SETTINGS_SERVICE_H_