Skip to content

Commit

Permalink
Add insertRule method
Browse files Browse the repository at this point in the history
  • Loading branch information
ZoltanFridrich committed Jun 30, 2021
1 parent 57022f1 commit 5df1cee
Show file tree
Hide file tree
Showing 25 changed files with 323 additions and 57 deletions.
8 changes: 7 additions & 1 deletion doc/man/usbguard.1.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,13 @@ Append the 'rule' to the current rule set.
Available options:

*-a, --after* 'id'::
Append the new rule after a rule with the specified rule 'id'.
Append the new rule after a rule with the specified rule 'id'
instead of appending it at the end of the rule set.
If 'id' is 0, then the rule is appended to the beginning
of the rule set.

*-r, --ruleset* 'prefix'::
Append the new rule into a rule set with specified prefix.

*-t, --temporary*::
Make the decision temporary. The rule policy file will not be updated.
Expand Down
5 changes: 4 additions & 1 deletion scripts/bash_completion/usbguard
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,14 @@ function _usbguard()
if _usbguard_contains "-a --after" $prev; then
opts=$(_usbguard_get_rules || :)

elif _usbguard_contains "-r --ruleset" $prev; then
return 0

elif ! _usbguard_in_option && [[ $args -eq 2 ]]; then
return 0

else
opts="$opts -a --after -t --temporary"
opts="$opts -a --after -r --ruleset -t --temporary"
fi
;;

Expand Down
1 change: 1 addition & 0 deletions scripts/usbguard-zsh-completion
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ case $state in
'<rule>[rule]'
_command_args=( \
'(--after)--after <id>[Append the new rule after a rule with the specified id instead of appending it]' \
'(--ruleset)--ruleset <prefix>[Append the new rule into a rule set with specified prefix.]' \
'(--help)--help[Show help]'
)
;;
Expand Down
23 changes: 16 additions & 7 deletions src/CLI/usbguard-append-rule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@

namespace usbguard
{
static const char* options_short = "ha:t";
static const char* options_short = "ha:r:t";

static const struct ::option options_long[] = {
{ "help", no_argument, nullptr, 'h' },
{ "after", required_argument, nullptr, 'a' },
{ "ruleset", required_argument, nullptr, 'r' },
{ "temporary", no_argument, nullptr, 't' },
{ nullptr, 0, nullptr, 0 }
};
Expand All @@ -43,17 +44,21 @@ namespace usbguard
stream << " Usage: " << usbguard_arg0 << " append-rule [OPTIONS] <rule>" << std::endl;
stream << std::endl;
stream << " Options:" << std::endl;
stream << " -a, --after <id> Append the new rule after a rule with the specified id" << std::endl;
stream << " instead of appending it at the end of the rule set." << std::endl;
stream << " -t, --temporary Make the decision temporary. The rule policy file will not" << std::endl;
stream << " be updated." << std::endl;
stream << " -h, --help Show this help." << std::endl;
stream << " -a, --after <id> Append the new rule after a rule with the specified id" << std::endl;
stream << " instead of appending it at the end of the rule set." << std::endl;
stream << " If 'id' is 0, then the rule is appended to the beginning" << std::endl;
stream << " of the rule set." << std::endl;
stream << " -r, --ruleset <prefix> Append the new rule into a ruleset with specified prefix." << std::endl;
stream << " -t, --temporary Make the decision temporary. The rule policy file will not" << std::endl;
stream << " be updated." << std::endl;
stream << " -h, --help Show this help." << std::endl;
stream << std::endl;
}

