From 710e47758db725a551a8d44d25beda98c6d46e8c Mon Sep 17 00:00:00 2001 From: Marty Oehme Date: Wed, 18 Sep 2019 16:01:06 +0200 Subject: [PATCH] Add rofi-gopass to quickly enter gopass entries --- .config/sxhkd/sxhkdrc | 4 + .local/bin/rofi-gopass | 240 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100755 .local/bin/rofi-gopass diff --git a/.config/sxhkd/sxhkdrc b/.config/sxhkd/sxhkdrc index bf146a4..0303661 100644 --- a/.config/sxhkd/sxhkdrc +++ b/.config/sxhkd/sxhkdrc @@ -12,6 +12,10 @@ super + space super + r exec rofi -modi combi,ssh -show combi -combi-modi "window,clipboard:greenclip print,run" +# open more extensive run menu +super + p + exec rofi-gopass + # System functionality # Enable lock screen (TODO does not stop music, etc yet diff --git a/.local/bin/rofi-gopass b/.local/bin/rofi-gopass new file mode 100755 index 0000000..6ba13f1 --- /dev/null +++ b/.local/bin/rofi-gopass @@ -0,0 +1,240 @@ +#!/bin/bash + +# Code belongs to https://github.com/carnager/rofi-pass/ +# Copyright (C) 2019 carnager + +# rofi wrapper. Add custom settings here. +_rofi() { + tofi -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_check() { + exit_value=$1 + if [[ "${exit_value}" == "1" ]]; then + exit + fi +} + +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() { + gopass list --flat +} + +autopass() { + local entry + local autotype + entry="${1}" + autotype="$(gopass show "${entry}" autotype)" + autotype="${autotype:-user :tab pass}" + + 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 ;; + 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")" + exit_value=$? + exit_check "${exit_value}" + case "${exit_value}" in + "10") + autopass "${entry}" + exit + ;; + "11") + printf '%s' "$(gopass show "${entry}" user)" | _dotool type + exit + ;; + "12") + printf '%s' "$(gopass show --password "${entry}")" | _dotool type + exit + ;; + esac + do_menu "${entry}" +} + +main