// 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/stl_util.h>
#include <base/synchronization/waitable_event.h>
#include <chromeos/message_loops/message_loop.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)
    : policy_store_(policy_store.Pass()),
      policy_key_(policy_key),
      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() {
  chromeos::MessageLoop::current()->PostTask(
      FROM_HERE, base::Bind(&PolicyService::PersistKeyOnLoop,
                            weak_ptr_factory_.GetWeakPtr()));
}

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

void PolicyService::PersistPolicyWithCompletion(Completion completion) {
  chromeos::MessageLoop::current()->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() {
  OnKeyPersisted(key()->Persist());
}

void PolicyService::PersistPolicyOnLoop(Completion completion) {
  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
