USBGuard
Software framework that protects your computer against rogue USB devices by implementing basic whitelisting and blacklisting capabilities.
Rule.hpp
1 //
2 // Copyright (C) 2015 Red Hat, Inc.
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // Authors: Daniel Kopecek <dkopecek@redhat.com>
18 // Radovan Sroka <rsroka@redhat.com>
19 //
20 #pragma once
21 
22 #include "RuleCondition.hpp"
23 #include "Exception.hpp"
24 #include "Logger.hpp"
25 #include "Predicates.hpp"
26 #include "Typedefs.hpp"
27 #include "USB.hpp"
28 
29 #include <cstdint>
30 #include <chrono>
31 #include <string>
32 #include <vector>
33 #include <memory>
34 
35 namespace usbguard
36 {
37 
44  template<typename T>
45  std::string toRuleString(T* const value)
46  {
47  return value->toRuleString();
48  }
49 
56  template<typename T>
57  std::string toRuleString(const T& value)
58  {
59  return value.toRuleString();
60  }
61 
68  template<>
69  std::string DLL_PUBLIC toRuleString(const std::string& value);
70 
71  class RulePrivate;
72 
77  class DLL_PUBLIC Rule
78  {
79  public:
86  enum class Target {
87  Allow = 0,
90  Block = 1,
91  Reject = 2,
93  Match = 3,
95  Unknown = 4,
96  Device = 5,
98  Empty = 6,
100  Invalid = 7
101  };
102 
111  static const std::string targetToString(Target target);
112 
120  static Target targetFromString(const std::string& target_string);
121 
128  static uint32_t targetToInteger(Target target);
129 
138  static Target targetFromInteger(uint32_t target_integer);
139 
143  enum class SetOperator {
144  AllOf,
146  OneOf,
148  NoneOf,
150  Equals,
152  EqualsOrdered,
155  Match
157  };
158 
167  static const std::string setOperatorToString(const Rule::SetOperator& op);
168 
177  static SetOperator setOperatorFromString(const std::string& set_operator_string);
178 
182  static const uint32_t RootID;
183 
188  static const uint32_t DefaultID;
189 
194  static const uint32_t LastID;
195 
199  static const uint32_t ImplicitID;
200 
208  template<class ValueType>
209  class Attribute
210  {
211  public:
220  Attribute(const char* name)
221  {
222  _name = name;
223  _set_operator = SetOperator::Equals;
224  }
225 
231  Attribute(const Attribute<ValueType>& rhs) = default;
232 
238  Attribute& operator=(const Attribute<ValueType>& rhs) = default;
239 
246  {
247  _set_operator = op;
248  }
249 
256  {
257  return _set_operator;
258  }
259 
265  void append(ValueType&& value)
266  {
267  _values.emplace_back(std::move(value));
268  }
269 
275  void append(const ValueType& value)
276  {
277  _values.push_back(value);
278  }
279 
285  size_t count() const
286  {
287  return _values.size();
288  }
289 
296  bool empty() const
297  {
298  return count() == 0;
299  }
300 
307  void clear()
308  {
309  _values.clear();
310  _set_operator = SetOperator::Equals;
311  }
312 
318  std::string getName() const
319  {
320  return _name;
321  }
322 
329  const ValueType& get() const
330  {
331  if (count() == 1) {
332  return _values[0];
333  }
334  else if (count() == 0) {
335  throw std::runtime_error("BUG: Accessing an empty attribute");
336  }
337  else {
338  throw std::runtime_error("BUG: Accessing a multivalued attribute using get()");
339  }
340  }
341 
349  const ValueType& get(size_t index) const
350  {
351  return _values.at(index);
352  }
353 
360  void set(ValueType&& value)
361  {
362  if (count() > 1) {
363  throw std::runtime_error("BUG: Setting single value for a multivalued attribute");
364  }
365 
366  if (count() == 0) {
367  append(value);
368  }
369  else {
370  _values[0] = std::move(value);
371  }
372  }
373 
380  void set(const ValueType& value)
381  {
382  if (count() > 1) {
383  throw std::runtime_error("BUG: Setting single value for a multivalued attribute");
384  }
385 
386  if (count() == 0) {
387  append(value);
388  }
389  else {
390  _values[0] = value;
391  }
392  }
393 
400  void set(const std::vector<ValueType>& values, SetOperator op)
401  {
402  _values = values;
403  _set_operator = op;
404  }
405 
417  bool appliesTo(const Attribute<ValueType>& target) const
418  {
419  USBGUARD_LOG(Trace) << "entry:"
420  << " source=" << this->toRuleString()
421  << " target=" << target.toRuleString();
422  bool applies = false;
423 
424  /* Nothing applies to anything */
425  if (empty()) {
426  USBGUARD_LOG(Debug) << "empty source value, setting applies=true";
427  applies = true;
428  }
429  else {
430  USBGUARD_LOG(Debug) << "set_operator=" << setOperatorToString(setOperator());
431 
432  switch (setOperator()) {
433  case SetOperator::Match:
434  applies = true;
435  break;
436 
437  case SetOperator::AllOf:
438  applies = setSolveAllOf(_values, target._values);
439  break;
440 
441  case SetOperator::OneOf:
442  applies = setSolveOneOf(_values, target._values);
443  break;
444 
445  case SetOperator::NoneOf:
446  applies = setSolveNoneOf(_values, target._values);
447  break;
448 
449  case SetOperator::Equals:
450  applies = setSolveEquals(_values, target._values);
451  break;
452 
453  case SetOperator::EqualsOrdered:
454  applies = setSolveEqualsOrdered(_values, target._values);
455  break;
456 
457  default:
458  throw USBGUARD_BUG("Invalid set operator value");
459  }
460  }
461 
462  USBGUARD_LOG(Trace) << "return:"
463  << " applies=" << applies;
464  return applies;
465  }
466 
479  std::string toRuleString() const
480  {
481  std::string result;
482  result.append(_name);
483  result.append(" ");
484  const bool nondefault_op = setOperator() != SetOperator::Equals;
485  const bool multiset_form = count() > 1 || nondefault_op;
486 
487  if (multiset_form) {
488  if (nondefault_op) {
489  result.append(setOperatorToString(setOperator()));
490  result.append(" ");
491  }
492 
493  result.append("{ ");
494  }
495 
496  for (const auto& value : _values) {
497  result.append(usbguard::toRuleString(value));
498  result.append(" ");
499  }
500 
501  if (multiset_form) {
502  result.append("}");
503  }
504  else {
505  /*
506  * Remove the trailing space in case of a single
507  * valued attribute.
508  */
509  result.erase(result.end() - 1);
510  }
511 
512  return result;
513  }
514 
520  const std::vector<ValueType>& values() const
521  {
522  return _values;
523  }
524 
530  std::vector<ValueType>& values()
531  {
532  return _values;
533  }
534 
535  private:
545  bool setSolveAllOf(const std::vector<ValueType>& source_set, const std::vector<ValueType>& target_set) const
546  {
547  USBGUARD_LOG(Trace);
548 
549  for (auto const& source_item : source_set) {
550  bool match = false;
551 
552  for (auto const& target_item : target_set) {
553  if (Predicates::isSubsetOf(source_item, target_item)) {
554  match = true;
555  break;
556  }
557  }
558 
559  if (!match) {
560  return false;
561  }
562  }
563 
564  return true;
565  }
566 
576  bool setSolveOneOf(const std::vector<ValueType>& source_set, const std::vector<ValueType>& target_set) const
577  {
578  USBGUARD_LOG(Trace);
579 
580  for (auto const& source_item : source_set) {
581  for (auto const& target_item : target_set) {
582  if (Predicates::isSubsetOf(source_item, target_item)) {
583  return true;
584  }
585  }
586  }
587 
588  return false;
589  }
590 
600  bool setSolveNoneOf(const std::vector<ValueType>& source_set, const std::vector<ValueType>& target_set) const
601  {
602  USBGUARD_LOG(Trace);
603 
604  for (auto const& source_item : source_set) {
605  for (auto const& target_item : target_set) {
606  if (Predicates::isSubsetOf(source_item, target_item)) {
607  return false;
608  }
609  }
610  }
611 
612  return true;
613  }
614 
625  bool setSolveEquals(const std::vector<ValueType>& source_set, const std::vector<ValueType>& target_set) const
626  {
627  USBGUARD_LOG(Trace);
628 
629  if (source_set.size() != target_set.size()) {
630  return false;
631  }
632  else {
633  for (auto const& source_item : source_set) {
634  bool match = false;
635 
636  for (auto const& target_item : target_set) {
637  if (Predicates::isSubsetOf(source_item, target_item)) {
638  match = true;
639  break;
640  }
641  }
642 
643  if (!match) {
644  return false;
645  }
646  }
647 
648  return true;
649  }
650  }
651 
660  bool setSolveEqualsOrdered(const std::vector<ValueType>& source_set, const std::vector<ValueType>& target_set) const
661  {
662  USBGUARD_LOG(Trace);
663 
664  if (source_set.size() != target_set.size()) {
665  return false;
666  }
667 
668  for (size_t i = 0; i < source_set.size(); ++i) {
669  if (!Predicates::isSubsetOf(source_set[i], target_set[i])) {
670  return false;
671  }
672  }
673 
674  return true;
675  }
676 
677  std::string _name;
678  SetOperator _set_operator;
681  std::vector<ValueType> _values;
682  };
683 
690  Rule();
691 
695  ~Rule();
696 
702  Rule(const Rule& rhs);
703 
710  const Rule& operator=(const Rule& rhs);
711 
717  void setRuleID(uint32_t rule_id);
718 
724  uint32_t getRuleID() const;
725 
734  void setTarget(Rule::Target target);
735 
741  Target getTarget() const;
742 
749  void setDeviceID(const USBDeviceID& value);
750 
757  const USBDeviceID& getDeviceID() const;
758 
764  const Attribute<USBDeviceID>& attributeDeviceID() const;
765 
771  Attribute<USBDeviceID>& attributeDeviceID();
772 
779  void setSerial(const std::string& value);
780 
787  const std::string& getSerial() const;
788 
794  const Attribute<std::string>& attributeSerial() const;
795 
801  Attribute<std::string>& attributeSerial();
802 
814  void setLabel(const std::string& value);
815 
822  const std::string& getLabel() const;
823 
829  const Attribute<std::string>& attributeLabel() const;
830 
836  Attribute<std::string>& attributeLabel();
837 
848  void setWithConnectType(const std::string& value);
849 
856  const std::string& getWithConnectType() const;
857 
863  const Attribute<std::string>& attributeWithConnectType() const;
864 
870  Attribute<std::string>& attributeWithConnectType();
871 
878  void setName(const std::string& value);
879 
886  const std::string& getName() const;
887 
893  const Attribute<std::string>& attributeName() const;
894 
900  Attribute<std::string>& attributeName();
901 
908  void setHash(const std::string& value);
909 
916  const std::string& getHash() const;
917 
923  const Attribute<std::string>& attributeHash() const;
924 
930  Attribute<std::string>& attributeHash();
931 
938  void setParentHash(const std::string& value);
939 
946  const std::string& getParentHash() const;
947 
953  const Rule::Attribute<std::string>& attributeParentHash() const;
954 
960  Rule::Attribute<std::string>& attributeParentHash();
961 
970  void setViaPort(const std::string& value);
971 
978  const std::string& getViaPort() const;
979 
985  const Attribute<std::string>& attributeViaPort() const;
986 
992  Attribute<std::string>& attributeViaPort();
993 
1004  const Attribute<USBInterfaceType>& attributeWithInterface() const;
1005 
1016  Attribute<USBInterfaceType>& attributeWithInterface();
1017 
1023  const Attribute<RuleCondition>& attributeConditions() const;
1024 
1030  Attribute<RuleCondition>& attributeConditions();
1031 
1038  bool appliesTo(std::shared_ptr<const Rule> rhs) const;
1039 
1046  bool appliesTo(const Rule& rhs) const;
1047 
1055  bool appliesTo(const Rule& rhs);
1056 
1062  bool isImplicit() const;
1063 
1071  operator bool() const;
1072 
1083  std::string toString(bool invalid = false, bool hide_serial = false) const;
1084 
1097  void updateMetaDataCounters(bool applied = true, bool evaluated = false);
1098 
1104  std::unique_ptr<RulePrivate>& internal();
1105 
1111  const std::unique_ptr<RulePrivate>& internal() const;
1112 
1113  /*************************************************************************
1114  ***************************** STATIC METHODS ****************************
1115  *************************************************************************/
1116 
1125  static Rule fromString(const std::string& rule_string);
1126 
1127  private:
1128  std::unique_ptr<RulePrivate> d_pointer;
1129  };
1130 } /* namespace usbguard */
1131 
1132 /* vim: set ts=2 sw=2 et */
Target
Enumeration of possible rule targets.
Definition: Rule.hpp:86
std::vector< ValueType > & values()
Returns mutable vector of attribute values.
Definition: Rule.hpp:530
static const uint32_t ImplicitID
Sequence number of the implicit target rule.
Definition: Rule.hpp:199
static const uint32_t RootID
Sequence number of the (fake) root rule.
Definition: Rule.hpp:182
Represents USB device in USBGuard.
Definition: Device.hpp:41
const ValueType & get(size_t index) const
Returns value at given index in values vector.
Definition: Rule.hpp:349
size_t count() const
Returns number of values of this attribute.
Definition: Rule.hpp:285
const ValueType & get() const
Returns value of single-value attribute.
Definition: Rule.hpp:329
void set(ValueType &&value)
Sets value in single-value attribute using move semantics.
Definition: Rule.hpp:360
SetOperator
Defines set operators that can be used in the rules.
Definition: Rule.hpp:143
void append(ValueType &&value)
Appends new value into attribute values using move semantics.
Definition: Rule.hpp:265
static const uint32_t DefaultID
Sequence number assigned to default constructed rules. Cannot be used for searching.
Definition: Rule.hpp:188
Specifies which devices to match or what condition have to be met for the rule to be aplicable.
Definition: Rule.hpp:209
void set(const ValueType &value)
Sets value in single-value attribute.
Definition: Rule.hpp:380
std::string getName() const
Returns name of the attribute.
Definition: Rule.hpp:318
std::string toRuleString() const
Returns string representation of this attribute.
Definition: Rule.hpp:479
void append(const ValueType &value)
Appends new value into attribute values.
Definition: Rule.hpp:275
Attribute(const char *name)
Constructs new rule attribute with a given name and default set operator.
Definition: Rule.hpp:220
Determines whether USB device mathing specified criteria should be authorized, deauthorized or remove...
Definition: Rule.hpp:77
static const uint32_t LastID
Sequence number for specifying that the last rule in the ruleset should be used in context of the ope...
Definition: Rule.hpp:194
void setSetOperator(SetOperator op)
Sets set operator.
Definition: Rule.hpp:245
SetOperator setOperator() const
Returns set operator of this attribute.
Definition: Rule.hpp:255
bool empty() const
Checks whether attribute does not contain any values.
Definition: Rule.hpp:296
void clear()
Clears all values of this attribute and sets set operator to default.
Definition: Rule.hpp:307
const std::vector< ValueType > & values() const
Returns imutable vector of attribute values.
Definition: Rule.hpp:520
bool appliesTo(const Attribute< ValueType > &target) const
Checks whether attribute applies to target attribute.
Definition: Rule.hpp:417
void set(const std::vector< ValueType > &values, SetOperator op)
Sets given values and set operator.
Definition: Rule.hpp:400