// Copyright 2014 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. #include "components/ownership/owner_settings_service.h" #include #include #include #include "base/bind.h" #include "base/callback.h" #include "base/location.h" #include "base/logging.h" #include "base/single_thread_task_runner.h" #include "base/task_runner.h" #include "base/task_runner_util.h" #include "base/threading/thread_task_runner_handle.h" #include "base/values.h" #include "components/ownership/owner_key_util.h" #include "crypto/scoped_nss_types.h" namespace em = enterprise_management; namespace ownership { namespace { using ScopedSGNContext = std::unique_ptr< SGNContext, crypto::NSSDestroyer1>; std::unique_ptr AssembleAndSignPolicy( std::unique_ptr policy, scoped_refptr private_key) { DCHECK(private_key->key()); // Assemble the policy. std::unique_ptr policy_response( new em::PolicyFetchResponse()); if (!policy->SerializeToString(policy_response->mutable_policy_data())) { LOG(ERROR) << "Failed to encode policy payload."; return nullptr; } ScopedSGNContext sign_context(SGN_NewContext( SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, private_key->key())); if (!sign_context) { NOTREACHED(); return nullptr; } SECItem signature_item; if (SGN_Begin(sign_context.get()) != SECSuccess || SGN_Update(sign_context.get(), reinterpret_cast( policy_response->policy_data().c_str()), policy_response->policy_data().size()) != SECSuccess || SGN_End(sign_context.get(), &signature_item) != SECSuccess) { LOG(ERROR) << "Failed to create policy signature."; return nullptr; } policy_response->mutable_policy_data_signature()->assign( reinterpret_cast(signature_item.data), signature_item.len); SECITEM_FreeItem(&signature_item, PR_FALSE); return policy_response; } } // namepace OwnerSettingsService::OwnerSettingsService( const scoped_refptr& owner_key_util) : owner_key_util_(owner_key_util), weak_factory_(this) { } OwnerSettingsService::~OwnerSettingsService() { DCHECK(thread_checker_.CalledOnValidThread()); } void OwnerSettingsService::AddObserver(Observer* observer) { if (observer && !observers_.HasObserver(observer)) observers_.AddObserver(observer); } void OwnerSettingsService::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } bool OwnerSettingsService::IsOwner() { DCHECK(thread_checker_.CalledOnValidThread()); return private_key_.get() && private_key_->key(); } void OwnerSettingsService::IsOwnerAsync(const IsOwnerCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); if (private_key_.get()) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(callback, IsOwner())); } else { pending_is_owner_callbacks_.push_back(callback); } } bool OwnerSettingsService::AssembleAndSignPolicyAsync( base::TaskRunner* task_runner, std::unique_ptr policy, const AssembleAndSignPolicyAsyncCallback& callback) { DCHECK(thread_checker_.CalledOnValidThread()); if (!task_runner || !IsOwner()) return false; return base::PostTaskAndReplyWithResult( task_runner, FROM_HERE, base::Bind(&AssembleAndSignPolicy, base::Passed(&policy), private_key_), callback); } bool OwnerSettingsService::SetBoolean(const std::string& setting, bool value) { DCHECK(thread_checker_.CalledOnValidThread()); base::Value in_value(value); return Set(setting, in_value); } bool OwnerSettingsService::SetInteger(const std::string& setting, int value) { DCHECK(thread_checker_.CalledOnValidThread()); base::Value in_value(value); return Set(setting, in_value); } bool OwnerSettingsService::SetDouble(const std::string& setting, double value) { DCHECK(thread_checker_.CalledOnValidThread()); base::Value in_value(value); return Set(setting, in_value); } bool OwnerSettingsService::SetString(const std::string& setting, const std::string& value) { DCHECK(thread_checker_.CalledOnValidThread()); base::Value in_value(value); return Set(setting, in_value); } void OwnerSettingsService::ReloadKeypair() { ReloadKeypairImpl( base::Bind(&OwnerSettingsService::OnKeypairLoaded, as_weak_ptr())); } void OwnerSettingsService::OnKeypairLoaded( const scoped_refptr& public_key, const scoped_refptr& private_key) { DCHECK(thread_checker_.CalledOnValidThread()); public_key_ = public_key; private_key_ = private_key; const bool is_owner = IsOwner(); std::vector is_owner_callbacks; is_owner_callbacks.swap(pending_is_owner_callbacks_); for (std::vector::iterator it(is_owner_callbacks.begin()); it != is_owner_callbacks.end(); ++it) { it->Run(is_owner); } OnPostKeypairLoadedActions(); } } // namespace ownership