// 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 <grp.h>
#include <linux/usb/ch9.h>
#include <sys/epoll.h>
#include <unistd.h>

#include <string>
#include <vector>

#include <base/bind.h>
#include <base/logging.h>
#include <chromeos/dbus/dbus.h>
#include <chromeos/dbus/service_constants.h>

#include "permission_broker/allow_group_tty_device_rule.h"
#include "permission_broker/allow_hidraw_device_rule.h"
#include "permission_broker/allow_tty_device_rule.h"
#include "permission_broker/allow_usb_device_rule.h"
#include "permission_broker/deny_claimed_hidraw_device_rule.h"
#include "permission_broker/deny_claimed_usb_device_rule.h"
#include "permission_broker/deny_group_tty_device_rule.h"
#include "permission_broker/deny_uninitialized_device_rule.h"
#include "permission_broker/deny_unsafe_hidraw_device_rule.h"
#include "permission_broker/deny_usb_device_class_rule.h"
#include "permission_broker/deny_usb_vendor_id_rule.h"
#include "permission_broker/rule.h"

using permission_broker::AllowGroupTtyDeviceRule;
using permission_broker::AllowHidrawDeviceRule;
using permission_broker::AllowTtyDeviceRule;
using permission_broker::AllowUsbDeviceRule;
using permission_broker::DenyClaimedHidrawDeviceRule;
using permission_broker::DenyClaimedUsbDeviceRule;
using permission_broker::DenyGroupTtyDeviceRule;
using permission_broker::DenyUninitializedDeviceRule;
using permission_broker::DenyUnsafeHidrawDeviceRule;
using permission_broker::DenyUsbDeviceClassRule;
using permission_broker::DenyUsbVendorIdRule;
using permission_broker::PermissionBroker;

namespace {
const uint16_t kLinuxFoundationUsbVendorId = 0x1d6b;
}

namespace permission_broker {

PermissionBroker::PermissionBroker(
    chromeos::dbus_utils::ExportedObjectManager* object_manager,
    const std::string& access_group_name,
    const std::string& udev_run_path,
    int poll_interval_msecs)
    : org::chromium::PermissionBrokerAdaptor(this),
      rule_engine_(udev_run_path, poll_interval_msecs),
      dbus_object_(object_manager,
                   object_manager->GetBus(),
                   dbus::ObjectPath(kPermissionBrokerServicePath)),
      // Create the FirewalldProxy object here, that way the PortTracker object
      // doesn't need to know about D-Bus, which makes testing easier.
      firewalld_(object_manager->GetBus(), firewalld::kServiceName),
      // |firewalld_| is owned by PermissionBroker, the PortTracker object
      // will only call D-Bus methods.
      port_tracker_(&firewalld_) {
  CHECK(!access_group_name.empty()) << "You must specify a group name via the "
                                    << "--access_group flag.";
  struct group group_buffer;
  struct group* access_group = NULL;
  char buffer[256];
  getgrnam_r(access_group_name.c_str(), &group_buffer, buffer, sizeof(buffer),
             &access_group);
  CHECK(access_group) << "Could not resolve \"" << access_group_name << "\" "
                      << "to a named group.";
  access_group_ = access_group->gr_gid;

  rule_engine_.AddRule(new AllowUsbDeviceRule());
  rule_engine_.AddRule(new AllowTtyDeviceRule());
  rule_engine_.AddRule(new DenyClaimedUsbDeviceRule());
  rule_engine_.AddRule(new DenyUninitializedDeviceRule());
  rule_engine_.AddRule(new DenyUsbDeviceClassRule(USB_CLASS_HUB));
  rule_engine_.AddRule(new DenyUsbDeviceClassRule(USB_CLASS_MASS_STORAGE));
  rule_engine_.AddRule(new DenyUsbVendorIdRule(kLinuxFoundationUsbVendorId));
  rule_engine_.AddRule(new AllowHidrawDeviceRule());
  rule_engine_.AddRule(new AllowGroupTtyDeviceRule("serial"));
  rule_engine_.AddRule(new DenyGroupTtyDeviceRule("modem"));
  rule_engine_.AddRule(new DenyGroupTtyDeviceRule("tty"));
  rule_engine_.AddRule(new DenyGroupTtyDeviceRule("uucp"));
  rule_engine_.AddRule(new DenyClaimedHidrawDeviceRule());
  rule_engine_.AddRule(new DenyUnsafeHidrawDeviceRule());
}

PermissionBroker::~PermissionBroker() {}

void PermissionBroker::RegisterAsync(
    const chromeos::dbus_utils::AsyncEventSequencer::CompletionAction& cb) {
  RegisterWithDBusObject(&dbus_object_);
  dbus_object_.RegisterAsync(cb);
}

bool PermissionBroker::CheckPathAccess(const std::string& in_path) {
  return rule_engine_.ProcessPath(in_path, -1 /* all interfaces */);
}

bool PermissionBroker::RequestPathAccess(const std::string& in_path,
                                         int32_t in_interface_id) {
  if (rule_engine_.ProcessPath(in_path, in_interface_id)) {
    return GrantAccess(in_path);
  }
  return false;
}

bool PermissionBroker::RequestTcpPortAccess(
    uint16_t in_port,
    const std::string& in_interface,
    const dbus::FileDescriptor& in_lifeline_fd) {
  return port_tracker_.ProcessTcpPort(in_port, in_interface,
                                      in_lifeline_fd.value());
}

bool PermissionBroker::RequestUdpPortAccess(
    uint16_t in_port,
    const std::string& in_interface,
    const dbus::FileDescriptor& in_lifeline_fd) {
  return port_tracker_.ProcessUdpPort(in_port, in_interface,
                                      in_lifeline_fd.value());
}

bool PermissionBroker::ReleaseTcpPort(uint16_t in_port,
                                      const std::string& in_interface) {
  return port_tracker_.ReleaseTcpPort(in_port, in_interface);
}

bool PermissionBroker::ReleaseUdpPort(uint16_t in_port,
                                      const std::string& in_interface) {
  return port_tracker_.ReleaseUdpPort(in_port, in_interface);
}

bool PermissionBroker::RequestVpnSetup(
    const std::vector<std::string>& usernames,
    const std::string& interface,
    const dbus::FileDescriptor& in_lifeline_fd) {
  return port_tracker_.ProcessVpnSetup(usernames,
                                       interface,
                                       in_lifeline_fd.value());
}

bool PermissionBroker::RemoveVpnSetup() {
  return port_tracker_.RemoveVpnSetup();
}

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;
}

}  // namespace permission_broker
