From e6d3f3e0c5671ff853404a962d856ec493b8dbdb Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Mon, 27 Feb 2012 11:25:28 -0300 Subject: Multiple recipients file support --- README | 14 ++++++- keyringer | 3 +- lib/keyringer/functions | 95 +++++++++++++++++++++++++++++++++++++++++----- share/keyringer/edit | 5 ++- share/keyringer/encrypt | 5 ++- share/keyringer/recipients | 31 +++++++++++++-- share/keyringer/recrypt | 5 ++- 7 files changed, 140 insertions(+), 18 deletions(-) diff --git a/README b/README index 585550a..a20c32c 100644 --- a/README +++ b/README @@ -61,9 +61,21 @@ Managing recipients Your next step is tell keyringer the GPG key ids to encrypt files to: - keyringer recipients edit + keyringer recipients edit [recipient-name] keyringer recipients ls +Keyringer support multiple recipients in a per-folder style. Try it by +creating a sample keyringer + + keyringer recipients edit closest-friends + +Fill it with your friends key IDs. Now encrypt a secret just for then: + + keyringer encrypt closest-friends/secret + +In other words, if keyringer finds a recipient file matching a given path, +it will use it instead of the global recipients file. + Managing keys ---------------- diff --git a/keyringer b/keyringer index 391646a..8904685 100755 --- a/keyringer +++ b/keyringer @@ -57,8 +57,7 @@ function keyringer_init { mkdir -p "$BASEDIR/"{config,keys} # Setup recipients - echo "# Use entries in the form of 'john@doe.com XXXXXXXX" > "$RECIPIENTS" - echo "" >> "$RECIPIENTS" + keyringer_create_new_recipients "$RECIPIENTS/default" # Setup options touch "$OPTIONS" diff --git a/lib/keyringer/functions b/lib/keyringer/functions index da8be2e..a1c95a8 100644 --- a/lib/keyringer/functions +++ b/lib/keyringer/functions @@ -173,7 +173,8 @@ function keyringer_set_env { BASEDIR="$1" SUBCOMMAND="$2" KEYDIR="$BASEDIR/keys" - RECIPIENTS="$BASEDIR/config/recipients" + RECIPIENTS_BASE="config/recipients" + RECIPIENTS="$BASEDIR/$RECIPIENTS_BASE" OPTIONS="$BASEDIR/config/options" VERSION_INFO="$BASEDIR/config/version" @@ -182,7 +183,7 @@ function keyringer_set_env { exit 1 fi - if [ ! -f "$RECIPIENTS" ]; then + if [ ! -e "$RECIPIENTS" ]; then echo "No recipient config was found" exit 1 fi @@ -209,14 +210,17 @@ function keyringer_set_env { GPG="gpg" fi + # Check keyring config version + keyringer_check_version + + # Upgrade configuration + keyringer_upgrade + # Check recipients file keyringer_check_recipients $SUBCOMMAND # Ensure that keydir exists mkdir -p "$KEYDIR" && chmod 700 "$KEYDIR" - - # Check keyring config version - keyringer_check_version } # Configuration version tracking to help keyring upgrades @@ -232,6 +236,26 @@ function keyringer_check_version { VERSION="`cat $VERSION_INFO`" } +# Configuration upgrades +function keyringer_upgrade { + # Upgrade 0.1 + if [ "$VERSION" == "0" ]; then + if [ ! -d "$RECIPIENTS" ]; then + echo "Converting recipients to the new scheme..." + mv $RECIPIENTS $RECIPIENTS.tmp + mkdir $RECIPIENTS + mv $RECIPIENTS.tmp $RECIPIENTS/default + keyringer_exec git "$BASEDIR" add $RECIPIENTS_BASE/default + keyringer_exec git "$BASEDIR" add config/version + keyringer_exec git "$BASEDIR" commit -m "Config-upgrade-0.1" + echo "Upgrade to version 0.1 completed" + fi + + # Update version information + echo 0.1 > $VERSION_INFO + fi +} + # Get a file argument function keyringer_get_file { FILE="$(keyringer_filename "$1")" @@ -284,16 +308,16 @@ function keyringer_action_usage { # Check recipients function keyringer_check_recipients { # Check if recipients file is empty. - if [ "`grep -vE "^#|^$" "$RECIPIENTS" | wc -l`" == 0 ] && [ "$SUBCOMMAND" != "edit" ]; then + if [ "`grep -vE "^#|^$" "$RECIPIENTS"/* | wc -l`" == 0 ] && [ "$SUBCOMMAND" != "edit" ]; then echo "Fatal: no recipients configured for this keyring." echo "Please edit your recipients file first." exit 1 fi # Check recipients header for updates. - if grep -qe ' XXXXXXXX$' "$RECIPIENTS"; then + if grep -qe ' XXXXXXXX$' "$RECIPIENTS"/*; then echo "Updating recipients file..." - sed -i -e 's/ XXXXXXXX$/ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/' "$RECIPIENTS" + sed -i -e 's/ XXXXXXXX$/ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/' "$RECIPIENTS"/* fi if [ "$1" == "edit" ]; then @@ -301,7 +325,7 @@ function keyringer_check_recipients { return fi - for recipient in $(cat "$RECIPIENTS" | grep -v '^#' | awk '{ print $2 }'); do + for recipient in $(cat "$RECIPIENTS"/* | grep -v '^#' | awk '{ print $2 }'); do size=$(echo "$recipient" | wc -c) if (( $size < 41 )); then echo "Fatal: please set the full GPG signature hash for key ID $recipient:" @@ -329,6 +353,59 @@ EOF done } +# Set recipients +function keyringer_set_recipients { + if [ -z "$1" ]; then + keyringer_set_default_recipients + else + candidate="$1" + + # Find the first matching recipient + while [ ! -z "$candidate" ] && [ "$candidate" != "." ] && [ "$candidate" != "/" ]; do + if [ -e "$RECIPIENTS/$candidate" ]; then + RECIPIENTS_FILE="$RECIPIENTS/$candidate" + RECIPIENTS_FILE_BASE="$RECIPIENTS_BASE/$candidate" + return + fi + + candidate="`dirname $candidate`" + done + + keyringer_set_default_recipients "$1" + + fi +} + +# Set default recipients +function keyringer_set_default_recipients { + if [ -e "$RECIPIENTS/default" ]; then + RECIPIENTS_FILE="$RECIPIENTS/default" + RECIPIENTS_FILE_BASE="$RECIPIENTS_BASE/default" + else + echo "Fatal: no suitable recipient file found for path $1" + exit 1 + fi +} + +# Set a new recipient, avoid file checks +function keyringer_set_new_recipients { + if [ -z "$1" ]; then + keyringer_set_default_recipients + else + RECIPIENTS_FILE="$RECIPIENTS/$1" + RECIPIENTS_FILE_BASE="$RECIPIENTS_BASE/$1" + fi +} + +# Create a new recipients file +function keyringer_create_new_recipients { + if [ ! -e "$1" ]; then + mkdir -p "`dirname $1`" + echo "# Use entries in the form of 'john@doe.com XXXXXXXX" > "$1" + echo "" >> "$1" + fi +} + # Setup environment if [ "$(basename "$0")" != "keyringer" ]; then keyringer_set_env $* diff --git a/share/keyringer/edit b/share/keyringer/edit index 73a59d9..10798e2 100755 --- a/share/keyringer/edit +++ b/share/keyringer/edit @@ -10,6 +10,9 @@ source "$LIB" || exit 1 # Get file keyringer_get_file "$2" +# Set recipients file +keyringer_set_recipients "$FILE" + # Warn user echo "Make sure that $BASEDIR is atop of an encrypted volume." @@ -25,7 +28,7 @@ read key "$EDITOR" "$TMPWORK" # Encrypt again -$GPG --yes -o "$KEYDIR/$FILE" --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS") "$TMPWORK" +$GPG --yes -o "$KEYDIR/$FILE" --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") "$TMPWORK" # Remove temp file keyringer_unset_tmpfile "$TMPWORK" diff --git a/share/keyringer/encrypt b/share/keyringer/encrypt index 709aac3..da0941f 100755 --- a/share/keyringer/encrypt +++ b/share/keyringer/encrypt @@ -10,6 +10,9 @@ source "$LIB" || exit 1 # Aditional parameters keyringer_get_new_file "$2" +# Set recipients file +keyringer_set_recipients "$FILE" + # Encrypt mkdir -p "$KEYDIR/`dirname $FILE`" @@ -18,7 +21,7 @@ if [ "$BASENAME" == "encrypt" ]; then echo "Type your message and finish your input with EOF (Ctrl-D)." fi -$GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS") - > "$KEYDIR/$FILE" +$GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") - > "$KEYDIR/$FILE" # Stage if [ -d "$BASEDIR/.git" ]; then diff --git a/share/keyringer/recipients b/share/keyringer/recipients index 2fe2ddf..ab61bd7 100755 --- a/share/keyringer/recipients +++ b/share/keyringer/recipients @@ -10,11 +10,36 @@ source "$LIB/functions" || exit 1 # Command parser keyringer_get_command "$2" +# Set recipients file +keyringer_set_new_recipients "$3" + if [ "$COMMAND" == "ls" ]; then - cat "$RECIPIENTS" + if [ ! -z "$3" ]; then + if [ -e "$RECIPIENTS_FILE" ]; then + cat "$RECIPIENTS_FILE" + else + echo "Recipients file not found: $RECIPIENTS_FILE_BASE" + exit 1 + fi + else + for recipients in `ls $RECIPIENTS`; do + echo "In recipients file $recipients:" + echo "-----------------------------------------------------------------------------------" + cat $RECIPIENTS/$recipients + echo "" + done + fi elif [ "$COMMAND" == "edit" ]; then - "$EDITOR" "$RECIPIENTS" - keyringer_check_recipients + if [ ! -z "$3" ]; then + keyringer_create_new_recipients $RECIPIENTS_FILE + "$EDITOR" "$RECIPIENTS_FILE" + keyringer_check_recipients + keyringer_exec git "$BASEDIR" add "$RECIPIENTS_FILE_BASE" + else + echo "Please specify one recipient to edit among the available:" + ls $RECIPIENTS | sed -e 's/^/\t/' + exit 1 + fi else printf "%s: No such command %s\n" "$BASENAME" "$COMMAND" exit 1 diff --git a/share/keyringer/recrypt b/share/keyringer/recrypt index 438039d..cbf1af9 100755 --- a/share/keyringer/recrypt +++ b/share/keyringer/recrypt @@ -11,8 +11,11 @@ function keyringer_recrypt { # Get file keyringer_get_file "$1" + # Set recipients file + keyringer_set_recipients "$FILE" + # Recrypt - $GPG --use-agent -d "$KEYDIR/$FILE" | $GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS") > "$KEYDIR/$FILE" + $GPG --use-agent -d "$KEYDIR/$FILE" | $GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") > "$KEYDIR/$FILE" if [ "$?" != "0" ]; then exit 1 -- cgit v1.2.3