aboutsummaryrefslogtreecommitdiff
path: root/lib/bash/functions
diff options
context:
space:
mode:
Diffstat (limited to 'lib/bash/functions')
-rw-r--r--lib/bash/functions327
1 files changed, 327 insertions, 0 deletions
diff --git a/lib/bash/functions b/lib/bash/functions
new file mode 100644
index 0000000..58f7ad1
--- /dev/null
+++ b/lib/bash/functions
@@ -0,0 +1,327 @@
+#!/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 <keyring> $BASENAME <command> [arguments]"
+ else
+ echo "Usage: keyringer <keyring> $BASENAME <file>"
+ 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