Skip to content

Commit e0e5936

Browse files
muelliCropi
authored andcommitted
Added a new signal: DevicePolicyApplied to inform about actions on a device
The DevicePolicyChanged signal is guarded by a check for whether the "target" changed. That is, it fired whenever a device was present, inserted, or a rule has changed, *except* if a) a rule has matched and b) it has changed whatever the outcome under the implicit rule was. That behaviour is arguably much more difficult to explain than just firing whenever a device is present, inserted, or had a rule changed. At the same time, such a signal is much more useful for consumers. More precisely: Now, consumers can listen to that signal and get to know what happened to a device, i.e. whether it was accepted or rejected. Before this change, this was difficult at best, if not impossible. The other PresentChanged signal exists and it tells you whenever a devices is inserted. But then you wouldn't know whether the target it carries is the final one or whether a PolicyChange signal will come to tell what happened with the device. So you needed to invent a timeout after which you believe that USBGuard won't throw any further signals and only then act accordingly, e.g. allow or reject a device. This is a new signal in order to not break existing applications.
1 parent b15ef71 commit e0e5936

16 files changed

Lines changed: 210 additions & 13 deletions

src/CLI/IPCSignalWatcher.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,28 @@ namespace usbguard
127127
}
128128
}
129129

130+
void IPCSignalWatcher::DevicePolicyApplied(uint32_t id,
131+
Rule::Target target_new,
132+
const std::string& device_rule,
133+
uint32_t rule_id)
134+
{
135+
std::cout << "[device] PolicyApplied: id=" << id << std::endl;
136+
std::cout << " target_new=" << Rule::targetToString(target_new) << std::endl;
137+
std::cout << " device_rule=" << device_rule << std::endl;
138+
std::cout << " rule_id=" << rule_id << std::endl;
139+
140+
if (hasOpenExecutable()) {
141+
const std::map<std::string, std::string> env = {
142+
{ "USBGUARD_IPC_SIGNAL", "Device.PolicyApplied" },
143+
{ "USBGUARD_DEVICE_ID", std::to_string(id) },
144+
{ "USBGUARD_DEVICE_TARGET_NEW", Rule::targetToString(target_new) },
145+
{ "USBGUARD_DEVICE_RULE", device_rule },
146+
{ "USBGUARD_DEVICE_RULE_ID", std::to_string(rule_id) }
147+
};
148+
runExecutable(env);
149+
}
150+
}
151+
130152
void IPCSignalWatcher::PropertyParameterChanged(const std::string& name,
131153
const std::string& value_old,
132154
const std::string& value_new)

src/CLI/IPCSignalWatcher.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ namespace usbguard
4646
const std::string& device_rule,
4747
uint32_t rule_id) override;
4848

49+
void DevicePolicyApplied(uint32_t id,
50+
Rule::Target target_new,
51+
const std::string& device_rule,
52+
uint32_t rule_id) override;
53+
4954
void PropertyParameterChanged(const std::string& name,
5055
const std::string& value_old,
5156
const std::string& value_new) override;

src/DBus/DBusBridge.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,27 @@ namespace usbguard
270270
}
271271
}
272272

273+
void DBusBridge::DevicePolicyApplied(uint32_t id,
274+
Rule::Target target_new,
275+
const std::string& device_rule,
276+
uint32_t rule_id)
277+
{
278+
GVariantBuilder* gv_builder_attributes = deviceRuleToAttributes(device_rule);
279+
g_dbus_connection_emit_signal(p_gdbus_connection, nullptr,
280+
DBUS_DEVICES_PATH, DBUS_DEVICES_INTERFACE, "DevicePolicyApplied",
281+
g_variant_new("(uusua{ss})",
282+
id,
283+
Rule::targetToInteger(target_new),
284+
device_rule.c_str(),
285+
rule_id,
286+
gv_builder_attributes),
287+
nullptr);
288+
289+
if (gv_builder_attributes != nullptr) {
290+
g_variant_builder_unref(gv_builder_attributes);
291+
}
292+
}
293+
273294
void DBusBridge::PropertyParameterChanged(const std::string& name,
274295
const std::string& value_old,
275296
const std::string& value_new)

src/DBus/DBusBridge.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ namespace usbguard
6363
const std::string& device_rule,
6464
uint32_t rule_id) override;
6565

