// 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/device_policy_service.h"

#include <secmodt.h>
#include <stdint.h>

#include <vector>

#include <base/files/file_util.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/message_loop/message_loop_proxy.h>
#include <chromeos/switches/chrome_switches.h>
#include <crypto/rsa_private_key.h>
#include <crypto/scoped_nss_types.h>

#include "bindings/chrome_device_policy.pb.h"
#include "bindings/device_management_backend.pb.h"
#include "bindings/install_attributes.pb.h"
#include "login_manager/dbus_error_types.h"
#include "login_manager/key_generator.h"
#include "login_manager/login_metrics.h"
#include "login_manager/nss_util.h"
#include "login_manager/owner_key_loss_mitigator.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_store.h"

namespace em = enterprise_management;

namespace login_manager {
using crypto::RSAPrivateKey;
using google::protobuf::RepeatedPtrField;

namespace {

// Returns true if |policy| was not pushed by an enterprise.
bool IsConsumerPolicy(const em::PolicyFetchResponse& policy) {
  em::PolicyData poldata;
  if (!policy.has_policy_data() ||
      !poldata.ParseFromString(policy.policy_data())) {
    return false;
  }
  return !poldata.has_request_token() && poldata.has_username();
}

const char kInstallAttributesPath[] = "/home/.shadow/install_attributes.pb";

}  // namespace

// static
const char DevicePolicyService::kPolicyPath[] = "/var/lib/whitelist/policy";
// static
const char DevicePolicyService::kSerialRecoveryFlagFile[] =
    "/var/lib/enterprise_serial_number_recovery";
// static
const char DevicePolicyService::kDevicePolicyType[] = "google/chromeos/device";
// static
const char DevicePolicyService::kAttrEnterpriseMode[] = "enterprise.mode";
// static
const char DevicePolicyService::kEnterpriseDeviceMode[] = "enterprise";

DevicePolicyService::~DevicePolicyService() {
}

// static
DevicePolicyService* DevicePolicyService::Create(
    LoginMetrics* metrics,
    PolicyKey* owner_key,
    OwnerKeyLossMitigator* mitigator,
    NssUtil* nss,
    const scoped_refptr<base::MessageLoopProxy>& main_loop) {
  return new DevicePolicyService(
      base::FilePath(kSerialRecoveryFlagFile),
      base::FilePath(kPolicyPath),
      base::FilePath(kInstallAttributesPath),
      scoped_ptr<PolicyStore>(new PolicyStore(base::FilePath(kPolicyPath))),
      owner_key,
      main_loop,
      metrics,
      mitigator,
      nss);
}

bool DevicePolicyService::CheckAndHandleOwnerLogin(
    const std::string& current_user,
    PK11SlotInfo* slot,
    bool* is_owner,
    Error* error) {
  // Record metrics around consumer usage of user whitelisting.
  if (IsConsumerPolicy(store()->Get()))
    metrics_->SendConsumerAllowsNewUsers(PolicyAllowsNewUsers(store()->Get()));

  // If the current user is the owner, and isn't whitelisted or set as the owner
  // in the settings blob, then do so.
  scoped_ptr<RSAPrivateKey> signing_key(
      GetOwnerKeyForGivenUser(key()->public_key_der(), slot, error));
  if (signing_key.get()) {
    if (!StoreOwnerProperties(current_user, signing_key.get(), error))
      return false;
  }

  // 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 = GivenUserIsOwner(current_user);
  if (*is_owner && !signing_key.get()) {
    if (!mitigator_->Mitigate(current_user))
      return false;
  }
  return true;
}

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

  Error error;
  scoped_ptr<RSAPrivateKey> signing_key(
      GetOwnerKeyForGivenUser(pub_key, slot, &error));
  if (!signing_key.get())
    return false;

  if (mitigator_->Mitigating()) {
    // Mitigating: Depending on whether the public key is still present, either
    // clobber or populate regularly.
    if (!(key()->IsPopulated() ? key()->ClobberCompromisedKey(pub_key)
                               : key()->PopulateFromBuffer(pub_key))) {
      return false;
    }
  } else {
    // Not mitigating, so regular key population should work.
    if (!key()->PopulateFromBuffer(pub_key))
      return false;
    // Clear policy in case we're re-establishing ownership.
    store()->Set(em::PolicyFetchResponse());
  }

  if (StoreOwnerProperties(current_user, signing_key.get(), &error)) {
    PersistKey();
    PersistPolicy();
  } else {
    LOG(WARNING) << "Could not immediately store owner properties in policy";
  }
  return true;
}

DevicePolicyService::DevicePolicyService(
    const base::FilePath& serial_recovery_flag_file,
    const base::FilePath& policy_file,
    const base::FilePath& install_attributes_file,
    scoped_ptr<PolicyStore> policy_store,
    PolicyKey* policy_key,
    const scoped_refptr<base::MessageLoopProxy>& main_loop,
    LoginMetrics* metrics,
    OwnerKeyLossMitigator* mitigator,
    NssUtil* nss)
    : PolicyService(policy_store.Pass(), policy_key, main_loop),
      serial_recovery_flag_file_(serial_recovery_flag_file),
      policy_file_(policy_file),
      install_attributes_file_(install_attributes_file),
      metrics_(metrics),
      mitigator_(mitigator),
      nss_(nss) {
}

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

