// 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 "cros-disks/archive_manager.h"

#include <utility>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <brillo/cryptohome.h>

#include "cros-disks/archive_mounter.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/rar_mounter.h"
#include "cros-disks/user.h"

namespace cros_disks {

ArchiveManager::ArchiveManager(const std::string& mount_root,
                               Platform* platform,
                               Metrics* metrics,
                               brillo::ProcessReaper* process_reaper)
    : MountManager(mount_root, platform, metrics, process_reaper) {}

ArchiveManager::~ArchiveManager() = default;

bool ArchiveManager::Initialize() {
  if (!MountManager::Initialize())
    return false;

  {
    SandboxedExecutable executable = {
        base::FilePath("/usr/bin/fuse-zip"),
        base::FilePath("/usr/share/policy/fuse-zip-seccomp.policy")};

    auto sandbox_factory =
        CreateSandboxFactory(std::move(executable), "fuse-zip");
    std::vector<int> password_needed_codes = {
        23,   // ZIP_ER_BASE + ZIP_ER_ZLIB
        36,   // ZIP_ER_BASE + ZIP_ER_NOPASSWD
        37};  // ZIP_ER_BASE + ZIP_ER_WRONGPASSWD

    mounters_.push_back(std::make_unique<ArchiveMounter>(
        platform(), process_reaper(), "zip", metrics(), "FuseZip",
        std::move(password_needed_codes), std::move(sandbox_factory)));
  }

  {
    SandboxedExecutable executable = {
        base::FilePath("/usr/bin/rar2fs"),
        base::FilePath("/usr/share/policy/rar2fs-seccomp.policy")};

    auto sandbox_factory =
        CreateSandboxFactory(std::move(executable), "fuse-rar2fs");

    mounters_.push_back(std::make_unique<RarMounter>(
        platform(), process_reaper(), metrics(), std::move(sandbox_factory)));
  }

  // TODO(nigeltao): refactor the ArchiveMounter C++ class (and superclasses)
  // to break the "1 instance = 1 file extension" assumption. That would let us
  // add just 1 element to mounters_, not 1 per file extension.
  const char* const archivemount_extensions[] = {
      // The empty // comments make clang-format place one entry per line.
      "7z",       //
      "bz2",      //
      "crx",      //
      "gz",       //
      "iso",      //
      "tar",      //
      "tbz",      //
      "tbz2",     //
      "tgz",      //
  };
  for (const char* const ext : archivemount_extensions) {
    SandboxedExecutable executable = {
        base::FilePath("/usr/bin/archivemount"),
        base::FilePath("/usr/share/policy/archivemount-seccomp.policy")};

    auto sandbox_factory =
        CreateSandboxFactory(std::move(executable), "fuse-archivemount");
    // The archivemount program (or, at least, the way we use it) doesn't
    // support passwords.
    std::vector<int> password_needed_codes = {};

    mounters_.push_back(std::make_unique<ArchiveMounter>(
        platform(), process_reaper(), ext, metrics(), "Archivemount",
        std::move(password_needed_codes), std::move(sandbox_factory)));
  }

  return true;
}

bool ArchiveManager::ResolvePath(const std::string& path,
                                 std::string* real_path) {
  std::unique_ptr<brillo::ScopedMountNamespace> mount_ns;
  if (!platform()->PathExists(path)) {
    // Try to locate the file in Chrome's mount namespace.
    mount_ns = brillo::ScopedMountNamespace::CreateFromPath(
        base::FilePath(ArchiveMounter::kChromeNamespace));
    if (!mount_ns) {
      PLOG(ERROR) << "Cannot find archive " << redact(path)
                  << " in mount namespace "
                  << quote(ArchiveMounter::kChromeNamespace);
      return false;
    }
  }
  return platform()->GetRealPath(path, real_path);
}

bool ArchiveManager::IsInAllowedFolder(const std::string& source_path) {
  std::vector<std::string> parts;
  base::FilePath(source_path).GetComponents(&parts);

  if (parts.size() < 2 || parts[0] != "/")
    return false;

  if (parts[1] == "home")
    return parts.size() > 5 && parts[2] == "chronos" &&
           base::StartsWith(parts[3], "u-", base::CompareCase::SENSITIVE) &&
           brillo::cryptohome::home::IsSanitizedUserName(parts[3].substr(2)) &&
           parts[4] == "MyFiles";

  if (parts[1] == "media")
    return parts.size() > 4 && (parts[2] == "archive" || parts[2] == "fuse" ||
                                parts[2] == "removable");

  if (parts[1] == "run")
    return parts.size() > 8 && parts[2] == "arc" && parts[3] == "sdcard" &&
           parts[4] == "write" && parts[5] == "emulated" && parts[6] == "0";

  return false;
}

std::string ArchiveManager::SuggestMountPath(
    const std::string& source_path) const {
  // Use the archive name to name the mount directory.
  base::FilePath base_name = base::FilePath(source_path).BaseName();
  return mount_root().Append(base_name).value();
}

std::vector<gid_t> ArchiveManager::GetSupplementaryGroups() const {
  std::vector<gid_t> groups;

  // To access Play Files.
  gid_t gid;
  if (platform()->GetGroupId("android-everybody", &gid))
    groups.push_back(gid);

  return groups;
}

bool ArchiveManager::CanMount(const std::string& source_path) const {
  if (IsInAllowedFolder(source_path)) {
    base::FilePath name;
    for (const auto& m : mounters_) {
      if (m->CanMount(source_path, {}, &name)) {
        return true;
      }
    }
  }
  return false;
}

std::unique_ptr<MountPoint> ArchiveManager::DoMount(
    const std::string& source_path,
    const std::string& filesystem_type,
    const std::vector<std::string>& options,
    const base::FilePath& mount_path,
    MountErrorType* error) {
  // Here source_path is already resolved and free from symlinks and '..' by
  // the base class.
  if (!IsInAllowedFolder(source_path)) {
    LOG(ERROR) << "Source path " << redact(source_path) << " is not allowed";
    *error = MOUNT_ERROR_INVALID_DEVICE_PATH;
    return nullptr;
  }
  base::FilePath name;
  for (const auto& m : mounters_) {
    if (m->CanMount(source_path, {}, &name)) {
      return m->Mount(source_path, mount_path, options, error);
    }
  }
  LOG(ERROR) << "Cannot find mounter for archive " << redact(source_path)
             << " of type " << quote(filesystem_type);
  *error = MOUNT_ERROR_UNKNOWN_FILESYSTEM;
  return nullptr;
}

std::unique_ptr<FUSESandboxedProcessFactory>
ArchiveManager::CreateSandboxFactory(SandboxedExecutable executable,
                                     const std::string& user_name) const {
  // To access Play Files.
  std::vector<gid_t> groups;
  gid_t gid;
  if (platform()->GetGroupId("android-everybody", &gid))
    groups.push_back(gid);

  OwnerUser run_as;
  if (!platform()->GetUserAndGroupId(user_name, &run_as.uid, &run_as.gid)) {
    PLOG(ERROR) << "Cannot resolve required user " << quote(user_name);
    return nullptr;
  }
  // Archivers need to run in chronos-access group to be able to access
  // user's files.
  run_as.gid = kChronosAccessGID;

  return std::make_unique<FUSESandboxedProcessFactory>(
      platform(), std::move(executable), std::move(run_as),
      /* has_network_access= */ false, std::move(groups));
}

}  // namespace cros_disks