int usbguard_append_rule(int argc, char* argv[])
{
uint32_t parent_id = usbguard::Rule::LastID;
std::string ruleset;
bool permanent = true;
int opt = 0;

Expand All @@ -67,6 +72,10 @@ namespace usbguard
parent_id = std::stoul(optarg);
break;

case 'r':
ruleset = optarg;
break;

case 't':
permanent = false;
break;
Expand All @@ -89,7 +98,7 @@ namespace usbguard

usbguard::IPCClient ipc(/*connected=*/true);
const std::string rule_spec = argv[0];
const uint32_t id = ipc.appendRule(rule_spec, parent_id, permanent);
const uint32_t id = ipc.insertRule(rule_spec, parent_id, ruleset, permanent);
std::cout << id << std::endl;
return EXIT_SUCCESS;
}
Expand Down
15 changes: 13 additions & 2 deletions src/DBus/DBusBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,19 @@ namespace usbguard
return;
}

if (method_name == "insertRule") {
const char* rule_spec_cstr = nullptr;
uint32_t parent_id = 0;
const char* ruleset_cstr = nullptr;
gboolean temporary = false;
g_variant_get(parameters, "(&sub)", &rule_spec_cstr, &parent_id, &ruleset_cstr, &temporary);
std::string rule_spec(rule_spec_cstr);
std::string ruleset(ruleset_cstr);
const uint32_t rule_id = insertRule(rule_spec, parent_id, ruleset, !temporary);
g_dbus_method_invocation_return_value(invocation, g_variant_new("(u)", rule_id));
return;
}

if (method_name == "appendRule") {
const char* rule_spec_cstr = nullptr;
uint32_t parent_id = 0;
Expand Down Expand Up @@ -337,11 +350,9 @@ namespace usbguard
g_variant_builder_add(builder, "{ss}",
"with-interface",
with_interface_string.c_str());

g_variant_builder_add(builder, "{ss}",
"with-connect-type",
device_rule.getWithConnectType().c_str());

return builder;
}
} /* namespace usbguard */
Expand Down
24 changes: 24 additions & 0 deletions src/DBus/DBusInterface.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,30 @@
<arg name="ruleset" direction="out" type="a(us)"/>
</method>

<!--
insertRule:
@rule: The rule that should be appended to the policy.
@parent_id: Rule id of the parent rule.
@ruleset: Prefix of a ruleset where the rule should be appended.
@temporary: A boolean to avoid adding this rule to the policy file.
@id: The rule id assigned to the succesfully appended rule.
Append a new rule to the current policy. Using the parent_id
parameter and ruleset prefix, the rule can be inserted anywhere in the
policy. 4294967293 (UINT32_MAX-2) is the last possible
ID and thus, when using this as parent_id, the rule is effectively
appended to the end of the ruleset. If parent_id is 0, the rule is
appended to the beginning of the ruleset. When the rule is successfully
appended, the id assigned to the new rule is returned.
-->
<method name="insertRule">
<arg name="rule" direction="in" type="s"/>
<arg name="parent_id" direction="in" type="u"/>
<arg name="ruleset" direction="in" type="s"/>
<arg name="temporary" direction="in" type="b"/>
<arg name="id" direction="out" type="u"/>
</method>

<!--
appendRule:
@rule: The rule that should be appended to the policy.
Expand Down
9 changes: 9 additions & 0 deletions src/DBus/org.usbguard1.policy
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
</defaults>
</action>

<action id="org.usbguard.Policy1.insertRule">
<description>Append a new rule to the policy</description>
<message>Prevents from appending rules to the USBGuard policy</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin</allow_active>
</defaults>
</action>

<action id="org.usbguard.Policy1.appendRule">
<description>Append a new rule to the policy</description>
<message>Prevents from appending rules to the USBGuard policy</message>
Expand Down
19 changes: 19 additions & 0 deletions src/Daemon/Daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,6 +730,25 @@ namespace usbguard
}
}

