diff options
Diffstat (limited to 'lib/keyringer/functions')
-rwxr-xr-x | lib/keyringer/functions | 199 |
1 files changed, 131 insertions, 68 deletions
diff --git a/lib/keyringer/functions b/lib/keyringer/functions index e594fd1..e60657a 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")" @@ -540,8 +551,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 +634,91 @@ 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." + + exit 1 + fi + fi +} - # Current date - seconds="`date +%s`" +# Check key expiration +function keyringer_check_expiration { + # Variables + local recipient="$1" + local not_expired="0" - # Check the main key - expiry="`gpg --with-colons --fixed-list-mode --list-keys "$recipient" | grep ^pub | cut -d : -f 7`" + # Current date + seconds="`date +%s`" - # 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 - - if [ "$not_expired" != "1" ]; then - echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." - exit 1 - fi - done - fi + # 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 + if [ ! -z "$expiry" ] && [[ "$seconds" -gt "$expiry" ]]; then + echo "Fatal: primary key for $recipient expired on `date --date="@$expiry"`" + exit 1 + fi + # 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 [ ! -z "$expiry" ] && [ "$not_expired" != "1" ]; then + echo "Fatal: key $recipient has no keys suitable for encryption: all subkeys expired." + exit 1 + fi } # Set recipients |