diff --git a/target/bin/addmailuser b/target/bin/addmailuser index 04b40b4b..3b486863 100755 --- a/target/bin/addmailuser +++ b/target/bin/addmailuser @@ -22,13 +22,20 @@ escape() { [ -z "$USER" ] && { usage; errex "no username specified"; } expr index "$USER" "@" >/dev/null || { usage; errex "username must include the domain"; } -grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null && - errex "User \"$USER\" already exists" +# Protect config file with lock to avoid race conditions +touch $DATABASE +( + flock -e 200 -if [ -z "$PASSWD" ]; then - read -s -p "Enter Password: " PASSWD - echo - [ -z "$PASSWD" ] && errex "Password must not be empty" -fi -HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" -echo "$USER|$HASH" >> $DATABASE + grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null && + errex "User \"$USER\" already exists" + + if [ -z "$PASSWD" ]; then + read -s -p "Enter Password: " PASSWD + echo + [ -z "$PASSWD" ] && errex "Password must not be empty" + fi + + HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" + echo "$USER|$HASH" >> $DATABASE +) 200<$DATABASE diff --git a/target/bin/delmailuser b/target/bin/delmailuser index d73db74f..8f4e0368 100755 --- a/target/bin/delmailuser +++ b/target/bin/delmailuser @@ -33,25 +33,31 @@ shift $((OPTIND-1)) [ -z "$@" ] && { usage; errex "No user specifed"; } [ -s "$DATABASE" ] || exit 0 -for USER in "$@"; do - #very simple plausibility check - [[ "$USER" != *"@"*"."* ]] && errex "No valid address: $USER" - MAILARR=(${USER//@/ }) - # XXX $USER must not contain /s and other syntactic characters - USER=$(escape "$USER") - sed -i "/^"$USER"|/d" $DATABASE - [ $? != 0 ] && errex "$USER couldn't be deleted in $DATABASE. $?" - # Delete all aliases where the user is the only recipient( " $USER$" ) - # Delete user only for all aliases that deliver to multiple recipients ( ",$USER" "$USER," ) - sed -i -e "/ "$USER"$/d" \ - -e "s/,"$USER"//g" \ - -e "s/"$USER",//g" $ALIAS_DATABASE - [ $? = 0 ] && echo "$USER and potential aliases deleted." || errex "Aliases for $USER couldn't be deleted in $ALIAS_DATABASE. $?" - if [ "$MAILDEL" != "y" ]; then - read -p "Do you want to delete the maildir as well(all mails will be removed)?(y/n) " MAILDEL - echo - fi - [ "$MAILDEL" != "y" ] && errex "Leaving the maildir untouched. If you want to delete it at a later point use \"sudo docker exec mail rm -R /var/mail/${MAILARR[1]}/${MAILARR[0]}\"" - rm -r -f /var/mail/${MAILARR[1]}/${MAILARR[0]} - [ $? = 0 ] && echo "Maildir deleted." || errex "Maildir couldn't be deleted: $?" -done +# Protect config file with lock to avoid race conditions +( + flock -e 200 + + for USER in "$@"; do + # very simple plausibility check + [[ "$USER" != *"@"*"."* ]] && errex "No valid address: $USER" + MAILARR=(${USER//@/ }) + # XXX $USER must not contain /s and other syntactic characters + USER=$(escape "$USER") + sed -i "/^"$USER"|/d" $DATABASE + [ $? != 0 ] && errex "$USER couldn't be deleted in $DATABASE. $?" + # Delete all aliases where the user is the only recipient( " $USER$" ) + # Delete user only for all aliases that deliver to multiple recipients ( ",$USER" "$USER," ) + sed -i -e "/ "$USER"$/d" \ + -e "s/,"$USER"//g" \ + -e "s/"$USER",//g" $ALIAS_DATABASE + [ $? = 0 ] && echo "$USER and potential aliases deleted." || errex "Aliases for $USER couldn't be deleted in $ALIAS_DATABASE. $?" + if [ "$MAILDEL" != "y" ]; then + read -p "Do you want to delete the maildir as well(all mails will be removed)?(y/n) " MAILDEL + echo + fi + [ "$MAILDEL" != "y" ] && errex "Leaving the maildir untouched. If you want to delete it at a later point use \"sudo docker exec mail rm -R /var/mail/${MAILARR[1]}/${MAILARR[0]}\"" + rm -r -f /var/mail/${MAILARR[1]}/${MAILARR[0]} + [ $? = 0 ] && echo "Maildir deleted." || errex "Maildir couldn't be deleted: $?" + done + +) 200<$DATABASE diff --git a/target/bin/listmailuser b/target/bin/listmailuser index 04352a5d..658c52eb 100755 --- a/target/bin/listmailuser +++ b/target/bin/listmailuser @@ -10,4 +10,9 @@ errex() { [ -f $DATABASE ] || errex "No postfix-accounts.cf file" [ -s $DATABASE ] || errex "Empty postfix-accounts.cf - no users have been added" -awk -F '|' '{ print $1; }' $DATABASE +# Lock database even though we are only reading +( + flock -e 200 + awk -F '|' '{ print $1; }' $DATABASE +) 200<$DATABASE + diff --git a/target/bin/updatemailuser b/target/bin/updatemailuser index 1d32d0f0..cf9a4a8c 100755 --- a/target/bin/updatemailuser +++ b/target/bin/updatemailuser @@ -27,7 +27,13 @@ if [ -z "$PASSWD" ]; then [ -z "$PASSWD" ] && errex "Password must not be empty" fi HASH="$(doveadm pw -s SHA512-CRYPT -u "$USER" -p "$PASSWD")" -grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null || - errex "User \"$USER\" does not exist" -sed -i "s ^"$USER"|.* "$USER"|"$HASH" " $DATABASE +# Protect config file with lock to avoid race conditions +( + flock -e 200 + + grep -qi "^$(escape "$USER")|" $DATABASE 2>/dev/null || + errex "User \"$USER\" does not exist" + + sed -i "s ^"$USER"|.* "$USER"|"$HASH" " $DATABASE +) 200<$DATABASE diff --git a/target/check-for-changes.sh b/target/check-for-changes.sh index 5a5ab494..afcb059b 100755 --- a/target/check-for-changes.sh +++ b/target/check-for-changes.sh @@ -37,8 +37,7 @@ for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf; do done # Wait to make sure server is up before we start -# Plus the files have just been generated, no hurry to process changes -sleep 20 +sleep 10 # Run forever while true; do @@ -46,7 +45,7 @@ while true; do # recreate logdate log_date=$(date +"%Y-%m-%d %H:%M:%S ") -# Get chksum and check it. +# Get chksum and check it, no need to lock config yet chksum=$(sha512sum -c --ignore-missing $CHKSUM_FILE) if [[ $chksum == *"FAIL"* ]]; then @@ -57,6 +56,11 @@ if [[ $chksum == *"FAIL"* ]]; then # Also note that changes are performed in place and are not atomic # We should fix that and write to temporary files, stop, swap and start + # Lock configuration while working + # Not fixing indentation yet to reduce diff (fix later in separate commit) + ( + flock -e 200 + #regen postix aliases. echo "root: ${PM_ADDRESS}" > /etc/aliases if [ -f /tmp/docker-mailserver/postfix-aliases.cf ]; then @@ -195,6 +199,8 @@ if [[ $chksum == *"FAIL"* ]]; then echo "${log_date} Update checksum" sha512sum ${cf_files[@]/#/--tag } >$CHKSUM_FILE + + ) 200