uint32_t Daemon::insertRule(const std::string& rule_spec,
uint32_t parent_id, const std::string& ruleset, bool permanent)
{
USBGUARD_LOG(Trace) << "entry:"
<< " rule_spec=" << rule_spec
<< " parent_id=" << parent_id
<< " ruleset=" << ruleset;
const Rule rule = Rule::fromString(rule_spec);
/* TODO: reevaluate the firewall rules for all active devices */
const uint32_t id = _policy.insertRule(rule, parent_id, ruleset);

if (_config.hasSettingValue("RuleFile") && permanent) {
_policy.save();
}

USBGUARD_LOG(Trace) << "return: id=" << id;
return id;
}

uint32_t Daemon::appendRule(const std::string& rule_spec,
uint32_t parent_id, bool permanent)
{
Expand Down
1 change: 1 addition & 0 deletions src/Daemon/Daemon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ namespace usbguard
std::string setParameter(const std::string& name, const std::string& value) override;
std::string getParameter(const std::string& name) override;

uint32_t insertRule(const std::string& rule_spec, uint32_t parent_id, const std::string& ruleset, bool permanent) override;
uint32_t appendRule(const std::string& rule_spec, uint32_t parent_id, bool permanent) override;
void removeRule(uint32_t id) override;
const std::vector<Rule> listRules(const std::string& query) override;
Expand Down
2 changes: 2 additions & 0 deletions src/Daemon/FileRuleSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "FileRuleSet.hpp"

#include "Common/Utility.hpp"
#include "usbguard/Typedefs.hpp"
#include "usbguard/Rule.hpp"
#include "usbguard/RuleParser.hpp"
Expand All @@ -36,6 +37,7 @@ namespace usbguard
: RuleSet(interface_ptr),
_rulesPath(path)
{
setName(filenameFromPath(path, false));
setWritable();
USBGUARD_LOG(Info) << "Creating FileRuleSet";
}
Expand Down
2 changes: 1 addition & 1 deletion src/Daemon/RuleSetFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace usbguard
}
}

