diff --git a/.github/workflows/generic_build.yml b/.github/workflows/generic_build.yml
index 0f375d45..ccef46f5 100644
--- a/.github/workflows/generic_build.yml
+++ b/.github/workflows/generic_build.yml
@@ -64,7 +64,7 @@ jobs:
# When full, the least accessed cache upload is evicted to free up storage.
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows
- name: 'Handle Docker build layer cache'
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: cache-buildx-${{ steps.derive-image-cache-key.outputs.digest }}
diff --git a/.github/workflows/generic_publish.yml b/.github/workflows/generic_publish.yml
index 00771221..d7a791c5 100644
--- a/.github/workflows/generic_publish.yml
+++ b/.github/workflows/generic_publish.yml
@@ -46,7 +46,7 @@ jobs:
# NOTE: Until adopting `type=gha` scoped cache exporter (in `docker/build-push-action`),
# only AMD64 image is expected to be cached, ARM images will build from scratch.
- name: 'Retrieve image build from build cache'
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: cache-buildx-${{ inputs.cache-key }}
diff --git a/.github/workflows/generic_test.yml b/.github/workflows/generic_test.yml
index 5b8bac62..2c1d1045 100644
--- a/.github/workflows/generic_test.yml
+++ b/.github/workflows/generic_test.yml
@@ -29,7 +29,7 @@ jobs:
# This should always be a cache-hit, thus `restore-keys` fallback is not used.
# No new cache uploads should ever happen for this job.
- name: 'Retrieve image built from build cache'
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: cache-buildx-${{ inputs.cache-key }}
diff --git a/.github/workflows/generic_vulnerability-scan.yml b/.github/workflows/generic_vulnerability-scan.yml
index 896ee80e..b261de91 100644
--- a/.github/workflows/generic_vulnerability-scan.yml
+++ b/.github/workflows/generic_vulnerability-scan.yml
@@ -28,7 +28,7 @@ jobs:
# This should always be a cache-hit, thus `restore-keys` fallback is not used.
# No new cache uploads should ever happen for this job.
- name: 'Retrieve image built from build cache'
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: cache-buildx-${{ inputs.cache-key }}
@@ -55,7 +55,7 @@ jobs:
provenance: false
- name: 'Run the Anchore Grype scan action'
- uses: anchore/scan-action@v3.5.0
+ uses: anchore/scan-action@v3.6.0
id: scan
with:
image: mailserver-testing:ci
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30fa1d54..d8fbe449 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -33,6 +33,13 @@ The most noteworthy change of this release is the update of the container's base
- `smtpd_relay_restrictions` (relay policy) is now evaluated after `smtpd_recipient_restrictions` (spam policy). Previously it was evaluated before `smtpd_recipient_restrictions`. Mail to be relayed via DMS must now pass through the spam policy first.
- The TLS fingerprint policy has changed the default from MD5 to SHA256 (_DMS does not modify this Postfix parameter, but may affect any user customizations that do_).
+### Fixes
+
+- **Dovecot:**
+ - Restrict the auth mechanisms for PassDB configs we manage (oauth2, passwd-file, ldap) ([#3812](https://github.com/docker-mailserver/docker-mailserver/pull/3812))
+ - Prevents misleading auth failures from attempting to authenticate against a PassDB with incompatible auth mechanisms.
+ - When the new OAuth2 feature was enabled, it introduced false-positives with logged auth failures which triggered Fail2Ban to ban the IP.
+
## [v13.3.0](https://github.com/docker-mailserver/docker-mailserver/releases/tag/v13.3.0)
### Features
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 53254c78..f86435f4 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -814,14 +814,21 @@ Thanks goes to these wonderful people ✨
fl42
+
+
+
+
+ nilshoell
+
+ |
+
stigok
- |
-
+
@@ -856,15 +863,15 @@ Thanks goes to these wonderful people ✨
thomasschmit
- |
+
+
Thiritin
- |
-
+
@@ -899,15 +906,15 @@ Thanks goes to these wonderful people ✨
k3it
- |
+
+
Drakulix
- |
-
+
@@ -942,13 +949,6 @@ Thanks goes to these wonderful people ✨
allddd
- |
-
-
-
-
- nilshoell
-
|
@@ -1022,21 +1022,28 @@ Thanks goes to these wonderful people ✨
romansey
|
+
+
+
+
+ norrs
+
+ |
MightySCollins
- |
+
+
501st-alpha1
- |
-
+
@@ -1071,15 +1078,15 @@ Thanks goes to these wonderful people ✨
sjmudd
- |
+
+
simonsystem
- |
-
+
@@ -1114,15 +1121,15 @@ Thanks goes to these wonderful people ✨
okamidash
- |
+
+
olaf-mandel
- |
-
+
@@ -1157,15 +1164,15 @@ Thanks goes to these wonderful people ✨
rmlhuk
- |
+
+
rriski
- |
-
+
@@ -1200,15 +1207,15 @@ Thanks goes to these wonderful people ✨
strarsis
- |
+
+
tamueller
- |
-
+
@@ -1243,15 +1250,15 @@ Thanks goes to these wonderful people ✨
arcaine2
- |
+
+
awb99
- |
-
+
@@ -1286,15 +1293,15 @@ Thanks goes to these wonderful people ✨
eleith
- |
+
+
ghnp5
- |
-
+
@@ -1329,15 +1336,15 @@ Thanks goes to these wonderful people ✨
ixeft
- |
+
+
jjtt
- |
-
+
@@ -1372,15 +1379,15 @@ Thanks goes to these wonderful people ✨
marios88
- |
+
+
matrixes
- |
-
+
@@ -1388,13 +1395,6 @@ Thanks goes to these wonderful people ✨
mchamplain
|
-
-
-
-
- 0xflotus
-
- |
@@ -1452,21 +1452,28 @@ Thanks goes to these wonderful people ✨
danielvandenberg95
|
+
+
+
+
+ denisix
+
+ |
mlatorre31
- |
+
+
mazzz1y
- |
-
+
@@ -1501,15 +1508,15 @@ Thanks goes to these wonderful people ✨
ekkis
- |
+
+
ErikEngerd
- |
-
+
@@ -1532,12 +1539,20 @@ Thanks goes to these wonderful people ✨
|
-
-
+
+
- froks
+ thechubbypanda
|
+
+
+
+
+ 0xflotus
+
+ |
+
@@ -1551,8 +1566,7 @@ Thanks goes to these wonderful people ✨
20th
- |
-
+
@@ -1580,7 +1594,8 @@ Thanks goes to these wonderful people ✨
vifino
- |
+
+
@@ -1594,8 +1609,7 @@ Thanks goes to these wonderful people ✨
alexanderneu
- |
-
+
@@ -1623,7 +1637,8 @@ Thanks goes to these wonderful people ✨
green-anger
- |
+
+
@@ -1637,8 +1652,7 @@ Thanks goes to these wonderful people ✨
MrFreezeex
- |
-
+
@@ -1666,7 +1680,8 @@ Thanks goes to these wonderful people ✨
spock
- |
+
+
@@ -1680,14 +1695,6 @@ Thanks goes to these wonderful people ✨
crash7
- |
-
-
-
-
-
- fkefer
-
|
@@ -1716,15 +1723,15 @@ Thanks goes to these wonderful people ✨
LeoWinterDE
- |
+
+
linhandev
- |
-
+
@@ -1759,15 +1766,15 @@ Thanks goes to these wonderful people ✨
maxemann96
- |
+
+
dragetd
- |
-
+
@@ -1802,15 +1809,15 @@ Thanks goes to these wonderful people ✨
MohammedNoureldin
- |
+
+
mpldr
- |
-
+
@@ -1832,6 +1839,21 @@ Thanks goes to these wonderful people ✨
radicand
|
+
+
+
+
+ froks
+
+ |
+
+
+
+
+ fkefer
+
+ |
+
@@ -1852,8 +1874,7 @@ Thanks goes to these wonderful people ✨
glandais
- |
-
+
@@ -1874,7 +1895,8 @@ Thanks goes to these wonderful people ✨
HeySora
- |
+
+
@@ -1895,8 +1917,7 @@ Thanks goes to these wonderful people ✨
jcalfee
- |
-
+
@@ -1917,7 +1938,8 @@ Thanks goes to these wonderful people ✨
Jeidnx
- |
+
+
@@ -1938,8 +1960,7 @@ Thanks goes to these wonderful people ✨
jmccl
- |
-
+
@@ -1960,20 +1981,14 @@ Thanks goes to these wonderful people ✨
Kaan88
- |
+
+
akkumar
- |
-
-
-
-
- thechubbypanda
-
|
diff --git a/mailserver.env b/mailserver.env
index 9b085c9f..1d131696 100644
--- a/mailserver.env
+++ b/mailserver.env
@@ -388,7 +388,7 @@ SPAMASSASSIN_SPAM_TO_INBOX=1
# spam messages will be moved in the Junk folder (SPAMASSASSIN_SPAM_TO_INBOX=1 required)
MOVE_SPAM_TO_JUNK=1
-# spam messages wil be marked as read
+# spam messages will be marked as read
MARK_SPAM_AS_READ=0
# add 'spam info' headers at, or above this level
diff --git a/target/dovecot/auth-ldap.conf.ext b/target/dovecot/auth-ldap.conf.ext
new file mode 100644
index 00000000..222769aa
--- /dev/null
+++ b/target/dovecot/auth-ldap.conf.ext
@@ -0,0 +1,21 @@
+# NOTE: This is effectively the same default LDAP config shipped by Dovecot
+# The only difference is the addition of the passdb mechanisms field,
+# which restricts what auth mechanisms are supported / expected.
+# This prevents unnecessary auth failure logs triggering Fail2Ban when
+# additional passdb are enabled (OAuth2).
+
+passdb {
+ driver = ldap
+ mechanism = plain login
+
+ # Path for LDAP configuration file, see example-config/dovecot-ldap.conf.ext
+ args = /etc/dovecot/dovecot-ldap.conf.ext
+}
+
+userdb {
+ driver = ldap
+ args = /etc/dovecot/dovecot-ldap.conf.ext
+
+ # Default fields can be used to specify defaults that LDAP may override
+ #default_fields = home=/home/virtual/%u
+}
diff --git a/target/dovecot/auth-oauth2.conf.ext b/target/dovecot/auth-oauth2.conf.ext
index 6096d1e4..99a7986b 100644
--- a/target/dovecot/auth-oauth2.conf.ext
+++ b/target/dovecot/auth-oauth2.conf.ext
@@ -1,5 +1,12 @@
+# Allow clients to use these additional mechanisms:
auth_mechanisms = $auth_mechanisms oauthbearer xoauth2
+# Dovecot docs consider the oauth2 driver as a "success/failure" type PassDB:
+# https://doc.dovecot.org/configuration_manual/authentication/password_databases_passdb/#success-failure-database
+# Which implies it cannot be configured for the non-plaintext SASL mechanisms listed here:
+# https://doc.dovecot.org/configuration_manual/authentication/authentication_mechanisms/#dovecot-supports-the-following-non-plaintext-mechanisms
+# However that is not the case, these mechanisms are still valid to prevent trying other incompatible mechanisms (like `plain`).
+
passdb {
driver = oauth2
mechanisms = xoauth2 oauthbearer
diff --git a/target/dovecot/auth-passwdfile.inc b/target/dovecot/auth-passwdfile.inc
index 6bbf8258..38be4e5f 100644
--- a/target/dovecot/auth-passwdfile.inc
+++ b/target/dovecot/auth-passwdfile.inc
@@ -9,6 +9,7 @@
passdb {
driver = passwd-file
+ mechanisms = plain login
args = scheme=SHA512-CRYPT username_format=%u /etc/dovecot/userdb
}
diff --git a/target/scripts/startup/setup-stack.sh b/target/scripts/startup/setup-stack.sh
index f55cb548..c3c54cc3 100644
--- a/target/scripts/startup/setup-stack.sh
+++ b/target/scripts/startup/setup-stack.sh
@@ -94,6 +94,10 @@ function _setup_apply_fixes_after_configuration() {
_log 'debug' 'Removing files and directories from older versions'
rm -rf /var/mail-state/spool-postfix/{dev,etc,lib,pid,usr,private/auth}
+
+ # /tmp/docker-mailserver/rspamd/dkim
+ _log 'debug' "Ensuring ${RSPAMD_DMS_DKIM_D} is owned by '_rspamd:_rspamd'"
+ chown -R _rspamd:_rspamd "${RSPAMD_DMS_DKIM_D}"
}
function _run_user_patches() {
diff --git a/test/config/oauth2/Caddyfile b/test/config/oauth2/Caddyfile
index e116aa55..f87ffc80 100644
--- a/test/config/oauth2/Caddyfile
+++ b/test/config/oauth2/Caddyfile
@@ -38,6 +38,9 @@
}
}
+# NOTE: This portion of config is only relevant for understanding what happens seamlesssly,
+# DMS tests no longer use raw IMAP commands with netcat, thus none of this is relevant beyond reference for troubleshooting.
+#
# /imap/xoauth2
# Generate IMAP commands for authentication testing
# Base64 encoded credentials can alternative be done via CLI with:
diff --git a/test/files/auth/imap-oauth2-oauthbearer.txt b/test/files/auth/imap-oauth2-oauthbearer.txt
deleted file mode 100644
index d85c63e8..00000000
--- a/test/files/auth/imap-oauth2-oauthbearer.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-a0 NOOP See test/config/oauth2/Caddyfile to generate the below OAUTHBEARER string
-a1 AUTHENTICATE OAUTHBEARER bixhPXVzZXIxQGxvY2FsaG9zdC5sb2NhbGRvbWFpbiwBaG9zdD1sb2NhbGhvc3QBcG9ydD0xNDMBYXV0aD1CZWFyZXIgRE1TX1lXTmpaWE56WDNSdmEyVnUBAQ==
-a2 EXAMINE INBOX
-a3 LOGOUT
diff --git a/test/files/auth/imap-oauth2-xoauth2.txt b/test/files/auth/imap-oauth2-xoauth2.txt
deleted file mode 100644
index 0371b0cf..00000000
--- a/test/files/auth/imap-oauth2-xoauth2.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-a0 NOOP See test/config/oauth2/Caddyfile to generate the below XOAUTH2 string
-a1 AUTHENTICATE XOAUTH2 dXNlcj11c2VyMUBsb2NhbGhvc3QubG9jYWxkb21haW4BYXV0aD1CZWFyZXIgRE1TX1lXTmpaWE56WDNSdmEyVnUBAQ==
-a2 EXAMINE INBOX
-a3 LOGOUT
diff --git a/test/tests/serial/mail_with_oauth2.bats b/test/tests/serial/mail_with_oauth2.bats
index 0cc34a01..9b4d12fe 100644
--- a/test/tests/serial/mail_with_oauth2.bats
+++ b/test/tests/serial/mail_with_oauth2.bats
@@ -58,21 +58,59 @@ function teardown_file() {
docker network rm "${DMS_TEST_NETWORK}"
}
-@test "should authenticate with XOAUTH2 over IMAP" {
- _nc_wrapper 'auth/imap-oauth2-xoauth2.txt' '-w 1 0.0.0.0 143'
- __verify_successful_login 'XOAUTH2'
+@test "should authenticate with XOAUTH2" {
+ __should_login_successfully_with 'XOAUTH2'
}
-@test "should authenticate with OAUTHBEARER over IMAP" {
- _nc_wrapper 'auth/imap-oauth2-oauthbearer.txt' '-w 1 0.0.0.0 143'
- __verify_successful_login 'OAUTHBEARER'
+@test "should authenticate with OAUTHBEARER" {
+ __should_login_successfully_with 'OAUTHBEARER'
}
-function __verify_successful_login() {
+function __should_login_successfully_with() {
local AUTH_METHOD=${1}
+ # These values are the auth credentials checked against the Caddy `/userinfo` endpoint:
+ local USER_ACCOUNT='user1@localhost.localdomain'
+ local ACCESS_TOKEN='DMS_YWNjZXNzX3Rva2Vu'
+ __verify_auth_with_imap
+ __verify_auth_with_smtp
+}
+
+# Dovecot direct auth verification via IMAP:
+function __verify_auth_with_imap() {
+ # NOTE: Include the `--verbose` option if you're troubleshooting and want to see the protocol exchange messages
+ # NOTE: `--user username:password` is valid for testing `PLAIN` auth mechanism, but you should prefer swaks instead.
+ _run_in_container curl --silent \
+ --login-options "AUTH=${AUTH_METHOD}" --oauth2-bearer "${ACCESS_TOKEN}" --user "${USER_ACCOUNT}" \
+ --url 'imap://localhost:143' -X 'LOGOUT'
+
+ __dovecot_logs_should_verify_success
+}
+
+# Postfix delegates by default to Dovecot via SASL:
+# NOTE: This won't be compatible with LDAP if `ENABLE_SASLAUTHD=1` with `ldap` SASL mechanism:
+function __verify_auth_with_smtp() {
+ # NOTE: `--upload-file` with some mail content seems required for using curl to test OAuth2 authentication.
+ # TODO: Replace with swaks and early exit option when it supports XOAUTH2 + OAUTHBEARER:
+ _run_in_container curl --silent \
+ --login-options "AUTH=${AUTH_METHOD}" --oauth2-bearer "${ACCESS_TOKEN}" --user "${USER_ACCOUNT}" \
+ --url 'smtp://localhost:587' --mail-from "${USER_ACCOUNT}" --mail-rcpt "${USER_ACCOUNT}" --upload-file - <<< 'RFC 5322 content - not important'
+
+ # Postfix specific auth logs:
+ _run_in_container grep 'postfix/submission/smtpd' /var/log/mail.log
+ assert_output --partial "sasl_method=${AUTH_METHOD}, sasl_username=${USER_ACCOUNT}"
+
+ # Dovecot logs should still be checked as it is handling the actual auth process under the hood:
+ __dovecot_logs_should_verify_success
+}
+
+function __dovecot_logs_should_verify_success() {
# Inspect the relevant Dovecot logs to catch failure / success:
_run_in_container grep 'dovecot:' /var/log/mail.log
refute_output --partial 'oauth2 failed: Introspection failed'
- assert_output --partial "dovecot: imap-login: Login: user=, method=${AUTH_METHOD}"
+ assert_output --partial "dovecot: imap-login: Login: user=<${USER_ACCOUNT}>, method=${AUTH_METHOD}"
+
+ # If another PassDB is enabled, it should not have been attempted with the XOAUTH2 / OAUTHBEARER mechanisms:
+ # dovecot: auth: passwd-file(${USER_ACCOUNT},127.0.0.1): Password mismatch (SHA1 of given password: d390c1) - trying the next passdb
+ refute_output --partial 'trying the next passdb'
}