// 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 "permission_broker/permission_broker.h"

#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <gflags/gflags.h>
#include <glib.h>
#include <grp.h>
#include <libudev.h>
#include <poll.h>
#include <stdint.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>
#include <vector>

#include "base/logging.h"
#include "base/stl_util.h"
#include "base/stringprintf.h"
#include "chromeos/dbus/dbus.h"
#include "chromeos/dbus/service_constants.h"
#include "permission_broker/rule.h"

DEFINE_string(access_group, "", "The group which has resource access granted "
              "to it. Must not be empty.");
DEFINE_int32(poll_interval, 100, "The interval at which to poll for udev "
             "events");

using std::string;
using std::vector;

namespace permission_broker {

PermissionBroker::PermissionBroker(const gid_t access_group)
    : udev_(udev_new()), access_group_(access_group) {}

PermissionBroker::PermissionBroker() : udev_(udev_new()) {
  CHECK(udev_) << "Could not create udev context, is sysfs mounted?";
  CHECK(!FLAGS_access_group.empty()) << "You must specify a group name via the "
                                     << "--access_group flag.";

  struct group *access_group = getgrnam(FLAGS_access_group.c_str());
  CHECK(access_group) << "Could not resolve \"" << FLAGS_access_group << "\" "
                      << "to a named group.";
  access_group_ = access_group->gr_gid;
}

PermissionBroker::~PermissionBroker() {
  STLDeleteContainerPointers(rules_.begin(), rules_.end());
  udev_unref(udev_);
}

void PermissionBroker::Run() {
  DBusConnection *const connection = dbus_g_connection_get_connection(
      chromeos::dbus::GetSystemBusConnection().g_connection());
  CHECK(connection) << "Cannot connect to system bus";

  DBusError error;
  dbus_error_init(&error);
  dbus_bus_request_name(connection,
      permission_broker::kPermissionBrokerServiceName, 0, &error);
  if (dbus_error_is_set(&error)) {
    LOG(FATAL) << "Failed to register "
               << permission_broker::kPermissionBrokerServiceName
               << ": " << error.message;
    dbus_error_free(&error);
    return;
  }

  DBusObjectPathVTable vtable;
  memset(&vtable, 0, sizeof(vtable));
  vtable.message_function = &MainDBusMethodHandler;

  const dbus_bool_t registration_result = dbus_connection_register_object_path(
      connection, kPermissionBrokerServicePath, &vtable, this);
  CHECK(registration_result) << "Could not register object path";

  GMainLoop *const loop = g_main_loop_new(NULL, false);
  g_main_loop_run(loop);
}

void PermissionBroker::AddUsbException(const uint16_t vendor_id,
                                       const uint16_t product_id) {
  usb_exceptions_.insert(std::make_pair(vendor_id, product_id));
}

void PermissionBroker::AddRule(Rule *rule) {
  CHECK(rule) << "Cannot add NULL as a rule.";
  rules_.push_back(rule);
}

bool PermissionBroker::ProcessPath(const string &path,
                                   int interface_id) {
  WaitForEmptyUdevQueue();

  LOG(INFO) << "ProcessPath(" << path << ")";
  Rule::Result result = Rule::IGNORE;
  for (unsigned int i = 0; i < rules_.size(); ++i) {
    const Rule::Result rule_result = rules_[i]->Process(path,
                                                        interface_id);
    LOG(INFO) << "  " << rules_[i]->name() << ": "
              << Rule::ResultToString(rule_result);
    if (rule_result == Rule::DENY)
      return false;
    else if (rule_result == Rule::ALLOW)
      result = Rule::ALLOW;
  }
  LOG(INFO) << "Verdict for " << path << ": " << Rule::ResultToString(result);

  if (result == Rule::ALLOW)
    return GrantAccess(path);
  return false;
}

bool PermissionBroker::GrantAccess(const std::string &path) {
  if (chown(path.c_str(), -1, access_group_)) {
    LOG(INFO) << "Could not grant access to " << path;
    return false;
  }
  return true;
}

bool PermissionBroker::ExpandUsbIdentifiersToPaths(
    const uint16_t vendor_id,
    const uint16_t product_id,
    vector<string> *paths) {
  CHECK(paths) << "Cannot invoke ExpandUsbIdentifiersToPaths with NULL paths.";
  paths->clear();

  struct udev_enumerate *const enumerate = udev_enumerate_new(udev_);
  udev_enumerate_add_match_is_initialized(enumerate);
  udev_enumerate_add_match_subsystem(enumerate, "usb");
  udev_enumerate_add_match_sysattr(enumerate, "idVendor", StringPrintf("%.4x",
      vendor_id).c_str());
  udev_enumerate_add_match_sysattr(enumerate, "idProduct", StringPrintf("%.4x",
      product_id).c_str());
  udev_enumerate_scan_devices(enumerate);

  struct udev_list_entry *entry = NULL;
  udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(enumerate)) {
    const char *const path = udev_list_entry_get_name(entry);
    struct udev_device *device = udev_device_new_from_syspath(udev_, path);
    paths->push_back(udev_device_get_devnode(device));
    udev_device_unref(device);
  }

  udev_enumerate_unref(enumerate);
  return !paths->empty();
}