66+
void DevicePolicyApplied(uint32_t id,
67+
Rule::Target target_new,
68+
const std::string& device_rule,
69+
uint32_t rule_id) override;
70+
6671
void PropertyParameterChanged(const std::string& name,
6772
const std::string& value_old,
6873
const std::string& value_new) override;

src/DBus/DBusInterface.xml

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@
152152
If the permanent flag is set to True, a rule will be appended to the policy or an exiting device
153153
rule will be modified in order to permanently store the authorization decision.
154154
155-
Sucessfull exection of this method will cause the DevicePolicyChanged signal to be broadcasted if
156-
the device authorization target was different than the applied target.
155+
Successful execution of this method will cause the DevicePolicyChanged signal to be broadcasted if
156+
the device authorization target was different from the applied target.
157157
-->
158158
<method name="applyDevicePolicy">
159159
<arg name="id" direction="in" type="u"/>
@@ -205,6 +205,7 @@
205205
DevicePolicyChanged:
206206
@id: Device id of the device
207207
@target_old: Previous authorization target in numerical form.
208+
0 = Allow. 1 = Block. 2 = Reject.
208209
@target_new: Current authorization target in numerical form.
209210
@device_rule: Device specific rule.
210211
@rule_id: A rule id of the matched rule. Otherwise a reserved rule id value is used.
@@ -234,6 +235,41 @@
234235
<arg name="rule_id" direction="out" type="u"/>
235236
<arg name="attributes" direction="out" type="a{ss}"/>
236237
</signal>
238+
239+
<!--
240+
DevicePolicyApplied:
241+
@id: Device id of the device
242+
@target_new: Current authorization target in numerical form.
243+
0 = Allow. 1 = Block. 2 = Reject.
244+
@device_rule: Device specific rule.
245+
@rule_id: A rule id of the matched rule. Otherwise a reserved rule id value is used.
246+
Reserved values are:
247+
4294967294 (UINT32_MAX - 1) for an implicit rule, e.g.
248+
ImplicitPolicyTarget or InsertedDevicePolicy.
249+
@attributes: A dictionary of device attributes and their values.
250+
251+
Notify about a change of a USB device.
252+
This is a superset of DevicePolicyChanged and will always be thrown
253+
when a device is inserted, authorised, or rejected.
254+
255+
The device attribute dictionary contains the following attributes:
256+
- id (the USB device ID in the form VID:PID)
257+
- name
258+
- serial
259+
- via-port
260+
- hash
261+
- parent-hash
262+
- with-interface
263+
- with-connect-type (either "hardwired", "hotplug", or the empty string for unknown)
264+
265+
-->
266+
<signal name="DevicePolicyApplied">
267+
<arg name="id" direction="out" type="u"/>
268+
<arg name="target_new" direction="out" type="u"/>
269+
<arg name="device_rule" direction="out" type="s"/>
270+
<arg name="rule_id" direction="out" type="u"/>
271+
<arg name="attributes" direction="out" type="a{ss}"/>
272+
</signal>
237273
</interface>
238274
</node>
239275

src/Daemon/Daemon.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,9 @@ namespace usbguard
850850
matched_rule->getTarget());
851851
const bool target_changed = target_old != device_post->getTarget();
852852

853+
std::shared_ptr<const Rule> device_rule = \
854+
device_post->getDeviceRule(/*with_port=*/true,
855+
/*with_parent_hash=*/true);
853856
if (target_changed || matched_rule->getRuleID() == Rule::ImplicitID) {
854857
if (target_changed) {
855858
USBGUARD_LOG(Debug) << "Device target changed:"
@@ -860,16 +863,18 @@ namespace usbguard
860863
USBGUARD_LOG(Debug) << "Implicit rule matched";
861864
}
862865

863-
std::shared_ptr<const Rule> device_rule = \
864-
device_post->getDeviceRule(/*with_port=*/true,
865-
/*with_parent_hash=*/true);
866866
DevicePolicyChanged(device->getID(),
867867
target_old,
868868
device_post->getTarget(),
869869
device_rule->toString(),
870870
matched_rule->getRuleID());
871871
}
872872

873+
DevicePolicyApplied(device->getID(),
874+
device_post->getTarget(),
875+
device_rule->toString(),
876+
matched_rule->getRuleID());
877+
873878
matched_rule->updateMetaDataCounters(/*applied=*/true);
874879
audit_event.success();
875880
}

