Skip to content

Commit

Permalink
ash: Add D-Bus client for usbguard's DevicePolicyChanged.
Browse files Browse the repository at this point in the history
In order to show notifications about blocked USB devices when
appropriate, ash needs to be aware of these events. This CL adds the
logic necessary to observe the appropriate D-Bus signal.

Bug: 987351
Change-Id: I3eacbc3c401ba2f7d6dc0272a0b56c689ac8cd5b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1772369
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Jorge Lucangeli Obes <jorgelo@chromium.org>
Commit-Queue: Allen Webb <allenwebb@google.com>
Cr-Commit-Position: refs/heads/master@{#698936}
  • Loading branch information
Allen-Webb authored and Commit Bot committed Sep 23, 2019
1 parent 5b5211e commit d1a8e23
Show file tree
Hide file tree
Showing 8 changed files with 391 additions and 0 deletions.
1 change: 1 addition & 0 deletions ash/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ include_rules = [
# TODO(https://crbug.com/644355): Eliminate this.
"+chromeos/dbus/shill",
"+chromeos/dbus/system_clock",
"+chromeos/dbus/usb",
# TODO(https://crbug.com/644355): Eliminate this.
"+chromeos/network",
"+chromeos/services/assistant/public" ,
Expand Down
5 changes: 5 additions & 0 deletions ash/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/dbus/initialize_dbus_client.h"
#include "chromeos/dbus/power/power_policy_controller.h"
#include "chromeos/dbus/usb/usbguard_client.h"
#include "chromeos/system/devicemode.h"
#include "components/exo/file_helper.h"
#include "components/prefs/pref_registry_simple.h"
Expand Down Expand Up @@ -835,6 +836,8 @@ Shell::~Shell() {

shell_delegate_.reset();

chromeos::UsbguardClient::Shutdown();

// Must be shut down after detachable_base_handler_.
chromeos::HammerdClient::Shutdown();

Expand All @@ -854,6 +857,8 @@ void Shell::Init(
// Required by DetachableBaseHandler.
chromeos::InitializeDBusClient<chromeos::HammerdClient>(dbus_bus.get());

chromeos::InitializeDBusClient<chromeos::UsbguardClient>(dbus_bus.get());

local_state_ = local_state;

// This creates the MessageCenter object which is used by some other objects
Expand Down
5 changes: 5 additions & 0 deletions chromeos/dbus/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ component("dbus") {
"smb_provider_client.h",
"update_engine_client.cc",
"update_engine_client.h",
"usb/fake_usbguard_client.cc",
"usb/fake_usbguard_client.h",
"usb/usbguard_client.cc",
"usb/usbguard_client.h",
"usb/usbguard_observer.h",
"util/version_loader.cc",
"util/version_loader.h",
"virtual_file_provider_client.cc",
Expand Down
55 changes: 55 additions & 0 deletions chromeos/dbus/usb/fake_usbguard_client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2019 The Chromium 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 "chromeos/dbus/usb/fake_usbguard_client.h"

namespace chromeos {

namespace {

FakeUsbguardClient* g_instance = nullptr;

} // namespace

FakeUsbguardClient::FakeUsbguardClient() {
DCHECK(!g_instance);
g_instance = this;
}

FakeUsbguardClient::~FakeUsbguardClient() {
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}
// static
FakeUsbguardClient* FakeUsbguardClient::Get() {
DCHECK(g_instance);
return g_instance;
}

void FakeUsbguardClient::AddObserver(UsbguardObserver* observer) {
observers_.AddObserver(observer);
}

void FakeUsbguardClient::RemoveObserver(UsbguardObserver* observer) {
observers_.RemoveObserver(observer);
}

bool FakeUsbguardClient::HasObserver(const UsbguardObserver* observer) const {
return observers_.HasObserver(observer);
}

void FakeUsbguardClient::SendDevicePolicyChanged(
uint32_t id,
UsbguardObserver::Target target_old,
UsbguardObserver::Target target_new,
const std::string& device_rule,
uint32_t rule_id,
const std::map<std::string, std::string>& attributes) {
for (auto& observer : observers_) {
observer.DevicePolicyChanged(id, target_old, target_new, device_rule,
rule_id, attributes);
}
}

} // namespace chromeos
49 changes: 49 additions & 0 deletions chromeos/dbus/usb/fake_usbguard_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_DBUS_USB_FAKE_USBGUARD_CLIENT_H_
#define CHROMEOS_DBUS_USB_FAKE_USBGUARD_CLIENT_H_

#include <map>

#include "base/component_export.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "chromeos/dbus/usb/usbguard_client.h"
#include "chromeos/dbus/usb/usbguard_observer.h"

namespace chromeos {

class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeUsbguardClient
: public UsbguardClient {
public:
FakeUsbguardClient();
~FakeUsbguardClient() override;

// Returns the global instance if initialized. May return null.
static FakeUsbguardClient* Get();

// UsbguardClient:
void AddObserver(UsbguardObserver* observer) override;
void RemoveObserver(UsbguardObserver* observer) override;
bool HasObserver(const UsbguardObserver* observer) const override;

// Simulates receiving a DevicePolicyChanged signal with the given parameters.
void SendDevicePolicyChanged(
uint32_t id,
UsbguardObserver::Target target_old,
UsbguardObserver::Target target_new,
const std::string& device_rule,
uint32_t rule_id,
const std::map<std::string, std::string>& attributes);

private:
base::ObserverList<UsbguardObserver> observers_;

DISALLOW_COPY_AND_ASSIGN(FakeUsbguardClient);
};

} // namespace chromeos

#endif // CHROMEOS_DBUS_USB_FAKE_USBGUARD_CLIENT_H_
156 changes: 156 additions & 0 deletions chromeos/dbus/usb/usbguard_client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Copyright 2019 The Chromium 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 "chromeos/dbus/usb/usbguard_client.h"

#include <map>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/observer_list.h"
#include "chromeos/dbus/usb/fake_usbguard_client.h"
#include "chromeos/dbus/usb/usbguard_observer.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/usbguard/dbus-constants.h"

namespace chromeos {

namespace {
UsbguardClient* g_instance = nullptr;
} // namespace

class UsbguardClientImpl : public UsbguardClient {
public:
UsbguardClientImpl() = default;
~UsbguardClientImpl() override = default;

// UsbguardClient:
void AddObserver(UsbguardObserver* observer) override {
observers_.AddObserver(observer);
}

// UsbguardClient:
void RemoveObserver(UsbguardObserver* observer) override {
observers_.RemoveObserver(observer);
}

// UsbguardClient:
bool HasObserver(const UsbguardObserver* observer) const override {
return observers_.HasObserver(observer);
}

void Init(dbus::Bus* bus) {
bus_ = bus;

usbguard_proxy_ = bus_->GetObjectProxy(
usbguard::kUsbguardServiceName,
dbus::ObjectPath(usbguard::kUsbguardDevicesInterfacePath));

usbguard_proxy_->ConnectToSignal(
usbguard::kUsbguardDevicesInterface,
usbguard::kDevicePolicyChangedSignalName,
base::Bind(&UsbguardClientImpl::DevicePolicyChanged,
weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&UsbguardClientImpl::OnSignalConnected,
weak_ptr_factory_.GetWeakPtr()));
}

private:
// Dispatches the DevicePolicyChanged signal with signature: uuusua{ss}
void DevicePolicyChanged(dbus::Signal* signal) {
dbus::MessageReader signal_reader(signal);
dbus::MessageReader array_reader(nullptr);

uint32_t id;
uint32_t target_old;
uint32_t target_new;
std::string device_rule;
uint32_t rule_id;
if (!signal_reader.PopUint32(&id) ||
!signal_reader.PopUint32(&target_old) ||
!signal_reader.PopUint32(&target_new) ||
!signal_reader.PopString(&device_rule) ||
!signal_reader.PopUint32(&rule_id) ||
!signal_reader.PopArray(&array_reader)) {
LOG(ERROR) << "Error reading signal from usbguard: "
<< signal->ToString();
return;
}

std::map<std::string, std::string> attributes;
while (array_reader.HasMoreData()) {
dbus::MessageReader dict_entry(nullptr);
std::string key;
std::string value;
if (!array_reader.PopDictEntry(&dict_entry) ||
!dict_entry.PopString(&key) || !dict_entry.PopString(&value)) {
LOG(ERROR) << "Error reading array from signal from usbguard: "
<< signal->ToString();
return;
}
attributes[key] = value;
}

for (auto& observer : observers_) {
observer.DevicePolicyChanged(
id, static_cast<UsbguardObserver::Target>(target_old),
static_cast<UsbguardObserver::Target>(target_new), device_rule,
rule_id, attributes);
}
}

// Called when the biometrics signal is initially connected.
void OnSignalConnected(const std::string& interface_name,
const std::string& signal_name,
bool success) {
LOG_IF(ERROR, !success)
<< "Failed to connect to usbguard signal: " << signal_name;
}

dbus::Bus* bus_ = nullptr;
dbus::ObjectProxy* usbguard_proxy_ = nullptr;
base::ObserverList<UsbguardObserver> observers_;

// Note: This should remain the last member so it'll be destroyed and
// invalidate its weak pointers before any other members are destroyed.
base::WeakPtrFactory<UsbguardClientImpl> weak_ptr_factory_{this};

DISALLOW_COPY_AND_ASSIGN(UsbguardClientImpl);
};

UsbguardClient::UsbguardClient() {
DCHECK(!g_instance);
g_instance = this;
}

UsbguardClient::~UsbguardClient() {
DCHECK_EQ(this, g_instance);
g_instance = nullptr;
}

// static
void UsbguardClient::Initialize(dbus::Bus* bus) {
DCHECK(bus);
(new UsbguardClientImpl())->Init(bus);
}

// static
void UsbguardClient::InitializeFake() {
new FakeUsbguardClient();
}

// static
void UsbguardClient::Shutdown() {
DCHECK(g_instance);
delete g_instance;
}

// static
UsbguardClient* UsbguardClient::Get() {
return g_instance;
}

} // namespace chromeos
51 changes: 51 additions & 0 deletions chromeos/dbus/usb/usbguard_client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_DBUS_USB_USBGUARD_CLIENT_H_
#define CHROMEOS_DBUS_USB_USBGUARD_CLIENT_H_

#include "base/component_export.h"
#include "base/macros.h"
#include "chromeos/dbus/usb/usbguard_observer.h"

namespace dbus {
class Bus;
}

namespace chromeos {

class COMPONENT_EXPORT(CHROMEOS_DBUS) UsbguardClient {
public:
virtual ~UsbguardClient();

// Creates and initializes the global instance. |bus| must not be null.
static void Initialize(dbus::Bus* bus);

// Creates and initializes a fake global instance if not already created.
static void InitializeFake();

// Destroys the global instance which must have been initialized.
static void Shutdown();

// Returns the global instance if initialized. May return null.
static UsbguardClient* Get();

// Adds the given observer.
virtual void AddObserver(UsbguardObserver* observer) = 0;
// Removes the given observer if this object has the observer.
virtual void RemoveObserver(UsbguardObserver* observer) = 0;
// Returns true if this object has the given observer.
virtual bool HasObserver(const UsbguardObserver* observer) const = 0;

protected:
// Initialize/Shutdown should be used instead.
UsbguardClient();

private:
DISALLOW_COPY_AND_ASSIGN(UsbguardClient);
};

} // namespace chromeos

#endif // CHROMEOS_DBUS_USB_USBGUARD_CLIENT_H_
Loading

0 comments on commit d1a8e23

Please sign in to comment.