From fdefa19c057e79e5fca0f7f4a0df0bbd3ff80f8c Mon Sep 17 00:00:00 2001 From: zawz Date: Tue, 7 Jul 2020 13:41:16 +0200 Subject: [PATCH] Add rzpass --- zpass/rzpass | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++ zpass/zpass | 35 +++++---- 2 files changed, 223 insertions(+), 15 deletions(-) create mode 100755 zpass/rzpass diff --git a/zpass/rzpass b/zpass/rzpass new file mode 100755 index 0000000..3b37696 --- /dev/null +++ b/zpass/rzpass @@ -0,0 +1,203 @@ +#!/bin/sh + +fname=$(basename "$0") +usage() +{ + echo "$fname +Call zpass using a remote machine +[Global Operations]: + list-files List eligible files in data path. Shortcut 'lsf' + cache-clear Delete all cached keys. Shortcut 'cc' + help Display help +[File Operations]: + create Create a file or change key + cached Returns wether or not a key is currently cached. Shortcut 'ch' + ls [path] List contents at given path + tree List all contents + get Get the value of target + copy Copy the target value to clipboard. Shortcut 'x' + set Set the value of target + new [length] Generate a random password at target + rm Delete the target + rm-file Remove the current file. Shortcut 'rmf' + +[Config]: + *Variable* *Default value* *Description* + ---------------------------------------------------------------------------- + CONFIGFILE '\$XDG_CONFIG_HOME/zpass/r-defaut.conf' Path to the config file to load + ZPASS_REMOTE_ADDR Key to use for encrypting/decrypting files + ZPASS_REMOTE_PORT '22' Port + ZPASS_REMOTE_COMMAND 'zpass' Command to use on remote host + ZPASS_SSH_ID Private SSH key to use + ZPASS_KEY Key to use for encrypting/decrypting files + ZPASS_CLIPBOARD_TIME '30' Time until clipboard gets cleared after copy, in seconds + ZPASS_UNK_OP_CALL 'copy' Operation to call on unrecognized first argument + +All operations can be shortened to their first char unless specified +Unknown first argument will perform the operation described in 'ZPASS_UNK_OP_CALL' on that argument +" +} + +# XDG config +datapath="$HOME/.local/share/zpass" +cachepath="$HOME/.cache/zpass" +configpath="$HOME/.config/zpass" +[ -n "$XDG_DATA_HOME" ] && datapath="$XDG_DATA_HOME/zpass" +[ -n "$XDG_CONFIG_HOME" ] && configpath="$XDG_CONFIG_HOME/zpass" +[ -n "$XDG_CACHE_HOME" ] && cachepath="$XDG_CACHE_HOME/zpass" +[ -z "$CONFIGFILE" ] && CONFIGFILE="$configpath/r-default.conf" + +# stash env config +ZPASS_CLIPBOARD_TIME_T=$ZPASS_CLIPBOARD_TIME +ZPASS_UNK_OP_CALL_T=$ZPASS_UNK_OP_CALL +ZPASS_REMOTE_ADDR_T=$ZPASS_REMOTE_ADDR +ZPASS_REMOTE_PORT_T=$ZPASS_REMOTE_PORT +ZPASS_REMOTE_COMMAND_T=$ZPASS_REMOTE_COMMAND +ZPASS_SSH_ID_T=$ZPASS_SSH_ID + +# load config file +[ -f "$CONFIGFILE" ] && { . "$CONFIGFILE" || exit $? ; } + +# insert env config +[ -n "$ZPASS_CLIPBOARD_TIME_T" ] && ZPASS_CLIPBOARD_TIME=$ZPASS_CLIPBOARD_TIME_T +[ -n "$ZPASS_UNK_OP_CALL_T" ] && ZPASS_UNK_OP_CALL=$ZPASS_UNK_OP_CALL_T +[ -n "$ZPASS_REMOTE_ADDR_T" ] && ZPASS_REMOTE_ADDR=$ZPASS_REMOTE_ADDR_T +[ -n "$ZPASS_REMOTE_PORT_T" ] && ZPASS_REMOTE_PORT=$ZPASS_REMOTE_PORT_T +[ -n "$ZPASS_REMOTE_COMMAND_T" ] && ZPASS_REMOTE_COMMAND=$ZPASS_REMOTE_COMMAND_T +[ -n "$ZPASS_SSH_ID_T" ] && ZPASS_SSH_ID=$ZPASS_SSH_ID_T + +# default ZPASS config +[ -z "$ZPASS_CLIPBOARD_TIME" ] && ZPASS_CLIPBOARD_TIME=30 # in seconds +[ -z "$ZPASS_UNK_OP_CALL" ] && ZPASS_UNK_OP_CALL=copy +[ -z "$ZPASS_REMOTE_PORT" ] && ZPASS_REMOTE_PORT=22 +[ -z "$ZPASS_REMOTE_COMMAND" ] && ZPASS_REMOTE_COMMAND=zpass + + +file="$datapath/$ZPASS_FILE$ZPASS_EXTENSION" + +mkdir -p "$datapath" 2>/dev/null || error 1 "Could not create '$datapath'" +mkdir -p "$cachepath" 2>/dev/null && chmod -R go-rwx "$cachepath" 2>/dev/null + +escape_chars() { + echo "$*" | sed 's|\.|\\\.|g;s|/|\\/|g' +} + +error(){ + ret=$1 && shift 1 && echo $* >&2 && exit $ret +} + +# $1 = delay in sec +clipboard_clear() { + if [ -n "$1" ] + then + for I in $(screen -ls | grep "$fname"_clipboard | awk '{print $1}') + do + screen -S "$I" -X stuff "^C" + done + screen -dmS "$fname"_clipboard sh -c "sleep $1 ; printf '' | xclip -selection clipboard ; sleep 1" # put empty string into clipboard + else + xclip -selection clipboard < /dev/null + fi +} + +# $1 = prompt message +prompt_password() { + if [ -n "$DISPLAY" ] + then + if which kdialog >/dev/null 2>&2 + then kdialog --title "zpass" --password "$1" 2>/dev/null + else zenity --title "zpass" --password 2>/dev/null + fi + else + printf "%s:" "$1" >&2 + stty -echo + read -r PASSWORD || return $? + stty echo + printf "\n" >&2 + echo $PASSWORD + fi +} + +# $1 = message +error_dialog() { + if which kdialog >/dev/null 2>&2 + then kdialog --title "zpass" --error "$1" 2>/dev/null + else zenity --title "zpass" --error --text="$1" 2>/dev/null + fi +} + +new_key_with_confirm() +{ + [ -n "$ZPASS_KEY" ] && echo "$ZPASS_KEY" && return 0 + pass1=1 + pass2=2 + while [ "$pass1" != "$pass2" ] + do + pass1=$(prompt_password "Enter new key") || error 100 "Cancelled" + pass2=$(prompt_password "Confirm key") || error 100 "Cancelled" + [ "$pass1" != "$pass2" ] && error_dialog "Passwords do not match.\nTry again" + done + echo "$pass1" +} + +# $1 = prompt message +get_key() { + message="Enter key" + [ -n "$1" ] && message="$1" + key=$(prompt_password "$message") || return $? + echo "$key" +} + +copy() +{ + { keyed_remote g "$@" || return $? ; } | tr -d '\n' | xclip -selection clipboard && clipboard_clear "$ZPASS_CLIPBOARD_TIME" +} + +[ -z "$1" ] && usage && return 1 + +keyed_confirm_remote() +{ + new_key=$(new_key_with_confirm) + { + if ! remote ch + then + [ -z "$ZPASS_KEY" ] && { remote ch || ZPASS_KEY=$(get_key) ; } + echo "$ZPASS_KEY" + fi + echo "$new_key" + echo "$new_key" + } | remote "$@" +} + +keyed_remote() +{ + [ -z "$ZPASS_KEY" ] && { remote ch || ZPASS_KEY=$(get_key) ; } + echo "$ZPASS_KEY" | remote "$@" +} + +remote() +{ + if [ -n "$ZPASS_SSH_ID" ] + then + ssh "$ZPASS_REMOTE_ADDR" -i "$ZPASS_SSH_ID" -p "$ZPASS_REMOTE_PORT" $ZPASS_REMOTE_COMMAND "$@" + else + ssh "$ZPASS_REMOTE_ADDR" -p "$ZPASS_REMOTE_PORT" $ZPASS_REMOTE_COMMAND "$@" + fi +} + +case $1 in + lsf|list-files) remote "$@" ;; + rmf|rm-file) remote "$@" ;; + cc|cache-clear) remote "$@" ;; + ch|cached) remote "$@" ;; + c|create) keyed_confirm_remote "$@" ;; + l|ls|list) keyed_remote "$@" ;; + t|tree) keyed_remote "$@" ;; + g|get) keyed_remote "$@" ;; + s|set) keyed_remote "$@" ;; + n|new) keyed_remote "$@" ;; + r|rm) keyed_remote "$@" ;; + x|copy|clipboard) copy "$2" ;; + -h|h|help) usage ;; + *) [ -n "$ZPASS_UNK_OP_CALL" ] && "$0" $ZPASS_UNK_OP_CALL "$@" ;; +esac diff --git a/zpass/zpass b/zpass/zpass index 7c1afae..5c6c7c6 100755 --- a/zpass/zpass +++ b/zpass/zpass @@ -18,6 +18,7 @@ usage() new [length] Generate a random password at target rm Delete the target rm-file Remove the current file. Shortcut 'rmf' + cached Returns wether or not a key is currently cached. Shortcut 'ch' [Config]: *Variable* *Default value* *Description* @@ -77,6 +78,8 @@ ZPASS_UNK_OP_CALL_T=$ZPASS_UNK_OP_CALL [ -z "$ZPASS_CLIPBOARD_TIME" ] && ZPASS_CLIPBOARD_TIME=30 # in seconds [ -z "$ZPASS_UNK_OP_CALL" ] && ZPASS_UNK_OP_CALL=copy +[ -z "$TMPDIR" ] && TMPDIR=/tmp + file="$datapath/$ZPASS_FILE$ZPASS_EXTENSION" @@ -102,18 +105,18 @@ randpass() { } keyfile(){ - printf "%s.key" "$(echo "$file" | md5sum | cut -d' ' -f1)" + printf "%s.key" "$(readlink -f "$file" | md5sum | cut -d' ' -f1)" } # $1 = delay in sec clipboard_clear() { if [ -n "$1" ] then - for I in $(screen -ls | grep "zpass_clipboard" | awk '{print $1}') + for I in $(screen -ls | grep "$fname"_clipboard | awk '{print $1}') do screen -S "$I" -X stuff "^C" done - screen -dmS "zpass_clipboard" sh -c "sleep $1 ; printf '' | xclip -selection clipboard ; sleep 1" # call zpass for autoclean + screen -dmS "$fname"_clipboard sh -c "sleep $1 ; printf '' | xclip -selection clipboard ; sleep 1" # put empty string into clipboard else xclip -selection clipboard < /dev/null fi @@ -123,11 +126,11 @@ clipboard_clear() { delete_cache() { if [ "$1" -gt 0 ] 2>/dev/null then - for I in $(screen -ls | grep "zpass_$(keyfile)" | awk '{print $1}') + for I in $(screen -ls | grep "$fname"_"$(keyfile)" | awk '{print $1}') do screen -S "$I" -X stuff "^C" done - screen -dmS "zpass_$(keyfile)" sh -c "sleep $(($1*60)) ; $0" # call zpass for autoclean + screen -dmS "$fname"_"$(keyfile)" sh -c "sleep $(($1*60)) ; $0" # call zpass for autoclean else rm -f "$cachepath/$(keyfile)" 2>/dev/null fi @@ -137,11 +140,11 @@ clean_cache() { # key cache find "$cachepath" -type f -mmin +"$ZPASS_KEY_CACHE_TIME" -exec rm '{}' ';' # tmp folders older than 1 min - rm -rd $(find /tmp -maxdepth 1 -type d -name "zpass_*" ! -mmin 1) + rm -rd $(find "$TMPDIR" -maxdepth 1 -type d -name "$fname"'_*' ! -mmin 1) } clear_cache() { - rm "$cachepath/*" + rm "$cachepath"/* } write_cache() { @@ -150,6 +153,7 @@ write_cache() { } get_key_cached() { + [ ! -f "$file" ] && return 0 cat "$cachepath/$(keyfile)" 2>/dev/null } @@ -158,8 +162,8 @@ prompt_password() { if [ -n "$DISPLAY" ] then if which kdialog >/dev/null 2>&2 - then kdialog --title "zpass" --password "$1" 2>/dev/null - else zenity --title "zpass" --password 2>/dev/null + then kdialog --title "$fname" --password "$1" 2>/dev/null + else zenity --title "$fname" --password 2>/dev/null fi else printf "%s:" "$1" >&2 @@ -174,8 +178,8 @@ prompt_password() { # $1 = message error_dialog() { if which kdialog >/dev/null 2>&2 - then kdialog --title "zpass" --error "$1" 2>/dev/null - else zenity --title "zpass" --error --text="$1" 2>/dev/null + then kdialog --title "$fname" --error "$1" 2>/dev/null + else zenity --title "$fname" --error --text="$1" 2>/dev/null fi } @@ -278,7 +282,7 @@ setval() { err=0 # tmp files - tmpdir="/tmp/zpass_$(randalnum 5)" + tmpdir="$TMPDIR/$fname"_"$(randalnum 5)" keyfile="$tmpdir/$(randalnum 5).key" # operation ( @@ -294,7 +298,7 @@ setval() remove() { # tmp files - tmpdir="/tmp/zpass_$(randalnum 5)" + tmpdir="$TMPDIR/$fname"_"$(randalnum 5)" keyfile="$tmpdir/$(randalnum 5).key" # operation unpack "$tmpdir" "$keyfile" || return $? @@ -306,7 +310,7 @@ remove() create() { if [ -f "$file" ] then - tmpdir="/tmp/zpass_$(randalnum 5)" + tmpdir="$TMPDIR/$fname"_"$(randalnum 5)" # pack n repack with no tmp key: create new unpack "$tmpdir" || return $? pack "$tmpdir" || { echo "Encryption error" >&2 && return 1 ; } @@ -344,7 +348,7 @@ tree() get(){ err=0 - tmpdir="/tmp/zpass_$(randalnum 5)" && mkdir -p "$tmpdir" + tmpdir="$TMPDIR/$fname"_"$(randalnum 5)" && mkdir -p "$tmpdir" decrypt | tar -C "$tmpdir" -xf - || err=$? [ "$err" -eq 0 ] && { ( @@ -378,6 +382,7 @@ case $1 in n|new) setval "$2" "$(randpass $3)" ;; r|rm) remove "$2" "$3" ;; x|copy|clipboard) copy "$2" ;; + ch|cached) get_key_cached >/dev/null 2>&1 ; exit $? ;; -h|h|help) usage ;; *) [ -n "$ZPASS_UNK_OP_CALL" ] && "$0" $ZPASS_UNK_OP_CALL "$@" ;; esac