// Copyright 2016 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 <memory>

#include <base/memory/ptr_util.h>
#include <base/memory/weak_ptr.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/syslog_logging.h>
#include <install_attributes/libinstallattributes.h>

#include "authpolicy/authpolicy.h"
#include "authpolicy/constants.h"
#include "authpolicy/path_service.h"
#include "authpolicy/platform_helper.h"

namespace {

const char kObjectServicePath[] = "/org/chromium/AuthPolicy/ObjectManager";
const char kAuthPolicydUser[] = "authpolicyd";
const char kAuthPolicydExecUser[] = "authpolicyd-exec";

const int kExitCodeStartupFailure = 175;  // This number is hex AF.

}  // namespace

namespace authpolicy {

class Daemon : public brillo::DBusServiceDaemon {
 public:
  explicit Daemon(bool device_is_locked)
      : DBusServiceDaemon(kAuthPolicyServiceName, kObjectServicePath),
        device_is_locked_(device_is_locked),
        weak_ptr_factory_(this) {}

  // Cleans the authpolicy daemon state directory. Returns true if all files
  // were cleared.
  static bool CleanState() {
    PathService path_service;
    return AuthPolicy::CleanState(&path_service);
  }

 protected:
  void RegisterDBusObjectsAsync(
      brillo::dbus_utils::AsyncEventSequencer* sequencer) override {
    brillo::dbus_utils::AsyncEventSequencer::Handler handler =
        sequencer->GetHandler("AuthPolicy.RegisterAsync() failed.", true);
    auth_policy_.RegisterAsync(
        AuthPolicy::GetDBusObject(object_manager_.get()),
        base::Bind(&Daemon::OnAuthPolicyRegistered,
                   weak_ptr_factory_.GetWeakPtr(), handler));
  }

 private:
  void OnAuthPolicyRegistered(
      const brillo::dbus_utils::AsyncEventSequencer::Handler& handler,
      bool success) {
    // If it wasn't successful, the sequencer handler should print an error and
    // exit.
    handler.Run(success);
    CHECK(success);
    LOG(INFO) << "authpolicyd started";

    // Initialize authpolicy here, so that stuff like the machine password check
    // happens after the daemon is registered.
    ErrorType error = auth_policy_.Initialize(device_is_locked_);
    if (error != ERROR_NONE) {
      LOG(ERROR) << "SambaInterface failed to initialize with error code "
                 << error;
      exit(kExitCodeStartupFailure);
    }
  }

  bool device_is_locked_;

  // Keep this order! auth_policy_ must be last as it depends on the other two.
  AuthPolicyMetrics metrics_;
  PathService path_service_;
  AuthPolicy auth_policy_{&metrics_, &path_service_};

  base::WeakPtrFactory<Daemon> weak_ptr_factory_;
  DISALLOW_COPY_AND_ASSIGN(Daemon);
};

}  // namespace authpolicy

int main(int /* argc */, char* /* argv */ []) {
  brillo::OpenLog("authpolicyd", true);
  brillo::InitLog(brillo::kLogToSyslog);

  // Verify we're running as authpolicyd user.
  uid_t authpolicyd_uid = authpolicy::GetUserId(kAuthPolicydUser);
  if (authpolicyd_uid != authpolicy::GetEffectiveUserId()) {
    LOG(ERROR) << "Failed to verify effective UID (must run as authpolicyd).";
    exit(kExitCodeStartupFailure);
  }

  // Make it possible to switch to authpolicyd-exec without caps and drop caps.
  uid_t authpolicyd_exec_uid = authpolicy::GetUserId(kAuthPolicydExecUser);
  if (!authpolicy::SetSavedUserAndDropCaps(authpolicyd_exec_uid)) {
    LOG(ERROR) << "Failed to establish user ids and drop caps.";
    exit(kExitCodeStartupFailure);
  }

  // Safety check to ensure that authpolicyd cannot run after the device has
  // been locked to a mode other than enterprise_ad.  (The lifetime management
  // of authpolicyd happens through upstart, this check only serves as a second
  // line of defense.)
  bool device_is_locked = false;
  InstallAttributesReader install_attributes_reader;
  if (install_attributes_reader.IsLocked()) {
    const std::string& mode = install_attributes_reader.GetAttribute(
        InstallAttributesReader::kAttrMode);
    if (mode != InstallAttributesReader::kDeviceModeEnterpriseAD) {
      LOG(ERROR) << "OOBE completed but device not in Active Directory "
                    "management mode. Cleaning state and exiting.";
      CHECK(authpolicy::Daemon::CleanState());
      exit(kExitCodeStartupFailure);
    } else {
      LOG(INFO) << "Install attributes locked to Active Directory mode.";

      // A configuration file should be present in this case.
      device_is_locked = true;
    }
  } else {
    LOG(INFO) << "No install attributes found. Cleaning state.";
    CHECK(authpolicy::Daemon::CleanState());
  }

  // Run daemon.
  LOG(INFO) << "authpolicyd starting";
  authpolicy::Daemon daemon(device_is_locked);
  int res = daemon.Run();
  LOG(INFO) << "authpolicyd stopping with exit code " << res;

  return res;
}
