summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog28
-rw-r--r--Makefile6
-rw-r--r--development.mdwn9
-rw-r--r--index.mdwn29
-rwxr-xr-xkeyringer24
-rwxr-xr-xlib/keyringer/actions/append2
l---------lib/keyringer/actions/clip1
-rwxr-xr-xlib/keyringer/actions/commands1
-rwxr-xr-xlib/keyringer/actions/decrypt2
-rwxr-xr-xlib/keyringer/actions/edit14
-rwxr-xr-xlib/keyringer/actions/encrypt4
-rwxr-xr-xlib/keyringer/actions/find19
-rwxr-xr-xlib/keyringer/actions/genpair2
-rwxr-xr-xlib/keyringer/actions/git10
l---------lib/keyringer/actions/help1
-rwxr-xr-xlib/keyringer/actions/ls2
-rwxr-xr-xlib/keyringer/actions/mkdir19
-rwxr-xr-xlib/keyringer/actions/mv28
-rwxr-xr-xlib/keyringer/actions/options1
-rwxr-xr-xlib/keyringer/actions/preferences3
-rwxr-xr-xlib/keyringer/actions/recipients1
-rwxr-xr-xlib/keyringer/actions/recrypt2
-rwxr-xr-xlib/keyringer/actions/rmdir19
-rwxr-xr-xlib/keyringer/actions/shell57
-rwxr-xr-xlib/keyringer/actions/teardown28
-rwxr-xr-xlib/keyringer/actions/tree4
-rwxr-xr-xlib/keyringer/actions/usage3
-rwxr-xr-xlib/keyringer/actions/xclip59
-rw-r--r--lib/keyringer/completions/bash/keyringer6
-rw-r--r--lib/keyringer/completions/zsh/_keyringer6
-rwxr-xr-xlib/keyringer/functions82
-rw-r--r--share/man/keyringer.155
-rw-r--r--share/man/keyringer.1.mdwn35
33 files changed, 494 insertions, 68 deletions
diff --git a/ChangeLog b/ChangeLog
index 9cc7bb2..e7f7cf7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,16 +1,32 @@
+2014-02-20 - 0.3 - Silvio Rhatto <rhatto@riseup.net>
+
+ Try to find a similar file at keyringer_get_file
+
+ Added xclip action (#33)
+
+ Check key expirations (#37)
+
+ Proper error handling at edit action
+
+ New actions: find, mv, rmdir
+
+ Support for RELATIVE_FOLDER at git action
+
+ New actions: shell (#34), help, mkdir, teardown
+
2013-11-26 - 0.2.9 Silvio Rhatto <rhatto@riseup.net>
- Added 'tree' action
+ Added 'tree' action
- Added 'rm' alias to 'del' action
+ Added 'rm' alias to 'del' action
- Set .gitignore during initialization and when using tmp inside the repository
+ Set .gitignore during initialization and when using tmp inside the repository
- Pass options to git-rm at del action
+ Pass options to git-rm at del action
- Simpler ramdisk/tmpfs check at keyringer_check_tmp
+ Simpler ramdisk/tmpfs check at keyringer_check_tmp
- Better mode check on keyringer_check_tmp (closes #30)
+ Better mode check on keyringer_check_tmp (closes #30)
Fixed minor typos
diff --git a/Makefile b/Makefile
index 360bd29..42f6d9b 100644
--- a/Makefile
+++ b/Makefile
@@ -56,7 +56,9 @@ tarball:
release:
@make build_man
git commit -a -m "Keyringer $(VERSION)"
- git tag -s $(VERSION) -m "Keyringer $(VERSION)"
@make tarball
- gpg --armor --detach-sign --output ../tarballs/keyringer-$(VERSION).tar.bz2.asc ../tarballs/keyringer-$(VERSION).tar.bz2
+ gpg --use-agent --armor --detach-sign --output ../tarballs/keyringer-$(VERSION).tar.bz2.asc ../tarballs/keyringer-$(VERSION).tar.bz2
scp ../tarballs/keyringer-$(VERSION).tar.bz2* keyringer:/var/sites/keyringer/releases/
+ # We're doing tagging afterwards:
+ # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=568375
+ git tag -s $(VERSION) -m "Keyringer $(VERSION)"
diff --git a/development.mdwn b/development.mdwn
index 3400643..cf969fe 100644
--- a/development.mdwn
+++ b/development.mdwn
@@ -60,6 +60,7 @@ Update the debian branch:
git-import-orig --upstream-vcs-tag=$VERSION ../tarballs/keyringer-$VERSION.tar.bz2
dch -e # fine tune the changelog prepared by git-dch
git commit -a -m "Updating debian/changelog"
+ git-buildpackage --git-tag-only --git-sign-tags
Push everything:
@@ -74,10 +75,6 @@ Run lintian (or [add it to your pbuilder hooks](http://askubuntu.com/questions/1
lintian --info --display-info --pedantic --color auto \
../build-area/keyringer_$VERSION*.changes
-Create a signed tag in the debian branch:
-
- git-buildpackage --git-tag-only --git-sign-tags
-
Notes:
* `git-import-orig` takes care of running `pristine-tar commit`, of merging of the tag and orig tarball into the upstream branch, and then it merges the result into the debian branch. With the above configuration, it also runs git-dch to do the bulk of the work in `debian/changelog`.
@@ -101,9 +98,7 @@ Setup:
Teardown:
- rm -rf ~/code/tests/keyringer
- rm ~/.keyringer/test
- sed -i -e '/^test=/d' ~/.keyringer/config
+ keyringer test teardown -y
Translation
-----------
diff --git a/index.mdwn b/index.mdwn
index 148da07..1a3fe52 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -1,6 +1,6 @@
[[!meta title="Keyringer: encrypted and distributed secret sharing software"]]
-Keyringer lets you manage and share secrets using GPG and git with custom
+Keyringer lets you manage and share secrets using GnuPG and Git with custom
commands to encrypt, decrypt, recrypt, create key pairs, etc.
- Project page: [https://keyringer.pw](https://keyringer.pw)
@@ -73,6 +73,9 @@ Fill it with your friends key IDs. Now encrypt a secret just for then:
In other words, if keyringer finds a recipient file matching a given path,
it will use it instead of the global recipients file.
+Each recipient list is defined in a file placed at `config/recipients` in your
+keyring repository. Take care to add just trustable recipients.
+
Managing secrets
----------------
@@ -111,17 +114,18 @@ Appending information to a secret
Editing a secret
-To edit a secret, use
-
- keyringer <keyring> edit <file>
+ keyringer <keyring> edit <secret>
Use this option with caution as it keeps temporary unencrypted data
-into keyringer temp folder and at your editor's temp files.
+into a temporary folder.
Listing secrets
keyringer <keyring> ls [arguments]
+Each `<secret>` is stored as a file inside the `keys/` folder of your keyring
+directory.
+
Git wrapper
-----------
@@ -155,18 +159,6 @@ Example:
keyringer <keyring> preferences add KEYID=0123456789ABCDEF0123456789ABCDE012345678
-Notes
------
-
- 1. The `<file>` is any file inside the `keys/` folder of your
- keyring directory.
-
- 2. Never decrypt a key and write it to the disk, except
- if you're adding it to your personall keyring.
-
- 3. Recipients are defined at file `config/recipients`.
- Take care to add just trustable recipients.
-
Concepts
--------
@@ -207,6 +199,9 @@ given key), but it's possible to:
- Or to consider an integration with gpg's --hidden-recipient option.
+Never decrypt a key and write it to the disk, except if you're adding it to
+your personall keyring.
+
Requirements
------------
diff --git a/keyringer b/keyringer
index 11b8aa1..0930637 100755
--- a/keyringer
+++ b/keyringer
@@ -3,21 +3,22 @@
# Keyringer key management system.
#
# Copyright (C) 2010 Silvio Rhatto - rhatto at riseup.net
-#
+#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License,
# or any later version.
-#
+#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
-#
+#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+# Initialize a new keyring
function keyringer_init {
BASEDIR="$3"
URL="$4"
@@ -104,6 +105,7 @@ function keyringer_init {
fi
}
+# Action dispatcher
function keyringer_dispatch {
BASEDIR="`keyringer_config $KEYRING`"
@@ -120,7 +122,7 @@ function keyringer_dispatch {
# Config
NAME="keyringer"
-KEYRINGER_VERSION="0.2.9"
+KEYRINGER_VERSION="0.3"
CONFIG_VERSION="0.1"
CONFIG_BASE="$HOME/.$NAME"
CONFIG="$CONFIG_BASE/config"
@@ -131,10 +133,12 @@ ACTION="$2"
# Turn off pathname expansion so expansion can work properly
set -f
-# Export preferences and version for other scripts
+# Export globals for other scripts
export PREFERENCES="`dirname $CONFIG`/$KEYRING"
export KEYRINGER_VERSION
export CONFIG_VERSION
+export KEYRING
+export CONFIG
# Set functions location
if [ -e "`dirname $(readlink -f $0)`/lib/$NAME/functions" ]; then
@@ -160,12 +164,14 @@ source "$LIB" || exit 1
# Setup main configuration and load preferences
keyringer_config_load
-if [ -z "$ACTION" ]; then
+# Dispatch
+if [ -z "$KEYRING" ]; then
keyringer_usage
exit 1
-fi
-
-if [ "$ACTION" == "init" ]; then
+elif [ -z "$ACTION" ]; then
+ # Run shell if no action were given
+ keyringer $KEYRING shell
+elif [ "$ACTION" == "init" ]; then
keyringer_init $*
elif keyringer_has_action "$ACTION"; then
keyringer_dispatch $*
diff --git a/lib/keyringer/actions/append b/lib/keyringer/actions/append
index e307056..fbb6c1c 100755
--- a/lib/keyringer/actions/append
+++ b/lib/keyringer/actions/append
@@ -17,4 +17,4 @@ fi
# Append content to an existing secret
( keyringer_exec decrypt "$BASEDIR" "$FILE" && cat ) | \
- keyringer_exec encrypt-batch $BASEDIR $FILE
+ keyringer_exec encrypt-batch "$BASEDIR" "$FILE"
diff --git a/lib/keyringer/actions/clip b/lib/keyringer/actions/clip
new file mode 120000
index 0000000..8b8c16c
--- /dev/null
+++ b/lib/keyringer/actions/clip
@@ -0,0 +1 @@
+xclip \ No newline at end of file
diff --git a/lib/keyringer/actions/commands b/lib/keyringer/actions/commands
index 2605666..cb49c02 100755
--- a/lib/keyringer/actions/commands
+++ b/lib/keyringer/actions/commands
@@ -7,4 +7,5 @@
LIB="`dirname $0`/../functions"
source "$LIB" || exit 1
+# Dispatch
keyringer_show_actions
diff --git a/lib/keyringer/actions/decrypt b/lib/keyringer/actions/decrypt
index 2b1401c..b63b74e 100755
--- a/lib/keyringer/actions/decrypt
+++ b/lib/keyringer/actions/decrypt
@@ -11,7 +11,7 @@ source "$LIB" || exit 1
keyringer_get_file "$2"
# Decrypt
-$GPG --quiet --use-agent -d "$KEYDIR/$FILE"
+$GPG --use-agent -d "$KEYDIR/$FILE"
# Exit
exit "$?"
diff --git a/lib/keyringer/actions/edit b/lib/keyringer/actions/edit
index 9a3e488..03ccdab 100755
--- a/lib/keyringer/actions/edit
+++ b/lib/keyringer/actions/edit
@@ -24,6 +24,7 @@ keyringer_set_tmpfile $BASENAME.$EXTENSION
# Decrypt the information to the file
$GPG --yes -o "$TMPWORK" --use-agent -d "$KEYDIR/$FILE"
+# Action check
if [ "$BASENAME" == "edit" ]; then
APP="$EDITOR"
elif [ "$BASENAME" == "open" ]; then
@@ -43,5 +44,18 @@ $APP "$TMPWORK"
# Encrypt again
$GPG --yes -o "$KEYDIR/$FILE" --use-agent --armor -e -s $(keyringer_recipients "$RECIPIENTS_FILE") "$TMPWORK"
+# Check exit status
+errcrypt="$?"
+
# Remove temp file
keyringer_unset_tmpfile "$TMPWORK"
+
+# Check exit status again
+errwipe="$?"
+
+# Error handling must be done after temp file removal
+if [ "$errcrypt" != "0" ]; then
+ exit "$errcrypt"
+elif [ "$errwipe" != "0" ]; then
+ exit $errwipe
+fi
diff --git a/lib/keyringer/actions/encrypt b/lib/keyringer/actions/encrypt
index 0a40bc1..e9bf453 100755
--- a/lib/keyringer/actions/encrypt
+++ b/lib/keyringer/actions/encrypt
@@ -106,12 +106,13 @@ else
keyringer_encrypt $FILE $UNENCRYPTED_FILE
fi
+# Check exit status
err="$?"
-
if [ "$err" != "0" ]; then
exit "$err"
fi
+# Wipe information
if [ "$UNENCRYPTED_FILE" != "-" ]; then
echo "Done. PLEASE WIPE the non-encrypted $UNENCRYPTED_FILE."
fi
@@ -121,4 +122,5 @@ if [ -d "$BASEDIR/.git" ]; then
keyringer_exec git "$BASEDIR" add "keys/$FILE"
fi
+# Done
exit "$?"
diff --git a/lib/keyringer/actions/find b/lib/keyringer/actions/find
new file mode 100755
index 0000000..21afc7a
--- /dev/null
+++ b/lib/keyringer/actions/find
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Find secrets.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Aditional parameters
+CWD="`pwd`"
+
+# Avoid leading slash
+shift
+ARGS="`echo "$*" | sed -e "s|^/*||"`"
+
+# Run find command
+cd "$KEYDIR/$RELATIVE_PATH" && find -iname "*$ARGS*" | sed -e 's|^./||g'
+cd "$CWD"
diff --git a/lib/keyringer/actions/genpair b/lib/keyringer/actions/genpair
index f048bc7..6898b0f 100755
--- a/lib/keyringer/actions/genpair
+++ b/lib/keyringer/actions/genpair
@@ -184,7 +184,7 @@ source "$LIB" || exit 1
# Aditional parameters
KEYTYPE="$2"
-FILE="$3"
+FILE="$RELATIVE_PATH/$3"
NODE="$4"
OUTFILE="$5"
CWD="`pwd`"
diff --git a/lib/keyringer/actions/git b/lib/keyringer/actions/git
index 3c4f435..108ccea 100755
--- a/lib/keyringer/actions/git
+++ b/lib/keyringer/actions/git
@@ -12,5 +12,13 @@ CWD="`pwd`"
# Run git command
shift
-mkdir -p "$BASEDIR" && cd "$BASEDIR" && git $*
+
+# Set working folder
+if [ ! -z "$RELATIVE_PATH" ]; then
+ WORK="$KEYDIR/$RELATIVE_PATH"
+else
+ WORK="$BASEDIR"
+fi
+
+mkdir -p "$WORK" && cd "$WORK" && git $*
cd "$CWD"
diff --git a/lib/keyringer/actions/help b/lib/keyringer/actions/help
new file mode 120000
index 0000000..ae18295
--- /dev/null
+++ b/lib/keyringer/actions/help
@@ -0,0 +1 @@
+usage \ No newline at end of file
diff --git a/lib/keyringer/actions/ls b/lib/keyringer/actions/ls
index bb66263..93f5f75 100755
--- a/lib/keyringer/actions/ls
+++ b/lib/keyringer/actions/ls
@@ -15,5 +15,5 @@ shift
ARGS="`echo "$*" | sed -e "s|^/*||"`"
# Run list command
-cd "$KEYDIR" && ls $ARGS
+cd "$KEYDIR/$RELATIVE_PATH" && ls $ARGS
cd "$CWD"
diff --git a/lib/keyringer/actions/mkdir b/lib/keyringer/actions/mkdir
new file mode 100755
index 0000000..b31eb0b
--- /dev/null
+++ b/lib/keyringer/actions/mkdir
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Create folders.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Aditional parameters
+CWD="`pwd`"
+
+# Avoid leading slash
+shift
+ARGS="`echo "$*" | sed -e "s|^/*||"`"
+
+# Run mkdir command
+cd "$KEYDIR/$RELATIVE_PATH" && mkdir -p $ARGS
+cd "$CWD"
diff --git a/lib/keyringer/actions/mv b/lib/keyringer/actions/mv
new file mode 100755
index 0000000..aaf6772
--- /dev/null
+++ b/lib/keyringer/actions/mv
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Move secrets.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Avoid leading slash
+ORIG="$(keyringer_filename `echo "$2" | sed -e "s|^/*||"`)"
+DEST="`echo "$3" | sed -e "s|^/*||"`"
+
+# Set destination
+if [ ! -d "$KEYDIR/$RELATIVE_PATH/$DEST" ]; then
+ keyringer_get_new_file $DEST
+else
+ FILE="$DEST"
+fi
+
+# Check if secret exists
+if ! echo "$ORIG" | grep -q '*' && [ ! -e "$KEYDIR/$RELATIVE_PATH/$ORIG" ]; then
+ echo "Secret not found: $ORIG"
+ exit 1
+fi
+
+# Run move command
+keyringer_exec git "$BASEDIR" mv $ORIG $FILE
diff --git a/lib/keyringer/actions/options b/lib/keyringer/actions/options
index 8508aea..3bf0e43 100755
--- a/lib/keyringer/actions/options
+++ b/lib/keyringer/actions/options
@@ -17,6 +17,7 @@ if [ ! -e "$OPTIONS" ]; then
keyringer_exec git "$BASEDIR" add config/options
fi
+# Dispatch
if [ "$COMMAND" == "ls" ]; then
cat "$OPTIONS"
elif [ "$COMMAND" == "edit" ]; then
diff --git a/lib/keyringer/actions/preferences b/lib/keyringer/actions/preferences
index e82848d..f7507a7 100755
--- a/lib/keyringer/actions/preferences
+++ b/lib/keyringer/actions/preferences
@@ -7,8 +7,10 @@
LIB="`dirname $0`/../functions"
source "$LIB" || exit 1
+# Options
COMMAND="$2"
+# Syntax check
if [ -z "$COMMAND" ]; then
echo "Usage: keyringer <keyring> preferences <command> [arguments]"
echo "Available commands:"
@@ -24,6 +26,7 @@ if [ ! -e "$PREFERENCES" ]; then
touch "$PREFERENCES"
fi
+# Dispatch
if [ "$COMMAND" == "ls" ]; then
cat "$PREFERENCES"
elif [ "$COMMAND" == "edit" ]; then
diff --git a/lib/keyringer/actions/recipients b/lib/keyringer/actions/recipients
index 7093a6b..4149786 100755
--- a/lib/keyringer/actions/recipients
+++ b/lib/keyringer/actions/recipients
@@ -13,6 +13,7 @@ keyringer_get_command "$2"
# Set recipients file
keyringer_set_new_recipients "$3"
+# Syntax check and dispatcher
if [ "$COMMAND" == "ls" ]; then
if [ ! -z "$3" ]; then
if [ -e "$RECIPIENTS_FILE" ]; then
diff --git a/lib/keyringer/actions/recrypt b/lib/keyringer/actions/recrypt
index 014fef7..696399b 100755
--- a/lib/keyringer/actions/recrypt
+++ b/lib/keyringer/actions/recrypt
@@ -7,6 +7,7 @@
LIB="`dirname $0`/../functions"
source "$LIB" || exit 1
+# Recrypt a single secret
function keyringer_recrypt {
# Get file
keyringer_get_file "$1"
@@ -34,6 +35,7 @@ function keyringer_recrypt {
echo "$recrypted" > "$KEYDIR/$FILE"
}
+# Syntax check and dispatcher
if [ ! -z "$2" ]; then
keyringer_recrypt $2
else
diff --git a/lib/keyringer/actions/rmdir b/lib/keyringer/actions/rmdir
new file mode 100755
index 0000000..398cf11
--- /dev/null
+++ b/lib/keyringer/actions/rmdir
@@ -0,0 +1,19 @@
+#!/bin/bash
+#
+# Remove folders.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Aditional parameters
+CWD="`pwd`"
+
+# Avoid leading slash
+shift
+ARGS="`echo "$*" | sed -e "s|^/*||"`"
+
+# Run rmdir command
+cd "$KEYDIR/$RELATIVE_PATH" && rmdir $ARGS
+cd "$CWD"
diff --git a/lib/keyringer/actions/shell b/lib/keyringer/actions/shell
new file mode 100755
index 0000000..ab170b1
--- /dev/null
+++ b/lib/keyringer/actions/shell
@@ -0,0 +1,57 @@
+#!/bin/bash
+#
+# Interactive shell.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Basic parameters
+SHELLPATH="/"
+
+# Show usage
+keyringer_usage $KEYRING
+
+# While a "quit" command isn't entered, read STDIN
+while read -rep "keyringer:/${KEYRING}${SHELLPATH}> " STDIN; do
+ if [ "$STDIN" == "quit" ] || [ "$STDIN" == "exit" ] || [ "$STDIN" == "bye" ]; then
+ break
+ elif [ "$STDIN" == "shell" ]; then
+ echo "Why you need nesting?"
+ elif [[ "$STDIN" == "cd"* ]]; then
+
+ # Update current path
+ OLDPATH="$SHELLPATH"
+ SHELLPATH="`echo $STDIN | sed -e 's/^cd//' | cut -d ' ' -f 2`"
+
+ # Fix current path
+ if [ "$SHELLPATH" == "/" ] || [ "$SHELLPATH" == "" ]; then
+ SHELLPATH="/"
+ elif [[ "$SHELLPATH" == ".."* ]]; then
+ ARGS="$SHELLPATH"
+ SHELLPATH="$OLDPATH"
+ for colons in `echo $ARGS | sed -e 's|/| |g'`; do
+ SHELLPATH="`dirname $SHELLPATH | sed -e 's|^\.||'`"
+ done
+ fi
+
+ # Ensure path is absolute
+ if echo "$SHELLPATH" | grep -v -q -e "^/"; then
+ SHELLPATH="/$OLDPATH/$SHELLPATH"
+ fi
+
+ # Removing multiple slashes
+ SHELLPATH="`echo $SHELLPATH | sed -e 's/\/\+/\//g'`"
+
+ # Check if path exists
+ if [ ! -d "$KEYDIR/$SHELLPATH" ]; then
+ echo "No such folder $SHELLPATH"
+ SHELLPATH="$OLDPATH"
+ fi
+
+ elif [[ -n "$STDIN" && "$STDIN" != "#"* ]]; then
+ # If line is not empty or commented, process command
+ RELATIVE_PATH="$SHELLPATH" keyringer "$KEYRING" $STDIN
+ fi
+done
diff --git a/lib/keyringer/actions/teardown b/lib/keyringer/actions/teardown
new file mode 100755
index 0000000..64da740
--- /dev/null
+++ b/lib/keyringer/actions/teardown
@@ -0,0 +1,28 @@
+#!/bin/bash
+#
+# Remove a keyring.
+#
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Options
+CONFIRM="$2"
+
+# Confirmation
+if [ -z "$CONFIRM" ] || [ "$CONFIRM" != "-y" ]; then
+ echo "WARNING: about to remove the LOCAL copy of $KEYRING"
+ echo "WARNING: This will irrevocably destroy $KEYDIR"
+ echo "WARNING: the action cannot be undone!"
+
+ read -rep "Are you sure to WIPE keyring $KEYRING (type YES to confirm)? " key
+ if [ "$key" != "YES" ]; then
+ exit 1
+ fi
+fi
+
+# Teardown
+keyringer_shred `dirname $KEYDIR`
+keyringer_shred $HOME/.keyringer/$KEYRING
+sed -i -e "/^$KEYRING=/d" $HOME/.keyringer/config
diff --git a/lib/keyringer/actions/tree b/lib/keyringer/actions/tree
index 8e94cb0..8f9d7cd 100755
--- a/lib/keyringer/actions/tree
+++ b/lib/keyringer/actions/tree
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# List keys.
+# List keys, tree version.
#
# Thanks http://www.centerkey.com/tree/
@@ -27,5 +27,5 @@ else
fi
# Run list command
-cd "$KEYDIR" && $TREE $ARGS
+cd "$KEYDIR/$RELATIVE_PATH" && $TREE $ARGS
cd "$CWD"
diff --git a/lib/keyringer/actions/usage b/lib/keyringer/actions/usage
index f4ac0fa..2ca7639 100755
--- a/lib/keyringer/actions/usage
+++ b/lib/keyringer/actions/usage
@@ -7,4 +7,5 @@
LIB="`dirname $0`/../functions"
source "$LIB" || exit 1
-keyringer_usage
+# Dispatch
+keyringer_usage $KEYRING
diff --git a/lib/keyringer/actions/xclip b/lib/keyringer/actions/xclip
new file mode 100755
index 0000000..b28984f
--- /dev/null
+++ b/lib/keyringer/actions/xclip
@@ -0,0 +1,59 @@
+#!/bin/bash
+#
+# Decrypt secret header to clipboard.
+#
+
+# Copy contents to clipboard.
+# Function thanks to Password Store by Jason A. Donenfeld <Jason@zx2c4.com>
+# distributed under GPLv2+: http://www.zx2c4.com/projects/password-store/
+clip() {
+ # This base64 business is a disgusting hack to deal with newline inconsistancies
+ # in shell. There must be a better way to deal with this, but because I'm a dolt,
+ # we're going with this for now.
+
+ before="$(xclip -o -selection clipboard | base64)"
+ echo -n "$1" | xclip -selection clipboard
+ (
+ sleep 45
+ now="$(xclip -o -selection clipboard | base64)"
+ if [[ $now != $(echo -n "$1" | base64) ]]; then
+ before="$now"
+ fi
+
+ # It might be nice to programatically check to see if klipper exists,
+ # as well as checking for other common clipboard managers. But for now,
+ # this works fine -- if qdbus isn't there or if klipper isn't running,
+ # this essentially becomes a no-op.
+ #
+ # Clipboard managers frequently write their history out in plaintext,
+ # so we axe it here:
+ qdbus org.kde.klipper /klipper org.kde.klipper.klipper.clearClipboardHistory &>/dev/null
+
+ echo "$before" | base64 -d | xclip -selection clipboard
+ ) & disown
+ echo "Copied $2 to clipboard. Will clear in 45 seconds."
+}
+
+# Load functions
+LIB="`dirname $0`/../functions"
+source "$LIB" || exit 1
+
+# Check for xclip
+if ! which xclip; then
+ echo "fatal: xclip not found"
+ exit 1
+fi
+
+# Get file
+keyringer_get_file "$2"
+
+# Decrypt
+pass="$($GPG --use-agent -d "$KEYDIR/$FILE" | head -n 1)"
+
+# Copy to clipboard
+if [ ! -z "$pass" ]; then
+ clip "$pass" "$2"
+fi
+
+# Exit
+exit "$?"
diff --git a/lib/keyringer/completions/bash/keyringer b/lib/keyringer/completions/bash/keyringer
index eeda27f..a640583 100644
--- a/lib/keyringer/completions/bash/keyringer
+++ b/lib/keyringer/completions/bash/keyringer
@@ -70,10 +70,10 @@ _keyringer() {
# Process config
source $config/config
- keyrings="`ls --color=never $config | sed -e 's/config//' | xargs`"
+ keyrings="`ls --color=never $config | sed -e '/^config$/d' | xargs`"
# Available instances
- instances="`echo $keyrings | sed -e 's/ /\\\|/g'`"
+ instances="`echo $keyrings | sed -e 's/ /$\\\|^/g' -e 's/^/^/' -e 's/$/$/'`"
# The current instance
instance="${COMP_WORDS[1]}"
@@ -94,7 +94,7 @@ _keyringer() {
recipients)
opts="ls edit"
;;
- ls|tree|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open)
+ ls|tree|mkdir|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open|clip|xclip)
cur="`echo ${cur} | sed -e "s|^/*||"`" # avoid leading slash
opts="$(bash -c "set -f && export KEYRINGER_CHECK_VERSION=false && keyringer $instance ls -p -d ${cur}*" 2> /dev/null)"
;;
diff --git a/lib/keyringer/completions/zsh/_keyringer b/lib/keyringer/completions/zsh/_keyringer
index 5717b00..1a6d8c6 100644
--- a/lib/keyringer/completions/zsh/_keyringer
+++ b/lib/keyringer/completions/zsh/_keyringer
@@ -20,9 +20,9 @@ _keyringer() {
# Process config
source $config/config
- local keyrings="`ls --color=never $config | sed -e 's/config//' | xargs`"
+ local keyrings="`ls --color=never $config | sed -e '/^config$/d' | xargs`"
local keyring_path="`eval echo '$'$words[2]`"
- local instances="`echo $keyrings | sed -e 's/ /\\\|/g'`"
+ local instances="`echo $keyrings | sed -e 's/ /$\\\|^/g' -e 's/^/^/' -e 's/$/$/'`"
_arguments \
'1: :->keyring' \
@@ -50,7 +50,7 @@ _keyringer() {
recipients)
compadd "$@" ls edit
;;
- ls|tree|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open)
+ ls|tree|mkdir|encrypt|encrypt-batch|decrypt|edit|append|append-batch|del|rm|recrypt|open|clip|xclip)
words[4]="`echo $words[4] | sed -e "s|^/*||"`" # avoid leading slash
compadd "$@" $(KEYRINGER_CHECK_VERSION=false keyringer $words[2] ls -p -d $words[4]'*' 2> /dev/null)
;;
diff --git a/lib/keyringer/functions b/lib/keyringer/functions
index bef00d9..014c2c9 100755
--- a/lib/keyringer/functions
+++ b/lib/keyringer/functions
@@ -206,10 +206,17 @@ function keyringer_shred {
echo "$message $path using $tool..."
if [ -d "$path" ]; then
- find $path -exec $tool -f {} \;
- rmdir $path
+ if [ "$tool" == "wipe" ] || [ "$tool" == "rm" ]; then
+ $tool -rf $path
+ else
+ find $path -exec $tool -uf {} \;
+ fi
else
- $tool -f "$path"
+ if [ "$tool" == "wipe" ] || [ "$tool" == "rm" ]; then
+ $tool -f "$path"
+ else
+ $tool -uf "$path"
+ fi
fi
}
@@ -283,9 +290,9 @@ function keyringer_set_env {
fi
if [ ! -z "$KEYID" ]; then
- GPG="gpg -u $KEYID"
+ GPG="gpg --quiet -u $KEYID"
else
- GPG="gpg"
+ GPG="gpg --quiet"
fi
# Check keyring config version
@@ -398,14 +405,39 @@ function keyringer_upgrade {
# Get a file argument
function keyringer_get_file {
- FILE="$(keyringer_filename "$1")"
+ FILE="$(keyringer_filename "$RELATIVE_PATH/$1")"
if [ -z "$FILE" ]; then
keyringer_action_usage
exit 1
elif [ ! -f "$KEYDIR/$FILE" ]; then
- echo "File not found: $KEYDIR/$FILE"
- exit 1
+ # Try to find a similar file
+ count=0
+ candidates=(`keyringer_exec find "$BASEDIR" "$1" | grep -e '.asc$'`)
+
+ if [ ! -z "$candidates" ]; then
+ echo "Could not find exact match \"$1\", please chose one"
+ echo "of the following secrets:"
+ echo ""
+
+ for candidate in ${candidates[@]}; do
+ echo -e "\t[$count] $candidate"
+ let count++
+ done
+
+ echo ""
+ read -p "Enter option: " option
+
+ if [[ "$option" =~ ^[0-9]+$ ]] && [ ! -z "${candidates[$option]}" ]; then
+ FILE="$(keyringer_filename "$RELATIVE_PATH/${candidates[$option]}")"
+ else
+ echo "Invalid option"
+ exit 1
+ fi
+ else
+ echo "File not found: $KEYDIR/$FILE"
+ exit 1
+ fi
fi
}
@@ -427,7 +459,7 @@ function keyringer_get_new_file {
fi
# Complete file name
- FILE="$(keyringer_filename "$FILE")"
+ FILE="$RELATIVE_PATH/$(keyringer_filename "$FILE")"
if [ -z "$*" ]; then
keyringer_action_usage
@@ -474,9 +506,10 @@ function keyringer_usage {
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
+ # Display only when not in a keyring context
+ if [ ! -z "$keyrings" ] && [ -z "$1" ]; then
+ printf "\tinit <path> [remote]\n\n" $BASENAME
printf "Available keyrings: %s \n" "$keyrings"
fi
}
@@ -533,6 +566,31 @@ EOF
echo "Please check for this key or fix the recipient file."
exit 1
fi
+
+ # Current date
+ seconds="`date +%s`"
+
+ # Check the main key
+ expiry="`gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^pub | cut -d : -f 7`"
+
+ # Check if key is expired
+ if [ ! -z "$expiry" ] && [[ "$seconds" -gt "$expiry" ]]; then
+ echo "Fatal: primary key for $recipient expired on `date --date="@$expiry"`"
+ exit 1
+ else
+ # Check the subkeys
+ for expiry in `gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^sub | cut -d : -f 7`; do
+ if [[ "$seconds" -lt "$expiry" ]]; then
+ not_expired="1"
+ fi
+
+ if [ "$not_expired" != "1" ]; then
+ echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired."
+ exit 1
+ fi
+ done
+ fi
+
fi
done
}
@@ -546,7 +604,7 @@ function keyringer_set_recipients {
candidate_no_extension="`echo $1 | sed -e 's/.asc$//'`"
# Find the first matching recipient
- while [ ! -z "$candidate" ] && [ "$candidate" != "." ] && [ "$candidate" != "/" ]; do
+ while [ ! -z "$candidate" ] && [ "$candidate" != "." ] && [ "$candidate" != "/" ] && [ "$candidate" != "/." ]; do
if [ -e "$RECIPIENTS/$candidate" ]; then
RECIPIENTS_FILE="$RECIPIENTS/$candidate"
RECIPIENTS_FILE_BASE="$RECIPIENTS_BASE/$candidate"
diff --git a/share/man/keyringer.1 b/share/man/keyringer.1
index c0fed1c..8402b9c 100644
--- a/share/man/keyringer.1
+++ b/share/man/keyringer.1
@@ -31,6 +31,11 @@ and other read/write operations on secrets.
Configuration actions, handling repository metadata.
.SH REPOSITORY LOOKUP AND MANIPULATION ACTIONS
.TP
+.B find <\f[I]expression\f[]>
+Find secrets in the repository.
+.RS
+.RE
+.TP
.B init <\f[I]path\f[]> [\f[I]remote\f[]]
Initialize a new keyringer repository.
If a \f[I]remote\f[] URL is specified, keyringer will clone an existing
@@ -60,6 +65,16 @@ command.
.RS
.RE
.TP
+.B mkdir <\f[I]path\f[]>
+Create a directory inside the repository \f[I]keys\f[] folder.
+.RS
+.RE
+.TP
+.B :rmdir <\f[I]path\f[]>
+Remove an empty folder inside the repository \f[I]keys\f[] folder.
+.RS
+.RE
+.TP
.B tree <\f[I]path\f[]>
List contents from the toplevel repository \f[I]keys\f[] folder or from
relative paths if \f[I]path\f[] is specified using a tree-like format.
@@ -67,6 +82,25 @@ Like the ls wrapper, this is a wrapper around the \f[I]TREE(1)\f[]
command.
.RS
.RE
+.TP
+.B shell
+Run keyringer on interactive mode from a built-in command-line prompt
+where all other actions can be called and are operated from the current
+selected keyring.
+.RS
+.PP
+An additional "cd" internal command is available for directory
+navigation.
+.PP
+All <\f[I]secret\f[]> parameters from actions invoked from the shell are
+called relatively from the current selected directory.
+.RE
+.TP
+.B teardown
+Remove permanently a local copy of a repository, very dangerous if you
+have just a single copy.
+.RS
+.RE
.SH SECRET MANIPULATION ACTIONS
.PP
All secret manipulation actions operate upon a \f[I]secret\f[] which is
@@ -115,6 +149,11 @@ Alias for \f[I]del\f[] action.
.RS
.RE
.TP
+.B mv <\f[I]secret\f[]> <\f[I]dest\f[]>
+Rename a secret.
+.RS
+.RE
+.TP
.B edit <\f[I]secret\f[]>
Edit a secret by temporarily decrypting it, opening the decrypted copy
into the text editor defined by the \f[I]$EDITOR\f[] environment
@@ -162,6 +201,17 @@ If no \f[I]secret\f[] is given, all secrets in the repository are
re-encrypted.
.RS
.RE
+.TP
+.B clip <\f[I]secret\f[]>
+Copy the first line of a secret to the clipboard, following
+password-store convention.
+.RS
+.RE
+.TP
+.B xclip <\f[I]secret\f[]>
+Alis to clip action.
+.RS
+.RE
.SH CONFIGURATION ACTIONS
.TP
.B commands
@@ -200,6 +250,11 @@ Show keyringer usage information.
.RS
.RE
.TP
+.B help
+Alias for usage action.
+.RS
+.RE
+.TP
.B recipients <\f[I]ls\f[]|\f[I]edit\f[]> <\f[I]recipients-file\f[]>
List, create or edit recipients configuration.
.RS
diff --git a/share/man/keyringer.1.mdwn b/share/man/keyringer.1.mdwn
index d4b71e3..e8df829 100644
--- a/share/man/keyringer.1.mdwn
+++ b/share/man/keyringer.1.mdwn
@@ -37,6 +37,9 @@ Keyringer has three types of actions:
# REPOSITORY LOOKUP AND MANIPULATION ACTIONS
+find <*expression*>
+: Find secrets in the repository.
+
init <*path*> [*remote*]
: Initialize a new keyringer repository. If a *remote* URL is specified, keyringer will
clone an existing repository.
@@ -56,11 +59,31 @@ ls <*path*>
if *path* is specified. Like the git wrapper, this is a wrapper around the *LS(1)*
command.
+mkdir <*path*>
+: Create a directory inside the repository *keys* folder.
+
+:rmdir <*path*>
+: Remove an empty folder inside the repository *keys* folder.
+
tree <*path*>
: List contents from the toplevel repository *keys* folder or from relative paths
if *path* is specified using a tree-like format. Like the ls wrapper, this is a
wrapper around the *TREE(1)* command.
+shell
+: Run keyringer on interactive mode from a built-in command-line prompt where
+ all other actions can be called and are operated from the current selected
+ keyring.
+
+ An additional "cd" internal command is available for directory navigation.
+
+ All <*secret*> parameters from actions invoked from the shell are called
+ relatively from the current selected directory.
+
+teardown
+: Remove permanently a local copy of a repository, very dangerous if you
+ have just a single copy.
+
# SECRET MANIPULATION ACTIONS
All secret manipulation actions operate upon a *secret* which is the pathname
@@ -96,6 +119,9 @@ del <*secret*>
rm <*secret*>
: Alias for *del* action.
+mv <*secret*> <*dest*>
+: Rename a secret.
+
edit <*secret*>
: Edit a secret by temporarily decrypting it, opening the decrypted copy into the
text editor defined by the *$EDITOR* environment variable and then re-encrypting it.
@@ -124,6 +150,12 @@ recrypt <*secret*>
into the recipient configuration. If no *secret* is given, all secrets in the repository
are re-encrypted.
+clip <*secret*>
+: Copy the first line of a secret to the clipboard, following password-store convention.
+
+xclip <*secret*>
+: Alis to clip action.
+
# CONFIGURATION ACTIONS
commands
@@ -151,6 +183,9 @@ preferences <*ls*|*edit*|*add*>
usage
: Show keyringer usage information.
+help
+: Alias for usage action.
+
recipients <*ls*|*edit*> <*recipients-file*>
: List, create or edit recipients configuration.