blob: ce64f199497b818a93aadc1c096aec513f09d05c [file] [log] [blame]
// 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