diff --git a/.gitignore b/.gitignore index 319c0355..1ad63838 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .DS_Store docker-compose.yml postfix/ssl/* -assert.sh* letsencrypt/ diff --git a/Dockerfile b/Dockerfile index 6f94a855..5f53147d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ RUN apt-get autoclean && rm -rf /var/lib/apt/lists/* # Configures Saslauthd RUN rm -rf /var/run/saslauthd && ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd RUN adduser postfix sasl -RUN echo 'NAME="saslauthd"\nSTART=yes\nMECHANISMS="sasldb"\nTHREADS=0\nPWDIR=/var/spool/postfix/var/run/saslauthd\nPIDFILE="${PWDIR}/saslauthd.pid"\nOPTIONS="-n 0 -r -m /var/spool/postfix/var/run/saslauthd"' > /etc/default/saslauthd +RUN echo 'NAME="saslauthd"\nSTART=yes\nMECHANISMS="sasldb"\nTHREADS=0\nPWDIR=/var/spool/postfix/var/run/saslauthd\nPIDFILE="${PWDIR}/saslauthd.pid"\nOPTIONS="-n 0 -c -m /var/spool/postfix/var/run/saslauthd"' > /etc/default/saslauthd # Configures Courier RUN sed -i -r 's/daemons=5/daemons=1/g' /etc/courier/authdaemonrc diff --git a/Makefile b/Makefile index e049fd92..a019057e 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ run: cp test/virtual postfix/ # Run container docker run -d --name mail -v "`pwd`/postfix":/tmp/postfix -v "`pwd`/spamassassin":/tmp/spamassassin -v "`pwd`/test":/tmp/test -h mail.my-domain.com -t $(NAME):$(VERSION) - sleep 15 + sleep 25 prepare: # Reinitialize logs diff --git a/assert.sh b/assert.sh new file mode 100644 index 00000000..ffd2b955 --- /dev/null +++ b/assert.sh @@ -0,0 +1,186 @@ +#!/bin/bash +# assert.sh 1.1 - bash unit testing framework +# Copyright (C) 2009-2015 Robert Lehmann +# +# http://github.com/lehmannro/assert.sh +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +export DISCOVERONLY=${DISCOVERONLY:-} +export DEBUG=${DEBUG:-} +export STOP=${STOP:-} +export INVARIANT=${INVARIANT:-} +export CONTINUE=${CONTINUE:-} + +args="$(getopt -n "$0" -l \ + verbose,help,stop,discover,invariant,continue vhxdic $*)" \ +|| exit -1 +for arg in $args; do + case "$arg" in + -h) + echo "$0 [-vxidc]" \ + "[--verbose] [--stop] [--invariant] [--discover] [--continue]" + echo "`sed 's/./ /g' <<< "$0"` [-h] [--help]" + exit 0;; + --help) + cat < [stdin] + (( tests_ran++ )) || : + [[ -z "$DISCOVERONLY" ]] || return + expected=$(echo -ne "${2:-}") + result="$(eval 2>/dev/null $1 <<< ${3:-})" || true + if [[ "$result" == "$expected" ]]; then + [[ -z "$DEBUG" ]] || echo -n . + return + fi + result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")" + [[ -z "$result" ]] && result="nothing" || result="\"$result\"" + [[ -z "$2" ]] && expected="nothing" || expected="\"$2\"" + _assert_fail "expected $expected${_indent}got $result" "$1" "$3" +} + +assert_raises() { + # assert_raises [stdin] + (( tests_ran++ )) || : + [[ -z "$DISCOVERONLY" ]] || return + status=0 + (eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$? + expected=${2:-0} + if [[ "$status" -eq "$expected" ]]; then + [[ -z "$DEBUG" ]] || echo -n . + return + fi + _assert_fail "program terminated with code $status instead of $expected" "$1" "$3" +} + +_assert_fail() { + # _assert_fail + [[ -n "$DEBUG" ]] && echo -n X + report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1" + if [[ -n "$STOP" ]]; then + [[ -n "$DEBUG" ]] && echo + echo "$report" + exit 1 + fi + tests_errors[$tests_failed]="$report" + (( tests_failed++ )) || : +} + +skip_if() { + # skip_if + (eval $@) > /dev/null 2>&1 && status=0 || status=$? + [[ "$status" -eq 0 ]] || return + skip +} + +skip() { + # skip (no arguments) + shopt -q extdebug && tests_extdebug=0 || tests_extdebug=1 + shopt -q -o errexit && tests_errexit=0 || tests_errexit=1 + # enable extdebug so returning 1 in a DEBUG trap handler skips next command + shopt -s extdebug + # disable errexit (set -e) so we can safely return 1 without causing exit + set +o errexit + tests_trapped=0 + trap _skip DEBUG +} +_skip() { + if [[ $tests_trapped -eq 0 ]]; then + # DEBUG trap for command we want to skip. Do not remove the handler + # yet because *after* the command we need to reset extdebug/errexit (in + # another DEBUG trap.) + tests_trapped=1 + [[ -z "$DEBUG" ]] || echo -n s + return 1 + else + trap - DEBUG + [[ $tests_extdebug -eq 0 ]] || shopt -u extdebug + [[ $tests_errexit -eq 1 ]] || set -o errexit + return 0 + fi +} + + +_assert_reset +: ${tests_suite_status:=0} # remember if any of the tests failed so far +_assert_cleanup() { + local status=$? + # modify exit code if it's not already non-zero + [[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status +} +trap _assert_cleanup EXIT diff --git a/postfix/main.cf b/postfix/main.cf index b4114b1f..32ba810e 100644 --- a/postfix/main.cf +++ b/postfix/main.cf @@ -43,7 +43,7 @@ smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA smtpd_sasl_auth_enable = yes smtpd_sasl_path = smtpd smtpd_sasl_type = cyrus -smtpd_sasl_security_options = noanonymous, noplaintext +smtpd_sasl_security_options = noanonymous smtpd_sasl_local_domain = $myhostname cyrus_sasl_config_path = /etc/postfix/sasl broken_sasl_auth_clients = yes diff --git a/postfix/master.cf b/postfix/master.cf index c782b3da..8804f632 100644 --- a/postfix/master.cf +++ b/postfix/master.cf @@ -73,7 +73,7 @@ smtp-amavis unix - - - - 2 smtp -o disable_dns_lookups=yes -o max_use=20 -127.0.0.1:10025 inet n - - - - smtpd +127.0.0.1:10025 inet n - n - - smtpd -o content_filter= -o local_recipient_maps= -o relay_recipient_maps= diff --git a/postfix/sasl/smtpd.conf b/postfix/sasl/smtpd.conf index 75293ec9..f02eb91d 100644 --- a/postfix/sasl/smtpd.conf +++ b/postfix/sasl/smtpd.conf @@ -1,3 +1,4 @@ pwcheck_method: auxprop -mech_list: digest-md5 cram-md5 -log_level: 7 \ No newline at end of file +auxprop_plugin: sasldb +mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5 +log_level: 7 diff --git a/start-mailserver.sh b/start-mailserver.sh index 22ecdc53..8edb783b 100644 --- a/start-mailserver.sh +++ b/start-mailserver.sh @@ -104,6 +104,7 @@ esac echo "Fixing permissions" chown -R 5000:5000 /var/mail mkdir -p /var/log/clamav && chown -R clamav:root /var/log/clamav +chown postfix.sasl /etc/sasldb2 echo "Creating /etc/mailname" echo $(hostname -d) > /etc/mailname diff --git a/test/test.sh b/test/test.sh index 43bce4f1..13a648ee 100644 --- a/test/test.sh +++ b/test/test.sh @@ -14,6 +14,10 @@ assert_raises "docker exec mail ps aux --forest | grep '/usr/sbin/amavisd-new'" assert_raises "docker exec mail nc -w 1 0.0.0.0 143 | grep '* OK' | grep 'STARTTLS' | grep 'Courier-IMAP ready'" 0 assert_raises "docker exec mail /bin/sh -c 'nc -w 1 0.0.0.0 143 < /tmp/test/email-templates/test-imap.txt'" 0 +# Testing SASL +assert_raises "docker exec mail testsaslauthd -u user2 -r otherdomain.tld -p mypassword | grep 'OK \"Success.\"'" 0 +assert_raises "docker exec mail testsaslauthd -u user2 -r otherdomain.tld -p BADPASSWORD | grep 'NO \"authentication failed\"'" 0 + # Testing user creation assert "docker exec mail sasldblistusers2" "user1@localhost.localdomain: userPassword\nuser2@otherdomain.tld: userPassword" assert "docker exec mail ls -A /var/mail/localhost.localdomain/user1" "cur\nnew\ntmp"