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

#include <stdint.h>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ref_counted.h>
#include <base/memory/scoped_ptr.h>
#include <base/stl_util.h>
#include <base/strings/string_util.h>
#include <chromeos/cryptohome.h>

#include "bindings/chrome_device_policy.pb.h"
#include "login_manager/dbus_error_types.h"
#include "login_manager/policy_key.h"
#include "login_manager/policy_service.h"
#include "login_manager/policy_store.h"

namespace em = enterprise_management;

namespace login_manager {

const base::FilePath::CharType DeviceLocalAccountPolicyService::kPolicyDir[] =
    FILE_PATH_LITERAL("policy");

const base::FilePath::CharType
    DeviceLocalAccountPolicyService::kPolicyFileName[] =
        FILE_PATH_LITERAL("policy");

DeviceLocalAccountPolicyService::DeviceLocalAccountPolicyService(
    const base::FilePath& device_local_account_dir,
    PolicyKey* owner_key)
    : device_local_account_dir_(device_local_account_dir),
      owner_key_(owner_key) {}

DeviceLocalAccountPolicyService::~DeviceLocalAccountPolicyService() {
  STLDeleteValues(&policy_map_);
}

bool DeviceLocalAccountPolicyService::Store(
    const std::string& account_id,
    const uint8_t* policy_data,
    uint32_t policy_data_size,
    PolicyService::Completion completion) {
  PolicyService* service = GetPolicyService(account_id);
  if (!service) {
    PolicyService::Error error(dbus_error::kInvalidAccount,
                               "Invalid device-local account");
    completion.Run(error);
    return false;
  }

  // NB: Passing 0 for flags disallows all key changes.
  return service->Store(policy_data, policy_data_size, completion, 0);
}

bool DeviceLocalAccountPolicyService::Retrieve(
    const std::string& account_id,
    std::vector<uint8_t>* policy_data) {
  PolicyService* service = GetPolicyService(account_id);
  if (!service)
    return false;

  return service->Retrieve(policy_data);
}

void DeviceLocalAccountPolicyService::UpdateDeviceSettings(
    const em::ChromeDeviceSettingsProto& device_settings) {
  // Update the policy map.
  typedef google::protobuf::RepeatedPtrField<em::DeviceLocalAccountInfoProto>
      DeviceLocalAccountList;
  std::map<std::string, PolicyService*> new_policy_map;
  const DeviceLocalAccountList& list(
      device_settings.device_local_accounts().account());
  for (DeviceLocalAccountList::const_iterator account(list.begin());
       account != list.end();
       ++account) {
    std::string account_key;
    if (account->has_account_id()) {
      account_key = GetAccountKey(account->account_id());
    } else if (!account->has_type() &&
               account->has_deprecated_public_session_id()) {
      account_key = GetAccountKey(account->deprecated_public_session_id());
    }
    if (!account_key.empty()) {
      new_policy_map[account_key] = policy_map_[account_key];
      policy_map_[account_key] = NULL;
    }
  }
  policy_map_.swap(new_policy_map);
  STLDeleteValues(&new_policy_map);

  MigrateUppercaseDirs();

  // Purge all existing on-disk accounts that are no longer defined.
  base::FileEnumerator enumerator(
      device_local_account_dir_, false, base::FileEnumerator::DIRECTORIES);
  base::FilePath subdir;
  while (!(subdir = enumerator.Next()).empty()) {
    if (IsValidAccountKey(subdir.BaseName().value()) &&
        policy_map_.find(subdir.BaseName().value()) == policy_map_.end()) {
      LOG(INFO) << "Purging " << subdir.value();
      if (!base::DeleteFile(subdir, true))
        LOG(ERROR) << "Failed to delete " << subdir.value();
    }
  }
}

bool DeviceLocalAccountPolicyService::MigrateUppercaseDirs(void) {
  base::FileEnumerator enumerator(
      device_local_account_dir_, false, base::FileEnumerator::DIRECTORIES);
  base::FilePath subdir;

  while (!(subdir = enumerator.Next()).empty()) {
    std::string upper = subdir.BaseName().value();
    std::string lower = base::StringToLowerASCII(upper);
    if (IsValidAccountKey(lower) && lower != upper) {
      base::FilePath subdir_to(subdir.DirName().Append(lower));
      LOG(INFO) << "Migrating " << upper << " to " << lower;
      if (!base::ReplaceFile(subdir, subdir_to, NULL))
        LOG(ERROR) << "Failed to migrate " << subdir.value();
    }
  }

  return true;
}

PolicyService* DeviceLocalAccountPolicyService::GetPolicyService(
    const std::string& account_id) {
  const std::string key = GetAccountKey(account_id);
  std::map<std::string, PolicyService*>::iterator entry = policy_map_.find(key);
  if (entry == policy_map_.end())
    return NULL;

  // Lazily create and initialize the policy service instance.
  if (!entry->second) {
    const base::FilePath policy_path =
        device_local_account_dir_
        .AppendASCII(key)
        .Append(kPolicyDir)
        .Append(kPolicyFileName);
    if (!base::CreateDirectory(policy_path.DirName())) {
      LOG(ERROR) << "Failed to create directory for " << policy_path.value();
      return NULL;
    }

    scoped_ptr<PolicyStore> store(new PolicyStore(policy_path));
    if (!store->LoadOrCreate()) {
      // This is non-fatal, the policy may not have been stored yet.
      LOG(WARNING) << "Failed to load policy for device-local account "
                   << account_id;
    }
    entry->second = new PolicyService(store.Pass(), owner_key_);
  }

  return entry->second;
}

std::string DeviceLocalAccountPolicyService::GetAccountKey(
    const std::string& account_id) {
  return chromeos::cryptohome::home::SanitizeUserName(account_id);
}

bool DeviceLocalAccountPolicyService::IsValidAccountKey(
    const std::string& str) {
  return chromeos::cryptohome::home::IsSanitizedUserName(str);
}

}  // namespace login_manager
