// Copyright (c) 2011 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 "device_policy_service.h"

#include <base/file_path.h>
#include <base/logging.h>
#include <base/message_loop_proxy.h>
#include <base/task.h>

#include "login_manager/bindings/chrome_device_policy.pb.h"
#include "login_manager/bindings/device_management_backend.pb.h"
#include "login_manager/key_generator.h"
#include "login_manager/nss_util.h"
#include "login_manager/owner_key.h"
#include "login_manager/owner_key_loss_mitigator.h"
#include "login_manager/policy_store.h"

namespace em = enterprise_management;

namespace login_manager {
using google::protobuf::RepeatedPtrField;
using std::string;

// static
const char DevicePolicyService::kPolicyPath[] = "/var/lib/whitelist/policy";
// static
const char DevicePolicyService::kDevicePolicyType[] = "google/chromeos/device";

DevicePolicyService::~DevicePolicyService() {
}

// static
DevicePolicyService* DevicePolicyService::Create(
    OwnerKeyLossMitigator* mitigator,
    const scoped_refptr<base::MessageLoopProxy>& main_loop,
    const scoped_refptr<base::MessageLoopProxy>& io_loop) {
  NssUtil* nss = NssUtil::Create();
  return new DevicePolicyService(new PolicyStore(FilePath(kPolicyPath)),
                                 new OwnerKey(nss->GetOwnerKeyFilePath()),
                                 main_loop,
                                 io_loop,
                                 nss,
                                 mitigator);
}

bool DevicePolicyService::CheckAndHandleOwnerLogin(
    const std::string& current_user,
    bool* is_owner,
    Error* error) {
  // If the current user is the owner, and isn't whitelisted or set as the owner
  // in the settings blob, then do so.
  bool can_access_key = CurrentUserHasOwnerKey(key()->public_key_der(), error);
  if (can_access_key)
    StoreOwnerProperties(current_user, NULL);

  // Now, the flip side...if we believe the current user to be the owner based
  // on the user field in policy, and she DOESN'T have the private half of the
  // public key, we must mitigate.
  *is_owner = CurrentUserIsOwner(current_user);
  if (*is_owner && !can_access_key) {
    if (!mitigator_->Mitigate(key()))
      return false;
  }
  return true;
}

bool DevicePolicyService::ValidateAndStoreOwnerKey(
    const std::string& current_user,
    const std::string& buf) {
  std::vector<uint8> pub_key;
  NssUtil::BlobFromBuffer(buf, &pub_key);

  Error error;
  if (!CurrentUserHasOwnerKey(pub_key, &error))
   return false;

  // If we're not mitigating a key loss, we should be able to populate |key_|.
  // If we're mitigating a key loss, we should be able to clobber |key_|.
  if ((!mitigator_->Mitigating() && !key()->PopulateFromBuffer(pub_key)) ||
      (mitigator_->Mitigating() && !key()->ClobberCompromisedKey(pub_key))) {
    return false;
  }
  PersistKey();
  if (StoreOwnerProperties(current_user, &error)) {
    PersistPolicy();
  } else {
    LOG(WARNING) << "Could not immediately store owner properties in policy";
  }
  return true;
}

DevicePolicyService::DevicePolicyService(
    PolicyStore* policy_store,
    OwnerKey* policy_key,
    const scoped_refptr<base::MessageLoopProxy>& main_loop,
    const scoped_refptr<base::MessageLoopProxy>& io_loop,
    NssUtil* nss,
    OwnerKeyLossMitigator* mitigator)
    : PolicyService(policy_store, policy_key, main_loop, io_loop),
      nss_(nss),
      mitigator_(mitigator) {
}

bool DevicePolicyService::KeyMissing() {
  return key()->HaveCheckedDisk() && !key()->IsPopulated();
}

bool DevicePolicyService::StoreOwnerProperties(const std::string& current_user,
                                               Error* error) {
  const em::PolicyFetchResponse& policy(store()->Get());
  em::PolicyData poldata;
  if (policy.has_policy_data())
    poldata.ParseFromString(policy.policy_data());
  em::ChromeDeviceSettingsProto polval;
  if (poldata.has_policy_type() &&
      poldata.policy_type() == kDevicePolicyType) {
    if (poldata.has_policy_value())
      polval.ParseFromString(poldata.policy_value());
  } else {
    poldata.set_policy_type(kDevicePolicyType);
  }
  // If there existed some device policy, we've got it now!
  // Update the UserWhitelistProto inside the ChromeDeviceSettingsProto we made.
  em::UserWhitelistProto* whitelist_proto = polval.mutable_user_whitelist();
  bool on_list = false;
  const RepeatedPtrField<string>& whitelist = whitelist_proto->user_whitelist();
  for (RepeatedPtrField<string>::const_iterator it = whitelist.begin();
       it != whitelist.end();
       ++it) {
    if (on_list = (current_user == *it))
      break;
  }
  if (poldata.has_username() && poldata.username() == current_user &&
      on_list &&
      key()->Equals(policy.new_public_key())) {
    return true;  // No changes are needed.
  }
  if (!on_list) {
    // Add owner to the whitelist and turn off whitelist enforcement if it is
    // currently not explicitly turned on or off.
    whitelist_proto->add_user_whitelist(current_user);
    if (!polval.has_allow_new_users())
      polval.mutable_allow_new_users()->set_allow_new_users(true);
  }
  poldata.set_username(current_user);

  // We have now updated the whitelist and owner setting in |polval|.
  // We need to put it into |poldata|, serialize that, sign it, and
  // write it back.
  poldata.set_policy_value(polval.SerializeAsString());
  std::string new_data = poldata.SerializeAsString();
  std::vector<uint8> sig;
  const uint8* data = reinterpret_cast<const uint8*>(new_data.c_str());
  if (!key() || !key()->Sign(data, new_data.length(), &sig)) {
    const char err_msg[] = "Could not sign policy containing new owner data.";
    LOG_IF(ERROR, error) << err_msg;
    LOG_IF(WARNING, !error) << err_msg;
    error->Set(CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, err_msg);
    return false;
  }

  em::PolicyFetchResponse new_policy;
  new_policy.CheckTypeAndMergeFrom(policy);
  new_policy.set_policy_data(new_data);
  new_policy.set_policy_data_signature(
      std::string(reinterpret_cast<const char*>(&sig[0]), sig.size()));
  const std::vector<uint8>& key_der = key()->public_key_der();
  new_policy.set_new_public_key(
      std::string(reinterpret_cast<const char*>(&key_der[0]), key_der.size()));
  store()->Set(new_policy);
  return true;
}

bool DevicePolicyService::CurrentUserHasOwnerKey(const std::vector<uint8>& key,
                                                 Error* error) {
  if (!nss_->MightHaveKeys())
    return false;
  if (!nss_->OpenUserDB()) {
    const char msg[] = "Could not open the current user's NSS database.";
    LOG(ERROR) << msg;
    error->Set(CHROMEOS_LOGIN_ERROR_NO_USER_NSSDB, msg);
    return false;
  }
  if (!nss_->GetPrivateKey(key)) {
    const char msg[] = "Could not verify that public key belongs to the owner.";
    LOG(WARNING) << msg;
    error->Set(CHROMEOS_LOGIN_ERROR_ILLEGAL_PUBKEY, msg);
    return false;
  }
  return true;
}

bool DevicePolicyService::CurrentUserIsOwner(const std::string& current_user) {
  const em::PolicyFetchResponse& policy(store()->Get());
  em::PolicyData poldata;
  if (!policy.has_policy_data())
    return false;
  if (poldata.ParseFromString(policy.policy_data())) {
    return (!poldata.has_request_token() &&
            poldata.has_username() &&
            poldata.username() == current_user);
  }
  return false;
}

}  // namespace login_manager
