#!/bin/bash # # Common functions. # # Setup main configuration and load preferences function keyringer_config_load { if [ -f "$HOME/.$NAME" ]; then echo "Converting legacy configuration scheme..." mv "$HOME/.$NAME" "$HOME/.$NAME.tmp" mkdir "$HOME/.$NAME" mv "$HOME/.$NAME.tmp" "$CONFIG" fi if [ ! -e "$CONFIG" ]; then echo "Creating $CONFIG..." mkdir -p `dirname $CONFIG` touch "$CONFIG" chmod 600 "$CONFIG" echo "# Keyringer config file." > "$CONFIG" echo "" >> "$CONFIG" fi keyringer_config_load_preferences } # Load config preferences function keyringer_config_load_preferences { # Load custom keyring preferences if [ ! -z "$PREFERENCES" ] && [ -f "$PREFERENCES" ]; then source "$PREFERENCES" fi } # Load a parameter from config function keyringer_config { if [ -z "$CONFIG" ]; then echo "Your have to set CONFIG variable in the code" exit 1 elif [ -e "$CONFIG" ]; then grep -e "^$1=" "$CONFIG" | tail -n 1 | cut -d = -f 2 | sed -e 's/"//g' -e "s/'//g" | sed -e 's/ *#.*$//' else echo "Config file not found: $CONFIG" exit 1 fi } # Return the list of recipients function keyringer_recipients { grep -v '^#' "$1" | grep -v '^$' | awk '{ print "-r " $2 }' | xargs } # Check if keyringer has a given action function keyringer_has_action { if [ -z "$ACTIONS" ]; then echo "Your have to set ACTIONS variable in the code" exit 1 fi if [ -e "$ACTIONS/$1" ]; then true else false fi } # Execute an action function keyringer_exec { # Setup action="$1" basedir="$2" shift 2 # Dispatch if keyringer_has_action "$action"; then "$ACTIONS/$action" "$basedir" $* fi } # Return a filename with correct extension function keyringer_filename { if [ -z "$1" ]; then return else printf "%s/%s.asc\n" "$(dirname "$1")" "$(basename "$1" .asc)" fi } # Check if a folder is inside a git repository function keyringer_is_git { if [ -z "$1" ]; then false elif [ ! -d "$1" ]; then false elif [ -d "$1/.git" ]; then true else cwd="`pwd`" cd "$1" && git="`git status &> /dev/null`" && cd "$cwd" if [ "$git" != "128" ]; then true else false fi fi } # Setup a temporary file function keyringer_set_tmpfile { if [ -z "$BASEDIR" ]; then echo "Please set BASEDIR before creating a tmp file" exit 1 fi if [ -z "$1" ]; then template="$BASEDIR/tmp/keyringer.XXXXXXXXXX" else template="$BASEDIR/tmp/$1.XXXXXXXXXX" fi mkdir -p "$BASEDIR/tmp" keyringer_git_ignore 'tmp/*' if [ "$2" == "-d" ]; then TMPWORK="$(mktemp -d "$template")" else TMPWORK="$(mktemp "$template")" fi if [ "$?" != "0" ]; then printf "Error: can't set TMPWORK %s\n" "$TMPWORK" exit 1 fi trap "keyringer_unset_tmpfile $TMPWORK; exit" INT TERM EXIT } # Remove a temporary file function keyringer_unset_tmpfile { if [ -z "$1" ]; then echo "No tmp file set" fi rm -f "$1" if [ "$?" != "0" ]; then echo "Warning: could not delete file $1. Please delete it manually as it might have sensitive information." exit 1 fi } # Add a pattern into gitignore function keyringer_git_ignore { if [ ! -z "$BASEDIR/.gitignore" ]; then echo "$1" > "$BASEDIR/.gitignore" keyringer_exec git "$BASEDIR" add .gitignore else if ! grep -q -e "^$1$" "$BASEDIR/.gitignore"; then echo "$1" >> "$BASEDIR/.gitignore" fi fi } # Set needed environment variables and do basic checks. function keyringer_set_env { if [ -z "$1" ]; then echo "Error: missing arguments for keyringer_set_env" exit 1 fi ACTIONS="`dirname $0`" BASENAME="`basename $0`" BASEDIR="$1" SUBCOMMAND="$2" KEYDIR="$BASEDIR/keys" RECIPIENTS="$BASEDIR/config/recipients" OPTIONS="$BASEDIR/config/options" VERSION_INFO="$BASEDIR/config/version" if [ -z "$BASEDIR" ]; then keyringer_action_usage exit 1 fi if [ ! -f "$RECIPIENTS" ]; then echo "No recipient config was found" exit 1 fi if [ -z "$EDITOR" ]; then if type sensible-editor > /dev/null 2>&1 ; then EDITOR=sensible-editor elif type editor > /dev/null 2>&1 ; then EDITOR=editor else echo "You have to set EDITOR env variable" exit 1 fi fi if [ ! -f "$OPTIONS" ]; then echo "No option config was found" exit 1 fi if [ ! -z "$KEYID" ]; then GPG="gpg -u $KEYID" else GPG="gpg" fi # 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 function keyringer_check_version { if [ ! -f "$VERSION_INFO" ]; then echo "Creating configuration version file..." echo 0 > "$VERSION_INFO" keyringer_exec git "$BASEDIR" add config/version fi VERSION="`cat $VERSION_INFO`" } # Get a file argument function keyringer_get_file { FILE="$(keyringer_filename "$1")" if [ -z "$FILE" ]; then keyringer_action_usage exit 1 elif [ ! -f "$KEYDIR/$FILE" ]; then echo "File not found: $KEYDIR/$FILE" exit 1 fi } # Get a new file argument function keyringer_get_new_file { FILE="$(keyringer_filename "$1")" if [ -z "$FILE" ]; then keyringer_action_usage exit 1 fi } # Get a command argument function keyringer_get_command { # Aditional parameters COMMAND="$1" if [ -z "$COMMAND" ]; then keyringer_action_usage command exit 1 fi } # Run the action usage function keyringer_action_usage { if [ "`type -t "keyringer_usage_$BASENAME"`" == "function" ]; then # Use custom action usage "keyringer_usage_$BASENAME" else # Default usage if [ "$1" == "command" ]; then echo "Usage: keyringer $BASENAME [arguments]" else echo "Usage: keyringer $BASENAME " fi fi } # Check recipients function keyringer_check_recipients { # Check recipients header for updates. if grep -qe ' XXXXXXXX$' "$RECIPIENTS"; then echo "Updating recipients file..." sed -i -e 's/ XXXXXXXX$/ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/' "$RECIPIENTS" fi if [ "$1" == "edit" ]; then # Don't do the other checks at edit mode. return fi 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:" cat <<-EOF Recipients file can't have 32-bit keyids (e.g. DEADBEEF or DECAF123). These are trivial to spoof. With a few gigs of disk space and a day of time on cheap, readily-available hardware, it's possible to build keys to match every possible 32-bit keyid. The search space just isn't big enough. If you're going to specify keys by keyid, they should be specified by full 160-bit OpenPGP fingerprint. It would be very bad if someone spoofed a keyID and caused another participant in a keyringer instance to reencrypt a secret store to the spoofed key in addition to your own. EOF exit 1 else gpg --list-key "$recipient" &> /dev/null if [ "$?" != "0" ]; then echo "Fatal: no such key $recipient on your GPG keyring." echo "Please check for this key or fix the recipient file." exit 1 fi fi done } # Setup environment if [ "$(basename "$0")" != "keyringer" ]; then keyringer_set_env $* fi