From 08bec486b5b004b64ec2748dc47fe37e9cbfb7f1 Mon Sep 17 00:00:00 2001 From: Fabio Scotto di Santolo Date: Tue, 14 Apr 2026 14:46:20 +0200 Subject: [PATCH] Store udiskie passwords in GNOME Keyring --- ansible/inventory/group_vars/desktop.yml | 8 ++ dotfiles/desktop/.config/hypr/hyprland.conf | 2 +- dotfiles/desktop/.config/i3/config | 2 +- dotfiles/desktop/.config/sway/config | 2 +- dotfiles/desktop/.config/udiskie/config.yml | 13 +++ dotfiles/desktop/.local/bin/udiskie-password | 89 ++++++++++++++++++++ 6 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 dotfiles/desktop/.config/udiskie/config.yml create mode 100755 dotfiles/desktop/.local/bin/udiskie-password diff --git a/ansible/inventory/group_vars/desktop.yml b/ansible/inventory/group_vars/desktop.yml index e80923f..e40ed45 100644 --- a/ansible/inventory/group_vars/desktop.yml +++ b/ansible/inventory/group_vars/desktop.yml @@ -170,6 +170,10 @@ desktop_common_dotfiles: src: .config/opencode/ dest: .config/opencode/ mode: preserve + - name: Udiskie config + src: .config/udiskie/ + dest: .config/udiskie/ + mode: preserve - name: Codex config src: .codex/ dest: .codex/ @@ -218,6 +222,10 @@ desktop_common_dotfiles: src: .local/bin/update-turnstile-env dest: .local/bin/update-turnstile-env mode: "0755" + - name: Udiskie password helper + src: .local/bin/udiskie-password + dest: .local/bin/udiskie-password + mode: "0755" desktop_i3_dotfiles: - name: i3 config diff --git a/dotfiles/desktop/.config/hypr/hyprland.conf b/dotfiles/desktop/.config/hypr/hyprland.conf index 0db9525..0b904ef 100644 --- a/dotfiles/desktop/.config/hypr/hyprland.conf +++ b/dotfiles/desktop/.config/hypr/hyprland.conf @@ -21,7 +21,7 @@ exec-once = wireplumber exec-once = /usr/libexec/xfce-polkit exec-once = nm-applet exec-once = blueman-applet -exec-once = udiskie --tray --automount +exec-once = udiskie env = XCURSOR_THEME,Yaru env = XCURSOR_SIZE,24 diff --git a/dotfiles/desktop/.config/i3/config b/dotfiles/desktop/.config/i3/config index e15e30e..1355597 100644 --- a/dotfiles/desktop/.config/i3/config +++ b/dotfiles/desktop/.config/i3/config @@ -26,7 +26,7 @@ exec --no-startup-id dunst exec --no-startup-id /usr/libexec/xfce-polkit exec --no-startup-id nm-applet exec --no-startup-id blueman-applet -exec --no-startup-id udiskie --tray --automount +exec --no-startup-id udiskie exec --no-startup-id volumeicon exec --no-startup-id xfce4-clipman diff --git a/dotfiles/desktop/.config/sway/config b/dotfiles/desktop/.config/sway/config index b2f7444..0597c24 100644 --- a/dotfiles/desktop/.config/sway/config +++ b/dotfiles/desktop/.config/sway/config @@ -33,7 +33,7 @@ exec swayosd-server exec /usr/libexec/xfce-polkit exec nm-applet exec blueman-applet -exec udiskie --tray --automount +exec udiskie exec xfce4-clipman # Input and output defaults diff --git a/dotfiles/desktop/.config/udiskie/config.yml b/dotfiles/desktop/.config/udiskie/config.yml new file mode 100644 index 0000000..0fe11c1 --- /dev/null +++ b/dotfiles/desktop/.config/udiskie/config.yml @@ -0,0 +1,13 @@ +--- +program_options: + tray: auto + automount: true + notify: true + password_cache: false + password_prompt: + - /bin/sh + - -c + - 'exec "$HOME/.local/bin/udiskie-password" "$1" "$2"' + - sh + - '{id_uuid}' + - '{device_presentation}' diff --git a/dotfiles/desktop/.local/bin/udiskie-password b/dotfiles/desktop/.local/bin/udiskie-password new file mode 100755 index 0000000..2c1d3d9 --- /dev/null +++ b/dotfiles/desktop/.local/bin/udiskie-password @@ -0,0 +1,89 @@ +#!/bin/sh + +set -eu + +id_uuid=${1:-} +device_presentation=${2:-Encrypted disk} +pinentry_program=pinentry-gtk-2 + +if [ -z "$id_uuid" ]; then + printf '%s\n' "udiskie-password: missing device UUID" >&2 + exit 1 +fi + +assuan_escape() { + python3 -c 'import sys +value = sys.argv[1] +value = value.replace("%", "%25").replace("\n", "%0A").replace("\r", "%0D") +sys.stdout.write(value)' "$1" +} + +pinentry_getpin() { + title=$(assuan_escape "Unlock disk") + prompt=$(assuan_escape "Passphrase:") + description=$(assuan_escape "Enter passphrase for $device_presentation") + response=$( + { + printf 'SETTITLE %s\n' "$title" + printf 'SETPROMPT %s\n' "$prompt" + printf 'SETDESC %s\n' "$description" + printf 'GETPIN\n' + } | "$pinentry_program" + ) || return 1 + + printf '%s\n' "$response" | + python3 -c 'import sys +for line in sys.stdin.read().splitlines(): + if line.startswith("D "): + value = line[2:].replace("%0A", "\n").replace("%0D", "\r") + i = 0 + out = [] + while i < len(value): + if value[i] == "%" and i + 2 < len(value): + out.append(chr(int(value[i + 1:i + 3], 16))) + i += 3 + else: + out.append(value[i]) + i += 1 + sys.stdout.write("".join(out)) + break +else: + sys.exit(1)' +} + +pinentry_confirm_save() { + title=$(assuan_escape "Save disk password") + description=$(assuan_escape "Save the unlock passphrase for $device_presentation in GNOME Keyring?") + button_ok=$(assuan_escape "Save") + button_cancel=$(assuan_escape "Skip") + + { + printf 'SETTITLE %s\n' "$title" + printf 'SETDESC %s\n' "$description" + printf 'SETOK %s\n' "$button_ok" + printf 'SETCANCEL %s\n' "$button_cancel" + printf 'CONFIRM\n' + } | "$pinentry_program" >/dev/null 2>&1 +} + +if password=$(secret-tool lookup app udiskie id_uuid "$id_uuid" 2>/dev/null); then + if [ -n "$password" ]; then + printf '%s' "$password" + exit 0 + fi +fi + +password=$(pinentry_getpin) || exit 1 + +if [ -z "$password" ]; then + exit 1 +fi + +if pinentry_confirm_save; then + printf '%s' "$password" | secret-tool store \ + --label="udiskie LUKS $device_presentation" \ + app udiskie \ + id_uuid "$id_uuid" >/dev/null +fi + +printf '%s' "$password"