// Copyright 2018 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/drivefs_helper.h"

#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>

#include "cros-disks/fuse_mounter.h"
#include "cros-disks/mount_options.h"
#include "cros-disks/platform.h"
#include "cros-disks/quote.h"
#include "cros-disks/system_mounter.h"
#include "cros-disks/uri.h"

namespace cros_disks {
namespace {

const char kDataDirOptionPrefix[] = "datadir=";
const char kIdentityOptionPrefix[] = "identity=";
const char kMyFilesOptionPrefix[] = "myfiles=";
const char kPathPrefixOptionPrefix[] = "prefix=";

const char kOldUser[] = "fuse-drivefs";
const char kHelperTool[] = "/opt/google/drive-file-stream/drivefs";
const char kSeccompPolicyFile[] =
    "/opt/google/drive-file-stream/drivefs-seccomp.policy";
const char kType[] = "drivefs";
const char kDbusSocketPath[] = "/run/dbus";

// The deepest expected path within a DriveFS datadir is
// {content,thumbnails}_cache/d<number>/d<number>/<number>. Allow one extra
// level just in case.
constexpr int kMaxTraversalDepth = 5;

// Ensures that the datadir has the correct owner. If not, recursively chown the
// contents, skipping directories with the expected owner. During directory
// descent, set group to the eventual group to allow directory traversal to
// allow access to the contents. On ascent, set user to the expected user,
// marking the directory as having the correct ownership.
bool EnsureOwnership(const Platform& platform,
                     const base::FilePath& path,
                     uid_t mounter_uid,
                     gid_t files_gid,
                     uid_t old_mounter_uid,
                     int depth = 0) {
  if (depth > kMaxTraversalDepth) {
    LOG(ERROR) << "Reached maximum traversal depth ensuring drivefs datadir "
                  "ownership: "
               << path.value();
    return false;
  }
  uid_t current_uid;
  gid_t current_gid;
  if (!platform.GetOwnership(path.value(), &current_uid, &current_gid)) {
    LOG(ERROR) << "Cannot access datadir " << quote(path);
    return false;
  }
  if (current_uid == mounter_uid && current_gid == files_gid) {
    return true;
  }
  if (current_uid != old_mounter_uid) {
    LOG(ERROR) << "Unexpected old uid for " << quote(path) << ": Expected "
               << old_mounter_uid << " but found " << current_uid;
    return false;
  }
  // Set group to |files_gid| to ensure the directory is traversable. Keep the
  // |current_uid| so this directory isn't treated as having the correct
  // ownership in case this operation is interrupted.
  if (!platform.SetOwnership(path.value(), current_uid, files_gid)) {
    LOG(ERROR) << "Cannot chown " << quote(path) << " to " << current_uid << ":"
               << files_gid;
    return false;
  }
  base::FileEnumerator dirs(path, false, base::FileEnumerator::DIRECTORIES);
  for (auto dir_path = dirs.Next(); !dir_path.empty(); dir_path = dirs.Next()) {
    if (!EnsureOwnership(platform, dir_path, mounter_uid, files_gid,
                         old_mounter_uid, depth + 1)) {
      return false;
    }
  }
  base::FileEnumerator files(path, false, base::FileEnumerator::FILES);
  for (auto file_path = files.Next(); !file_path.empty();
       file_path = files.Next()) {
    if (!platform.SetOwnership(file_path.value(), mounter_uid, files_gid)) {
      LOG(ERROR) << "Cannot chown " << quote(file_path) << " to " << mounter_uid
                 << ":" << files_gid;
      return false;
    }
  }
  if (!platform.SetOwnership(path.value(), mounter_uid, files_gid)) {
    LOG(ERROR) << "Cannot chown " << quote(path) << " to " << mounter_uid << ":"
               << files_gid;
    return false;
  }
  return true;
}

class DrivefsMounter : public FUSEMounter {
 public:
  DrivefsMounter(const std::string& filesystem_type,
                 const MountOptions& mount_options,
                 const Platform* platform,
                 brillo::ProcessReaper* process_reaper,
                 const std::string& mount_program_path,
                 const std::string& mount_user,
                 const std::string& seccomp_policy,
                 const std::vector<BindPath>& accessible_paths)
      : FUSEMounter(filesystem_type,
                    mount_options,
                    platform,
                    process_reaper,
                    mount_program_path,
                    mount_user,
                    seccomp_policy,
                    accessible_paths,
                    true /* permit_network_access */) {}

