diff options
Diffstat (limited to 'rofi/bin/rofi_pass.sh')
-rw-r--r-- | rofi/bin/rofi_pass.sh | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/rofi/bin/rofi_pass.sh b/rofi/bin/rofi_pass.sh new file mode 100644 index 00000000..fb31a454 --- /dev/null +++ b/rofi/bin/rofi_pass.sh @@ -0,0 +1,92 @@ +# Pick password from local or remote password-store with rofi's dmenu emulation +# mode, and write it to the active X11 window. Optionally, prefix it with the +# username, being the last part of the slash-delimited password's name, and +# a TAB press to move to the next field in a form. +# +self=rofi_pass + +# Abstraction to handle running shell commands (args or stdin) in either +# a remote or local shell. If the environment variable PASSWORD_STORE_HOST is +# set, it's used as the destination SSH hostname to the password store. +# +pass_shell() { + [ "$#" -le 1 ] || return + if [ -n "$PASSWORD_STORE_HOST" ] ; then + ssh -o StrictHostKeyChecking=yes -T -X -- \ + "$PASSWORD_STORE_HOST" "$@" + elif [ "$#" -eq 1 ] ; then + "${SHELL:-/bin/sh}" -c "$1" + else + "${SHELL:-/bin/sh}" -s + fi +} + +# Get a list of all the password paths, relative to the password store root, +# including leading dot-slash and trailing .gpg extension. +# +get_paths() { + pass_shell <<-'EOF' + dir=${PASSWORD_STORE_DIR:-"$HOME"/.password-store} + cd -- "$dir" || exit + find . -name \*.gpg -type f || exit + EOF +} + +# Get a list of all the password names, bytewise-sorted, with leading dot-slash +# and trailing .gpg extension removed. +# +get_names() { + get_paths | + sed -e 's_^[.]/__' -e 's_[.]gpg$__' | + LC_COLLATE=C sort -f +} + +# Write a password name to a shell to retrieve it, and read its first line; +# write the name safely to the shell's input rather than as an argument. +# +get_password() { + name=$1 + [ -n "$name" ] || return + printf '%s\n' "$name" | + pass_shell 'IFS= read -r name ; pass show "$name"' | + head -n 1 +} + +# Check for --login/-l option to paste a username-password combo, not just the +# password (defaults to the latter). +# +login=0 +case $1 in + --login|-l) login=1 ;; +esac + +# Apply rofi -dmenu to pick a password name. Use case-insensitive matching, +# and don't accept arbitrary input. +# +name=$(get_names | rofi -dmenu -i -no-lazy-grab -only_match -p pass) || exit +[ -n "$name" ] || exit + +# Retrieve the username for the chosen password, and then the secret itself; +# check that we actually got more than an empty string back in both cases. +# +username=${name##*/} +[ -n "$username" ] || exit +password=$(get_password "$name") || exit +[ -n "$password" ] || exit + +# Have xdotool type either the username-TAB-password, or just the password; +# receiving it on its standard input rather than its arguments, for security. +# +if [ "$login" -eq 1 ] ; then + printf '%s\t%s' \ + "$username" "$password" +else + printf '%s' \ + "$password" +fi | xdotool type --clearmodifiers --delay=0 --file - || exit + +# Tell the user we wrote the password out, in case they're typing a password +# into a field with echo turned off. +# +notify-send --app-name="$self" --icon=gcr-password -- \ + 'Password typed' "$name" |