// Copyright (c) 2011 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.

// This is the Chaps daemon. It handles calls from multiple processes via D-Bus.
//

#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <memory>
#include <string>

#include <base/command_line.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/synchronization/lock.h>
#include <base/synchronization/waitable_event.h>
#include <base/threading/platform_thread.h>
#include <base/threading/thread.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/syslog_logging.h>
#include <libminijail.h>
#include <scoped_minijail.h>

#include "chaps/chaps_adaptor.h"
#include "chaps/chaps_factory_impl.h"
#include "chaps/chaps_service.h"
#include "chaps/chaps_utility.h"
#include "chaps/dbus_bindings/constants.h"
#include "chaps/platform_globals.h"
#include "chaps/slot_manager_impl.h"

#if USE_TPM2
#include "chaps/tpm2_utility_impl.h"
#else
#include "chaps/tpm_utility_impl.h"
#endif

using base::AutoLock;
using base::Lock;
using base::PlatformThread;
using base::PlatformThreadHandle;
using base::WaitableEvent;
using std::string;

namespace {

const char kTpmThreadName[] = "tpm_background_thread";
const char kInitThreadName[] = "async_init_thread";

void MaskSignals() {
  sigset_t signal_mask;
  CHECK_EQ(0, sigemptyset(&signal_mask));
  for (int signal : {SIGTERM, SIGINT, SIGHUP}) {
    CHECK_EQ(0, sigaddset(&signal_mask, signal));
  }
  CHECK_EQ(0, sigprocmask(SIG_BLOCK, &signal_mask, nullptr));
}

void InitAsync(WaitableEvent* started_event,
               Lock* lock,
               chaps::TPMUtility* tpm,
               chaps::SlotManagerImpl* slot_manager) {
  // It's important that we acquire 'lock' before signaling 'started_event'.
  // This will prevent any D-Bus requests from being processed until we've
  // finished initialization.
  AutoLock auto_lock(*lock);
  started_event->Signal();
  LOG(INFO) << "Starting asynchronous initialization.";
  if (!tpm->Init())
    // Just warn and continue in this case.  The effect will be a functional
    // daemon which handles dbus requests but any attempt to load a token will
    // fail.  To a PKCS #11 client this will look like a library with a few
    // empty slots.
    LOG(WARNING) << "TPM initialization failed (this is expected if no TPM is"
                 << " available).  PKCS #11 tokens will not be available.";
  if (!slot_manager->Init())
    LOG(FATAL) << "Slot initialization failed.";
}

void SetProcessUserAndGroup(const char* user_name,
                            const char* group_name) {
  // Make the umask more restrictive: u + rwx, g + rx.
  umask(0027);

  ScopedMinijail j(minijail_new());
  minijail_change_user(j.get(), user_name);
  minijail_change_group(j.get(), group_name);
  minijail_inherit_usergroups(j.get());
  minijail_no_new_privs(j.get());
  minijail_enter(j.get());
}

}  // namespace

namespace chaps {

class Daemon : public brillo::DBusServiceDaemon {
 public:
  Daemon(const std::string& srk_auth_data, bool auto_load_system_token)
      : DBusServiceDaemon(kChapsServiceName,
                          dbus::ObjectPath(kObjectManagerPath)),
        srk_auth_data_(srk_auth_data),
        auto_load_system_token_(auto_load_system_token),
        tpm_background_thread_(kTpmThreadName),
        async_init_thread_(kInitThreadName) {}

 protected:
  int OnInit() override {
#if USE_TPM2
    CHECK(tpm_background_thread_.StartWithOptions(
        base::Thread::Options(base::MessageLoop::TYPE_IO,
                              0 /* use default stack size */)));
    tpm_.reset(new TPM2UtilityImpl(tpm_background_thread_.task_runner()));
#else
    // Instantiate a TPM1.2 Utility.
    tpm_.reset(new TPMUtilityImpl(srk_auth_data_));
#endif

    factory_.reset(new ChapsFactoryImpl);
    slot_manager_.reset(new SlotManagerImpl(
        factory_.get(), tpm_.get(), auto_load_system_token_));
    service_.reset(new ChapsServiceImpl(slot_manager_.get()));

    // Initialize the TPM utility and slot manager asynchronously because
    // we might be able to serve some requests while they are being
    // initialized.
    WaitableEvent init_started(true, false);
    CHECK(async_init_thread_.StartWithOptions(
        base::Thread::Options(base::MessageLoop::TYPE_IO,
                              0 /* use default stack size */)));
    async_init_thread_.task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&InitAsync,
                   &init_started, &lock_, tpm_.get(), slot_manager_.get()));
    // We're not finished with initialization until the initialization thread
    // has had a chance to acquire the lock.
    init_started.Wait();
    // Now we can export D-Bus objects.
    return DBusServiceDaemon::OnInit();
  }

  void RegisterDBusObjectsAsync(
      brillo::dbus_utils::AsyncEventSequencer* sequencer) override {
    adaptor_.reset(new ChapsAdaptor(object_manager_.get(),
                                    &lock_,
                                    service_.get(),
                                    slot_manager_.get()));
    adaptor_->RegisterAsync(
        sequencer->GetHandler("RegisterAsync() failed", true));
  }

 private:
  std::string srk_auth_data_;
  bool auto_load_system_token_;
  base::Thread tpm_background_thread_;
  base::Thread async_init_thread_;
  Lock lock_;

  std::unique_ptr<TPMUtility> tpm_;
  std::unique_ptr<ChapsFactory> factory_;
  std::unique_ptr<SlotManagerImpl> slot_manager_;
  std::unique_ptr<ChapsInterface> service_;
  std::unique_ptr<ChapsAdaptor> adaptor_;

  DISALLOW_COPY_AND_ASSIGN(Daemon);
};

}  // namespace chaps

int main(int argc, char** argv) {
  base::CommandLine::Init(argc, argv);
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderr);
  chaps::ScopedOpenSSL openssl;

  LOG(INFO) << "Starting PKCS #11 services.";
  // Run as 'chaps'.
  SetProcessUserAndGroup(chaps::kChapsdProcessUser, chaps::kChapsdProcessGroup);
  // Determine SRK authorization data from the command line.
  string srk_auth_data;
  if (cl->HasSwitch("srk_password")) {
    srk_auth_data = cl->GetSwitchValueASCII("srk_password");
  } else if (cl->HasSwitch("srk_zeros")) {
    int zero_count = 0;
    if (base::StringToInt(cl->GetSwitchValueASCII("srk_zeros"),
                          &zero_count)) {
      srk_auth_data = string(zero_count, 0);
    } else {
      LOG(WARNING) << "Invalid value for srk_zeros: using empty string.";
    }
  }
  bool auto_load_system_token = cl->HasSwitch("auto_load_system_token");
  // Mask signals handled by the daemon thread. This makes sure we
  // won't handle shutdown signals on one of the other threads spawned
  // below.
  MaskSignals();
  LOG(INFO) << "Starting D-Bus dispatcher.";
  chaps::Daemon(srk_auth_data, auto_load_system_token).Run();
  return 0;
}