void PermissionBroker::WaitForEmptyUdevQueue() {
  struct udev_queue *queue = udev_queue_new(udev_);
  if (udev_queue_get_queue_is_empty(queue)) {
    udev_queue_unref(queue);
    return;
  }

  struct pollfd udev_poll;
  memset(&udev_poll, 0, sizeof(udev_poll));
  udev_poll.fd = inotify_init();
  udev_poll.events = POLLIN;

  const char *run_path = udev_get_run_path(udev_);
  int watch = inotify_add_watch(udev_poll.fd, run_path, IN_MOVED_TO);
  CHECK(watch != -1) << "Could not add watch for udev run path.";

  while (!udev_queue_get_queue_is_empty(queue)) {
    if (poll(&udev_poll, 1, FLAGS_poll_interval) > 0) {
      char buffer[sizeof(struct inotify_event)];
      const ssize_t result = read(udev_poll.fd, buffer, sizeof(buffer));
      if (result < 0)
        LOG(WARNING) << "Did not read complete udev event.";
    }
  }
  udev_queue_unref(queue);
  close(udev_poll.fd);
}

DBusHandlerResult PermissionBroker::MainDBusMethodHandler(
    DBusConnection *connection, DBusMessage *message, void *data) {
  CHECK(connection) << "Missing connection.";
  CHECK(message) << "Missing method.";
  CHECK(data) << "Missing pointer to broker.";

  if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  string interface(dbus_message_get_interface(message));
  if (interface != kPermissionBrokerInterface)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  DBusMessage *reply = NULL;
  string member(dbus_message_get_member(message));
  PermissionBroker *const broker = static_cast<PermissionBroker*>(data);
  if (member == kRequestPathAccess)
    reply = broker->HandleRequestPathAccessMethod(message);
  else if (member == kRequestUsbAccess)
    reply = broker->HandleRequestUsbAccessMethod(message);
  else
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  CHECK(dbus_connection_send(connection, reply, NULL));
  dbus_message_unref(reply);

  return DBUS_HANDLER_RESULT_HANDLED;
}

DBusMessage *PermissionBroker::HandleRequestPathAccessMethod(
    DBusMessage *message) {
  DBusMessage *reply = dbus_message_new_method_return(message);
  CHECK(reply) << "Could not allocate reply message for method call";

  dbus_bool_t success = false;
  char *path = NULL;
  int interface_id = Rule::ANY_INTERFACE;

  DBusError error;
  dbus_error_init(&error);
  if (!dbus_message_get_args(message, &error,
                             DBUS_TYPE_STRING, &path,
                             DBUS_TYPE_INT32, &interface_id,
                             DBUS_TYPE_INVALID)) {
    interface_id = Rule::ANY_INTERFACE;
    if (!dbus_message_get_args(message, &error,
                               DBUS_TYPE_STRING, &path,
                               DBUS_TYPE_INVALID)) {
      LOG(WARNING) << "Error parsing arguments: " << error.message;
      dbus_error_free(&error);

      dbus_message_append_args(reply,
                               DBUS_TYPE_BOOLEAN, &success,
                               DBUS_TYPE_INVALID);
      return reply;
    }
  }

  success = ProcessPath(path, interface_id);
  dbus_message_append_args(reply,
                           DBUS_TYPE_BOOLEAN, &success,
                           DBUS_TYPE_INVALID);
  return reply;
}

DBusMessage *PermissionBroker::HandleRequestUsbAccessMethod(
    DBusMessage *message) {
  DBusMessage *reply = dbus_message_new_method_return(message);
  CHECK(reply) << "Could not allocate reply message for method call";

  dbus_bool_t success = false;
  uint16_t vendor_id;
  uint16_t product_id;
  int interface_id = Rule::ANY_INTERFACE;

  DBusError error;
  dbus_error_init(&error);
  if (!dbus_message_get_args(message, &error,
                             DBUS_TYPE_UINT16, &vendor_id,
                             DBUS_TYPE_UINT16, &product_id,
                             DBUS_TYPE_INT32, &interface_id,
                             DBUS_TYPE_INVALID)) {
    interface_id = Rule::ANY_INTERFACE;
    if (!dbus_message_get_args(message, &error,
                               DBUS_TYPE_UINT16, &vendor_id,
                               DBUS_TYPE_UINT16, &product_id,
                               DBUS_TYPE_INVALID)) {
      LOG(WARNING) << "Error parsing arguments: " << error.message;
      dbus_error_free(&error);

      dbus_message_append_args(reply,
                               DBUS_TYPE_BOOLEAN, &success,
                               DBUS_TYPE_INVALID);
      return reply;
    }
  }

  if (ContainsKey(usb_exceptions_, std::make_pair(vendor_id, product_id))) {
    success = true;
  } else {
    vector<string> paths;
    if (ExpandUsbIdentifiersToPaths(vendor_id,
                                    product_id,
                                    &paths)) {
      success = true;
      for (unsigned int i = 0; i < paths.size(); ++i)
        success &= ProcessPath(paths[i], interface_id);
    } else {
      LOG(INFO) << "Could not expand (" << vendor_id << ", " << product_id
                << ") to a list of device nodes.";
    }
  }

  dbus_message_append_args(reply,
                           DBUS_TYPE_BOOLEAN, &success,
                           DBUS_TYPE_INVALID);
  return reply;
}

}  // namespace permission_broker
