// Copyright (c) 2012 The Chromium OS 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 "login_manager/policy_service.h"

#include <stdint.h>

#include <string>

#include <base/bind.h>
#include <base/callback.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/memory/weak_ptr.h>
#include <base/message_loop/message_loop_proxy.h>
#include <base/stl_util.h>
#include <base/synchronization/waitable_event.h>

#include "bindings/device_management_backend.pb.h"
#include "login_manager/dbus_error_types.h"
#include "login_manager/nss_util.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_store.h"
#include "login_manager/system_utils.h"

namespace em = enterprise_management;

namespace login_manager {

PolicyService::Error::Error() : code_(dbus_error::kNone) {
}

PolicyService::Error::Error(const std::string& code, const std::string& message)
    : code_(code), message_(message) {
}

void PolicyService::Error::Set(const std::string& code,
                               const std::string& message) {
  code_ = code;
  message_ = message;
}

PolicyService::Delegate::~Delegate() {
}

PolicyService::PolicyService(
    scoped_ptr<PolicyStore> policy_store,
    PolicyKey* policy_key,
    const scoped_refptr<base::MessageLoopProxy>& main_loop)
    : policy_store_(policy_store.Pass()),
      policy_key_(policy_key),
      main_loop_(main_loop),
      delegate_(NULL),
      weak_ptr_factory_(this) {
}

PolicyService::~PolicyService() {
  weak_ptr_factory_.InvalidateWeakPtrs();  // Must remain at top of destructor.
}

bool PolicyService::Store(const uint8_t* policy_blob,
                          uint32_t len,
                          Completion completion,
                          int flags) {
  em::PolicyFetchResponse policy;
  if (!policy.ParseFromArray(policy_blob, len) || !policy.has_policy_data() ||
      !policy.has_policy_data_signature()) {
    const char msg[] = "Unable to parse policy protobuf.";
    LOG(ERROR) << msg;
    Error error(dbus_error::kSigDecodeFail, msg);
    completion.Run(error);
    return false;
  }

  return StorePolicy(policy, completion, flags);
}

bool PolicyService::Retrieve(std::vector<uint8_t>* policy_blob) {
  const em::PolicyFetchResponse& policy = store()->Get();
  policy_blob->resize(policy.ByteSize());
  uint8_t* start = vector_as_array(policy_blob);
  uint8_t* end = policy.SerializeWithCachedSizesToArray(start);
  return (end - start >= 0 &&
          static_cast<size_t>(end - start) == policy_blob->size());
}

bool PolicyService::PersistPolicySync() {
  bool status = store()->Persist();
  OnPolicyPersisted(Completion(), status);
  return status;
}

void PolicyService::PersistKey() {
  main_loop_->PostTask(FROM_HERE,
                       base::Bind(&PolicyService::PersistKeyOnLoop,
                                  weak_ptr_factory_.GetWeakPtr()));
}

void PolicyService::PersistPolicy() {
  main_loop_->PostTask(FROM_HERE,
                       base::Bind(&PolicyService::PersistPolicyOnLoop,
                                  weak_ptr_factory_.GetWeakPtr(),
                                  Completion()));
}

void PolicyService::PersistPolicyWithCompletion(Completion completion) {
  main_loop_->PostTask(FROM_HERE,
                       base::Bind(&PolicyService::PersistPolicyOnLoop,
                                  weak_ptr_factory_.GetWeakPtr(),
                                  completion));
}

bool PolicyService::StorePolicy(const em::PolicyFetchResponse& policy,
                                Completion completion,
                                int flags) {
  // Determine if the policy has pushed a new owner key and, if so, set it.
  if (policy.has_new_public_key() && !key()->Equals(policy.new_public_key())) {
    // The policy contains a new key, and it is different from |key_|.
    std::vector<uint8_t> der;
    NssUtil::BlobFromBuffer(policy.new_public_key(), &der);

    bool installed = false;
    if (key()->IsPopulated()) {
      if (policy.has_new_public_key_signature() && (flags & KEY_ROTATE)) {
        // Graceful key rotation.
        LOG(INFO) << "Attempting policy key rotation.";
        std::vector<uint8_t> sig;
        NssUtil::BlobFromBuffer(policy.new_public_key_signature(), &sig);
        installed = key()->Rotate(der, sig);
      }
    } else if (flags & KEY_INSTALL_NEW) {
      LOG(INFO) << "Attempting to install new policy key.";
      installed = key()->PopulateFromBuffer(der);
    }
    if (!installed && (flags & KEY_CLOBBER)) {
      LOG(INFO) << "Clobbering existing policy key.";
      installed = key()->ClobberCompromisedKey(der);
    }

    if (!installed) {
      const char msg[] = "Failed to install policy key!";
      LOG(ERROR) << msg;
      Error error(dbus_error::kPubkeySetIllegal, msg);
      completion.Run(error);
      return false;
    }

    // If here, need to persist the key just loaded into memory to disk.
    PersistKey();
  }

  // Validate signature on policy and persist to disk.
  const std::string& data(policy.policy_data());
  const std::string& sig(policy.policy_data_signature());
  if (!key()->Verify(reinterpret_cast<const uint8_t*>(data.c_str()),
                     data.size(),
                     reinterpret_cast<const uint8_t*>(sig.c_str()),
                     sig.size())) {
    const char msg[] = "Signature could not be verified.";
    LOG(ERROR) << msg;
    Error error(dbus_error::kVerifyFail, msg);
    completion.Run(error);
    return false;
  }

  store()->Set(policy);
  PersistPolicyWithCompletion(completion);
  return true;
}

void PolicyService::OnKeyPersisted(bool status) {
  if (status)
    LOG(INFO) << "Persisted policy key to disk.";
  else
    LOG(ERROR) << "Failed to persist policy key to disk.";
  if (delegate_)
    delegate_->OnKeyPersisted(status);
}

void PolicyService::PersistKeyOnLoop() {
  DCHECK(main_loop_->BelongsToCurrentThread());
  OnKeyPersisted(key()->Persist());
}

void PolicyService::PersistPolicyOnLoop(Completion completion) {
  DCHECK(main_loop_->BelongsToCurrentThread());
  OnPolicyPersisted(completion, store()->Persist());
}

void PolicyService::OnPolicyPersisted(Completion completion,
                                      bool status) {
  if (status) {
    LOG(INFO) << "Persisted policy to disk.";
    if (!completion.is_null())
      completion.Run(Error());
  } else {
    std::string msg = "Failed to persist policy to disk.";
    LOG(ERROR) << msg;
    if (!completion.is_null()) {
      Error error(dbus_error::kSigEncodeFail, msg);
      completion.Run(error);
    }
  }

  if (delegate_)
    delegate_->OnPolicyPersisted(status);
}

}  // namespace login_manager
