96 lines
3.1 KiB
Bash
Executable File
96 lines
3.1 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# omarchy:hidden=true
|
|
# omarchy:summary=Create an approval request for a blocked USB device
|
|
|
|
set -euo pipefail
|
|
|
|
case "${USBGUARD_IPC_SIGNAL:-}" in
|
|
IPC.Connected)
|
|
# USBGuard scans present devices before accepting IPC connections. Repeat
|
|
# this on every reconnect: temporary approvals disappear on daemon restart.
|
|
blocked=$(usbguard list-devices --blocked) || exit 1
|
|
while IFS= read -r line; do
|
|
if [[ $line =~ ^([0-9]+):[[:space:]](block.*)$ ]]; then
|
|
USBGUARD_IPC_SIGNAL=Device.PolicyApplied \
|
|
USBGUARD_DEVICE_ID="${BASH_REMATCH[1]}" \
|
|
USBGUARD_DEVICE_TARGET_NEW=block \
|
|
USBGUARD_DEVICE_RULE="${BASH_REMATCH[2]}" \
|
|
"$OMARCHY_PATH/bin/omarchy-usb-authorization-event" || true
|
|
fi
|
|
done <<<"$blocked"
|
|
exit 0
|
|
;;
|
|
Device.PolicyApplied)
|
|
# PresenceChanged precedes policy evaluation, even for trusted devices.
|
|
# PolicyApplied also covers block-to-block and allow-to-block transitions.
|
|
[[ ${USBGUARD_DEVICE_TARGET_NEW:-} == "block" ]] || exit 0
|
|
;;
|
|
*) exit 0 ;;
|
|
esac
|
|
|
|
[[ ${USBGUARD_DEVICE_ID:-} =~ ^[0-9]+$ ]] || exit 0
|
|
[[ -n ${USBGUARD_DEVICE_RULE:-} ]] || exit 0
|
|
|
|
requests="$HOME/.local/state/omarchy/usb-authorization/requests"
|
|
mkdir -p "$requests"
|
|
chmod 700 "${requests%/*}" "$requests"
|
|
|
|
# The token is safe to carry through the presentation launcher's command
|
|
# string. The device-controlled rule itself stays in a mode-0600 JSON file and
|
|
# is never interpolated into a shell command.
|
|
token="request-$(printf '%s\0%s' "$USBGUARD_DEVICE_ID" "$USBGUARD_DEVICE_RULE" | sha256sum | cut -d' ' -f1)"
|
|
request="$requests/$token.json"
|
|
# watch executes handlers concurrently. A reconnect scan and a policy event
|
|
# can refer to the same device; publish only one pending request.
|
|
exec 9>"$requests/.lock"
|
|
# Keep retrying without needing another USB event. Handlers belong to the
|
|
# watcher service and are stopped with the graphical session.
|
|
while true; do
|
|
flock 9
|
|
[[ ! -e $request ]] || exit 0
|
|
|
|
# Discard events overtaken by another policy decision or device replacement.
|
|
blocked=$(usbguard list-devices --blocked) || exit 1
|
|
current=0
|
|
while IFS= read -r line; do
|
|
if [[ $line == "$USBGUARD_DEVICE_ID: $USBGUARD_DEVICE_RULE" ]]; then
|
|
current=1
|
|
break
|
|
fi
|
|
done <<<"$blocked"
|
|
(( current )) || exit 0
|
|
|
|
# Login and shell restarts can leave D-Bus alive before notifications are ready.
|
|
# Bound each wait so disappeared devices are rechecked between attempts.
|
|
if ! omarchy-notification-wait 1; then
|
|
flock -u 9
|
|
sleep 1
|
|
continue
|
|
fi
|
|
|
|
temporary=$(mktemp "$requests/.request.XXXXXXXXXX")
|
|
trap 'rm -f "$temporary"' EXIT
|
|
|
|
jq -n \
|
|
--arg id "$USBGUARD_DEVICE_ID" \
|
|
--arg rule "$USBGUARD_DEVICE_RULE" \
|
|
'{id: $id, rule: $rule}' >"$temporary"
|
|
chmod 600 "$temporary"
|
|
mv -f "$temporary" "$request"
|
|
|
|
if omarchy-notification-send \
|
|
--app-name omarchy-action \
|
|
--urgency critical \
|
|
--glyph \
|
|
"USB accessory blocked" \
|
|
"Click to review it. Keep it blocked unless you recognize the device." \
|
|
--exec omarchy-launch-floating-terminal-with-presentation \
|
|
omarchy-usb-authorization-review "$token"; then
|
|
exit 0
|
|
fi
|
|
rm -f "$request"
|
|
flock -u 9
|
|
sleep 1
|
|
done
|