bool DevicePolicyService::Mitigating() {
  return mitigator_->Mitigating();
}

bool DevicePolicyService::Initialize() {
  bool key_success = key()->PopulateFromDiskIfPossible();
  if (!key_success)
    LOG(ERROR) << "Failed to load device policy key from disk.";

  bool policy_success = store()->LoadOrCreate();
  if (!policy_success)
    LOG(WARNING) << "Failed to load device policy data, continuing anyway.";

  if (!key_success && policy_success && store()->Get().has_new_public_key()) {
    LOG(WARNING) << "Recovering missing owner key from policy blob!";
    std::vector<uint8_t> pub_key;
    NssUtil::BlobFromBuffer(store()->Get().new_public_key(), &pub_key);
    key_success = key()->PopulateFromBuffer(pub_key);
    if (key_success)
      PersistKey();
  }

  ReportPolicyFileMetrics(key_success, policy_success);
  UpdateSerialNumberRecoveryFlagFile();
  return key_success;
}

bool DevicePolicyService::Store(const uint8_t* policy_blob,
                                uint32_t len,
                                Completion completion,
                                int flags) {
  bool result = PolicyService::Store(policy_blob, len, completion, flags);

  if (result) {
    UpdateSerialNumberRecoveryFlagFile();

    // Flush the settings cache, the next read will decode the new settings.
    settings_.reset();
  }

  return result;
}

void DevicePolicyService::ReportPolicyFileMetrics(bool key_success,
                                                  bool policy_success) {
  LoginMetrics::PolicyFilesStatus status;
  if (!key_success) {  // Key load failed.
    status.owner_key_file_state = LoginMetrics::MALFORMED;
  } else {
    if (key()->IsPopulated()) {
      if (nss_->CheckPublicKeyBlob(key()->public_key_der()))
        status.owner_key_file_state = LoginMetrics::GOOD;
      else
        status.owner_key_file_state = LoginMetrics::MALFORMED;
    } else {
      status.owner_key_file_state = LoginMetrics::NOT_PRESENT;
    }
  }

  if (!policy_success) {
    status.policy_file_state = LoginMetrics::MALFORMED;
  } else {
    std::string serialized;
    if (!store()->Get().SerializeToString(&serialized))
      status.policy_file_state = LoginMetrics::MALFORMED;
    else if (serialized == "")
      status.policy_file_state = LoginMetrics::NOT_PRESENT;
    else
      status.policy_file_state = LoginMetrics::GOOD;
  }

  if (store()->DefunctPrefsFilePresent())
    status.defunct_prefs_file_state = LoginMetrics::GOOD;

  metrics_->SendPolicyFilesStatus(status);
}

std::vector<std::string> DevicePolicyService::GetStartUpFlags() {
  std::vector<std::string> policy_args;
  const em::ChromeDeviceSettingsProto& policy = GetSettings();
  if (policy.has_start_up_flags()) {
    const em::StartUpFlagsProto& flags_proto = policy.start_up_flags();
    const RepeatedPtrField<std::string>& flags = flags_proto.flags();
    policy_args.push_back(
        std::string("--").append(chromeos::switches::kPolicySwitchesBegin));
    for (RepeatedPtrField<std::string>::const_iterator it = flags.begin();
         it != flags.end();
         ++it) {
      std::string flag(*it);
      // Ignore empty flags.
      if (flag.empty() || flag == "-" || flag == "--")
        continue;
      // Check if the flag doesn't start with proper prefix and add it.
      if (flag.length() <= 1 || flag[0] != '-')
        flag = std::string("--").append(flag);
      policy_args.push_back(flag);
    }
    policy_args.push_back(
        std::string("--").append(chromeos::switches::kPolicySwitchesEnd));
  }
  return policy_args;
}

const em::ChromeDeviceSettingsProto& DevicePolicyService::GetSettings() {
  if (!settings_.get()) {
    settings_.reset(new em::ChromeDeviceSettingsProto());

    em::PolicyData policy_data;
    if (!policy_data.ParseFromString(store()->Get().policy_data()) ||
        !settings_->ParseFromString(policy_data.policy_value())) {
      LOG(ERROR) << "Failed to parse device settings, using empty defaults.";
    }
  }

  return *settings_;
}