if (ruleSet.empty()){
if (ruleSet.empty()) {
USBGUARD_LOG(Warning) << "RuleFile not set; Modification of the permanent policy won't be possible.";
ruleSet = generateDefaultRuleSet();
}
Expand Down
18 changes: 18 additions & 0 deletions src/Library/IPC/Policy.proto
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ message listRules {
}


message insertRuleRequest {
required string rule = 1;
required uint32 parent_id = 2;
required string ruleset = 3;
required bool permanent = 4;
}

message insertRuleResponse {
required uint32 id = 1;
}

message insertRule {
required MessageHeader header = 1;
required insertRuleRequest request = 2;
optional insertRuleResponse response = 3;
}


message appendRuleRequest {
required string rule = 1;
required uint32 parent_id = 2;
Expand Down
21 changes: 17 additions & 4 deletions src/Library/IPCClientPrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ namespace usbguard
registerHandler<IPC::getParameter>(&IPCClientPrivate::handleMethodResponse);
registerHandler<IPC::setParameter>(&IPCClientPrivate::handleMethodResponse);
registerHandler<IPC::listRules>(&IPCClientPrivate::handleMethodResponse);
registerHandler<IPC::insertRule>(&IPCClientPrivate::handleMethodResponse);
registerHandler<IPC::appendRule>(&IPCClientPrivate::handleMethodResponse);
registerHandler<IPC::removeRule>(&IPCClientPrivate::handleMethodResponse);
registerHandler<IPC::applyDevicePolicy>(&IPCClientPrivate::handleMethodResponse);
Expand Down Expand Up @@ -143,7 +144,6 @@ namespace usbguard
<< " do_wait=" << do_wait;
USBGUARD_LOG(Trace) << "_qb_conn=" << _qb_conn
<< " _qb_fd=" << _qb_fd;

std::unique_lock<std::mutex> disconnect_lock(_disconnect_mutex);

if (_qb_conn != nullptr && _qb_fd >= 0) {
Expand Down Expand Up @@ -386,6 +386,18 @@ namespace usbguard
return message_in->response().value();
}

uint32_t IPCClientPrivate::insertRule(const std::string& rule_spec,
uint32_t parent_id, const std::string& ruleset, bool permanent)
{
IPC::insertRule message_out;
message_out.mutable_request()->set_rule(rule_spec);
message_out.mutable_request()->set_parent_id(parent_id);
message_out.mutable_request()->set_ruleset(ruleset);
message_out.mutable_request()->set_permanent(permanent);
auto message_in = qbIPCSendRecvMessage(message_out);
return message_in->response().id();
}

uint32_t IPCClientPrivate::appendRule(const std::string& rule_spec, uint32_t parent_id, bool permanent)
{
IPC::appendRule message_out;
Expand Down Expand Up @@ -445,16 +457,17 @@ namespace usbguard
return devices;
}

bool IPCClientPrivate::checkIPCPermissions(const IPCServer::AccessControl::Section& section, const IPCServer::AccessControl::Privilege& privilege)
bool IPCClientPrivate::checkIPCPermissions(const IPCServer::AccessControl::Section& section,
const IPCServer::AccessControl::Privilege& privilege)
{
IPC::checkIPCPermissions message_out;
message_out.mutable_request()->set_uid(getuid());
message_out.mutable_request()->set_gid(getgid());
message_out.mutable_request()->set_section(
IPCServer::AccessControl::sectionToString(section)
IPCServer::AccessControl::sectionToString(section)
);
message_out.mutable_request()->set_privilege(
IPCServer::AccessControl::privilegeToString(privilege)
IPCServer::AccessControl::privilegeToString(privilege)
);
auto message_in = qbIPCSendRecvMessage(message_out);
return message_in->response().permit();
Expand Down
4 changes: 3 additions & 1 deletion src/Library/IPCClientPrivate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,16 @@ namespace usbguard
std::string setParameter(const std::string& name, const std::string& value);
std::string getParameter(const std::string& name);

uint32_t insertRule(const std::string& rule_spec, uint32_t parent_id, const std::string& ruleset, bool permanent);
uint32_t appendRule(const std::string& rule_spec, uint32_t parent_id, bool permanent);
void removeRule(uint32_t id);
const std::vector<Rule> listRules(const std::string& label);

uint32_t applyDevicePolicy(uint32_t id, Rule::Target target, bool permanent);
const std::vector<Rule> listDevices(const std::string& query);

bool checkIPCPermissions(const IPCServer::AccessControl::Section& section, const IPCServer::AccessControl::Privilege& privilege);
bool checkIPCPermissions(const IPCServer::AccessControl::Section& section,
const IPCServer::AccessControl::Privilege& privilege);

void processReceiveEvent();

Expand Down
13 changes: 7 additions & 6 deletions src/Library/IPCPrivate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ namespace usbguard
{ 0x04, "usbguard.IPC.DevicePolicyChangedSignal" },
{ 0x05, "usbguard.IPC.PropertyParameterChangedSignal" },
{ 0x06, "usbguard.IPC.listRules" },
{ 0x07, "usbguard.IPC.appendRule" },
{ 0x08, "usbguard.IPC.removeRule" },
{ 0x09, "usbguard.IPC.Exception" },
{ 0x0a, "usbguard.IPC.getParameter" },
{ 0x0b, "usbguard.IPC.setParameter" },
{ 0x0c, "usbguard.IPC.checkIPCPermissions" }
{ 0x07, "usbguard.IPC.insertRule" },
{ 0x08, "usbguard.IPC.appendRule" },
{ 0x09, "usbguard.IPC.removeRule" },
{ 0x0a, "usbguard.IPC.Exception" },
{ 0x0b, "usbguard.IPC.getParameter" },
{ 0x0c, "usbguard.IPC.setParameter" },
{ 0x0d, "usbguard.IPC.checkIPCPermissions" }
};

uint32_t IPC::messageTypeNameToNumber(const std::string& name)
Expand Down
Loading

0 comments on commit 5df1cee

Please sign in to comment.