src/Library/IPC/Devices.proto

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ message DevicePolicyChangedSignal {
5151
required uint32 rule_id = 5;
5252
}
5353

54+
message DevicePolicyAppliedSignal {
55+
required uint32 id = 1;
56+
required uint32 target_new = 2;
57+
required string device_rule = 3;
58+
required uint32 rule_id = 4;
59+
}
60+
5461
message PropertyParameterChangedSignal {
5562
required string name = 1;
5663
required string value_old = 2;

src/Library/IPCClientPrivate.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ namespace usbguard
8585
registerHandler<IPC::Exception>(&IPCClientPrivate::handleException);
8686
registerHandler<IPC::DevicePresenceChangedSignal>(&IPCClientPrivate::handleDevicePresenceChangedSignal);
8787
registerHandler<IPC::DevicePolicyChangedSignal>(&IPCClientPrivate::handleDevicePolicyChangedSignal);
88+
registerHandler<IPC::DevicePolicyAppliedSignal>(&IPCClientPrivate::handleDevicePolicyAppliedSignal);
8889
registerHandler<IPC::PropertyParameterChangedSignal>(&IPCClientPrivate::handlePropertyParameterChangedSignal);
8990

9091
if (connected) {
@@ -522,6 +523,17 @@ namespace usbguard
522523
signal->rule_id());
523524
}
524525

526+
void IPCClientPrivate::handleDevicePolicyAppliedSignal(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out)
527+
{
528+
(void)message_out;
529+
const IPC::DevicePolicyAppliedSignal* const signal = \
530+
reinterpret_cast<const IPC::DevicePolicyAppliedSignal*>(message_in.get());
531+
_p_instance.DevicePolicyApplied(signal->id(),
532+
Rule::targetFromInteger(signal->target_new()),
533+
signal->device_rule(),
534+
signal->rule_id());
535+
}
536+
525537
void IPCClientPrivate::handlePropertyParameterChangedSignal(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out)
526538
{
527539
(void)message_out;

src/Library/IPCClientPrivate.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ namespace usbguard
109109
void handleException(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out);
110110
void handleDevicePresenceChangedSignal(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out);
111111
void handleDevicePolicyChangedSignal(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out);
112+
void handleDevicePolicyAppliedSignal(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out);
112113
void handlePropertyParameterChangedSignal(IPC::MessagePointer& message_in, IPC::MessagePointer& message_out);
113114

114115
IPCClient& _p_instance;

src/Library/IPCPrivate.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ namespace usbguard
3838
{ 0x02, "usbguard.IPC.applyDevicePolicy" },
3939
{ 0x03, "usbguard.IPC.DevicePresenceChangedSignal" },
4040
{ 0x04, "usbguard.IPC.DevicePolicyChangedSignal" },
41-
{ 0x05, "usbguard.IPC.PropertyParameterChangedSignal" },
42-
{ 0x06, "usbguard.IPC.listRules" },
43-
{ 0x07, "usbguard.IPC.appendRule" },
44-
{ 0x08, "usbguard.IPC.removeRule" },
45-
{ 0x09, "usbguard.IPC.Exception" },
46-
{ 0x0a, "usbguard.IPC.getParameter" },
47-
{ 0x0b, "usbguard.IPC.setParameter" },
48-
{ 0x0c, "usbguard.IPC.checkIPCPermissions" }
41+
{ 0x05, "usbguard.IPC.DevicePolicyAppliedSignal" },
42+
{ 0x06, "usbguard.IPC.PropertyParameterChangedSignal" },
43+
{ 0x07, "usbguard.IPC.listRules" },
44+
{ 0x08, "usbguard.IPC.appendRule" },
45+
{ 0x09, "usbguard.IPC.removeRule" },
46+
{ 0x0a, "usbguard.IPC.Exception" },
47+
{ 0x0b, "usbguard.IPC.getParameter" },
48+
{ 0x0c, "usbguard.IPC.setParameter" },
49+
{ 0x0d, "usbguard.IPC.checkIPCPermissions" }
4950
};
5051

5152
uint32_t IPC::messageTypeNameToNumber(const std::string& name)

0 commit comments

Comments
 (0)