// 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.
//
// Provides the implementation of StatefulRecovery.

#include "cryptohome/stateful_recovery.h"

#include <linux/reboot.h>
#include <sys/reboot.h>
#include <unistd.h>

#include <string>

#include <base/files/file_path.h>
#include <base/json/json_writer.h>
#include <base/strings/string_util.h>
#include <base/values.h>

#include "cryptohome/platform.h"

using base::FilePath;

namespace cryptohome {

const char StatefulRecovery::kRecoverSource[] =
    "/mnt/stateful_partition/encrypted";
const char StatefulRecovery::kRecoverDestination[] =
    "/mnt/stateful_partition/decrypted";
const char StatefulRecovery::kRecoverBlockUsage[] =
    "/mnt/stateful_partition/decrypted/block-usage.txt";
const char StatefulRecovery::kRecoverFilesystemDetails[] =
    "/mnt/stateful_partition/decrypted/filesystem-details.txt";
const char StatefulRecovery::kFlagFile[] =
    "/mnt/stateful_partition/decrypt_stateful";

StatefulRecovery::StatefulRecovery(Platform* platform,
                                   MountFunction mountfn,
                                   UnmountFunction unmountfn,
                                   IsOwnerFunction isownerfn)
    : requested_(false),
      platform_(platform),
      mountfn_(mountfn),
      unmountfn_(unmountfn),
      isownerfn_(isownerfn) {}

bool StatefulRecovery::Requested() {
  requested_ = ParseFlagFile();
  return requested_;
}

bool StatefulRecovery::CopyPartitionInfo() {
  struct statvfs vfs;

  if (!platform_->StatVFS(FilePath(kRecoverSource), &vfs))
    return false;

  base::Value dv(base::Value::Type::DICTIONARY);
  dv.SetStringKey("filesystem", FilePath(kRecoverSource).value());
  dv.SetIntKey("blocks-total", vfs.f_blocks);
  dv.SetIntKey("blocks-free", vfs.f_bfree);
  dv.SetIntKey("blocks-avail", vfs.f_bavail);
  dv.SetIntKey("inodes-total", vfs.f_files);
  dv.SetIntKey("inodes-free", vfs.f_ffree);
  dv.SetIntKey("inodes-avail", vfs.f_favail);

  std::string output;
  base::JSONWriter::WriteWithOptions(dv, base::JSONWriter::OPTIONS_PRETTY_PRINT,
                                     &output);

  if (!platform_->WriteStringToFile(FilePath(kRecoverBlockUsage), output))
    return false;

  if (!platform_->ReportFilesystemDetails(FilePath(kRecoverSource),
                                          FilePath(kRecoverFilesystemDetails)))
    return false;

  return true;
}

bool StatefulRecovery::CopyUserContents() {
  int rc;
  FilePath path;

  if (!mountfn_.Run(user_, passkey_, &path)) {
    // mountfn_ logged the error already.
    return false;
  }

  rc = platform_->Copy(path, FilePath(kRecoverDestination));

  unmountfn_.Run();
  // If it failed, unmountfn_ would log the error.

  if (rc)
    return true;
  LOG(ERROR) << "Failed to copy " << path.value();
  return false;
}

bool StatefulRecovery::CopyPartitionContents() {
  int rc;

  rc = platform_->Copy(FilePath(kRecoverSource), FilePath(kRecoverDestination));
  if (rc)
    return true;
  LOG(ERROR) << "Failed to copy " << FilePath(kRecoverSource).value();
  return false;
}

bool StatefulRecovery::RecoverV1() {
  // Version 1 requires write protect be disabled.
  if (platform_->FirmwareWriteProtected()) {
    LOG(ERROR) << "Refusing v1 recovery request: firmware is write protected.";
    return false;
  }

  if (!CopyPartitionContents())
    return false;
  if (!CopyPartitionInfo())
    return false;

  return true;
}

bool StatefulRecovery::RecoverV2() {
  bool wrote_data = false;
  bool is_authenticated_owner = false;

  // If possible, copy user contents.
  if (CopyUserContents()) {
    wrote_data = true;
    // If user authenticated, check if they are the owner.
    if (isownerfn_.Run(user_)) {
      is_authenticated_owner = true;
    }
  }

  // Version 2 requires either write protect disabled or system owner.
  if (!platform_->FirmwareWriteProtected() || is_authenticated_owner) {
    if (!CopyPartitionContents() || !CopyPartitionInfo()) {
      // Even if we wrote out user data, claim failure here if the
      // encrypted-stateful partition couldn't be extracted.
      return false;
    }
    wrote_data = true;
  }

  return wrote_data;
}

bool StatefulRecovery::Recover() {
  if (!requested_)
    return false;

  // Start with a clean slate. Note that there is a window of opportunity for
  // another process to create the directory with funky permissions after the
  // delete takes place but before we manage to recreate. Since the parent
  // directory is root-owned though, this isn't a problem in practice.
  const FilePath kDestinationPath(kRecoverDestination);
  if (!platform_->DeletePathRecursively(kDestinationPath) ||
      !platform_->CreateDirectory(kDestinationPath)) {
    PLOG(ERROR) << "Failed to create fresh " << kDestinationPath.value();
    return false;
  }

  if (version_ == "2") {
    return RecoverV2();
  } else if (version_ == "1") {
    return RecoverV1();
  } else {
    LOG(ERROR) << "Unknown recovery version: " << version_;
    return false;
  }
}

void StatefulRecovery::PerformReboot() {
  // TODO(wad) Replace with a mockable helper.
  if (system("/usr/bin/crossystem recovery_request=1") != 0) {
    LOG(ERROR) << "Failed to set recovery request!";
  }
  platform_->Sync();
  reboot(LINUX_REBOOT_CMD_RESTART);
}

bool StatefulRecovery::ParseFlagFile() {
  std::string contents;
  size_t delim, pos;
  if (!platform_->ReadFileToString(FilePath(kFlagFile), &contents))
    return false;

  // Make sure there is a trailing newline.
  contents += "\n";

  do {
    pos = 0;
    delim = contents.find("\n", pos);
    if (delim == std::string::npos)
      break;
    version_ = contents.substr(pos, delim);

    if (version_ == "1")
      return true;

    if (version_ != "2")
      break;

    pos = delim + 1;
    delim = contents.find("\n", pos);
    if (delim == std::string::npos)
      break;
    user_ = contents.substr(pos, delim - pos);

    pos = delim + 1;
    delim = contents.find("\n", pos);
    if (delim == std::string::npos)
      break;
    passkey_ = contents.substr(pos, delim - pos);

    return true;
  } while (0);

  // TODO(ellyjones): UMA stat?
  LOG(ERROR) << "Bogus stateful recovery request file:" << contents;
  return false;
}

}  // namespace cryptohome
