summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSilvio Rhatto <rhatto@riseup.net>2013-11-14 18:39:49 -0200
committerSilvio Rhatto <rhatto@riseup.net>2013-11-14 18:39:49 -0200
commit39cba88c4122d956f4711cf692f387ef4d97d1b6 (patch)
tree38b116f28b3d7073fa7a3687337f00d8ee216537 /lib
parent7ffd60b5c34fa5fb19a52a12f2e7c5f4f032739d (diff)
parentf978a7fcc7917df39a64800838e814927971469e (diff)
downloadkeyringer-39cba88c4122d956f4711cf692f387ef4d97d1b6.tar.gz
keyringer-39cba88c4122d956f4711cf692f387ef4d97d1b6.tar.bz2
Merge tag 'upstream_keyringer_0.2.7' into debian
Upstream version 0.2.7
Diffstat (limited to 'lib')
-rwxr-xr-xlib/keyringer/actions/append38
l---------lib/keyringer/actions/append-batch1
-rwxr-xr-xlib/keyringer/actions/commands10
-rwxr-xr-xlib/keyringer/actions/decrypt17
-rwxr-xr-xlib/keyringer/actions/del16
-rwxr-xr-xlib/keyringer/actions/edit47
-rwxr-xr-xlib/keyringer/actions/encrypt87
l---------lib/keyringer/actions/encrypt-batch1
-rwxr-xr-xlib/keyringer/actions/genpair222
-rwxr-xr-xlib/keyringer/actions/git16
-rwxr-xr-xlib/keyringer/actions/ls16
l---------lib/keyringer/actions/open1
-rwxr-xr-xlib/keyringer/actions/options30
-rwxr-xr-xlib/keyringer/actions/preferences37
-rwxr-xr-xlib/keyringer/actions/recipients46
-rwxr-xr-xlib/keyringer/actions/recrypt45
-rwxr-xr-xlib/keyringer/actions/usage10
-rw-r--r--lib/keyringer/completions/bash/keyringer18
-rw-r--r--lib/keyringer/completions/zsh/_keyringer3
-rwxr-xr-xlib/keyringer/functions121
20 files changed, 766 insertions, 16 deletions
diff --git a/lib/keyringer/actions/append b/lib/keyringer/actions/append
new file mode 100755
index 0000000..e945bff
--- /dev/null
+++ b/lib/keyringer/actions/append
@@ -0,0 +1,38 @@
+#!/bin/bash
+#
+# Append information into encrypted files.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Get file
+keyringer_get_file "$2"
+
+OLDIFS="$IFS"
+IFS=$'\n'
+
+CONTENT=($(keyringer_exec decrypt "$BASEDIR" "$FILE"))
+
+if [ "$BASENAME" == "append" ]; then
+ # only display directions if we're running append, not append-batch
+ printf "\n%s currently has %d lines\n\n" "$FILE" "${#CONTENT[@]}"
+ printf "Now please write the content to be appended on %s, finnishing with Ctrl-D:\n" "$FILE"
+fi
+
+APPEND=($(cat -))
+
+NEW=( ${CONTENT[@]} ${APPEND[@]} )
+
+for element in $(seq 0 $((${#NEW[@]} - 1))); do
+ echo ${NEW[$element]}
+done | keyringer_exec encrypt-batch $BASEDIR $FILE
+
+err="$?"
+
+if [ "$err" != "0" ]; then
+ exit "$err"
+fi
+
+IFS="$OLDIFS"
diff --git a/lib/keyringer/actions/append-batch b/lib/keyringer/actions/append-batch
new file mode 120000
index 0000000..6b140f7
--- /dev/null
+++ b/lib/keyringer/actions/append-batch
@@ -0,0 +1 @@
+append \ No newline at end of file
diff --git a/lib/keyringer/actions/commands b/lib/keyringer/actions/commands
new file mode 100755
index 0000000..2605666
--- /dev/null
+++ b/lib/keyringer/actions/commands
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Show available commands
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+keyringer_show_actions
diff --git a/lib/keyringer/actions/decrypt b/lib/keyringer/actions/decrypt
new file mode 100755
index 0000000..2b1401c
--- /dev/null
+++ b/lib/keyringer/actions/decrypt
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Decrypt files.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Get file
+keyringer_get_file "$2"
+
+# Decrypt
+$GPG --quiet --use-agent -d "$KEYDIR/$FILE"
+
+# Exit
+exit "$?"
diff --git a/lib/keyringer/actions/del b/lib/keyringer/actions/del
new file mode 100755
index 0000000..babd212
--- /dev/null
+++ b/lib/keyringer/actions/del
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# Remove files.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Get file
+keyringer_get_file "$2"
+
+# Remove
+if [ -d "$BASEDIR/.git" ]; then
+ keyringer_exec git "$BASEDIR" rm "keys/$FILE"
+fi
diff --git a/lib/keyringer/actions/edit b/lib/keyringer/actions/edit
new file mode 100755
index 0000000..9a3e488
--- /dev/null
+++ b/lib/keyringer/actions/edit
@@ -0,0 +1,47 @@
+#!/bin/bash
+#
+# Edit keys.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Get file
+keyringer_get_file "$2"
+
+# Set recipients file
+keyringer_set_recipients "$FILE"
+
+# Get original file EXTENSION
+FILENAME="$(basename "$FILE" .asc)"
+FILENAME="$(basename "$FILENAME")"
+EXTENSION="${FILENAME##*.}"
+
+# Set a tmp file
+keyringer_set_tmpfile $BASENAME.$EXTENSION
+
+# Decrypt the information to the file
+$GPG --yes -o "$TMPWORK" --use-agent -d "$KEYDIR/$FILE"
+
+if [ "$BASENAME" == "edit" ]; then
+ APP="$EDITOR"
+elif [ "$BASENAME" == "open" ]; then
+ if which xdg-open &> /dev/null; then
+ APP="xdg-open"
+ else
+ echo "You should have xdg-open application to perform this action, aborting."
+ exit 1
+ fi
+fi
+
+# Prompt
+echo "Press any key to open the decrypted data with $APP, Ctrl-C to abort"
+read key
+$APP "$TMPWORK"
+
+# Encrypt again
+$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/lib/keyringer/actions/encrypt b/lib/keyringer/actions/encrypt
new file mode 100755
index 0000000..aadb9fa
--- /dev/null
+++ b/lib/keyringer/actions/encrypt
@@ -0,0 +1,87 @@
+#!/bin/bash
+#
+# Encrypt files to multiple recipients.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Usage
+function keyringer_usage_encrypt {
+ echo "Usage: keyringer <keyring> $BASENAME <secret> [file]"
+}
+
+# Alias for keyringer_usage_encrypt
+function keyringer_usage_encrypt_batch {
+ keyringer_usage_encrypt $*
+}
+
+# Usage
+if [ -z "$2" ]; then
+ keyringer_action_usage
+ exit 1
+fi
+
+# Aditional parameters
+if [ ! -z "$3" ]; then
+ # Set secret name and original file
+ FILE="$2"
+ shift 2
+ UNENCRYPTED_FILE="$*"
+
+ # Get original file EXTENSION
+ FILENAME="$(basename "$UNENCRYPTED_FILE")"
+ EXTENSION="${FILENAME##*.}"
+
+ # Append file extension in the secret name
+ #
+ # Useful when opening files and the application needs the
+ # extension to guess the file type.
+ if ! echo $FILE | grep -q -e "\.$EXTENSION$"; then
+ FILE="$FILE.$EXTENSION"
+ fi
+
+ keyringer_get_new_file $FILE
+
+ if [ ! -f "$UNENCRYPTED_FILE" ]; then
+ echo "Error: cannot encrypt $UNENCRYPTED_FILE: file not found."
+ exit 1
+ fi
+else
+ UNENCRYPTED_FILE="-"
+ shift
+ keyringer_get_new_file $*
+fi
+
+# Set recipients file
+keyringer_set_recipients "$FILE"
+
+# Encrypt
+mkdir -p "$KEYDIR/`dirname $FILE`"
+
+if [ "$BASENAME" == "encrypt" ]; then
+ # Only display directions if we're running encrypt, not encrypt-batch
+ if [ "$UNENCRYPTED_FILE" == "-" ]; then
+ echo "Type your message and finish your input with EOF (Ctrl-D)."
+ fi
+fi
+
+$GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") --yes --output "$KEYDIR/$FILE" "$UNENCRYPTED_FILE"
+
+err="$?"
+
+if [ "$err" != "0" ]; then
+ exit "$err"
+fi
+
+if [ "$UNENCRYPTED_FILE" != "-" ]; then
+ echo "Done. PLEASE WIPE the non-encrypted $UNENCRYPTED_FILE."
+fi
+
+# Stage
+if [ -d "$BASEDIR/.git" ]; then
+ keyringer_exec git "$BASEDIR" add "keys/$FILE"
+fi
+
+exit "$?"
diff --git a/lib/keyringer/actions/encrypt-batch b/lib/keyringer/actions/encrypt-batch
new file mode 120000
index 0000000..8267197
--- /dev/null
+++ b/lib/keyringer/actions/encrypt-batch
@@ -0,0 +1 @@
+encrypt \ No newline at end of file
diff --git a/lib/keyringer/actions/genpair b/lib/keyringer/actions/genpair
new file mode 100755
index 0000000..f048bc7
--- /dev/null
+++ b/lib/keyringer/actions/genpair
@@ -0,0 +1,222 @@
+#!/bin/bash
+#
+# Generate keypairs.
+#
+# This script is just a wrapper to easily generate keys for
+# automated systems.
+#
+
+# Generate a keypair, ssh version
+function genpair_ssh {
+ echo "Make sure that $KEYDIR is atop of an encrypted volume."
+ read -p "Hit ENTER to continue." prompt
+
+ # We're using empty passphrases
+ ssh-keygen -t rsa -P '' -f "$TMPWORK/id_rsa" -C "root@$NODE"
+
+ # Encrypt the result
+ echo "Encrypting secret key into keyringer..."
+ cat "$TMPWORK/id_rsa" | keyringer_exec encrypt "$BASEDIR" "$FILE"
+ echo "Encrypting public key into keyringer..."
+ cat "$TMPWORK/id_rsa.pub" | keyringer_exec encrypt "$BASEDIR" "$FILE.pub"
+
+ if [ ! -z "$OUTFILE" ]; then
+ mkdir -p `dirname $OUTFILE`
+ printf "Saving copies at %s and %s.pub\n" "$OUTFILE" "$OUTFILE"
+ cat "$TMPWORK/id_rsa" > "$OUTFILE"
+ cat "$TMPWORK/id_rsa.pub" > "$OUTFILE.pub"
+ fi
+
+ echo "Done"
+}
+
+# Generate a keypair, gpg version
+function genpair_gpg {
+ echo "Make sure that $KEYDIR is atop of an encrypted volume."
+
+ passphrase="no"
+ passphrase_confirm="confirm"
+
+ while [ "$passphrase" != "$passphrase_confirm" ]; do
+ read -s -p "Enter password for the private key: " passphrase
+ printf "\n"
+ read -s -p "Enter password again: " passphrase_confirm
+ printf "\n"
+
+ if [ "$passphrase" != "$passphrase_confirm" ]; then
+ echo "Password don't match."
+ fi
+ done
+
+ # TODO: insert random bytes
+ # TODO: custom Name-Comment and Name-Email
+ # TODO: allow for empty passphrases
+ $GPG --homedir "$TMPWORK" --gen-key --batch <<EOF
+ Key-Type: RSA
+ Key-Length: 4096
+ Subkey-Type: ELG-E
+ Subkey-Length: 4096
+ Name-Real: $NODE
+ Name-Email: root@$NODE
+ Expire-Date: 0
+ Passphrase: $passphrase
+ %commit
+EOF
+
+ # Encrypt the result
+ echo "Encrypting secret key into keyringer..."
+ $GPG --armor --homedir "$TMPWORK" --export-secret-keys | keyringer_exec encrypt "$BASEDIR" "$FILE"
+ echo "Encrypting public key into keyringer..."
+ $GPG --armor --homedir "$TMPWORK" --export | keyringer_exec encrypt "$BASEDIR" "$FILE.pub"
+ echo "Encrypting passphrase into keyringer..."
+ echo "Passphrase for $FILE: $passphrase" | keyringer_exec encrypt "$BASEDIR" "$FILE.passwd"
+
+ if [ ! -z "$OUTFILE" ]; then
+ mkdir -p `dirname $OUTFILE`
+ printf "Saving copies at %s and %s.pub\n" "$OUTFILE" "$OUTFILE"
+ $GPG --armor --homedir "$TMPWORK" --export-secret-keys > "$OUTFILE"
+ $GPG --armor --homedir "$TMPWORK" --export > "$OUTFILE.pub"
+ fi
+
+ echo "Done"
+}
+
+# Generate a keypair, ssl version
+function genpair_ssl {
+ echo "Make sure that $KEYDIR is atop of an encrypted volume."
+ read -p "Hit ENTER to continue." prompt
+
+ # Check for wildcard certs
+ if [ "`echo $NODE | cut -d . -f 1`" == "*" ]; then
+ WILDCARD="yes"
+ CNAME="$NODE"
+ NODE="`echo $NODE | sed -e 's/^\*\.//'`"
+ else
+ CNAME="${NODE}"
+ fi
+
+ # Setup
+ cd "$TMPWORK"
+
+ # Generate certificate
+cat <<EOF >> openssl.conf
+[ req ]
+default_keyfile = ${NODE}_privatekey.pem
+distinguished_name = req_distinguished_name
+encrypt_key = no
+req_extensions = v3_req # Extensions to add to certificate request
+string_mask = nombstr
+
+[ req_distinguished_name ]
+commonName_default = ${CNAME}
+organizationName = Organization Name
+organizationalUnitName = Organizational Unit Name
+emailAddress = Email Address
+localityName = Locality
+stateOrProvinceName = State
+countryName = Country Name
+commonName = Common Name
+
+[ v3_req ]
+extendedKeyUsage=serverAuth,clientAuth
+EOF
+
+ # Add SubjectAltNames so wildcard certs can work correctly.
+ if [ "$WILDCARD" == "yes" ]; then
+cat <<EOF >> openssl.conf
+subjectAltName=DNS:${NODE}, DNS:${CNAME}
+EOF
+ fi
+
+ echo "Please review your OpenSSL configuration:"
+ cat openssl.conf
+ read -p "Hit ENTER to continue." prompt
+
+ openssl req -batch -nodes -config openssl.conf -newkey rsa:2048 -sha256 \
+ -keyout ${NODE}_privatekey.pem -out ${NODE}_csr.pem
+
+ openssl req -noout -text -in ${NODE}_csr.pem
+
+ # Self-sign
+ if [ "$KEYTYPE" == "ssl-self" ]; then
+ openssl x509 -in "${NODE}_csr.pem" -out "$NODE.crt" -req -signkey "${NODE}_privatekey.pem" -days 365
+ chmod 600 "${NODE}_privatekey.pem"
+ fi
+
+ # Encrypt the result
+ echo "Encrypting private key into keyringer..."
+ cat "${NODE}_privatekey.pem" | keyringer_exec encrypt "$BASEDIR" "$FILE.pem"
+ echo "Encrypting certificate request into keyringer..."
+ cat "${NODE}_csr.pem" | keyringer_exec encrypt "$BASEDIR" "$FILE.csr"
+
+ if [ "$KEYTYPE" == "ssl-self" ]; then
+ echo "Encrypting certificate into keyringer..."
+ cat "${NODE}.crt" | keyringer_exec encrypt "$BASEDIR" "$FILE.crt"
+ elif [ -f "$BASEDIR/keys/$FILE.crt.asc" ]; then
+ # Remove any existing crt
+ keyringer_exec del "$BASEDIR" "$FILE.crt"
+ fi
+
+ cd "$CWD"
+
+ if [ ! -z "$OUTFILE" ]; then
+ mkdir -p `dirname $OUTFILE`
+ printf "Saving copies at %s\n" "`dirname $OUTFILE`"
+ cat "$TMPWORK/${NODE}_privatekey.pem" > "$OUTFILE.pem"
+ cat "$TMPWORK/${NODE}_csr.pem" > "$OUTFILE.csr"
+
+ if [ -f "$TMPWORK/${NODE}.crt" ]; then
+ cat "$TMPWORK/${NODE}.crt" > "$OUTFILE.crt"
+ fi
+ fi
+
+ # Show cert fingerprint
+ if [ "$KEYTYPE" == "ssl-self" ]; then
+ openssl x509 -noout -in "$TMPWORK/${NODE}.crt" -fingerprint
+ fi
+
+ echo "Done"
+}
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Aditional parameters
+KEYTYPE="$2"
+FILE="$3"
+NODE="$4"
+OUTFILE="$5"
+CWD="`pwd`"
+
+# Verify
+if [ -z "$NODE" ]; then
+ echo -e "Usage: keyringer <keyring> $BASENAME <gpg|ssh|ssl|ssl-self> <file> <hostname> [outfile]"
+ echo -e "Options:"
+ echo -e "\t gpg|ssh|ssl[-self]: key type."
+ echo -e "\t file : base file name for encrypted output (relative to keys folder),"
+ echo -e "\t without spaces"
+ echo -e "\t hostname : host for the key pair"
+ echo -e "\t outfile : optional unencrypted output file, useful for deployment,"
+ echo -e "\t without spaces"
+ exit 1
+elif [ ! -e "$KEYDIR" ]; then
+ echo "Folder not found: $KEYDIR, leaving"
+ exit 1
+fi
+
+# Set a tmp file
+keyringer_set_tmpfile genpair -d
+
+# Dispatch
+echo "Generating $KEYTYPE key for $NODE..."
+if [ "$KEYTYPE" == "ssl-self" ]; then
+ genpair_ssl
+else
+ genpair_"$KEYTYPE"
+fi
+
+# Cleanup
+cd "$CWD"
+rm -rf "$TMPWORK"
+trap - EXIT
diff --git a/lib/keyringer/actions/git b/lib/keyringer/actions/git
new file mode 100755
index 0000000..3c4f435
--- /dev/null
+++ b/lib/keyringer/actions/git
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# Git wrapper.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Aditional parameters
+CWD="`pwd`"
+
+# Run git command
+shift
+mkdir -p "$BASEDIR" && cd "$BASEDIR" && git $*
+cd "$CWD"
diff --git a/lib/keyringer/actions/ls b/lib/keyringer/actions/ls
new file mode 100755
index 0000000..ec8080b
--- /dev/null
+++ b/lib/keyringer/actions/ls
@@ -0,0 +1,16 @@
+#!/bin/bash
+#
+# List keys.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Aditional parameters
+CWD="`pwd`"
+
+# Run list command
+shift
+cd "$KEYDIR" && ls $*
+cd "$CWD"
diff --git a/lib/keyringer/actions/open b/lib/keyringer/actions/open
new file mode 120000
index 0000000..8491ab9
--- /dev/null
+++ b/lib/keyringer/actions/open
@@ -0,0 +1 @@
+edit \ No newline at end of file
diff --git a/lib/keyringer/actions/options b/lib/keyringer/actions/options
new file mode 100755
index 0000000..8508aea
--- /dev/null
+++ b/lib/keyringer/actions/options
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Recipient management.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Command parser
+keyringer_get_command "$2"
+
+# Create options file if old repository
+if [ ! -e "$OPTIONS" ]; then
+ echo "Creating options file..."
+ touch "$OPTIONS"
+ keyringer_exec git "$BASEDIR" add config/options
+fi
+
+if [ "$COMMAND" == "ls" ]; then
+ cat "$OPTIONS"
+elif [ "$COMMAND" == "edit" ]; then
+ "$EDITOR" "$OPTIONS"
+elif [ "$COMMAND" == "add" ]; then
+ shift 2
+ echo $* >> "$OPTIONS"
+else
+ printf "%s: No such command %s\n" "$BASENAME" "$COMMAND"
+ exit 1
+fi
diff --git a/lib/keyringer/actions/preferences b/lib/keyringer/actions/preferences
new file mode 100755
index 0000000..e82848d
--- /dev/null
+++ b/lib/keyringer/actions/preferences
@@ -0,0 +1,37 @@
+#!/bin/bash
+#
+# Manipulate preferences.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+COMMAND="$2"
+
+if [ -z "$COMMAND" ]; then
+ echo "Usage: keyringer <keyring> preferences <command> [arguments]"
+ echo "Available commands:"
+ echo " ls"
+ echo " edit"
+ echo " add"
+ exit 1
+fi
+
+# Create options file if old repository
+if [ ! -e "$PREFERENCES" ]; then
+ echo "Creating preferences file..."
+ touch "$PREFERENCES"
+fi
+
+if [ "$COMMAND" == "ls" ]; then
+ cat "$PREFERENCES"
+elif [ "$COMMAND" == "edit" ]; then
+ "$EDITOR" "$PREFERENCES"
+elif [ "$COMMAND" == "add" ]; then
+ shift 2
+ [[ -n $* ]] && echo $* >> "$PREFERENCES"
+else
+ printf "%s: No such command %s\n" "$BASENAME" "$COMMAND"
+ exit 1
+fi
diff --git a/lib/keyringer/actions/recipients b/lib/keyringer/actions/recipients
new file mode 100755
index 0000000..7093a6b
--- /dev/null
+++ b/lib/keyringer/actions/recipients
@@ -0,0 +1,46 @@
+#!/bin/bash
+#
+# Recipient management.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Command parser
+keyringer_get_command "$2"
+
+# Set recipients file
+keyringer_set_new_recipients "$3"
+
+if [ "$COMMAND" == "ls" ]; then
+ 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
+ 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
+fi
diff --git a/lib/keyringer/actions/recrypt b/lib/keyringer/actions/recrypt
new file mode 100755
index 0000000..014fef7
--- /dev/null
+++ b/lib/keyringer/actions/recrypt
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+# Re-encrypt files to multiple recipients.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+function keyringer_recrypt {
+ # Get file
+ keyringer_get_file "$1"
+
+ # Set recipients file
+ keyringer_set_recipients "$FILE"
+
+ # Decrypt
+ decrypted="$($GPG --use-agent -d "$KEYDIR/$FILE" 2> /dev/null)"
+
+ if [ "$?" != "0" ]; then
+ echo "Decryption error."
+ exit 1
+ fi
+
+ # Recrypt
+ recrypted="`echo "$decrypted" | $GPG --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE")`"
+
+ if [ "$?" != "0" ]; then
+ echo "Recryption error."
+ exit 1
+ fi
+
+ unset decrypted
+ echo "$recrypted" > "$KEYDIR/$FILE"
+}
+
+if [ ! -z "$2" ]; then
+ keyringer_recrypt $2
+else
+ cd $KEYDIR && find | while read file; do
+ if [ ! -d "$KEYDIR/$file" ]; then
+ keyringer_recrypt "$file"
+ fi
+ done
+fi
diff --git a/lib/keyringer/actions/usage b/lib/keyringer/actions/usage
new file mode 100755
index 0000000..f4ac0fa
--- /dev/null
+++ b/lib/keyringer/actions/usage
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+# Show available commands
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+keyringer_usage
diff --git a/lib/keyringer/completions/bash/keyringer b/lib/keyringer/completions/bash/keyringer
index 875e6ab..7bfa62f 100644
--- a/lib/keyringer/completions/bash/keyringer
+++ b/lib/keyringer/completions/bash/keyringer
@@ -42,6 +42,15 @@ _keyringer_git_complete() {
fi
}
+# Path completion
+function _keyringer_path_complete() {
+ # Thanks http://unix.stackexchange.com/questions/55520/create-bash-completion-script-to-autocomplete-paths-after-is-equal-sign
+ cur=${1//\\ / }
+ [[ ${cur} == "~/"* ]] && cur=${cur/\~/$HOME}
+
+ echo ${cur}
+}
+
_keyringer() {
# Standard stuff
local cur prev command config path keyrings instances instance opts
@@ -94,10 +103,7 @@ _keyringer() {
opts="$(_keyringer_git_complete ${cur})"
;;
init)
- # Thanks http://unix.stackexchange.com/questions/55520/create-bash-completion-script-to-autocomplete-paths-after-is-equal-sign
- cur=${cur//\\ / }
- [[ ${cur} == "~/"* ]] && cur=${cur/\~/$HOME}
-
+ cur="$(_keyringer_path_complete ${cur})"
opts="$(compgen -o dirnames ${cur})"
;;
*)
@@ -115,6 +121,10 @@ _keyringer() {
# TODO
opts="$(_keyringer_git_complete ${prev} ${cur})"
;;
+ encrypt|encrypt-batch)
+ cur="$(_keyringer_path_complete ${cur})"
+ opts="$(compgen -o dirnames ${cur})"
+ ;;
*)
;;
esac
diff --git a/lib/keyringer/completions/zsh/_keyringer b/lib/keyringer/completions/zsh/_keyringer
index 119d26d..50ff433 100644
--- a/lib/keyringer/completions/zsh/_keyringer
+++ b/lib/keyringer/completions/zsh/_keyringer
@@ -77,6 +77,9 @@ _keyringer() {
git)
compadd "$@" $(_keyringer_git_complete $words[4] $words[5])
;;
+ encrypt|encrypt-batch)
+ _files
+ ;;
*)
;;
esac
diff --git a/lib/keyringer/functions b/lib/keyringer/functions
index 66a23df..7570a94 100755
--- a/lib/keyringer/functions
+++ b/lib/keyringer/functions
@@ -111,20 +111,71 @@ function keyringer_is_git {
fi
}
+# Check the security of a temporary folder
+function keyringer_check_tmp {
+ local path="$1"
+ local minor
+ local mode
+
+ if [ -z "$path" ]; then
+ return
+ fi
+
+ # Mode check
+ if [ "`stat -c "%A" $path`" != "drwxrwxrwt" ]; then
+ return 1
+ fi
+
+ # Ramdisk check
+ if [ -x "/sbin/udevadm" ]; then
+ minor="$(/sbin/udevadm info --device-id-of-file "$path" | cut -d : -f 1)"
+ elif which mountpoint &> /dev/null; then
+ minor="$(mountpoint -d $(df "$path" | sed -n '$p' | awk '{print $NF}') | cut -d : -f 1)"
+ fi
+
+ if [ ! -z "$minor" ]; then
+ return $minor
+ else
+ return 1
+ fi
+}
+
# Setup a temporary file
function keyringer_set_tmpfile {
+ local tmp
+ local candidate
+ local candidates="/tmp /run/shm $TMP"
+
if [ -z "$BASEDIR" ]; then
echo "Please set BASEDIR before creating a tmp file"
exit 1
fi
+ # Ramdisk check
+ for candidate in $candidates; do
+ if keyringer_check_tmp $candidate; then
+ tmp="$candidate/keyringer.`whoami`"
+ break
+ fi
+ done
+
+ # Set base temp folder
+ if [ -z "$tmp" ]; then
+ echo "WARNING: neither one of $candidates is mounted in a tmpfs/ramdisk, using $BASEDIR/tmp as fallback."
+ echo "Make sure that $BASEDIR is atop of an encrypted volume."
+ echo "Press any key to continue, Ctrl-C to abort"
+ read key
+ tmp="$BASEDIR/tmp"
+ fi
+
+ # Determine template
if [ -z "$1" ]; then
- template="$BASEDIR/tmp/keyringer.XXXXXXXXXX"
+ template="$tmp/keyringer.XXXXXXXXXX"
else
- template="$BASEDIR/tmp/$1.XXXXXXXXXX"
+ template="$tmp/XXXXXXXXXX.$1"
fi
- mkdir -p "$BASEDIR/tmp"
+ mkdir -p "$tmp"
keyringer_git_ignore 'tmp/*'
if [ "$2" == "-d" ]; then
@@ -141,13 +192,46 @@ function keyringer_set_tmpfile {
trap "keyringer_unset_tmpfile $TMPWORK; exit" INT TERM EXIT
}
+# Shred files
+function keyringer_shred {
+ local path="$1"
+ local tool
+ local message="Removing"
+
+ if [ -z "$path" ]; then
+ return
+ elif [ ! -e "$path" ]; then
+ return
+ fi
+
+ # Get shred implementation
+ if which wipe &> /dev/null; then
+ tool="wipe"
+ elif which shred &> /dev/null; then
+ tool="shred"
+ else
+ # Worst implementation
+ message="WARNING $message"
+ tool="rm"
+ fi
+
+ echo "$message $path using $tool..."
+
+ if [ -d "$path" ]; then
+ find $path -exec $tool -f {} \;
+ rmdir $path
+ else
+ $tool -f "$path"
+ fi
+}
+
# Remove a temporary file
function keyringer_unset_tmpfile {
if [ -z "$1" ]; then
echo "No tmp file set"
fi
- rm -f "$1"
+ keyringer_shred "$1"
if [ "$?" != "0" ]; then
echo "Warning: could not delete file $1. Please delete it manually as it might have sensitive information."
@@ -342,16 +426,22 @@ function keyringer_get_new_file {
# File must not contain spaces
if [ ! -z "$2" ] ; then
FILE="`echo "$*" | sed -e 's/ /_/g'`"
- echo "File $* has spaces, secret will be named as $FILE..."
else
FILE="$1"
fi
# Sanitize and complete file name
- FILE="`echo $FILE | sed -e s/[^A-Za-z0-9.]/_/g`"
+ FILE="`echo $FILE | sed -e s/[^A-Za-z0-9.\/\-]/_/g`"
+
+ # Warn user about file name change
+ if [ "`basename $*`" != "`basename $FILE`" ]; then
+ echo "Sanitizing destination filename to `basename $FILE`"
+ fi
+
+ # Complete file name
FILE="$(keyringer_filename "$FILE")"
-
- if [ -z "$FILE" ]; then
+
+ if [ -z "$*" ]; then
keyringer_action_usage
exit 1
fi
@@ -361,7 +451,7 @@ function keyringer_get_new_file {
function keyringer_get_command {
# Aditional parameters
COMMAND="$1"
-
+
if [ -z "$COMMAND" ]; then
keyringer_action_usage command
exit 1
@@ -390,9 +480,16 @@ function keyringer_show_actions {
# Usage
function keyringer_usage {
- printf "Usage: %s <keyring> <action> [arguments]\n" "$BASENAME"
- printf "Available commands: \n"
+ local keyrings="$(ls --color=never `dirname $CONFIG` | sed -e 's/config//' | xargs)"
+
+ 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
+ printf "Available keyrings: %s \n" "$keyrings"
+ fi
}
# Check recipients
@@ -504,7 +601,7 @@ function keyringer_set_new_recipients {
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 "# Use entries in the form of 'john@doe.com XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'" > "$1"
echo "" >> "$1"
fi
}