// static
bool DevicePolicyService::PolicyAllowsNewUsers(
    const em::PolicyFetchResponse& policy) {
  em::PolicyData poldata;
  if (!policy.has_policy_data() ||
      !poldata.ParseFromString(policy.policy_data())) {
    return false;
  }
  em::ChromeDeviceSettingsProto polval;
  if (!poldata.has_policy_type() ||
      poldata.policy_type() != DevicePolicyService::kDevicePolicyType ||
      !poldata.has_policy_value() ||
      !polval.ParseFromString(poldata.policy_value())) {
    return false;
  }
  // Explicitly states that new users are allowed.
  bool explicitly_allowed = (polval.has_allow_new_users() &&
                             polval.allow_new_users().allow_new_users());
  // Doesn't state that new users are allowed, but also doesn't have a
  // non-empty whitelist.
  bool not_disallowed = !polval.has_allow_new_users() &&
                        !(polval.has_user_whitelist() &&
                          polval.user_whitelist().user_whitelist_size() > 0);
  // States that new users are not allowed, but doesn't specify a whitelist.
  // So, we fail open. Such policies are the result of a long-fixed bug, but
  // we're not certain all users ever got migrated.
  bool failed_open = polval.has_allow_new_users() &&
                     !polval.allow_new_users().allow_new_users() &&
                     !polval.has_user_whitelist();

  return explicitly_allowed || not_disallowed || failed_open;
}

bool DevicePolicyService::StoreOwnerProperties(const std::string& current_user,
                                               RSAPrivateKey* signing_key,
                                               Error* error) {
  CHECK(signing_key);
  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<std::string>& whitelist =
      whitelist_proto->user_whitelist();
  for (RepeatedPtrField<std::string>::const_iterator it = whitelist.begin();
       it != whitelist.end();
       ++it) {
    if (current_user == *it) {
      on_list = true;
      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_t> sig;
  const uint8_t* data = reinterpret_cast<const uint8_t*>(new_data.c_str());
  if (!nss_->Sign(data, new_data.length(), &sig, signing_key)) {
    const char err_msg[] = "Could not sign policy containing new owner data.";
    if (error) {
      LOG(WARNING) << err_msg;
      error->Set(dbus_error::kPubkeySetIllegal, err_msg);
    } else {
      LOG(ERROR) << 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_t>& 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;
}

RSAPrivateKey* DevicePolicyService::GetOwnerKeyForGivenUser(
    const std::vector<uint8_t>& key,
    PK11SlotInfo* slot,
    Error* error) {
  RSAPrivateKey* result = nss_->GetPrivateKeyForUser(key, slot);
  if (!result) {
    const char msg[] = "Could not verify that owner key belongs to this user.";
    LOG(WARNING) << msg;
    if (error)
      error->Set(dbus_error::kPubkeySetIllegal, msg);
    return NULL;
  }
  return result;
}

bool DevicePolicyService::GivenUserIsOwner(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;
}

void DevicePolicyService::UpdateSerialNumberRecoveryFlagFile() {
  bool recovery_needed = false;
  int64_t policy_size = 0;
  if (!base::GetFileSize(base::FilePath(policy_file_), &policy_size) ||
      !policy_size) {
    LOG(WARNING) << "Policy file empty or missing.";
    recovery_needed = true;
  }

  const em::PolicyFetchResponse& policy(store()->Get());
  em::PolicyData policy_data;
  bool policy_parsed = policy.has_policy_data() &&
                       policy_data.ParseFromString(policy.policy_data());

  if (policy_parsed && !policy_data.request_token().empty() &&
      policy_data.valid_serial_number_missing()) {
    LOG(WARNING) << "Serial number missing flag encountered in policy data.";
    recovery_needed = true;
  }

  // Expose serial number on "spontaneously unenrolled" devices to allow them to
  // go through the enrollment flow again:  https://crbug.com/389481
  if (policy_parsed && policy_data.request_token().empty()) {
    std::string contents;
    base::ReadFileToString(install_attributes_file_, &contents);
    cryptohome::SerializedInstallAttributes install_attributes;
    if (install_attributes.ParseFromString(contents)) {
      for (int i = 0; i < install_attributes.attributes_size(); ++i) {
        const cryptohome::SerializedInstallAttributes_Attribute& attribute =
            install_attributes.attributes(i);
        // Cast value to C string and back to remove trailing zero.
        if (attribute.name() == kAttrEnterpriseMode &&
            std::string(attribute.value().c_str()) == kEnterpriseDeviceMode) {
          LOG(WARNING) << "DM token missing on enrolled device.";
          recovery_needed = true;
          break;
        }
      }
    }
  }

  // We need to recreate the machine info file if |valid_serial_number_missing|
  // is set to true in the protobuf or if the policy file is missing or empty
  // and we need to re-enroll.
  // TODO(pastarmovj,wad): Only check if file is missing if enterprise enrolled.
  // To check that we need to access the install attributes here.
  // For more info see: http://crosbug.com/31537
  if (recovery_needed) {
    if (base::WriteFile(serial_recovery_flag_file_, NULL, 0) != 0) {
      PLOG(WARNING) << "Failed to write " << serial_recovery_flag_file_.value();
    }
  } else {
    if (!base::DeleteFile(serial_recovery_flag_file_, false)) {
      PLOG(WARNING) << "Failed to delete "
                    << serial_recovery_flag_file_.value();
    }
  }
}

}  // namespace login_manager
