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

#include <openssl/sha.h>
#include <stdint.h>

#include <algorithm>
#include <cstring>
#include <limits>
#include <vector>

#include <base/files/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>

using base::FilePath;

namespace brillo {
namespace cryptohome {
namespace home {

const char kGuestUserName[] = "$guest";

// Path to user homes mounted with the mount_hidden option. The user home mount
// will be located at:
// kHiddenUserHomeBaseDir/<sanitized_user_name>/kHiddenUserHomeMountSubdir
const char kHiddenUserHomeBaseDir[] = "/home/.shadow";
const char kHiddenUserHomeMountSubdir[] = "mount";

// Subdirectory of a user home mount where daemon-specific data is stored.
// This is used to assemble daemon data storage paths for hidden user home
// mounts.
const char kHiddenUserHomeRootSubdir[] = "root";

static char g_user_home_prefix[PATH_MAX] = "/home/user/";
static char g_root_home_prefix[PATH_MAX] = "/home/root/";
static char g_system_salt_path[PATH_MAX] = "/home/.shadow/salt";

static std::string* salt = nullptr;

static bool EnsureSystemSaltIsLoaded() {
  if (salt && !salt->empty())
    return true;
  FilePath salt_path(g_system_salt_path);
  int64_t file_size;
  if (!base::GetFileSize(salt_path, &file_size)) {
    PLOG(ERROR) << "Could not get size of system salt: " << g_system_salt_path;
    return false;
  }
  if (file_size > static_cast<int64_t>(std::numeric_limits<int>::max())) {
    LOG(ERROR) << "System salt too large: " << file_size;
    return false;
  }
  std::vector<char> buf;
  buf.resize(file_size);
  unsigned int data_read = base::ReadFile(salt_path, buf.data(), file_size);
  if (data_read != file_size) {
    PLOG(ERROR) << "Could not read entire file: " << data_read
                << " != " << file_size;
    return false;
  }

  if (!salt)
    salt = new std::string();
  salt->assign(buf.data(), file_size);
  return true;
}

std::string SanitizeUserName(const std::string& username) {
  if (!EnsureSystemSaltIsLoaded())
    return std::string();

  unsigned char binmd[SHA_DIGEST_LENGTH];
  std::string lowercase(username);
  std::transform(
      lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower);
  SHA_CTX ctx;
  SHA1_Init(&ctx);
  SHA1_Update(&ctx, salt->data(), salt->size());
  SHA1_Update(&ctx, lowercase.data(), lowercase.size());
  SHA1_Final(binmd, &ctx);
  std::string final = base::HexEncode(binmd, sizeof(binmd));
  // Stay compatible with CryptoLib::HexEncodeToBuffer()
  std::transform(final.begin(), final.end(), final.begin(), ::tolower);
  return final;
}

FilePath GetUserPathPrefix() {
  return FilePath(g_user_home_prefix);
}

FilePath GetRootPathPrefix() {
  return FilePath(g_root_home_prefix);
}

FilePath GetHashedUserPath(const std::string& hashed_username) {
  return FilePath(
      base::StringPrintf("%s%s", g_user_home_prefix, hashed_username.c_str()));
}

FilePath GetUserPath(const std::string& username) {
  if (!EnsureSystemSaltIsLoaded())
    return FilePath();
  return GetHashedUserPath(SanitizeUserName(username));
}

FilePath GetRootPath(const std::string& username) {
  if (!EnsureSystemSaltIsLoaded())
    return FilePath();
  return FilePath(base::StringPrintf(
      "%s%s", g_root_home_prefix, SanitizeUserName(username).c_str()));
}

FilePath GetDaemonPath(const std::string& username, const std::string& daemon) {
  if (!EnsureSystemSaltIsLoaded())
    return FilePath();
  return GetRootPath(username).Append(daemon);
}

FilePath GetDaemonPathForHiddenUserHome(const std::string& username,
                                        const std::string& daemon) {
  if (!EnsureSystemSaltIsLoaded())
    return FilePath();

  return FilePath(kHiddenUserHomeBaseDir)
      .Append(SanitizeUserName(username))
      .Append(kHiddenUserHomeMountSubdir)
      .Append(kHiddenUserHomeRootSubdir)
      .Append(daemon);
}

bool IsSanitizedUserName(const std::string& sanitized) {
  std::vector<uint8_t> bytes;
  return (sanitized.length() == 2 * SHA_DIGEST_LENGTH) &&
         base::HexStringToBytes(sanitized, &bytes);
}

void SetUserHomePrefix(const std::string& prefix) {
  if (prefix.length() < sizeof(g_user_home_prefix)) {
    snprintf(
        g_user_home_prefix, sizeof(g_user_home_prefix), "%s", prefix.c_str());
  }
}

void SetRootHomePrefix(const std::string& prefix) {
  if (prefix.length() < sizeof(g_root_home_prefix)) {
    snprintf(
        g_root_home_prefix, sizeof(g_root_home_prefix), "%s", prefix.c_str());
  }
}

std::string* GetSystemSalt() {
  return salt;
}

void SetSystemSalt(std::string* value) {
  salt = value;
}

}  // namespace home
}  // namespace cryptohome
}  // namespace brillo
