summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/keyringer/completions/bash/keyringer124
-rw-r--r--lib/keyringer/completions/zsh/_keyringer88
-rw-r--r--lib/keyringer/functions41
3 files changed, 245 insertions, 8 deletions
diff --git a/lib/keyringer/completions/bash/keyringer b/lib/keyringer/completions/bash/keyringer
new file mode 100644
index 0000000..e33977a
--- /dev/null
+++ b/lib/keyringer/completions/bash/keyringer
@@ -0,0 +1,124 @@
+#!bash
+#
+# Keyringer bash completion
+#
+
+if [[ -n ${ZSH_VERSION-} ]]; then
+ autoload -U +X bashcompinit && bashcompinit
+fi
+
+# Completion for git subcommand
+_keyringer_git_complete() {
+ if [ -e "/etc/bash_completion.d/git" ]; then
+ (
+ source /etc/bash_completion.d/git
+ cd $path
+ COMP_WORDS=(git $*)
+ COMP_CWORD=$((${#COMP_WORDS[*]} - 1))
+
+ if [ "$COMP_CWORD" == "0" ]; then
+ COMP_CWORD=1
+ fi
+
+ _git
+
+ LAST=${COMP_WORDS[COMP_CWORD]}
+ REPLY=${COMPREPLY[@]}
+
+ if [ "$REPLY" == "$LAST" ]; then
+ return
+ fi
+
+ echo ${COMPREPLY[@]}
+ )
+ fi
+}
+
+_keyringer() {
+ # Standard stuff
+ local cur prev opts config
+ COMPREPLY=()
+ cur="${COMP_WORDS[COMP_CWORD]}"
+ prev="${COMP_WORDS[COMP_CWORD-1]}"
+ command="${COMP_WORDS[2]}"
+
+ # Initial options
+ config="$HOME/.keyringer"
+
+ # Check if we have initial configuration
+ if [ ! -d "$config" ]; then
+ return
+ fi
+
+ # Process config
+ source $config/config
+ path="`eval echo '$'$instance`"
+ keyrings="`ls $config | sed -e 's/config//'`"
+
+ # Available instances
+ instances="`echo $keyrings | sed -e 's/ /|/'`"
+
+ # The current instance
+ instance="${COMP_WORDS[1]}"
+
+ # Command completions
+ if [ "${#COMP_WORDS[@]}" == "2" ]; then
+ opts="$keyrings"
+ elif [ "${#COMP_WORDS[@]}" == "3" ] && echo "${prev}" | grep -qe "[$instances]"; then
+ opts="`keyringer $instance commands`"
+ elif [ "${#COMP_WORDS[@]}" == "4" ]; then
+ case "${prev}" in
+ options|preferences)
+ opts="ls edit add"
+ ;;
+ recipients)
+ opts="ls edit"
+ ;;
+ ls|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|recrypt)
+ opts="$(bash -c "set -f && keyringer $instance ls -p -d ${cur}*" 2> /dev/null)"
+ ;;
+ genpair)
+ opts="gpg ssh ssl ssl-self"
+ ;;
+ git)
+ opts="$(_keyringer_git_complete ${cur})"
+ ;;
+ *)
+ ;;
+ esac
+ elif [ "${#COMP_WORDS[@]}" == "5" ]; then
+ case "${command}" in
+ recipients)
+ opts="$(cd $path/config/recipients && ls -p ${cur}* 2> /dev/null)"
+ ;;
+ genpair)
+ opts="$(bash -c "set -f && keyringer $instance ls -p -d ${cur}*" 2> /dev/null)"
+ ;;
+ git)
+ # TODO
+ opts="$(_keyringer_git_complete ${prev} ${cur})"
+ ;;
+ *)
+ ;;
+ esac
+ elif [ "${command}" == "git" ]; then
+ # TODO
+ opts="$(_keyringer_git_complete ${COMP_WORDS[@]:3})"
+ fi
+
+ # Avoid annoying bell and extra tab
+ if [ -z "$ZSH_VERSION" ]; then
+ bind 'set show-all-if-ambiguous on'
+ fi
+
+ # Return the available options
+ COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
+
+ if [ -z "$ZSH_VERSION" ]; then
+ [[ $COMPREPLY == */ ]] && compopt -o nospace
+ fi
+
+ return 0
+}
+
+complete -F _keyringer keyringer
diff --git a/lib/keyringer/completions/zsh/_keyringer b/lib/keyringer/completions/zsh/_keyringer
new file mode 100644
index 0000000..c8ada9b
--- /dev/null
+++ b/lib/keyringer/completions/zsh/_keyringer
@@ -0,0 +1,88 @@
+#compdef keyringer
+
+# Completion for git subcommand
+_keyringer_git_complete() {
+ # TODO: how to call _git() properly?
+ return
+}
+
+_keyringer() {
+ local curcontext="$curcontext" state line
+ typeset -A opt_args
+
+ # Initial options
+ local config="$HOME/.keyringer"
+
+ # Check if we have initial configuration
+ if [ ! -d "$config" ]; then
+ return
+ fi
+
+ # Process config
+ local keyrings="`ls $config | sed -e 's/config//'`"
+ source $config/config
+ keyring_path="`eval echo '$'$words[2]`"
+
+ _arguments \
+ '1: :->keyring' \
+ '2: :->action' \
+ '3: :->options' \
+ '4: :->misc' \
+ '*: :->final'
+
+ case $state in
+ keyring)
+ _arguments "1:Keyrings:($keyrings)"
+ ;;
+ action)
+ compadd "$@" `keyringer $words[2] commands`
+ ;;
+ options)
+ case $words[3] in
+ options|preferences)
+ compadd "$@" ls edit add
+ ;;
+ recipients)
+ compadd "$@" ls edit
+ ;;
+ ls|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|recrypt)
+ # TODO: do not rely on bash
+ compadd "$@" $(bash -c "set -f && keyringer $words[2] ls -p -d $words[4]*" 2> /dev/null)
+ ;;
+ genpair)
+ compadd "$@" gpg ssh ssl ssl-self
+ ;;
+ git)
+ compadd "$@" $(_keyringer_git_complete $words[4])
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ misc)
+ case "$words[3]" in
+ recipients)
+ compadd "$@" $(cd $keyring_path/config/recipients && ls -p $words[5]* 2> /dev/null)
+ ;;
+ genpair)
+ # TODO: do not rely on bash
+ compadd "$@" $(bash -c "set -f && keyringer $words[2] ls -p -d $words[5]*" 2> /dev/null)
+ ;;
+ git)
+ # TODO
+ compadd "$@" $(_keyringer_git_complete $words[4] $words[5])
+ ;;
+ *)
+ ;;
+ esac
+ ;;
+ *)
+ if [ $words[3] == "git" ]; then
+ # TODO
+ true
+ fi
+ ;;
+ esac
+}
+
+_keyringer "$@"
diff --git a/lib/keyringer/functions b/lib/keyringer/functions
index 6ac8bf8..3fa7170 100644
--- a/lib/keyringer/functions
+++ b/lib/keyringer/functions
@@ -74,6 +74,10 @@ function keyringer_exec {
# Dispatch
if keyringer_has_action "$action"; then
"$ACTIONS/$action" "$basedir" $*
+ err="$?"
+ if [ "$err" != "0" ]; then
+ exit "$err"
+ fi
fi
}
@@ -338,8 +342,24 @@ function keyringer_action_usage {
fi
}
+# Return available actions
+function keyringer_show_actions {
+ ls $ACTIONS
+}
+
+# Usage
+function keyringer_usage {
+ printf "Usage: %s <keyring> <action> [arguments]\n" "$BASENAME"
+ printf "Available commands: \n"
+ keyringer_show_actions | sed -e 's/^/\t/'
+}
+
# Check recipients
function keyringer_check_recipients {
+ if [ "$KEYRINGER_CHECK_RECIPIENTS" == "false" ]; then
+ return
+ fi
+
# Check if recipients file is empty.
if [ "`grep -vE "^#|^$" "$RECIPIENTS"/* | wc -l`" == 0 ] && [ "$SUBCOMMAND" != "edit" ]; then
echo "Fatal: no recipients configured for this keyring."
@@ -364,15 +384,19 @@ function keyringer_check_recipients {
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.
+Please provide a full OpenPGP fingerprint, for example:
+
+ john@doe.com ABCD1234ABCD12345678ABCD1234ABCD12345678
-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.
+Short key ids (for example, DEADBEEF or DECAF123) are not allowed in
+recipient files because they are easy to spoof. Researchers have proven
+that it is possible to build fake keys to match any possible short key
+id by using a few gigabytes of disk space, and a day of computation on
+common hardware.
+
+Otherwise, the encryption can be broken, if someone spoofs a short key
+id, and causes a participant in a keyringer repository to encrypt
+secrets to a fake key.
EOF
exit 1
else
@@ -446,5 +470,6 @@ function keyringer_create_new_recipients {
# Setup environment
if [ "$(basename "$0")" != "keyringer" ]; then
+ keyringer_config_load_preferences
keyringer_set_env $*
fi