aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhatto <rhatto>2006-10-13 19:26:34 +0000
committerrhatto <rhatto>2006-10-13 19:26:34 +0000
commitbe236f42e4d14fbe7f72ef34819402a1c12be65e (patch)
tree30b9bae1975ed522452fee9eb7fff8c72fb15a5b
parent9290bd98bfef3e7bd9cb4b4027fadf97aec70c69 (diff)
downloadfirma-be236f42e4d14fbe7f72ef34819402a1c12be65e.tar.gz
firma-be236f42e4d14fbe7f72ef34819402a1c12be65e.tar.bz2
GUIDELINES update and added anti-replay mechanism
-rwxr-xr-xGUIDELINES3
-rwxr-xr-xfirma257
2 files changed, 181 insertions, 79 deletions
diff --git a/GUIDELINES b/GUIDELINES
index fb8b0f1..fabe307 100755
--- a/GUIDELINES
+++ b/GUIDELINES
@@ -54,5 +54,6 @@ In the future this procedure will be automatic.
expect
fold
uniq
- mimencode
+ tac
+ sha1sum
diff --git a/firma b/firma
index 99274e7..46364d8 100755
--- a/firma
+++ b/firma
@@ -190,6 +190,15 @@ WARNING: $LIST_NAME: Removing this address from LIST_ADMIN."
LIST_REQUEST_ADDRESS="`echo $LIST_ADDRESS | cut -d @ -f 1`-request@`echo $LIST_ADDRESS | cut -d @ -f 2`"
fi
+ if [ "$REPLAY_PROTECTION" == "yes" ]; then
+ if [ -z "$REPLAY_COUNT" ]; then
+ REPLAY_COUNT="10"
+ fi
+ if [ -z "$REPLAY_FILE" ]; then
+ REPLAY_FILE="$REPLAY_DEFAULT_FILE"
+ fi
+ fi
+
SetDeliveryRandomization
return $return_code
@@ -701,100 +710,113 @@ function ProcessMessage {
# check if the message was encrypted
if GetGpgMessage; then
- # if it was, parse gpg decrypt STDERR to decide what to do next
- ParseGpgDecryptStderr
-
- # if the message was encrypted with the list's public key and if the
- #+message signature is valid, send message to list subscribers
- if AllowMessageProcessing; then
-
- # check if the list has valid subscribers
-
- GetSenderAddress
- GetMessageHeadersAndBody
- EditListMessageHeaders
- DecryptGpgMessage
-
- if [ "$MODE" == "list-message" ]; then
- if GetSubscribersList; then
- ReEncryptAndSendListMessage
- else
- return_code=1
+ # look for replay attacks
+ if ReplayProtectionCheck; then
+
+ # if it was, parse gpg decrypt STDERR to decide what to do next
+ ParseGpgDecryptStderr
+
+ # if the message was encrypted with the list's public key and if the
+ #+message signature is valid, send message to list subscribers
+ if AllowMessageProcessing; then
+
+ # check if the list has valid subscribers
+
+ GetSenderAddress
+ GetMessageHeadersAndBody
+ EditListMessageHeaders
+ DecryptGpgMessage
+
+ if [ "$MODE" == "list-message" ]; then
+ if GetSubscribersList; then
+ ReEncryptAndSendListMessage
+ else
+ return_code=1
+ fi
+ elif [ "$MODE" == "admin-non-interactive" ]; then
+ EmailListAdministration
fi
- elif [ "$MODE" == "admin-non-interactive" ]; then
- EmailListAdministration
- fi
-
- # else, if the message was correctly encrypted but its signature is invalid,
- #+send a warning about this to the list administrator(s) and to sender
- elif [ "$ENCRYPTED_TO_LIST" == "1" ] && [ "$BAD_SIGNATURE" == "1" ] && [ "$REQUIRE_SIGNATURE" == "yes" ]; then
-
- GetSenderAddress
-
- if [[ -n $(echo $LIST_ADMIN) || -n "$SENDER_ADDRESS" ]]; then
- ComposeAndSendWarningMessage
- fi
-
- # else, a bounce should be sent
- else
-
- # if bounce processing is enabled, continue
- if [[ "$SILENTLY_DISCARD_INVALID_MESSAGES" != 1 ]]; then
-
+
+ # else, if the message was correctly encrypted but its signature is invalid,
+ #+send a warning about this to the list administrator(s) and to sender
+ elif [ "$ENCRYPTED_TO_LIST" == "1" ] && [ "$BAD_SIGNATURE" == "1" ] && [ "$REQUIRE_SIGNATURE" == "yes" ]; then
+
GetSenderAddress
- if [[ -n "$SENDER_ADDRESS" ]]; then
-
- # if the message was encrypted with the list's public key
- if [[ $ENCRYPTED_TO_LIST == 1 ]]; then
-
- # then, if signature can't be checked, then probably the sender is not subscribed to the list
- # send a bounce, if possible
- if [ "$SIGNATURE_CHECKING_FAILED" == "1" ] && [ "$REQUIRE_SIGNATURE" == "yes" ]; then
-
- # this is the body of the message to be sent, so no indentation here
- MESSAGE_BODY="\
+
+ if [[ -n $(echo $LIST_ADMIN) || -n "$SENDER_ADDRESS" ]]; then
+ ComposeAndSendWarningMessage
+ fi
+
+ # else, a bounce should be sent
+ else
+
+ # if bounce processing is enabled, continue
+ if [[ "$SILENTLY_DISCARD_INVALID_MESSAGES" != 1 ]]; then
+
+ GetSenderAddress
+ if [[ -n "$SENDER_ADDRESS" ]]; then
+
+ # if the message was encrypted with the list's public key
+ if [[ $ENCRYPTED_TO_LIST == 1 ]]; then
+
+ # then, if signature can't be checked, then probably the sender is not subscribed to the list
+ # send a bounce, if possible
+ if [ "$SIGNATURE_CHECKING_FAILED" == "1" ] && [ "$REQUIRE_SIGNATURE" == "yes" ]; then
+
+ # this is the body of the message to be sent, so no indentation here
+ MESSAGE_BODY="\
It was not possible to process this message. Your email
address is not subscribed to this list. Contact the list
administrator if you have any questions."
- ComposeAndSendBounceMessage
-
- # or, if message can be decrypted but its signature can't be checked, then message wasn't signed
- # send a bounce, if possible
- elif [[ $MESSAGE_DECRYPTION_OKAY == 1 ]]; then
-
- # this is the body of the message to be sent, so no indentation here
- MESSAGE_BODY="\
+ ComposeAndSendBounceMessage
+
+ # or, if message can be decrypted but its signature can't be checked, then message wasn't signed
+ # send a bounce, if possible
+ elif [[ $MESSAGE_DECRYPTION_OKAY == 1 ]]; then
+
+ # this is the body of the message to be sent, so no indentation here
+ MESSAGE_BODY="\
It was not possible to process this message. Message was
not signed. Contact the list administrator if you have any
questions."
- ComposeAndSendBounceMessage
-
- elif [ "$SIGNATURE_MADE_BY_SENDER" != "1" ] && [ "$REQUIRE_SIGNATURE" == "yes" ]; then
-
- # this is the body of the message to be sent, so no indentation here
- MESSAGE_BODY="\
+ ComposeAndSendBounceMessage
+
+ elif [ "$SIGNATURE_MADE_BY_SENDER" != "1" ] && [ "$REQUIRE_SIGNATURE" == "yes" ]; then
+
+ # this is the body of the message to be sent, so no indentation here
+ MESSAGE_BODY="\
It was not possible to process this message. Message was
not sent by the person who signed it."
-
- ComposeAndSendBounceMessage
-
- fi
-
- # else, message wasn't encrypted with the list's public key
- # send a bounce, if possible
- else
-
- # this is the body of the message to be sent, so no indentation here
- MESSAGE_BODY="\
+
+ ComposeAndSendBounceMessage
+
+ fi
+
+ # else, message wasn't encrypted with the list's public key
+ # send a bounce, if possible
+ else
+
+ # this is the body of the message to be sent, so no indentation here
+ MESSAGE_BODY="\
It was not possible to process this message. Message was
not encrypted with the list's public key. Contact the list
administrator if you have any questions."
- ComposeAndSendBounceMessage
+ ComposeAndSendBounceMessage
+ fi
fi
fi
fi
+ else
+ # the anti-replay mechanism detected a repeated message
+ MESSAGE_BODY="\
+ It was not possible to process this message. This list
+ is configured to discarded replayed messages as an attack
+ protection measue. It looks like that your message was
+ already sent to the list and then it was discarded.
+ Contact the list administrator if you have any questions."
+ ComposeAndSendBounceMessage
fi
-
+
# else, message wasn't encrypted at all
# send a bounce, if possible
else
@@ -1044,6 +1066,9 @@ EOF
# fix permissions
chown -R $FIRMA_USER.$FIRMA_GROUP $LIST_HOMEDIR
+
+ echo "Your list was created. No check its configuration at $LIST_CONFIG_FILE."
+ echo "To see a list of optional config parameters, type firma --help config."
fi
else
echo "Cannot create list $LIST_HOMEDIR: Installation aborted"
@@ -2053,6 +2078,19 @@ function SourceListConfig {
\t of messages or if you're going to have a lot of encrypted mailing lists, all randomizing
\t its delivery." || \
DELIVERY_RANDOMIZATION="`EvalConfigParameter $LIST_CONFIG_FILE DELIVERY_RANDOMIZATION`"
+
+ [ "$1" == "help" ] && echo -e "\tREPLAY_PROTECTION= when set to \"yes\", stores sha1sums of the last REPLAY_COUNT
+\t received messages; then, if some message with an already stored sha1sum, then its bounced back
+\t to the sender and considered as an attempt of replay attack." || \
+ REPLAY_PROTECTION="`EvalConfigParameter $LIST_CONFIG_FILE REPLAY_PROTECTION`"
+
+ [ "$1" == "help" ] && echo -e "\tREPLAY_COUNT= number of messages to store sha1sums; defaults to 10 and only used
+\t when REPLAY_PROTECTION is set to \"yes\"." || \
+ REPLAY_COUNT="`EvalConfigParameter $LIST_CONFIG_FILE REPLAY_COUNT`"
+
+ [ "$1" == "help" ] && echo -e "\tREPLAY_FILE= file to store sha1sums of messages; only used when REPLAY_PROTECTION
+\t is set to \"yes\"; defaults to $REPLAY_DEFAULT_FILE" || \
+ REPLAY_FILE="`EvalConfigParameter $LIST_CONFIG_FILE REPLAY_FILE`"
}
@@ -2111,12 +2149,71 @@ function DeliveryRandomization {
fi
}
+
+function ReplayProtectionFlush {
+ #-------------------------------------------------------------
+ # flushes the replay database file
+ #
+ # parameter(s): none
+ # depends on function(s): none
+ # returns: 0
+ #-------------------------------------------------------------
+
+ if [ "$REPLAY_PROTECTION" == "yes" ]; then
+ if [ -f "$REPLAY_FILE" ]; then
+ if [ "`wc -l $REPLAY_FILE | awk '{ print $1 }'`" -gt "$REPLAY_COUNT" ]; then
+ tac $REPLAY_FILE | head -n $REPLAY_COUNT | tac > $REPLAY_FILE
+ fi
+ else
+ touch $REPLAY_FILE
+ chown $FIRMA_USER.$FIRMA_GROUP $REPLAY_FILE
+ chmod 600 $REPLAY_FILE
+ fi
+ fi
+
+ return 0
+}
+
+
+function ReplayProtectionCheck {
+ #-------------------------------------------------------------
+ # check if message was already received and stores it
+ #+in the database
+ #
+ # parameter(s): GetGpgMessage, ReplayProtectionFlush
+ # depends on function(s): none
+ # returns: 0 if message's sha1sum is not in replay database
+ # 1 if message's sha1sum is in the database
+ #-------------------------------------------------------------
+
+ local sha1
+
+ if [ "$REPLAY_PROTECTION" == "yes" ]; then
+ ReplayProtectionFlush
+ sha1="`echo $GPG_MESSAGE | sha1sum | awk '{ print $1 }'`"
+ if grep -q "^$sha1$" $REPLAY_FILE; then
+ touch $REPLAY_FILE.tmp
+ chown $FIRMA_USER.$FIRMA_GROUP $REPLAY_FILE.tmp
+ chmod 600 $REPLAY_FILE.tmp
+ cat $REPLAY_FILE | sed -e "/^$sha1$/d" > $REPLAY_FILE.tmp
+ mv $REPLAY_FILE.tmp $REPLAY_FILE
+ return 1
+ else
+ return 0
+ fi
+ echo $sha1 >> $REPLAY_FILE
+ else
+ return 0
+ fi
+}
+
#-------------------------------------------------------------
# main()
#-------------------------------------------------------------
# path to firma.conf and firma version
FIRMA_CONFIG_FILE="/usr/local/etc/firma.conf"
+REPLAY_DEFAULT_FILE="/var/log/firma/replay.db"
VERSION="0.3"
# set environmental variables and options
@@ -2153,7 +2250,11 @@ GLOBAL_VARS="
MODE
REQUIRE_SIGNATURE
SIGNATURE_MADE_BY_SENDER
- DELIVERY_RANDOMIZATION"
+ DELIVERY_RANDOMIZATION
+ REPLAY_FILE
+ REPLAY_DEFAULT_FILE
+ REPLAY_PROTECTION
+ REPLAY_COUNT"
FUNCTIONS="
Usage