USBGuard
Software framework that protects your computer against rogue USB devices by implementing basic whitelisting and blacklisting capabilities.
USB.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 //
19 #pragma once
20 
21 #include "Predicates.hpp"
22 #include "Typedefs.hpp"
23 
24 #include <functional>
25 #include <string>
26 #include <unordered_map>
27 #include <utility>
28 #include <vector>
29 
30 #include <climits>
31 #include <cstddef>
32 #include <cstdint>
33 
34 namespace usbguard
35 {
44  const size_t USB_GENERIC_STRING_MAX_LENGTH = UINT8_MAX - 2;
45 
49  const size_t USB_VID_STRING_MAX_LENGTH = 4;
50 
54  const size_t USB_PID_STRING_MAX_LENGTH = 4;
55 
59  const size_t USB_PORT_STRING_MAX_LENGTH = PATH_MAX;
60 
61  /*
62  * NOTE: The USB specification dictates that all multibyte data fields
63  * are in little-endian form. The structures defined bellow are
64  * used for platform-independed passing of the USB descriptor
65  * data to the Device class. The Device class assumes that the
66  * values are in host-specific endianness.
67  */
68  const uint8_t USB_DESCRIPTOR_TYPE_UNKNOWN = 0x00;
69  const uint8_t USB_DESCRIPTOR_TYPE_DEVICE = 0x01;
70  const uint8_t USB_DESCRIPTOR_TYPE_CONFIGURATION = 0x02;
71  const uint8_t USB_DESCRIPTOR_TYPE_STRING = 0x03;
72  const uint8_t USB_DESCRIPTOR_TYPE_INTERFACE = 0x04;
73  const uint8_t USB_DESCRIPTOR_TYPE_ENDPOINT = 0x05;
74  const uint8_t USB_DESCRIPTOR_TYPE_ASSOCIATION_INTERFACE = 0x0b;
75 
76  enum class USBDescriptorType : uint8_t {
77  Unknown = USB_DESCRIPTOR_TYPE_UNKNOWN,
78  Device = USB_DESCRIPTOR_TYPE_DEVICE,
79  Configuration = USB_DESCRIPTOR_TYPE_CONFIGURATION,
80  String = USB_DESCRIPTOR_TYPE_STRING,
81  Interface = USB_DESCRIPTOR_TYPE_INTERFACE,
82  Endpoint = USB_DESCRIPTOR_TYPE_ENDPOINT,
83  AssociationInterface = USB_DESCRIPTOR_TYPE_ASSOCIATION_INTERFACE
84  };
85 
86  struct DLL_PUBLIC USBDescriptorHeader {
87  uint8_t bLength;
88  uint8_t bDescriptorType;
89  } __attribute__((packed));
90 
91  struct DLL_PUBLIC USBDescriptor {
92  struct USBDescriptorHeader bHeader;
93  uint8_t bDescriptorData[256-sizeof(USBDescriptorHeader)];
94  } __attribute__((packed));
95 
96  struct DLL_PUBLIC USBDeviceDescriptor {
97  struct USBDescriptorHeader bHeader;
98  uint16_t bcdUSB;
99  uint8_t bDeviceClass;
100  uint8_t bDeviceSubClass;
101  uint8_t bDeviceProtocol;
102  uint8_t bMaxPacketSize;
103  uint16_t idVendor;
104  uint16_t idProduct;
105  uint16_t bcdDevice;
106  uint8_t iManufacturer;
107  uint8_t iProduct;
108  uint8_t iSerialNumber;
109  uint8_t bNumConfigurations;
110  } __attribute__((packed));
111 
112  struct DLL_PUBLIC USBConfigurationDescriptor {
113  struct USBDescriptorHeader bHeader;
114  uint16_t wTotalLength;
115  uint8_t bNumInterfaces;
116  uint8_t bConfigurationValue;
117  uint8_t iConfiguration;
118  uint8_t bmAttributes;
119  uint8_t bMaxPower;
120  } __attribute__((packed));
121 
122  struct DLL_PUBLIC USBInterfaceDescriptor {
123  struct USBDescriptorHeader bHeader;
124  uint8_t bInterfaceNumber;
125  uint8_t bAlternateSetting;
126  uint8_t bNumEndpoints;
127  uint8_t bInterfaceClass;
128  uint8_t bInterfaceSubClass;
129  uint8_t bInterfaceProtocol;
130  uint8_t iInterface;
131  } __attribute__((packed));
132 
134  struct USBDescriptorHeader bHeader;
135  uint8_t bEndpointAddress;
136  uint8_t bmAttributes;
137  uint16_t wMaxPacketSize;
138  uint8_t bInterval;
139  } __attribute__((packed));
140 
142  struct USBDescriptorHeader bHeader;
143  uint8_t bEndpointAddress;
144  uint8_t bmAttributes;
145  uint16_t wMaxPacketSize;
146  uint8_t bInterval;
147  uint8_t bRefresh;
148  uint8_t bSynchAddress;
149  } __attribute__((packed));
150 
158  class DLL_PUBLIC USBDeviceID
159  {
160  public:
164  USBDeviceID() = default;
165 
175  USBDeviceID(const std::string& vendor_id, const std::string& product_id = std::string());
176 
182  USBDeviceID(const USBDeviceID& rhs) = default;
183 
190  USBDeviceID& operator=(const USBDeviceID& rhs) = default;
191 
203  static void checkDeviceID(const std::string& vendor_id, const std::string& product_id);
204 
215  void setVendorID(const std::string& vendor_id);
216 
227  void setProductID(const std::string& product_id);
228 
234  const std::string& getVendorID() const;
235 
241  const std::string& getProductID() const;
242 
250  std::string toRuleString() const;
251 
257  std::string toString() const;
258 
268  bool isSubsetOf(const USBDeviceID& rhs) const;
269 
270  private:
271  std::string _vendor_id;
272  std::string _product_id;
273  };
274 
275  namespace Predicates DLL_PUBLIC
276  {
287  template<>
288  bool isSubsetOf(const USBDeviceID& source, const USBDeviceID& target);
289  }
290 
299  class DLL_PUBLIC USBInterfaceType
300  {
301  public:
302  static const uint8_t MatchClass = 1<<0;
303  static const uint8_t MatchSubClass = 1<<1;
304  static const uint8_t MatchProtocol = 1<<2;
305  static const uint8_t MatchAll = MatchClass|MatchSubClass|MatchProtocol;
306 
311 
323  USBInterfaceType(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask = MatchAll);
324 
334  USBInterfaceType(const USBInterfaceDescriptor& descriptor, uint8_t mask = MatchAll);
335 
341  USBInterfaceType(const std::string& type_string);
342 
352  bool operator==(const USBInterfaceType& rhs) const;
353 
361  bool appliesTo(const USBInterfaceType& rhs) const;
362 
371  const std::string typeString() const;
372 
380  const std::string toRuleString() const;
381 
394  static const std::string typeString(uint8_t bClass, uint8_t bSubClass, uint8_t bProtocol, uint8_t mask = MatchAll);
395 
396  private:
397  uint8_t _bClass;
398  uint8_t _bSubClass;
399  uint8_t _bProtocol;
400  uint8_t _mask;
403  };
404 
405  namespace Predicates DLL_PUBLIC
406  {
416  template<>
417  bool isSubsetOf(const USBInterfaceType& source, const USBInterfaceType& target);
418  }
419 
420  class USBDescriptorParser;
421 
422  class DLL_PUBLIC USBDescriptorParserHooks
423  {
424  public:
425  virtual void parseUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_in, USBDescriptor* descriptor_out);
426  virtual void loadUSBDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor);
427  };
428 
432  class DLL_PUBLIC USBDescriptorParser
433  {
434  public:
436 
443  size_t parse(std::istream& stream);
444 
455  const std::vector<USBDescriptor>* getDescriptor(uint8_t bDescriptorType) const;
456 
464  void setDescriptor(uint8_t bDescriptorType, const USBDescriptor& descriptor);
465 
472  void delDescriptor(uint8_t bDescriptorType);
473 
483  bool haveDescriptor(uint8_t bDescriptorType) const;
484 
490  const std::vector<std::pair<uint8_t, size_t>> getDescriptorCounts() const;
491 
492  private:
493  USBDescriptorParserHooks& _hooks;
494 
495  std::unordered_map<uint8_t, std::vector<USBDescriptor>> _dstate_map;
496  std::unordered_map<uint8_t, size_t> _count_map;
497  };
498 
499  void DLL_PUBLIC USBParseDeviceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw,
500  USBDescriptor* descriptor_out);
501  void DLL_PUBLIC USBParseConfigurationDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw,
502  USBDescriptor* descriptor_out);
503  void DLL_PUBLIC USBParseInterfaceDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw,
504  USBDescriptor* descriptor_out);
505  void DLL_PUBLIC USBParseEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw,
506  USBDescriptor* descriptor_out);
507  void DLL_PUBLIC USBParseAudioEndpointDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw,
508  USBDescriptor* descriptor_out);
509  void DLL_PUBLIC USBParseUnknownDescriptor(USBDescriptorParser* parser, const USBDescriptor* descriptor_raw,
510  USBDescriptor* descriptor_out);
511 
512 } /* namespace usbguard */
513 
514 /* vim: set ts=2 sw=2 et */
Definition: USB.hpp:122
Definition: USB.hpp:96
Definition: USB.hpp:133
Represents USB interface.
Definition: USB.hpp:299
Parses USB descriptors.
Definition: USB.hpp:432
Represents ID of a USB device.
Definition: USB.hpp:158
Definition: USB.hpp:91
Definition: USB.hpp:422
Definition: USB.hpp:86