// 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 "cryptohome/dbus_service.h"
#include "cryptohome/service.h"

#include <cstdlib>
#include <string>

#include <base/at_exit.h>
#include <base/command_line.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <chaps/pkcs11/cryptoki.h>
#include <brillo/syslog_logging.h>
#include <dbus/dbus.h>
#include <glib.h>
#include <openssl/evp.h>

#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/homedirs.h"
#include "cryptohome/platform.h"
#include "cryptohome/userdataauth.h"

namespace env {
static const char* kAttestationBasedEnrollmentDataFile = "ABE_DATA_FILE";
}

namespace switches {
static const char* kAttestationMode = "attestation_mode";
static const char* kDistributedModeOption = "dbus";
// Keeps std* open for debugging.
static const char* kNoCloseOnDaemonize = "noclose";
static const char* kNoLegacyMount = "nolegacymount";
static const char* kDirEncryption = "direncryption";
static const char* kNoDaemonize = "nodaemonize";
static const char* kUserDataAuthInterface = "user_data_auth_interface";
static const char* kCleanupThreshold =
  "cleanup_threshold";
static const char* kAggressiveThreshold =
  "aggressive_cleanup_threshold";
static const char* kTargetFreeSpace =
  "target_free_space";

}  // namespace switches

static std::string ReadAbeDataFileContents(cryptohome::Platform* platform) {
  std::string data;

  const char* abe_data_file =
      std::getenv(env::kAttestationBasedEnrollmentDataFile);
  if (!abe_data_file)
    return data;

  base::FilePath file_path(abe_data_file);
  if (!platform->ReadFileToString(file_path, &data))
    LOG(FATAL) << "Could not read attestation-based enterprise enrollment data"
                  " in: "
               << file_path.value();
  return data;
}

uint64_t ReadCleanupThreshold(const base::CommandLine* cl,
    const char* switch_name, uint64_t default_value) {
  std::string value = cl->GetSwitchValueASCII(switch_name);

  if (value.size() == 0) {
    return default_value;
  }

  uint64_t parsed_value;
  if (!base::StringToUint64(value, &parsed_value)) {
    LOG(ERROR) << "Failed to parse " << switch_name << "; using defaults";
    return default_value;
  }

  return parsed_value;
}

int main(int argc, char** argv) {
  // Initialize command line configuration early, as logging will require
  // command line to be initialized
  base::CommandLine::Init(argc, argv);

  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderr);

  // Read the file before we daemonize so it can be deleted as soon as we exit.
  cryptohome::Platform platform;
  std::string abe_data = ReadAbeDataFileContents(&platform);

  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  // Sanity check of attestation mode. Historically we had monolithic and
  // distributed mode, and now the monolithic mode has been obsoleted, so we
  // expect either the switch is missing or explicitly set to distributed mode.
  if (cl->HasSwitch(switches::kAttestationMode) &&
      cl->GetSwitchValueASCII(switches::kAttestationMode) !=
          switches::kDistributedModeOption) {
    LOG(FATAL) << "Unrecognized or obsoleted " << switches::kAttestationMode
               << " option: "
               << cl->GetSwitchValueASCII(switches::kAttestationMode);
  }
  int noclose = cl->HasSwitch(switches::kNoCloseOnDaemonize);
  bool nolegacymount = cl->HasSwitch(switches::kNoLegacyMount);
  bool direncryption = cl->HasSwitch(switches::kDirEncryption);
  bool daemonize = !cl->HasSwitch(switches::kNoDaemonize);
  bool use_new_dbus_interface = cl->HasSwitch(switches::kUserDataAuthInterface);
  uint64_t cleanup_threshold =
    ReadCleanupThreshold(cl, switches::kCleanupThreshold,
    cryptohome::kFreeSpaceThresholdToTriggerCleanup);
  uint64_t aggressive_cleanup_threshold =
    ReadCleanupThreshold(cl, switches::kAggressiveThreshold,
    cryptohome::kFreeSpaceThresholdToTriggerAggressiveCleanup);
  uint64_t target_free_space =
    ReadCleanupThreshold(cl, switches::kTargetFreeSpace,
    cryptohome::kTargetFreeSpaceAfterCleanup);

  if (daemonize) {
    PLOG_IF(FATAL, daemon(0, noclose) == -1) << "Failed to daemonize";
  }

  // Initialize OpenSSL.
  OpenSSL_add_all_algorithms();

  // Initialize cryptohome metrics
  cryptohome::ScopedMetricsInitializer metrics_initializer;

  // Make sure scrypt parameters are correct.
  cryptohome::CryptoLib::AssertProductionScryptParams();

  if (use_new_dbus_interface) {
#if USE_CRYPTOHOME_USERDATAAUTH_INTERFACE
    // Note that there's an AtExitManager in the constructor of
    // UserDataAuthDaemon
    cryptohome::UserDataAuthDaemon user_data_auth_daemon;

    // Set options on whether we are going to use legacy mount. See comments on
    // Mount::MountLegacyHome() for more information.
    user_data_auth_daemon.GetUserDataAuth()->set_legacy_mount(!nolegacymount);

    // Set options on whether we are going to use ext4 directory encryption or
    // eCryptfs.
    user_data_auth_daemon.GetUserDataAuth()->set_force_ecryptfs(!direncryption);

    // Set automatic cleanup thresholds.
    user_data_auth_daemon.GetUserDataAuth()->
      set_cleanup_threshold(cleanup_threshold);
    user_data_auth_daemon.GetUserDataAuth()->
      set_aggressive_cleanup_threshold(aggressive_cleanup_threshold);
    user_data_auth_daemon.GetUserDataAuth()->
      set_target_free_space(target_free_space);

    // Note the startup sequence is as following:
    // 1. UserDataAuthDaemon constructor => UserDataAuth constructor
    // 2. UserDataAuthDaemon::OnInit() (called by Daemon::Run())
    // 3. UserDataAuthDaemon::RegisterDBusObjectAsync() (called by 2.)
    // 4. UserDataAuth::Initialize() (called by 3.)
    // 5. UserDataAuth::PostDBusInitialize() (called by 3.)
    // Daemon::OnInit() needs to be called before Initialize(), because
    // Initialize() create threads, and thus mess with Daemon's
    // AsynchronousSignalHandler.

    // Start UserDataAuth daemon if the option is selected
    user_data_auth_daemon.Run();
#else
    LOG(FATAL) << "Unsupported option: " << switches::kUserDataAuthInterface;
#endif
  } else {
    // Start the old interface if nothing is selected

    // Setup threading. This needs to be called before other calls into glib and
    // before multiple threads are created that access dbus.
    dbus_threads_init_default();

    // Create an AtExitManager
    base::AtExitManager exit_manager;

    cryptohome::Service* service = cryptohome::Service::CreateDefault(abe_data);

    service->set_legacy_mount(!nolegacymount);
    service->set_force_ecryptfs(!direncryption);
    service->set_cleanup_threshold(cleanup_threshold);
    service->set_aggressive_cleanup_threshold(aggressive_cleanup_threshold);
    service->set_target_free_space(target_free_space);

    if (!service->Initialize()) {
      LOG(FATAL) << "Service initialization failed";
      return 1;
    }

    if (!service->Register(brillo::dbus::GetSystemBusConnection())) {
      LOG(FATAL) << "DBUS service registration failed";
      return 1;
    }

    if (!service->Run()) {
      LOG(FATAL) << "Service run failed.";
      return 1;
    }
  }
  // If PKCS #11 was initialized, this will tear it down.
  C_Finalize(NULL);

  return 0;
}
