diff options
author | Silvio Rhatto <rhatto@riseup.net> | 2014-02-20 11:10:22 -0300 |
---|---|---|
committer | Silvio Rhatto <rhatto@riseup.net> | 2014-02-20 11:10:22 -0300 |
commit | 4b4aff2edac956224849d36fe83f826303d25efd (patch) | |
tree | ed8446593f57b091730a40ea93c626548c7328dc /lib | |
parent | 5f1590e0722ee5ee9fed2ccc43adfb88f00218fd (diff) | |
parent | 013726598e074399344c0bf435e057bc8049959a (diff) | |
download | keyringer-4b4aff2edac956224849d36fe83f826303d25efd.tar.gz keyringer-4b4aff2edac956224849d36fe83f826303d25efd.tar.bz2 |
Imported Upstream version 0.3upstream_keyringer_0.3
Diffstat (limited to 'lib')
26 files changed, 349 insertions, 27 deletions
diff --git a/lib/keyringer/actions/append b/lib/keyringer/actions/append index e307056..fbb6c1c 100755 --- a/lib/keyringer/actions/append +++ b/lib/keyringer/actions/append @@ -17,4 +17,4 @@ fi # Append content to an existing secret ( keyringer_exec decrypt "$BASEDIR" "$FILE" && cat ) | \ - keyringer_exec encrypt-batch $BASEDIR $FILE + keyringer_exec encrypt-batch "$BASEDIR" "$FILE" diff --git a/lib/keyringer/actions/clip b/lib/keyringer/actions/clip new file mode 120000 index 0000000..8b8c16c --- /dev/null +++ b/lib/keyringer/actions/clip @@ -0,0 +1 @@ +xclip
\ No newline at end of file diff --git a/lib/keyringer/actions/commands b/lib/keyringer/actions/commands index 2605666..cb49c02 100755 --- a/lib/keyringer/actions/commands +++ b/lib/keyringer/actions/commands @@ -7,4 +7,5 @@ LIB="`dirname $0`/../functions" source "$LIB" || exit 1 +# Dispatch keyringer_show_actions diff --git a/lib/keyringer/actions/decrypt b/lib/keyringer/actions/decrypt index 2b1401c..b63b74e 100755 --- a/lib/keyringer/actions/decrypt +++ b/lib/keyringer/actions/decrypt @@ -11,7 +11,7 @@ source "$LIB" || exit 1 keyringer_get_file "$2" # Decrypt -$GPG --quiet --use-agent -d "$KEYDIR/$FILE" +$GPG --use-agent -d "$KEYDIR/$FILE" # Exit exit "$?" diff --git a/lib/keyringer/actions/edit b/lib/keyringer/actions/edit index 9a3e488..03ccdab 100755 --- a/lib/keyringer/actions/edit +++ b/lib/keyringer/actions/edit @@ -24,6 +24,7 @@ keyringer_set_tmpfile $BASENAME.$EXTENSION # Decrypt the information to the file $GPG --yes -o "$TMPWORK" --use-agent -d "$KEYDIR/$FILE" +# Action check if [ "$BASENAME" == "edit" ]; then APP="$EDITOR" elif [ "$BASENAME" == "open" ]; then @@ -43,5 +44,18 @@ $APP "$TMPWORK" # Encrypt again $GPG --yes -o "$KEYDIR/$FILE" --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") "$TMPWORK" +# Check exit status +errcrypt="$?" + # Remove temp file keyringer_unset_tmpfile "$TMPWORK" + +# Check exit status again +errwipe="$?" + +# Error handling must be done after temp file removal +if [ "$errcrypt" != "0" ]; then + exit "$errcrypt" +elif [ "$errwipe" != "0" ]; then + exit $errwipe +fi diff --git a/lib/keyringer/actions/encrypt b/lib/keyringer/actions/encrypt index 0a40bc1..e9bf453 100755 --- a/lib/keyringer/actions/encrypt +++ b/lib/keyringer/actions/encrypt @@ -106,12 +106,13 @@ else keyringer_encrypt $FILE $UNENCRYPTED_FILE fi +# Check exit status err="$?" - if [ "$err" != "0" ]; then exit "$err" fi +# Wipe information if [ "$UNENCRYPTED_FILE" != "-" ]; then echo "Done. PLEASE WIPE the non-encrypted $UNENCRYPTED_FILE." fi @@ -121,4 +122,5 @@ if [ -d "$BASEDIR/.git" ]; then keyringer_exec git "$BASEDIR" add "keys/$FILE" fi +# Done exit "$?" diff --git a/lib/keyringer/actions/find b/lib/keyringer/actions/find new file mode 100755 index 0000000..21afc7a --- /dev/null +++ b/lib/keyringer/actions/find @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Find secrets. +# + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Aditional parameters +CWD="`pwd`" + +# Avoid leading slash +shift +ARGS="`echo "$*" | sed -e "s|^/*||"`" + +# Run find command +cd "$KEYDIR/$RELATIVE_PATH" && find -iname "*$ARGS*" | sed -e 's|^./||g' +cd "$CWD" diff --git a/lib/keyringer/actions/genpair b/lib/keyringer/actions/genpair index f048bc7..6898b0f 100755 --- a/lib/keyringer/actions/genpair +++ b/lib/keyringer/actions/genpair @@ -184,7 +184,7 @@ source "$LIB" || exit 1 # Aditional parameters KEYTYPE="$2" -FILE="$3" +FILE="$RELATIVE_PATH/$3" NODE="$4" OUTFILE="$5" CWD="`pwd`" diff --git a/lib/keyringer/actions/git b/lib/keyringer/actions/git index 3c4f435..108ccea 100755 --- a/lib/keyringer/actions/git +++ b/lib/keyringer/actions/git @@ -12,5 +12,13 @@ CWD="`pwd`" # Run git command shift -mkdir -p "$BASEDIR" && cd "$BASEDIR" && git $* + +# Set working folder +if [ ! -z "$RELATIVE_PATH" ]; then + WORK="$KEYDIR/$RELATIVE_PATH" +else + WORK="$BASEDIR" +fi + +mkdir -p "$WORK" && cd "$WORK" && git $* cd "$CWD" diff --git a/lib/keyringer/actions/help b/lib/keyringer/actions/help new file mode 120000 index 0000000..ae18295 --- /dev/null +++ b/lib/keyringer/actions/help @@ -0,0 +1 @@ +usage
\ No newline at end of file diff --git a/lib/keyringer/actions/ls b/lib/keyringer/actions/ls index bb66263..93f5f75 100755 --- a/lib/keyringer/actions/ls +++ b/lib/keyringer/actions/ls @@ -15,5 +15,5 @@ shift ARGS="`echo "$*" | sed -e "s|^/*||"`" # Run list command -cd "$KEYDIR" && ls $ARGS +cd "$KEYDIR/$RELATIVE_PATH" && ls $ARGS cd "$CWD" diff --git a/lib/keyringer/actions/mkdir b/lib/keyringer/actions/mkdir new file mode 100755 index 0000000..b31eb0b --- /dev/null +++ b/lib/keyringer/actions/mkdir @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Create folders. +# + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Aditional parameters +CWD="`pwd`" + +# Avoid leading slash +shift +ARGS="`echo "$*" | sed -e "s|^/*||"`" + +# Run mkdir command +cd "$KEYDIR/$RELATIVE_PATH" && mkdir -p $ARGS +cd "$CWD" diff --git a/lib/keyringer/actions/mv b/lib/keyringer/actions/mv new file mode 100755 index 0000000..aaf6772 --- /dev/null +++ b/lib/keyringer/actions/mv @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Move secrets. +# + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Avoid leading slash +ORIG="$(keyringer_filename `echo "$2" | sed -e "s|^/*||"`)" +DEST="`echo "$3" | sed -e "s|^/*||"`" + +# Set destination +if [ ! -d "$KEYDIR/$RELATIVE_PATH/$DEST" ]; then + keyringer_get_new_file $DEST +else + FILE="$DEST" +fi + +# Check if secret exists +if ! echo "$ORIG" | grep -q '*' && [ ! -e "$KEYDIR/$RELATIVE_PATH/$ORIG" ]; then + echo "Secret not found: $ORIG" + exit 1 +fi + +# Run move command +keyringer_exec git "$BASEDIR" mv $ORIG $FILE diff --git a/lib/keyringer/actions/options b/lib/keyringer/actions/options index 8508aea..3bf0e43 100755 --- a/lib/keyringer/actions/options +++ b/lib/keyringer/actions/options @@ -17,6 +17,7 @@ if [ ! -e "$OPTIONS" ]; then keyringer_exec git "$BASEDIR" add config/options fi +# Dispatch if [ "$COMMAND" == "ls" ]; then cat "$OPTIONS" elif [ "$COMMAND" == "edit" ]; then diff --git a/lib/keyringer/actions/preferences b/lib/keyringer/actions/preferences index e82848d..f7507a7 100755 --- a/lib/keyringer/actions/preferences +++ b/lib/keyringer/actions/preferences @@ -7,8 +7,10 @@ LIB="`dirname $0`/../functions" source "$LIB" || exit 1 +# Options COMMAND="$2" +# Syntax check if [ -z "$COMMAND" ]; then echo "Usage: keyringer <keyring> preferences <command> [arguments]" echo "Available commands:" @@ -24,6 +26,7 @@ if [ ! -e "$PREFERENCES" ]; then touch "$PREFERENCES" fi +# Dispatch if [ "$COMMAND" == "ls" ]; then cat "$PREFERENCES" elif [ "$COMMAND" == "edit" ]; then diff --git a/lib/keyringer/actions/recipients b/lib/keyringer/actions/recipients index 7093a6b..4149786 100755 --- a/lib/keyringer/actions/recipients +++ b/lib/keyringer/actions/recipients @@ -13,6 +13,7 @@ keyringer_get_command "$2" # Set recipients file keyringer_set_new_recipients "$3" +# Syntax check and dispatcher if [ "$COMMAND" == "ls" ]; then if [ ! -z "$3" ]; then if [ -e "$RECIPIENTS_FILE" ]; then diff --git a/lib/keyringer/actions/recrypt b/lib/keyringer/actions/recrypt index 014fef7..696399b 100755 --- a/lib/keyringer/actions/recrypt +++ b/lib/keyringer/actions/recrypt @@ -7,6 +7,7 @@ LIB="`dirname $0`/../functions" source "$LIB" || exit 1 +# Recrypt a single secret function keyringer_recrypt { # Get file keyringer_get_file "$1" @@ -34,6 +35,7 @@ function keyringer_recrypt { echo "$recrypted" > "$KEYDIR/$FILE" } +# Syntax check and dispatcher if [ ! -z "$2" ]; then keyringer_recrypt $2 else diff --git a/lib/keyringer/actions/rmdir b/lib/keyringer/actions/rmdir new file mode 100755 index 0000000..398cf11 --- /dev/null +++ b/lib/keyringer/actions/rmdir @@ -0,0 +1,19 @@ +#!/bin/bash +# +# Remove folders. +# + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Aditional parameters +CWD="`pwd`" + +# Avoid leading slash +shift +ARGS="`echo "$*" | sed -e "s|^/*||"`" + +# Run rmdir command +cd "$KEYDIR/$RELATIVE_PATH" && rmdir $ARGS +cd "$CWD" diff --git a/lib/keyringer/actions/shell b/lib/keyringer/actions/shell new file mode 100755 index 0000000..ab170b1 --- /dev/null +++ b/lib/keyringer/actions/shell @@ -0,0 +1,57 @@ +#!/bin/bash +# +# Interactive shell. +# + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Basic parameters +SHELLPATH="/" + +# Show usage +keyringer_usage $KEYRING + +# While a "quit" command isn't entered, read STDIN +while read -rep "keyringer:/${KEYRING}${SHELLPATH}> " STDIN; do + if [ "$STDIN" == "quit" ] || [ "$STDIN" == "exit" ] || [ "$STDIN" == "bye" ]; then + break + elif [ "$STDIN" == "shell" ]; then + echo "Why you need nesting?" + elif [[ "$STDIN" == "cd"* ]]; then + + # Update current path + OLDPATH="$SHELLPATH" + SHELLPATH="`echo $STDIN | sed -e 's/^cd//' | cut -d ' ' -f 2`" + + # Fix current path + if [ "$SHELLPATH" == "/" ] || [ "$SHELLPATH" == "" ]; then + SHELLPATH="/" + elif [[ "$SHELLPATH" == ".."* ]]; then + ARGS="$SHELLPATH" + SHELLPATH="$OLDPATH" + for colons in `echo $ARGS | sed -e 's|/| |g'`; do + SHELLPATH="`dirname $SHELLPATH | sed -e 's|^\.||'`" + done + fi + + # Ensure path is absolute + if echo "$SHELLPATH" | grep -v -q -e "^/"; then + SHELLPATH="/$OLDPATH/$SHELLPATH" + fi + + # Removing multiple slashes + SHELLPATH="`echo $SHELLPATH | sed -e 's/\/\+/\//g'`" + + # Check if path exists + if [ ! -d "$KEYDIR/$SHELLPATH" ]; then + echo "No such folder $SHELLPATH" + SHELLPATH="$OLDPATH" + fi + + elif [[ -n "$STDIN" && "$STDIN" != "#"* ]]; then + # If line is not empty or commented, process command + RELATIVE_PATH="$SHELLPATH" keyringer "$KEYRING" $STDIN + fi +done diff --git a/lib/keyringer/actions/teardown b/lib/keyringer/actions/teardown new file mode 100755 index 0000000..64da740 --- /dev/null +++ b/lib/keyringer/actions/teardown @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Remove a keyring. +# + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Options +CONFIRM="$2" + +# Confirmation +if [ -z "$CONFIRM" ] || [ "$CONFIRM" != "-y" ]; then + echo "WARNING: about to remove the LOCAL copy of $KEYRING" + echo "WARNING: This will irrevocably destroy $KEYDIR" + echo "WARNING: the action cannot be undone!" + + read -rep "Are you sure to WIPE keyring $KEYRING (type YES to confirm)? " key + if [ "$key" != "YES" ]; then + exit 1 + fi +fi + +# Teardown +keyringer_shred `dirname $KEYDIR` +keyringer_shred $HOME/.keyringer/$KEYRING +sed -i -e "/^$KEYRING=/d" $HOME/.keyringer/config diff --git a/lib/keyringer/actions/tree b/lib/keyringer/actions/tree index 8e94cb0..8f9d7cd 100755 --- a/lib/keyringer/actions/tree +++ b/lib/keyringer/actions/tree @@ -1,6 +1,6 @@ #!/bin/bash # -# List keys. +# List keys, tree version. # # Thanks http://www.centerkey.com/tree/ @@ -27,5 +27,5 @@ else fi # Run list command -cd "$KEYDIR" && $TREE $ARGS +cd "$KEYDIR/$RELATIVE_PATH" && $TREE $ARGS cd "$CWD" diff --git a/lib/keyringer/actions/usage b/lib/keyringer/actions/usage index f4ac0fa..2ca7639 100755 --- a/lib/keyringer/actions/usage +++ b/lib/keyringer/actions/usage @@ -7,4 +7,5 @@ LIB="`dirname $0`/../functions" source "$LIB" || exit 1 -keyringer_usage +# Dispatch +keyringer_usage $KEYRING diff --git a/lib/keyringer/actions/xclip b/lib/keyringer/actions/xclip new file mode 100755 index 0000000..b28984f --- /dev/null +++ b/lib/keyringer/actions/xclip @@ -0,0 +1,59 @@ +#!/bin/bash +# +# Decrypt secret header to clipboard. +# + +# Copy contents to clipboard. +# Function thanks to Password Store by Jason A. Donenfeld <Jason@zx2c4.com> +# distributed under GPLv2+: http://www.zx2c4.com/projects/password-store/ +clip() { + # This base64 business is a disgusting hack to deal with newline inconsistancies + # in shell. There must be a better way to deal with this, but because I'm a dolt, + # we're going with this for now. + + before="$(xclip -o -selection clipboard | base64)" + echo -n "$1" | xclip -selection clipboard + ( + sleep 45 + now="$(xclip -o -selection clipboard | base64)" + if [[ $now != $(echo -n "$1" | base64) ]]; then + before="$now" + fi + + # It might be nice to programatically check to see if klipper exists, + # as well as checking for other common clipboard managers. But for now, + # this works fine -- if qdbus isn't there or if klipper isn't running, + # this essentially becomes a no-op. + # + # Clipboard managers frequently write their history out in plaintext, + # so we axe it here: + qdbus org.kde.klipper /klipper org.kde.klipper.klipper.clearClipboardHistory &>/dev/null + + echo "$before" | base64 -d | xclip -selection clipboard + ) & disown + echo "Copied $2 to clipboard. Will clear in 45 seconds." +} + +# Load functions +LIB="`dirname $0`/../functions" +source "$LIB" || exit 1 + +# Check for xclip +if ! which xclip; then + echo "fatal: xclip not found" + exit 1 +fi + +# Get file +keyringer_get_file "$2" + +# Decrypt +pass="$($GPG --use-agent -d "$KEYDIR/$FILE" | head -n 1)" + +# Copy to clipboard +if [ ! -z "$pass" ]; then + clip "$pass" "$2" +fi + +# Exit +exit "$?" diff --git a/lib/keyringer/completions/bash/keyringer b/lib/keyringer/completions/bash/keyringer index eeda27f..a640583 100644 --- a/lib/keyringer/completions/bash/keyringer +++ b/lib/keyringer/completions/bash/keyringer @@ -70,10 +70,10 @@ _keyringer() { # Process config source $config/config - keyrings="`ls --color=never $config | sed -e 's/config//' | xargs`" + keyrings="`ls --color=never $config | sed -e '/^config$/d' | xargs`" # Available instances - instances="`echo $keyrings | sed -e 's/ /\\\|/g'`" + instances="`echo $keyrings | sed -e 's/ /$\\\|^/g' -e 's/^/^/' -e 's/$/$/'`" # The current instance instance="${COMP_WORDS[1]}" @@ -94,7 +94,7 @@ _keyringer() { recipients) opts="ls edit" ;; - ls|tree|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open) + ls|tree|mkdir|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open|clip|xclip) cur="`echo ${cur} | sed -e "s|^/*||"`" # avoid leading slash opts="$(bash -c "set -f && export KEYRINGER_CHECK_VERSION=false && keyringer $instance ls -p -d ${cur}*" 2> /dev/null)" ;; diff --git a/lib/keyringer/completions/zsh/_keyringer b/lib/keyringer/completions/zsh/_keyringer index 5717b00..1a6d8c6 100644 --- a/lib/keyringer/completions/zsh/_keyringer +++ b/lib/keyringer/completions/zsh/_keyringer @@ -20,9 +20,9 @@ _keyringer() { # Process config source $config/config - local keyrings="`ls --color=never $config | sed -e 's/config//' | xargs`" + local keyrings="`ls --color=never $config | sed -e '/^config$/d' | xargs`" local keyring_path="`eval echo '$'$words[2]`" - local instances="`echo $keyrings | sed -e 's/ /\\\|/g'`" + local instances="`echo $keyrings | sed -e 's/ /$\\\|^/g' -e 's/^/^/' -e 's/$/$/'`" _arguments \ '1: :->keyring' \ @@ -50,7 +50,7 @@ _keyringer() { recipients) compadd "$@" ls edit ;; - ls|tree|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open) + ls|tree|mkdir|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open|clip|xclip) words[4]="`echo $words[4] | sed -e "s|^/*||"`" # avoid leading slash compadd "$@" $(KEYRINGER_CHECK_VERSION=false keyringer $words[2] ls -p -d $words[4]'*' 2> /dev/null) ;; diff --git a/lib/keyringer/functions b/lib/keyringer/functions index bef00d9..014c2c9 100755 --- a/lib/keyringer/functions +++ b/lib/keyringer/functions @@ -206,10 +206,17 @@ function keyringer_shred { echo "$message $path using $tool..." if [ -d "$path" ]; then - find $path -exec $tool -f {} \; - rmdir $path + if [ "$tool" == "wipe" ] || [ "$tool" == "rm" ]; then + $tool -rf $path + else + find $path -exec $tool -uf {} \; + fi else - $tool -f "$path" + if [ "$tool" == "wipe" ] || [ "$tool" == "rm" ]; then + $tool -f "$path" + else + $tool -uf "$path" + fi fi } @@ -283,9 +290,9 @@ function keyringer_set_env { fi if [ ! -z "$KEYID" ]; then - GPG="gpg -u $KEYID" + GPG="gpg --quiet -u $KEYID" else - GPG="gpg" + GPG="gpg --quiet" fi # Check keyring config version @@ -398,14 +405,39 @@ function keyringer_upgrade { # Get a file argument function keyringer_get_file { - FILE="$(keyringer_filename "$1")" + FILE="$(keyringer_filename "$RELATIVE_PATH/$1")" if [ -z "$FILE" ]; then keyringer_action_usage exit 1 elif [ ! -f "$KEYDIR/$FILE" ]; then - echo "File not found: $KEYDIR/$FILE" - exit 1 + # Try to find a similar file + count=0 + candidates=(`keyringer_exec find "$BASEDIR" "$1" | grep -e '.asc$'`) + + if [ ! -z "$candidates" ]; then + echo "Could not find exact match \"$1\", please chose one" + echo "of the following secrets:" + echo "" + + for candidate in ${candidates[@]}; do + echo -e "\t[$count] $candidate" + let count++ + done + + echo "" + read -p "Enter option: " option + + if [[ "$option" =~ ^[0-9]+$ ]] && [ ! -z "${candidates[$option]}" ]; then + FILE="$(keyringer_filename "$RELATIVE_PATH/${candidates[$option]}")" + else + echo "Invalid option" + exit 1 + fi + else + echo "File not found: $KEYDIR/$FILE" + exit 1 + fi fi } @@ -427,7 +459,7 @@ function keyringer_get_new_file { fi # Complete file name - FILE="$(keyringer_filename "$FILE")" + FILE="$RELATIVE_PATH/$(keyringer_filename "$FILE")" if [ -z "$*" ]; then keyringer_action_usage @@ -474,9 +506,10 @@ function keyringer_usage { printf "Usage: %s <keyring> <action> [arguments]\n\n" "$BASENAME" printf "Available commands: \n\n" keyringer_show_actions | sed -e 's/^/\t/' - printf "\tinit <path> [remote]\n\n" $BASENAME - if [ ! -z "$keyrings" ]; then + # Display only when not in a keyring context + if [ ! -z "$keyrings" ] && [ -z "$1" ]; then + printf "\tinit <path> [remote]\n\n" $BASENAME printf "Available keyrings: %s \n" "$keyrings" fi } @@ -533,6 +566,31 @@ EOF echo "Please check for this key or fix the recipient file." exit 1 fi + + # Current date + seconds="`date +%s`" + + # Check the main key + expiry="`gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^pub | cut -d : -f 7`" + + # Check if key is expired + if [ ! -z "$expiry" ] && [[ "$seconds" -gt "$expiry" ]]; then + echo "Fatal: primary key for $recipient expired on `date --date="@$expiry"`" + exit 1 + else + # Check the subkeys + for expiry in `gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^sub | cut -d : -f 7`; do + if [[ "$seconds" -lt "$expiry" ]]; then + not_expired="1" + fi + + if [ "$not_expired" != "1" ]; then + echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." + exit 1 + fi + done + fi + fi done } @@ -546,7 +604,7 @@ function keyringer_set_recipients { candidate_no_extension="`echo $1 | sed -e 's/.asc$//'`" # Find the first matching recipient - while [ ! -z "$candidate" ] && [ "$candidate" != "." ] && [ "$candidate" != "/" ]; do + while [ ! -z "$candidate" ] && [ "$candidate" != "." ] && [ "$candidate" != "/" ] && [ "$candidate" != "/." ]; do if [ -e "$RECIPIENTS/$candidate" ]; then RECIPIENTS_FILE="$RECIPIENTS/$candidate" RECIPIENTS_FILE_BASE="$RECIPIENTS_BASE/$candidate" |