  // FUSEMounter overrides:
  std::unique_ptr<MountPoint> Mount(const std::string& source,
                                    const base::FilePath& target_path,
                                    std::vector<std::string> options,
                                    MountErrorType* error) const override {
    return FUSEMounter::Mount("", target_path, options, error);
  }
};

}  // namespace

DrivefsHelper::DrivefsHelper(const Platform* platform,
                             brillo::ProcessReaper* process_reaper)
    : FUSEHelper(kType,
                 platform,
                 process_reaper,
                 base::FilePath(kHelperTool),
                 kFilesUser) {}

DrivefsHelper::~DrivefsHelper() = default;

std::unique_ptr<FUSEMounter> DrivefsHelper::CreateMounter(
    const base::FilePath& working_dir,
    const Uri& source,
    const base::FilePath& target_path,
    const std::vector<std::string>& options) const {
  const std::string& identity = source.path();

  // Enforced by FUSEHelper::CanMount().
  DCHECK(!identity.empty());

  auto data_dir = GetValidatedDirectory(options, kDataDirOptionPrefix);
  if (data_dir.empty()) {
    return nullptr;
  }

  uid_t files_uid;
  gid_t files_gid;
  if (!platform()->GetUserAndGroupId(kFilesUser, &files_uid, nullptr) ||
      !platform()->GetGroupId(kFilesGroup, &files_gid)) {
    LOG(ERROR) << "Invalid user configuration.";
    return nullptr;
  }

  auto my_files_path = GetValidatedDirectory(options, kMyFilesOptionPrefix);
  if (!my_files_path.empty() && !CheckMyFilesPermissions(my_files_path)) {
    return nullptr;
  }

  if (!SetupDirectoryForFUSEAccess(data_dir)) {
    return nullptr;
  }
  MountOptions mount_options;
  mount_options.EnforceOption(kDataDirOptionPrefix + data_dir.value());
  mount_options.EnforceOption(kIdentityOptionPrefix + identity);
  mount_options.EnforceOption(kPathPrefixOptionPrefix + target_path.value());
  if (!my_files_path.empty()) {
    mount_options.EnforceOption(kMyFilesOptionPrefix + my_files_path.value());
  }
  mount_options.Initialize(options, true, base::IntToString(files_uid),
                           base::IntToString(files_gid));

  // TODO(crbug.com/859802): Make seccomp mandatory when testing done.
  std::string seccomp =
      platform()->PathExists(kSeccompPolicyFile) ? kSeccompPolicyFile : "";

  // Bind datadir and DBus communication socket into the sandbox.
  std::vector<FUSEMounter::BindPath> paths = {
      {data_dir.value(), true /* writable */},
      {kDbusSocketPath, true},
  };
  if (!my_files_path.empty()) {
    paths.push_back(
        {my_files_path.value(), true /* writable */, true /* recursive */});
  }
  return std::make_unique<DrivefsMounter>(
      type(), mount_options, platform(), process_reaper(),
      program_path().value(), user(), seccomp, paths);
}

base::FilePath DrivefsHelper::GetValidatedDirectory(
    const std::vector<std::string>& options,
    const base::StringPiece prefix) const {
  for (const auto& option : options) {
    if (base::StartsWith(option, prefix, base::CompareCase::SENSITIVE)) {
      std::string path_string = option.substr(prefix.size());
      base::FilePath data_dir(path_string);
      if (data_dir.empty() || !data_dir.IsAbsolute() ||
          data_dir.ReferencesParent()) {
        LOG(ERROR) << "Invalid DriveFS option " << prefix << path_string;
        return {};
      }
      base::FilePath suffix_component;
      // If the datadir doesn't exist, canonicalize the parent directory
      // instead, and append the last path component to that path.
      if (!platform()->DirectoryExists(data_dir.value())) {
        suffix_component = data_dir.BaseName();
        data_dir = data_dir.DirName();
      }
      if (!platform()->GetRealPath(data_dir.value(), &path_string)) {
        return {};
      }
      return base::FilePath(path_string).Append(suffix_component);
    }
  }
  return {};
}

bool DrivefsHelper::SetupDirectoryForFUSEAccess(
    const base::FilePath& dir) const {
  CHECK(dir.IsAbsolute() && !dir.ReferencesParent())
      << "Unsafe path " << quote(dir);

  uid_t mounter_uid, old_mounter_uid;
  gid_t files_gid;
  if (!platform()->GetUserAndGroupId(user(), &mounter_uid, nullptr) ||
      !platform()->GetUserAndGroupId(kOldUser, &old_mounter_uid, nullptr) ||
      !platform()->GetGroupId(kFilesGroup, &files_gid)) {
    LOG(ERROR) << "Invalid user configuration.";
    return false;
  }

  std::string path = dir.value();
  if (platform()->DirectoryExists(path)) {
    return EnsureOwnership(*platform(), dir, mounter_uid, files_gid,
                           old_mounter_uid);
  }
  if (!platform()->CreateDirectory(path)) {
    LOG(ERROR) << "Cannot create datadir " << quote(path);
    return false;
  }
  if (!platform()->SetPermissions(path, 0770)) {
    LOG(ERROR) << "Cannot chmod datadir " << quote(path);
    return false;
  }
  if (!platform()->SetOwnership(path, mounter_uid, files_gid)) {
    LOG(ERROR) << "Cannot chown datadir " << quote(path);
    return false;
  }
  return true;
}

bool DrivefsHelper::CheckMyFilesPermissions(const base::FilePath& dir) const {
  CHECK(dir.IsAbsolute() && !dir.ReferencesParent())
      << "Unsafe 'My Files' path " << quote(dir);

  uid_t mounter_uid;
  if (!platform()->GetUserAndGroupId(user(), &mounter_uid, nullptr)) {
    LOG(ERROR) << "Invalid user configuration.";
    return false;
  }

  std::string path = dir.value();
  if (!platform()->DirectoryExists(path)) {
    LOG(ERROR) << "My files directory " << quote(path) << " does not exist";
    return false;
  }
  uid_t current_uid;
  if (!platform()->GetOwnership(path, &current_uid, nullptr)) {
    LOG(WARNING) << "Cannot access my files directory " << quote(path);
    return false;
  }
  if (current_uid != mounter_uid) {
    LOG(ERROR) << "Incorrect owner for my files directory " << quote(path);
    return false;
  }
  return true;
}

}  // namespace cros_disks
