From 4b46b1d173b7c9fa4875b59cc7e6a47bcb4be4ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bojan=20=C4=8Cekrli=C4=87?= Date: Sun, 21 Apr 2024 16:38:54 +0100 Subject: [PATCH] Fix #180: Rename authentication methods This is a really dirt fix for issue #180. It will replace "well-known" enumerated plugin names with SASL mechanism names. While this is more of a "bandage" than the actual proper fix, I have currently found no better ways to do it. Most likely this issue will rise up again with another SASL plugin and we will deal with it then. At this stage, it should cover most of the use cases transparently. --- scripts/common-run.sh | 6 +- scripts/common.sh | 57 +++++++++++++++++++ ..._convert_plugin_names_to_filter_names.bats | 35 ++++++++++++ unit-tests/Dockerfile | 3 +- 4 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 unit-tests/027_convert_plugin_names_to_filter_names.bats diff --git a/scripts/common-run.sh b/scripts/common-run.sh index 5bf17c8..fdf843c 100755 --- a/scripts/common-run.sh +++ b/scripts/common-run.sh @@ -406,7 +406,7 @@ postfix_setup_xoauth2_post_setup() { do_postconf -e 'smtp_tls_session_cache_database=lmdb:${data_directory}/smtp_scache' else # So, this fix should solve the issue #106, when password in the 'smtp_sasl_password_maps' was - # read as file instead of the actual password. It turns out that the culprit is the sasl-xoauth2 + # read as file instead of the actual password. It turns out that the culprit is the sasl-xoauth2 # plugin, which expect the filename in place of the password. And as the plugin injects itself # automatically in the list of SASL login mechanisms, it tries to read the password as a file and -- # naturally -- fails. @@ -418,7 +418,7 @@ postfix_setup_xoauth2_post_setup() { # Ubuntu/Debian have renamed pluginviewer to saslpluginviewer so this fails with those distros. plugin_viewer="saslpluginviewer" fi - other_plugins="$(${plugin_viewer} -c | grep Plugin | cut -d\ -f2 | cut -c2- | rev | cut -c2- | rev | grep -v EXTERNAL | grep -v sasl-xoauth2 | tr '\n' ',' | rev | cut -c2- | rev)" + other_plugins="$(${plugin_viewer} -c | grep Plugin | cut -d\ -f2 | cut -c2- | rev | cut -c2- | rev | grep -v EXTERNAL | grep -v sasl-xoauth2 | tr '\n' ',' | rev | cut -c2- | rev | convert_plugin_names_to_filter_names)" do_postconf -e "smtp_sasl_mechanism_filter=${other_plugins}" fi } @@ -472,7 +472,7 @@ EOF )" fi - debug 'Sasldb configured' + debug 'Sasldb configured' fi } diff --git a/scripts/common.sh b/scripts/common.sh index f80d6ab..44d3cba 100755 --- a/scripts/common.sh +++ b/scripts/common.sh @@ -227,4 +227,61 @@ zone_info_dir() { return } +################################################################### +# Remove leading and trailing whitespace from string +################################################################### +trim() { + local var + IFS='' read -d -r var + #var="$(<&1)" + # remove leading whitespace characters + var="${var#"${var%%[![:space:]]*}"}" + # remove trailing whitespace characters + var="${var%"${var##*[![:space:]]}"}" + printf '%s' "${var}" +} + +################################################################### +# Potential fix for #180. Plugin names do not neccessarily match +# filter names. +# +# This is an utility method which converts SASL plugin names into +# filter names. There's no reliable way to guess this, so the names +# have been hardcoded here. +# +# INPUT: +# The method expects as an input a list of plugin names, comma +# separated. +# +# OUTPUT: +# The list of plugin names, comma separated. +################################################################### +convert_plugin_names_to_filter_names() { + local line first value lowercase + while IFS=$',' read -ra line; do + for value in "${line[@]}"; do + value="$(printf '%s' "${value}" | trim)" + if [[ -z "${value}" ]]; then + continue; + fi + + if [[ -z "${first}" ]]; then + first="0" + else + printf '%s' ',' + fi + + lowercase="${value,,}" + + if [[ "${lowercase}" == "digestmd5" ]]; then + printf '%s' 'DIGEST-MD5' + elif [[ "${lowercase}" == "crammd5" ]]; then + printf '%s' 'CRAM-MD5' + else + printf '%s' "${value}" + fi + done + done +} + export reset green yellow orange orange_emphasis lightblue red gray emphasis underline diff --git a/unit-tests/027_convert_plugin_names_to_filter_names.bats b/unit-tests/027_convert_plugin_names_to_filter_names.bats new file mode 100644 index 0000000..8d6256e --- /dev/null +++ b/unit-tests/027_convert_plugin_names_to_filter_names.bats @@ -0,0 +1,35 @@ +#!/usr/bin/env bats + +load /code/scripts/common.sh + +assert_equals() { + local expected="$1" + local actual="$2" + if [[ "${expected}" != "${actual}" ]]; then + echo "Expected: \"${expected}\". Got: \"${actual}\"." >&2 + exit 1 + fi +} + +@test "check if trim works properly" { + assert_equals "bar" "$(echo "bar" | trim)" + assert_equals "foo bar" "$(echo "foo bar" | trim)" + assert_equals "foo bar" "$(echo " foo bar" | trim)" + assert_equals "foo bar" "$(echo "foo bar " | trim)" + assert_equals "foo bar" "$(echo " foo bar " | trim)" + assert_equals "foo bar" "$(printf '%s' " foo bar" | trim)" + assert_equals "foo bar" "$(printf '%s' $'\t\tfoo bar\r\n' | trim)" + assert_equals "foo bar" "$(printf '%s' $' foo bar\r\n' | trim)" +} + +@test "check if convert_plugin_names_to_filter_names works" { + assert_equals "foo" "$(echo "foo" | convert_plugin_names_to_filter_names)" + assert_equals "foo,bar" "$(echo "foo,bar" | convert_plugin_names_to_filter_names)" + assert_equals "foo,bar,baz" "$(echo "foo, bar, baz," | convert_plugin_names_to_filter_names)" + assert_equals "DIGEST-MD5" "$(echo "digestmd5" | convert_plugin_names_to_filter_names)" + assert_equals "CRAM-MD5" "$(echo "crammd5" | convert_plugin_names_to_filter_names)" + assert_equals "DIGEST-MD5,ntlm,CRAM-MD5,plain,login,anonymous" "$(echo "digestmd5,ntlm,crammd5,plain,login,anonymous" | convert_plugin_names_to_filter_names)" + assert_equals "DIGEST-MD5,ntlm,CRAM-MD5,plain,login,anonymous" "$(echo "DIGESTMD5,ntlm,CRAMMD5,plain,login,anonymous" | convert_plugin_names_to_filter_names)" + +} + diff --git a/unit-tests/Dockerfile b/unit-tests/Dockerfile index b95eff3..af40e30 100644 --- a/unit-tests/Dockerfile +++ b/unit-tests/Dockerfile @@ -1,4 +1,5 @@ -ARG ALPINE_VERSION=latest +# Changed this to specific alpine version so it doesn't get refreshed / pulled from Docker hub every time. +ARG ALPINE_VERSION=3.19 FROM alpine:${ALPINE_VERSION} as build ARG SASL_XOAUTH2_REPO_URL=https://github.com/tarickb/sasl-xoauth2.git