// 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/json/json_writer.h>
#include <base/strings/string_util.h>
#include <base/values.h>

#include "cryptohome/platform.h"
#include "cryptohome/service.h"

using std::string;

namespace cryptohome {

#define MNT_STATEFUL_PARTITION "/mnt/stateful_partition/"

const char *StatefulRecovery::kFlagFile =
    MNT_STATEFUL_PARTITION "decrypt_stateful";
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";

StatefulRecovery::StatefulRecovery(Platform *platform, Service *service)
    : requested_(false), platform_(platform), service_(service) { }
StatefulRecovery::~StatefulRecovery() { }

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

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

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

  base::DictionaryValue dv;
  dv.SetString("filesystem", kRecoverSource);
  dv.SetInteger("blocks-total", vfs.f_blocks);
  dv.SetInteger("blocks-free", vfs.f_bfree);
  dv.SetInteger("blocks-avail", vfs.f_bavail);
  dv.SetInteger("inodes-total", vfs.f_files);
  dv.SetInteger("inodes-free", vfs.f_ffree);
  dv.SetInteger("inodes-avail", vfs.f_favail);

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

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

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

  return true;
}

bool StatefulRecovery::CopyUserContents() {
  int rc;
  gint error_code;
  gboolean result;
  GError *error = NULL;
  std::string path;

  if (!service_->Mount(user_.c_str(), passkey_.c_str(), false, false,
                       &error_code, &result, &error) || !result) {
    LOG(ERROR) << "Could not authenticate user '" << user_
               << "' for stateful recovery: "
               << (error ? error->message : "[null]")
               << " (code:" << error_code << ")";
    return false;
  }

  if (!service_->GetMountPointForUser(user_.c_str(), &path)) {
    LOG(ERROR) << "Mount point missing after successful mount call!?";
    return false;
  }

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

  service_->UnmountForUser(user_.c_str(), &result, &error);

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

bool StatefulRecovery::CopyPartitionContents() {
  int rc;

  rc = platform_->Copy(kRecoverSource, kRecoverDestination);
  if (rc)
    return true;
  LOG(ERROR) << "Failed to copy " << kRecoverSource;
  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 (service_->IsOwner(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;

  if (!platform_->CreateDirectory(kRecoverDestination)) {
    LOG(ERROR) << "Failed to mkdir " << kRecoverDestination;
    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(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
