diff --git a/SOURCES/match-all.patch b/SOURCES/match-all.patch
new file mode 100644
index 0000000..f2c9c28
--- /dev/null
+++ b/SOURCES/match-all.patch
@@ -0,0 +1,242 @@
+diff --git a/doc/man/usbguard-rules.conf.5.adoc b/doc/man/usbguard-rules.conf.5.adoc
+index 44f399c..c0f86f8 100644
+--- a/doc/man/usbguard-rules.conf.5.adoc
++++ b/doc/man/usbguard-rules.conf.5.adoc
+@@ -93,6 +93,9 @@ where the optional 'operator' is one of:
+ *equals-ordered*::
+ The device attribute set must contain exactly the same set of values in the same order for the rule to match.
+
++*match-all*::
++ The device attribute set must be a subset of the specified values for the rule to match.
++
+ If the operator is not specified it is set to *equals*.
+
+ [.underline]#List of attributes:#
+diff --git a/src/Library/RuleParser/Grammar.hpp b/src/Library/RuleParser/Grammar.hpp
+index 4d785c0..764380e 100644
+--- a/src/Library/RuleParser/Grammar.hpp
++++ b/src/Library/RuleParser/Grammar.hpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #pragma once
+ #ifdef HAVE_BUILD_CONFIG_H
+@@ -53,12 +54,13 @@ namespace usbguard
+ struct str_none_of : TAOCPP_PEGTL_STRING("none-of") {};
+ struct str_equals : TAOCPP_PEGTL_STRING("equals") {};
+ struct str_equals_ordered : TAOCPP_PEGTL_STRING("equals-ordered") {};
++ struct str_match_all: TAOCPP_PEGTL_STRING("match-all") {};
+
+ /*
+ * Generic rule attribute
+ */
+ struct multiset_operator
+- : sor {};
++ : sor {};
+
+ template
+ struct attribute_value_multiset
+diff --git a/src/Library/RulePrivate.cpp b/src/Library/RulePrivate.cpp
+index 73140fa..6ceb12d 100644
+--- a/src/Library/RulePrivate.cpp
++++ b/src/Library/RulePrivate.cpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #ifdef HAVE_BUILD_CONFIG_H
+ #include
+@@ -177,6 +178,7 @@ namespace usbguard
+ case Rule::SetOperator::AllOf:
+ case Rule::SetOperator::Equals:
+ case Rule::SetOperator::EqualsOrdered:
++ case Rule::SetOperator::MatchAll:
+ meets_conditions = \
+ (conditionsState() == ((((uint64_t)1) << _conditions.count()) - 1));
+ break;
+diff --git a/src/Library/public/usbguard/Predicates.hpp b/src/Library/public/usbguard/Predicates.hpp
+index 412517e..95ede3a 100644
+--- a/src/Library/public/usbguard/Predicates.hpp
++++ b/src/Library/public/usbguard/Predicates.hpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #pragma once
+
+@@ -35,6 +36,15 @@ namespace usbguard
+ USBGUARD_LOG(Trace) << "generic isSubsetOf";
+ return source == target;
+ }
++
++ template
++ bool isSupersetOf(const T& source, const T& target)
++ {
++ USBGUARD_LOG(Error) << "Not implemented";
++ (void) source;
++ (void) target;
++ return true;
++ }
+ }
+ } /* namespace usbguard */
+
+diff --git a/src/Library/public/usbguard/Rule.cpp b/src/Library/public/usbguard/Rule.cpp
+index f7bb35a..fa97578 100644
+--- a/src/Library/public/usbguard/Rule.cpp
++++ b/src/Library/public/usbguard/Rule.cpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #ifdef HAVE_BUILD_CONFIG_H
+ #include
+@@ -325,7 +326,8 @@ namespace usbguard
+ { "none-of", Rule::SetOperator::NoneOf },
+ { "equals", Rule::SetOperator::Equals },
+ { "equals-ordered", Rule::SetOperator::EqualsOrdered },
+- { "match", Rule::SetOperator::Match }
++ { "match", Rule::SetOperator::Match },
++ { "match-all", Rule::SetOperator::MatchAll}
+ };
+
+ const std::string Rule::setOperatorToString(const Rule::SetOperator& op)
+diff --git a/src/Library/public/usbguard/Rule.hpp b/src/Library/public/usbguard/Rule.hpp
+index 0ebfdaf..67a67f0 100644
+--- a/src/Library/public/usbguard/Rule.hpp
++++ b/src/Library/public/usbguard/Rule.hpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #pragma once
+
+@@ -77,7 +78,8 @@ namespace usbguard
+ NoneOf,
+ Equals,
+ EqualsOrdered,
+- Match /* Special operator: matches anything, cannot be used directly in a rule */
++ Match, /* Special operator: matches anything, cannot be used directly in a rule */
++ MatchAll
+ };
+
+ static const std::string setOperatorToString(const Rule::SetOperator& op);
+@@ -237,6 +239,10 @@ namespace usbguard
+ applies = setSolveEqualsOrdered(_values, target._values);
+ break;
+
++ case SetOperator::MatchAll:
++ applies = setSolveMatchAll(_values, target._values);
++ break;
++
+ default:
+ throw USBGUARD_BUG("Invalid set operator value");
+ }
+@@ -409,6 +415,26 @@ namespace usbguard
+ return false;
+ }
+
++ /*
++ * All of the items in target set must match an item in the source set
++ */
++ bool setSolveMatchAll(const std::vector& source_set, const std::vector& target_set) const
++ {
++ USBGUARD_LOG(Trace);
++ size_t match = 0;
++
++ for (auto const& target_item : target_set) {
++ for (auto const& source_item : source_set) {
++ if (Predicates::isSupersetOf(source_item, target_item)) {
++ match++;
++ break;
++ }
++ }
++ }
++
++ return match == target_set.size();
++ }
++
+ std::string _name;
+ SetOperator _set_operator;
+ std::vector _values;
+diff --git a/src/Library/public/usbguard/USB.cpp b/src/Library/public/usbguard/USB.cpp
+index 281d1c9..54e5fb8 100644
+--- a/src/Library/public/usbguard/USB.cpp
++++ b/src/Library/public/usbguard/USB.cpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #ifdef HAVE_BUILD_CONFIG_H
+ #include
+@@ -125,6 +126,15 @@ namespace usbguard
+ return result;
+ }
+
++ template<>
++ bool Predicates::isSupersetOf(const USBDeviceID& source, const USBDeviceID& target)
++ {
++ USBGUARD_LOG(Trace) << "source=" << source.toString() << " target=" << target.toString();
++ const bool result = target.isSubsetOf(source);
++ USBGUARD_LOG(Trace) << "result=" << result;
++ return result;
++ }
++
+ USBInterfaceType::USBInterfaceType()
+ {
+ _bClass = 0;
+@@ -234,6 +244,12 @@ namespace usbguard
+ return source.appliesTo(target);
+ }
+
++ template<>
++ bool Predicates::isSupersetOf(const USBInterfaceType& source, const USBInterfaceType& target)
++ {
++ return source.appliesTo(target);
++ }
++
+ const std::string USBInterfaceType::typeString() const
+ {
+ return USBInterfaceType::typeString(_bClass, _bSubClass, _bProtocol, _mask);
+diff --git a/src/Library/public/usbguard/USB.hpp b/src/Library/public/usbguard/USB.hpp
+index 914d74b..f538aac 100644
+--- a/src/Library/public/usbguard/USB.hpp
++++ b/src/Library/public/usbguard/USB.hpp
+@@ -15,6 +15,7 @@
+ // along with this program. If not, see .
+ //
+ // Authors: Daniel Kopecek
++// Marek Tamaskovic
+ //
+ #pragma once
+
+@@ -169,6 +170,8 @@ namespace usbguard
+ {
+ template<>
+ bool isSubsetOf(const USBDeviceID& source, const USBDeviceID& target);
++ template<>
++ bool isSupersetOf(const USBDeviceID& source, const USBDeviceID& target);
+ }
+
+ class DLL_PUBLIC USBInterfaceType
+@@ -202,6 +205,8 @@ namespace usbguard
+ {
+ template<>
+ bool isSubsetOf(const USBInterfaceType& source, const USBInterfaceType& target);
++ template<>
++ bool isSupersetOf(const USBInterfaceType& source, const USBInterfaceType& target);
+ }
+
+ class USBDescriptorParser;
diff --git a/SPECS/usbguard.spec b/SPECS/usbguard.spec
index d03ece5..138381f 100644
--- a/SPECS/usbguard.spec
+++ b/SPECS/usbguard.spec
@@ -3,9 +3,11 @@
%define with_gui_qt5 0
%define with_dbus 1
+%bcond_without check
+
Name: usbguard
Version: 0.7.4
-Release: 2%{?dist}
+Release: 4%{?dist}
Summary: A tool for implementing USB device usage policy
Group: System Environment/Daemons
License: GPLv2+
@@ -49,6 +51,7 @@ BuildRequires: libxml2
%endif
Patch0: usbguard-0.7.4-loadFilesError.patch
+Patch1: match-all.patch
%description
The USBGuard software framework helps to protect your computer against rogue USB
@@ -107,6 +110,7 @@ a D-Bus interface to the USBGuard daemon component.
%prep
%setup -q
%patch0 -p1 -b .loadFilesError
+%patch1 -p1 -b .matchallkeyword
# Remove bundled library sources before build
rm -rf src/ThirdParty/{Catch,PEGTL}
@@ -133,8 +137,10 @@ autoreconf -i -v --no-recursive ./
make %{?_smp_mflags}
+%if %{with check}
%check
make check
+%endif
%install
make install INSTALL='install -p' DESTDIR=%{buildroot}
@@ -221,6 +227,12 @@ find %{buildroot} \( -name '*.la' -o -name '*.a' \) -exec rm -f {} ';'
%endif
%changelog
+* Mon Nov 25 2019 Marek Tamaskovic - 0.7.4-4
+- add match-all keyword
+
+* Tue May 21 2019 Daniel Kopeček - 0.7.4-3
+- spec: make the check phase conditional
+
* Fri Dec 14 2018 Jiri Vymazal - 0.7.4-2
Resolves: rhbz#1643057 - usbguard fails to report invalid value in IPCAccessControlFiles directive