123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- #!/usr/bin/env python
- from enum import Enum
- import subprocess
- import shlex
- class DeviceMode(Enum):
- BLOCK = 0
- ALLOW = 1
- def __str__(self):
- match self:
- case DeviceMode.ALLOW:
- return 'Allow'
- case DeviceMode.BLOCK:
- return 'Block'
- class Device:
- def __init__(self, mode, id, name, hash):
- self.mode = mode
- self.id = id
- self.name = name
- self.hash = hash
- def from_output_line(line):
- tokens = shlex.split(line, False, True)
- mode = DeviceMode.BLOCK
- id = None
- name = None
- hash = None
- for i, token in enumerate(tokens):
- if i == len(tokens) - 1:
- next = None
- else:
- next = tokens[i + 1]
- match token:
- case 'allow':
- mode = DeviceMode.ALLOW
- case 'id':
- id = next
- case 'name':
- name = next
- case 'hash':
- hash = next
- return Device(mode, id, name, hash)
- def __str__(self):
- match self.mode:
- case DeviceMode.ALLOW:
- mode = "Allowed"
- case _:
- mode = "Blocked"
- if len(self.name) == 0:
- name = "<no name>"
- else:
- name = self.name
- return f'{self.id}: {name} ({mode}, Hash: {self.hash})'
- def run_fuzzel(entries, prompt=None):
- cmd = ["fuzzel", "-d", "--index"]
- if prompt is not None:
- cmd.append(f'--prompt={prompt}')
- proc = subprocess.run(cmd,
- input='\n'.join(str(e) for e in entries),
- capture_output=True,
- text=True,
- shell=False)
- if proc.returncode != 0:
- return (-1, None)
- index = int(proc.stdout)
- return (index, entries[index])
- def get_implicit_policy_target():
- proc = subprocess.run(['usbguard',
- 'get-parameter',
- 'ImplicitPolicyTarget'],
- capture_output=True,
- text=True,
- check=True)
- match proc.stdout:
- case 'allow\n':
- return DeviceMode.ALLOW
- case 'block\n':
- return DeviceMode.BLOCK
- def set_implicit_policy_target(target):
- match target:
- case DeviceMode.ALLOW:
- mode = 'allow'
- case DeviceMode.BLOCK:
- mode = 'block'
- subprocess.run(['usbguard',
- 'set-parameter',
- 'ImplicitPolicyTarget',
- mode],
- check=True)
- def update_default_action():
- (index, _) = run_fuzzel(['Allow', 'Block'],
- 'Default action > ')
- match index:
- case 0:
- set_implicit_policy_target(DeviceMode.ALLOW)
- case 1:
- set_implicit_policy_target(DeviceMode.BLOCK)
- def update_device_mode(device):
- (_, action) = run_fuzzel(['Allow', 'Block', 'Reject'],
- device.name + ' > ')
- if action is None:
- exit()
- match action:
- case 'Allow':
- subprocess.check_output(['usbguard',
- 'allow-device',
- device.id], shell=False)
- case 'Reject':
- subprocess.check_output(['usbguard',
- 'reject-device',
- device.id], shell=False)
- case _:
- subprocess.check_output(['usbguard',
- 'block-device',
- device.id], shell=False)
- def main():
- devices = []
- proc = subprocess.run(["usbguard", "list-devices"],
- capture_output=True, text=True, check=True)
- for line in proc.stdout.splitlines():
- devices.append(Device.from_output_line(line))
- devices.append(f'Set default action (Current: {get_implicit_policy_target()})')
- (index, device) = run_fuzzel(devices)
- if index == len(devices) - 1:
- update_default_action()
- elif index != -1:
- update_device_mode(device)
- main()
|