From b24bd68b002e49b0fea6d1e9c04cdde0be98c899 Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Tue, 25 Feb 2014 16:00:09 -0300 Subject: Manpage update: check action --- share/man/keyringer.1.mdwn | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/share/man/keyringer.1.mdwn b/share/man/keyringer.1.mdwn index e8df829..9412b5d 100644 --- a/share/man/keyringer.1.mdwn +++ b/share/man/keyringer.1.mdwn @@ -62,7 +62,7 @@ ls <*path*> mkdir <*path*> : Create a directory inside the repository *keys* folder. -:rmdir <*path*> +rmdir <*path*> : Remove an empty folder inside the repository *keys* folder. tree <*path*> @@ -84,6 +84,9 @@ teardown : Remove permanently a local copy of a repository, very dangerous if you have just a single copy. +check +: Run maintenance checks in a keyring. + # SECRET MANIPULATION ACTIONS All secret manipulation actions operate upon a *secret* which is the pathname -- cgit v1.2.3 From 2b2cbe33a1aefb9b8eb2b812f1d4b3274e51a0df Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Tue, 25 Feb 2014 16:21:48 -0300 Subject: Break keyringer_check_recipients into smaller pieces --- lib/keyringer/actions/check | 5 +- lib/keyringer/functions | 180 +++++++++++++++++++++++++++----------------- 2 files changed, 112 insertions(+), 73 deletions(-) diff --git a/lib/keyringer/actions/check b/lib/keyringer/actions/check index 1ccd9c8..527af5a 100755 --- a/lib/keyringer/actions/check +++ b/lib/keyringer/actions/check @@ -22,10 +22,7 @@ source "$LIB" || exit 1 # Pull the keyring repository. # Git maintenance operations. # Fetch absent keys from all recipients. -# TODO: Check if keys in all recipients files are about to expire. -# TODO: Time to expire can be configured via repository options. -# TODO: Users can be alerted by mail if configured by user preferences. -# TODO: Outgoing emails can be encrypted. +# Check key expirations # This should be done here: # TODO: Check canaries' timestamps, warning by mail if configured by user preferences. diff --git a/lib/keyringer/functions b/lib/keyringer/functions index e594fd1..ca59501 100755 --- a/lib/keyringer/functions +++ b/lib/keyringer/functions @@ -540,8 +540,54 @@ function keyringer_check_repository { fi } +# Receive keys from keyservers +# TODO: gpg-maintenance trickery +# TODO: should be controlled by user preference +function keyringer_recv_keys { + local recipient="$1" + + echo "Trying to receive missing key $recipient..." + gpg --batch --recv-keys "$recipient" +} + +# Refresh keys from keyserver +# TODO: gpg-maintenance trickery +# TODO: should be controlled by user preference +function keyringer_refresh_keys { + local recipient="$1" + + echo "Trying to refresh key $recipient..." + gpg --batch --refresh-keys "$recipient" +} + +# Check recipient size +function keyringer_check_recipient_size { + local recipient="$1" + local size=$(echo "$recipient" | wc -c) + + if (( $size < 41 )); then + echo "Fatal: please set the full GPG signature hash for key ID $recipient:" + cat <<-EOF + +Please provide a full OpenPGP fingerprint, for example: + + john@doe.com ABCD1234ABCD12345678ABCD1234ABCD12345678 + +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 + fi +} + # Check recipients -# TODO: break in smaller pieces function keyringer_check_recipients { # Shall we check recipients? if [ "$KEYRINGER_CHECK_RECIPIENTS" == "false" ]; then @@ -577,85 +623,81 @@ function keyringer_check_recipients { processed="$processed$recipient:" fi - size=$(echo "$recipient" | wc -c) - if (( $size < 41 )); then - echo "Fatal: please set the full GPG signature hash for key ID $recipient:" - cat <<-EOF + # Check recipient size + keyringer_check_recipient_size "$recipient" -Please provide a full OpenPGP fingerprint, for example: + # Check if key is present + keyringer_check_recipient_key "$recipient" - john@doe.com ABCD1234ABCD12345678ABCD1234ABCD12345678 + # Refresh keys + if [ "$BASENAME" == "check" ] && [ "$refresh" != "no" ]; then + keyringer_refresh_keys "$recipient" + echo "" + fi -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. + # Check key expiration + keyringer_check_expiration "$recipient" -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 - gpg --list-key "$recipient" &> /dev/null - if [ "$?" != "0" ]; then - if [ "$BASENAME" == "check" ]; then - # TODO: gpg-maintenance trickery - # TODO: should be controlled by user preference - refresh="no" - echo "Trying to receive missing key $recipient..." - gpg --batch --recv-keys "$recipient" - echo "" - if [ "$?" != 0 ]; then - echo "Error fetching $recipient from keyservers." - continue - fi - else - 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 +} - # Refresh keys - if [ "$BASENAME" == "check" ] && [ "$refresh" != "no" ]; then - # TODO: gpg-maintenance trickery - # TODO: should be controlled by user preference - echo "Trying to refresh key $recipient..." - gpg --batch --refresh-keys "$recipient" - echo "" +# Check if a key is present +function keyringer_check_recipient_key { + local recipient="$1" + + gpg --list-key "$recipient" &> /dev/null + if [ "$?" != "0" ]; then + if [ "$BASENAME" == "check" ]; then + refresh="no" + keyringer_recvs_keys "$recipient" + if [ "$?" != 0 ]; then + echo "Error fetching $recipient from keyservers." + continue fi + echo "" + else + echo "Fatal: no such key $recipient on your GPG keyring." + echo "Please check for this key or fix the recipient file." - # Current date - seconds="`date +%s`" + exit 1 + fi + fi +} - # Check the main key - expiry="`gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^pub | cut -d : -f 7`" +# Check key expiration +# TODO: Check if keys in all recipients files are about to expire. +# TODO: Time to expire can be configured via repository options. +# TODO: Users can be alerted by mail if configured by user preferences. +# TODO: Outgoing emails can be encrypted. +function keyringer_check_expiration { + # Variables + local recipient="$1" + + # 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 + # TODO: check if key is about to expire + 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 + # TODO: check if subkey is about to expire + not_expired="1" + fi - # Check if key is expired - # TODO: check if key is about to expire - if [ ! -z "$expiry" ] && [[ "$seconds" -gt "$expiry" ]]; then - echo "Fatal: primary key for $recipient expired on `date --date="@$expiry"`" + if [ "$not_expired" != "1" ]; then + echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." 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 - # TODO: check if subkey is about to expire - 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 + done + fi } # Set recipients -- cgit v1.2.3 From f6b2f4910184cdce2c1a27fab16eeebecd789446 Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Tue, 25 Feb 2014 17:07:21 -0300 Subject: Check if keys are about to expire --- lib/keyringer/functions | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/lib/keyringer/functions b/lib/keyringer/functions index ca59501..4ded3b3 100755 --- a/lib/keyringer/functions +++ b/lib/keyringer/functions @@ -665,13 +665,10 @@ function keyringer_check_recipient_key { } # Check key expiration -# TODO: Check if keys in all recipients files are about to expire. -# TODO: Time to expire can be configured via repository options. -# TODO: Users can be alerted by mail if configured by user preferences. -# TODO: Outgoing emails can be encrypted. function keyringer_check_expiration { # Variables local recipient="$1" + local not_expired="0" # Current date seconds="`date +%s`" @@ -679,24 +676,37 @@ function keyringer_check_expiration { # Check the main key expiry="`gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^pub | cut -d : -f 7`" + # TODO: Time to expire can be configured via repository options. + ahead="$((86400 * 30 + $seconds))" + # Check if key is expired - # TODO: check if key is about to expire 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 - # TODO: check if subkey is about to expire - not_expired="1" - fi + fi - if [ "$not_expired" != "1" ]; then - echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." - exit 1 - fi - done + # Check if key is about to expire + # TODO: Users can be alerted by mail if configured by user preferences. + # TODO: Outgoing emails can be encrypted. + if [ "$BASENAME" == "check" ] && [ ! -z "$expiry" ] && [[ "$ahead" -gt "$expiry" ]]; then + echo "Warning: key $recipient will expire soon, on `date --date="@$expiry"`" + fi + + # 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 [[ "$ahead" -gt "$expiry" ]] && [ "$BASENAME" == "check" ]; then + echo "Warning: subkey from $recipient will expire soon, on `date --date="@$expiry"`" + fi + done + + # All subkeys are expired + if [ "$not_expired" != "1" ]; then + echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." + exit 1 fi } -- cgit v1.2.3 From d2b6a5193d7dbb28351ec2108ac119a42c7365e3 Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Tue, 25 Feb 2014 18:28:17 -0300 Subject: Skeleton for keyringer_get_option --- lib/keyringer/actions/options | 2 +- lib/keyringer/actions/preferences | 2 +- lib/keyringer/functions | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/keyringer/actions/options b/lib/keyringer/actions/options index 3bf0e43..b210e1a 100755 --- a/lib/keyringer/actions/options +++ b/lib/keyringer/actions/options @@ -1,6 +1,6 @@ #!/bin/bash # -# Recipient management. +# Repository options management. # # Load functions diff --git a/lib/keyringer/actions/preferences b/lib/keyringer/actions/preferences index f7507a7..114f9ac 100755 --- a/lib/keyringer/actions/preferences +++ b/lib/keyringer/actions/preferences @@ -1,6 +1,6 @@ #!/bin/bash # -# Manipulate preferences. +# Manipulate user preferences. # # Load functions diff --git a/lib/keyringer/functions b/lib/keyringer/functions index 4ded3b3..ec3eb0c 100755 --- a/lib/keyringer/functions +++ b/lib/keyringer/functions @@ -408,6 +408,17 @@ function keyringer_upgrade { fi } +# Get an option +# +# Given that options are shared among users through the +# repository, we can't just "source $OPTIONS" as we would +# be opening a simple arbitrary code execution hole. +# +# TODO +function keyringer_get_option { + false +} + # Get a file argument function keyringer_get_file { FILE="$(keyringer_filename "$RELATIVE_PATH/$1")" -- cgit v1.2.3 From 34ef511e0404012dff2b44fa3f8453c926aa5456 Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Thu, 27 Feb 2014 15:55:52 -0300 Subject: Do not trigger a false positive when subkeys has no expiry date --- lib/keyringer/functions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/keyringer/functions b/lib/keyringer/functions index ec3eb0c..e60657a 100755 --- a/lib/keyringer/functions +++ b/lib/keyringer/functions @@ -715,7 +715,7 @@ function keyringer_check_expiration { done # All subkeys are expired - if [ "$not_expired" != "1" ]; then + if [ ! -z "$expiry" ] && [ "$not_expired" != "1" ]; then echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." exit 1 fi -- cgit v1.2.3 From 66812bcf7655bf22aafe58d8d60c96a03114bf0b Mon Sep 17 00:00:00 2001 From: Silvio Rhatto Date: Fri, 28 Feb 2014 16:48:22 -0300 Subject: Software comparison --- index.mdwn | 3 +++ lib/keyringer/actions/check | 1 + 2 files changed, 4 insertions(+) diff --git a/index.mdwn b/index.mdwn index 652376d..ee3870a 100644 --- a/index.mdwn +++ b/index.mdwn @@ -206,6 +206,9 @@ given key), but it's possible to: Never decrypt a key and write it to the disk, except if you're adding it to your personall keyring. +Check [this page](https://wiki.koumbit.net/PasswordManagementService/SoftwareComparison) +a comparison on different password management tools. + Requirements ------------ diff --git a/lib/keyringer/actions/check b/lib/keyringer/actions/check index 527af5a..c80fa8f 100755 --- a/lib/keyringer/actions/check +++ b/lib/keyringer/actions/check @@ -7,6 +7,7 @@ # - git://lair.fifthhorseman.net/~mjgoins/cur # - https://gitorious.org/key-report # - https://github.com/ilf/gpg-maintenance.git +# - https://github.com/EtiennePerot/parcimonie.sh # - https://gaffer.ptitcanardnoir.org/intrigeri/code/parcimonie/ # # This script can run from a crontab, client or server side to check -- cgit v1.2.3