[gopass] Fix simple autoentry of user credentials
Simplify gopass autoentry script heavily. Will pick up user credentials from gopass store and enter them in whatever way the user wishes. Fix key entry for changes in gopass 1.9.* password display options. Several default variables can be customized, see the top of the rofi-gopass file.
This commit is contained in:
parent
3796fa8ce5
commit
6fe0b66bd1
1 changed files with 90 additions and 202 deletions
|
|
@ -1,228 +1,116 @@
|
|||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Code originally inspired by https://github.com/carnager/rofi-pass/
|
||||
|
||||
# Code belongs to https://github.com/carnager/rofi-pass/
|
||||
# Copyright (C) 2019 carnager
|
||||
# DEFAULT OPTIONS
|
||||
|
||||
# typing tool used, choice of:
|
||||
# xdotool |
|
||||
BACKEND=xdotool
|
||||
|
||||
# the complete typing chain autoentry uses
|
||||
# possible fields:
|
||||
# :tab | :space | :enter | username | password
|
||||
#
|
||||
# Note that spaces have to be passed explicitly with :space,
|
||||
# putting a literal ' ' in the chain will not work
|
||||
#
|
||||
# By default it enters the username, tabs down, and enters the password
|
||||
# It does not press return at the end for safety, though you can add
|
||||
# :return to make it do so.
|
||||
AUTOENTRY_CHAIN="username :tab password"
|
||||
|
||||
# wait time before entering each input
|
||||
# in milliseconds
|
||||
AUTOENTRY_DELAY=20
|
||||
|
||||
# default key bindings
|
||||
# Automatically enter username and password
|
||||
KEY_AUTOENTRY="Return"
|
||||
|
||||
# rofi wrapper. Add custom settings here.
|
||||
_rofi() {
|
||||
# TODO add check for dmenu
|
||||
exist rofi critical "rofi-pass" || exit 0
|
||||
rofi -dmenu -no-auto-select -i "$@" -theme /themes/dmenu
|
||||
}
|
||||
|
||||
# default settings
|
||||
backend=xdotool
|
||||
dotool_delay=20
|
||||
daemon_wait=2
|
||||
autotype_delay=2
|
||||
key_autotype="Return"
|
||||
key_usertype="Alt+2"
|
||||
key_passtype="Alt+3"
|
||||
key_actions="Alt+a"
|
||||
key_clipboard="Alt+1"
|
||||
key_fieldtype="Return"
|
||||
|
||||
# read config file
|
||||
get_config_file() {
|
||||
configs=("$ROFI_PASS_CONFIG"
|
||||
"$HOME/.config/rofi-pass/rofi-gopass.conf"
|
||||
"/etc/rofi-gopass.conf")
|
||||
|
||||
# return the first config file with a valid path
|
||||
for config in "${configs[@]}"; do
|
||||
# '! -z' is needed in case ROFI_PASS_CONFIG is not set
|
||||
if [[ ! -z "${config}" && -f "${config}" ]]; then
|
||||
printf "%s" "$config"
|
||||
return
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Make sure ESC will always end the programm.
|
||||
# Call this function with "exit_check $?" after each rofi call.
|
||||
# exit on escape pressed
|
||||
# rofi returns exit code 1 on esc
|
||||
exit_check() {
|
||||
exit_value=$1
|
||||
if [[ "${exit_value}" == "1" ]]; then
|
||||
exit
|
||||
fi
|
||||
[ "$1" -eq 1 ] && exit
|
||||
}
|
||||
|
||||
clipboard() {
|
||||
local entry
|
||||
local key
|
||||
local value
|
||||
entry="${1}"
|
||||
key="${2}"
|
||||
value="$(gopass show "${entry}" "${key}")"
|
||||
printf '%s' "${value}" | xclip -sel clip
|
||||
notify-send "rofi-gopass" "Copied ${key} to clipboard\nClearing in 45 seconds."
|
||||
(
|
||||
sleep 45
|
||||
printf '%s' "" | xclip
|
||||
printf '%s' "" | xclip -selection clipboard | notify-send "rofi-gopass" "Clipboard cleared"
|
||||
) &
|
||||
exit
|
||||
}
|
||||
|
||||
_ydotoold() {
|
||||
if ! pgrep -x "ydotoold" >/dev/null; then
|
||||
# ydotoold blocks the terminal, so we need to background it.
|
||||
# Sadly this way we never know when the process finished starting up.
|
||||
# Until ydotoold receives proper daemonizing we add a sleep value here.
|
||||
ydotoold &
|
||||
sleep "${daemon_wait}"
|
||||
fi
|
||||
}
|
||||
|
||||
_dotool() {
|
||||
local mode
|
||||
local key
|
||||
mode="${1}"
|
||||
key="${2:-null}"
|
||||
case "${mode}" in
|
||||
"type")
|
||||
case "${backend}" in
|
||||
"xdotool") xdotool type --delay "${dotool_delay}" --file - ;;
|
||||
"ydotool")
|
||||
_ydotoold
|
||||
ydotool type --delay "${dotool_delay}" --file -
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
"key")
|
||||
case "${backend}" in
|
||||
"xdotool") xdotool key "${key}" ;;
|
||||
"ydotool")
|
||||
_ydotoold
|
||||
ydotool key "${key}"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
list_passwords() {
|
||||
# simply return a list of all passwords in gopass store
|
||||
# TODO choose password store
|
||||
# TODO only show website names (+ folder names), and account names for multiple accounts on one site
|
||||
_gp_list_passwords() {
|
||||
gopass list --flat
|
||||
}
|
||||
|
||||
autopass() {
|
||||
local entry
|
||||
local autotype
|
||||
entry="${1}"
|
||||
autotype="$(gopass show "${entry}" autotype)"
|
||||
autotype="${autotype:-username :tab pass}"
|
||||
# return password for argument passed
|
||||
_gp_show_password() {
|
||||
gopass show -f --password "$1"
|
||||
}
|
||||
|
||||
for word in ${autotype}; do
|
||||
case "$word" in
|
||||
":tab") _dotool key Tab ;;
|
||||
":space") _dotool key " " ;;
|
||||
":delay") sleep "${autotype_delay}" ;;
|
||||
":enter") _dotool key enter ;;
|
||||
"pass") printf '%s' "$(gopass show --password "${entry}")" | _dotool type ;;
|
||||
*) printf '%s' "$(gopass show "${entry}" "${word}")" | _dotool type ;;
|
||||
GOPASS_USERNAME_ATTEMPTS="username user login"
|
||||
|
||||
# return username for argument passed
|
||||
_gp_show_username() {
|
||||
for key in $GOPASS_USERNAME_ATTEMPTS; do
|
||||
|
||||
done
|
||||
gopass show -f "$1" username || gopass -f show "$1" user || gopass -f show "$1" login
|
||||
}
|
||||
|
||||
# send password to clipboard
|
||||
_gp_clip_password() {
|
||||
gopass show -c "$1"
|
||||
}
|
||||
|
||||
# invoke the dotool to type inputs
|
||||
_type() {
|
||||
local tool
|
||||
local toolmode
|
||||
local key
|
||||
tool="${BACKEND}"
|
||||
toolmode="$1"
|
||||
key="$2"
|
||||
|
||||
"$tool" "$toolmode" --delay "$AUTOENTRY_DELAY" "$key"
|
||||
}
|
||||
|
||||
# automatically enter entry chain, set via AUTOENTRY_CHAIN
|
||||
# transform special chain entries into valid dotool commands
|
||||
autoentry() {
|
||||
local selected
|
||||
local autoentry_chain
|
||||
selected="${1}"
|
||||
autoentry_chain="${AUTOENTRY_CHAIN}"
|
||||
|
||||
for part in $autoentry_chain; do
|
||||
case "$part" in
|
||||
":tab") _type key Tab ;;
|
||||
":return") _type key Return ;;
|
||||
":space") _type key space ;;
|
||||
"username") _type type "$(_gp_show_username "$selected")" ;;
|
||||
"password") _type type "$(_gp_show_password "$selected")" ;;
|
||||
*) printf '%s' "$part" ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
list_keys() {
|
||||
# gopass has no option to only list keys, so we need to build the list ourselves.
|
||||
local entry
|
||||
local keys
|
||||
entry="${1}"
|
||||
keys="$(gopass show "${entry}")"
|
||||
printf '%s\n' "${keys}" | while read -r line; do
|
||||
if [[ "${line}" == *": "* ]]; then
|
||||
printf '%s\n' "${line%: *}"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
edit_key() {
|
||||
local entry
|
||||
local keys
|
||||
entry="${1}"
|
||||
keys="$(list_keys "${entry}")"
|
||||
key_name=$(printf '%s\n' "${keys}" | _rofi -mesg "Enter new key or chose existing one")
|
||||
exit_check $?
|
||||
value_name=$(printf '%s' "" | _rofi -mesg "Enter Value for key \"${key_name}\"")
|
||||
exit_check $?
|
||||
if [[ -z "${key_name}" ]]; then
|
||||
printf '%s' "${value_name}" | gopass insert -a "${entry}" "${key_name}"
|
||||
else
|
||||
printf '%s' "${value_name}" | gopass insert "${entry}" "${key_name}"
|
||||
fi
|
||||
}
|
||||
|
||||
# For dangerous operations call this function first. You can provide a message as argument.
|
||||
# Example: confirm "Are you sure you want to delete entry?"
|
||||
confirm() {
|
||||
local message
|
||||
message="${1}"
|
||||
confirm_content=(
|
||||
"Yes"
|
||||
"No")
|
||||
|
||||
confirm_menu=$(printf '%s\n' "${confirm_content[@]}" | _rofi -mesg "${message}")
|
||||
exit_check $?
|
||||
case "${confirm_menu}" in
|
||||
"Yes") : ;;
|
||||
"No") exit ;;
|
||||
esac
|
||||
}
|
||||
|
||||
custom_type() {
|
||||
local entry
|
||||
local keys
|
||||
entry="${1}"
|
||||
keys="$(list_keys "${entry}")"
|
||||
key_name=$(printf '%s\n' "${keys}" | _rofi -kb-accept-entry "" -no-custom -kb-custom-1 "${key_clipboard}" -kb-custom-2 "${key_fieldtype}" -mesg "${key_clipboard}: Copy to Clipboard | ${key_fieldtype}: Type Field")
|
||||
local exit_value=$?
|
||||
exit_check "${exit_value}"
|
||||
case "${exit_value}" in
|
||||
"10") clipboard "${entry}" "${key_name}" ;;
|
||||
"11")
|
||||
printf '%s' "$(gopass show "${entry}" "${key_name}")" | _dotool type
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
do_menu() {
|
||||
local entry
|
||||
entry="${1}"
|
||||
action_menu_content=(
|
||||
"< Go Back"
|
||||
"---"
|
||||
"Show Fields"
|
||||
"Add/Edit Keys"
|
||||
"Generate New Password"
|
||||
"Delete Entry"
|
||||
)
|
||||
|
||||
action_menu="$(printf '%s\n' "${action_menu_content[@]}" | _rofi -no-custom -mesg "Selected Entry: ${entry}" -p '> ')"
|
||||
exit_value=$?
|
||||
exit_check "${exit_value}"
|
||||
|
||||
case "${action_menu}" in
|
||||
"< Go Back") main ;;
|
||||
"Show Fields") custom_type "${entry}" ;;
|
||||
"Add/Edit Keys") edit_key "${entry}" ;;
|
||||
"Delete Entry")
|
||||
confirm "Delete ${entry}?"
|
||||
gopass rm -f "${entry}"
|
||||
;;
|
||||
"Generate New Password")
|
||||
confirm "Generate a new password for ${entry}?"
|
||||
gopass generate -f "${entry}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
main() {
|
||||
entry="$(list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${key_autotype}" -kb-custom-2 "${key_usertype}" -kb-custom-3 "${key_passtype}" -kb-custom-4 "${key_actions}" -mesg "${key_autotype}: Autotype | ${key_usertype}: Type User | ${key_passtype}: Type Pass | ${key_actions}: More Actions")"
|
||||
# entry="$(list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${key_autotype}" -kb-custom-2 "${key_usertype}" -kb-custom-3 "${key_passtype}" -kb-custom-4 "${key_actions}" -mesg "${key_autotype}: Autotype | ${key_usertype}: Type User | ${key_passtype}: Type Pass | ${key_actions}: More Actions")"
|
||||
|
||||
entry="$(_gp_list_passwords | _rofi -kb-accept-entry "" -kb-custom-1 "${KEY_AUTOENTRY}")"
|
||||
exit_value=$?
|
||||
|
||||
exit_check "${exit_value}"
|
||||
case "${exit_value}" in
|
||||
# autoentry selected
|
||||
"10")
|
||||
autopass "${entry}"
|
||||
autoentry "${entry}"
|
||||
exit
|
||||
;;
|
||||
"11")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue