usbauth: USB firewall against BadUSB attacks

It is a firewall against BadUSB attacks. A config file describes in which way USB interfaces would be accepted or denied.
To the kernel an interface authorization was developed with this firewall.
The firewall sets the authorization mask according to the rules.

udev mode, called by udev
usbauth udev-add

manual mode, called by notifier
usbauth allow DEVNUM PATH
usbauth deny DEVNUM PATH
PATH: path of USB interface, example /sys/bus/usb/devices/3-2/3-2:1.0/
DEVNUM: value of attribute, example 16 (from /sys/bus/usb/devices/3-2/devnum)

init mode, does apply rules for all available devices
usbauth init

Rules
----------

Attribute
[parameter operator value]
An attribute consists of a parameter, an operator and a value.


The allow/deny rule
allow|deny Attribute+
A allow/deny rule have at minimum one attribute.
That a allow/deny rule will enforced an USB interface must match all attributes

Example:
A rule describes all interfaces with the HID class 0x03.

The condition
condition Attribute+ case Attribute+

The first section describes the condition that must fullfilled. The second section with the keyword case defines for what interfaces the condition should apply.

Example:
All rules that describes HID interfaces should apply for two devices at maximum.
Then the device counter must be fullfilled. The second section describes the interface class 0x03.

There are default rules
allow|deny all

These rules for the generic case. If no other rule matches an interface.


Rules will checked top down. A rule at top could be overwritten by a rule at down.


Parameters
----------
The following parameters are defined at device section
busnum: number of the USB bus
devpath: nummer of the USB port
idVendor: vendor ID, defines the vendor of the USB device
idProduct: product ID, defines the product from a vendor
bDeviceClass: USB device class
bDeviceSubClass: USB device sub class
bDeviceProtocol: USB device protocol
bConfigurationValue: current USB configuration
serial: serial number of the device
manufacturer: manufacturer of device
product: product name string
connect_type: hotplug: external USB device, direct: internal USB device
bcdDevice: USB protocol version
speed: USB speed value
bNumConfigurations: the number of available USB configurations
bNumInterfaces: Number of available interfaces in active configuration

The following parameters are defined at configuration section
bInterfaceNumber: interface number
bInterfaceClass: interface class
bInterfaceSubClass: current sub class of interface
bInterfaceProtocol: In case of HID devices with this value keyboards (1) and mouses (2) could be distinct
bNumEndpoints: number of endpoints for the interface

The following parameters are specific and calculated internally by the firewall. They are not available in the SysFS.
They count how much devices or interfaces matches an rule

intfcount: Number of interfaces for an rule
devcount: Number of devices for an rule

The keyword anyChild could be used for a parameter to check not only the own interfaces attribute, also check the silbings attribute. If one silbing mathes the rule is valid.


Operators
----------
The following operators are defined: ==, !=, <=, >=, <, >

With operators two values are compared. One frome the data structure of a rule the other from an USB interface


Values
----------
The configured value will be compared with the default value type from sysfs.
If not specified the type of the configured value is assumed to be in sysfs value type.
Using \x as value prefix will set the configured value type as hexadecimal.
Using \d as value prefix will set the configured value type as decimal.
With an explicit integer value a type conversion will be done if the value type does not match the sysfs value type.
Using double quotes for the configured value foces a string comparisation. It allows to specify strings containing spaces, too.
Point separated integer values like 1.2.3 (e.g. for devpath) are possible, they allow also explicit type prefixing like \x1.2.3

Exampels
----------
Default rule to allow everything:
allow all

Default rule to deny everything:
deny all

Every configuration file should allow hubs, only special cases should limit these:
allow bDeviceClass==09 bInterfaceClass==09

Interfaces with device class 0 and interface class 08 (storage) will accepted:
allow bDeviceClass==00 bInterfaceClass==08

Interfaces interface class 08 (storage) will accepted:
allow bInterfaceClass==08

-> the device class is irrelevant in this case

Two USB storage devices will accepted at specific USB ports. Not more then one storage device is allowed during a condition:
allow idVendor==0781 idProduct==5406 bInterfaceClass==08 busnum==3 devpath==6
allow idVendor==8564 idProduct==1000 bInterfaceClass==08 busnum==3 devpath==4
condition devcount<=1 case bInterfaceClass==08

-> the condition is valid for all interfaces from class 08. Interfaces must comply with the condition for enforcing the two belonging allow rules.

Allow two HID (example keyboard and mouse) devices at maximum
allow bInterfaceClass==03 devcount<=2

Allow only one Keyboard:
allow bInterfaceClass==03 bInterfaceProtocol==01 devcount<=1

Allow only one Mouse:
allow bInterfaceClass==03 anyChild bInterfaceProtocol==02 devcount<=1

→ The parent device childs of the interface would enumerated to check for the attribute. If one matches the attribute then the rule will enforced.
A keyboard should have two interfaces. The bInterfaceProtocol of the first interface is "1", from the second "0".
With anyChild it is possible to allow a rule matching for both interfaces.

Allow only certain interfaces:
Example: A multi function device have three interfaces (0xFF, 0x07, 0x08).
0xFF is to scan, 0x07 is to print, and 0x08 is for storage devices connected to the multi function device.

With the following rules only the 0xFF and 0x07 interfaces are allowed. The device class must be 0.

allow idVendor==04b8 idProduct==089e bDeviceClass==00 bInterfaceClass==ff

allow idVendor==04b8 idProduct==089e bDeviceClass==00 bInterfaceClass==07

