From 4ad24228108aadf7a915bda7af0a3ef9ecffb92c Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Mar 2025 16:52:15 +0100 Subject: [PATCH 01/16] [Dovecot] Increase Timeout for HTTP Login Request --- data/conf/dovecot/auth/passwd-verify.lua | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/data/conf/dovecot/auth/passwd-verify.lua b/data/conf/dovecot/auth/passwd-verify.lua index cb2e928d0..d235173da 100644 --- a/data/conf/dovecot/auth/passwd-verify.lua +++ b/data/conf/dovecot/auth/passwd-verify.lua @@ -3,10 +3,10 @@ function auth_password_verify(request, password) return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "No such user" end - json = require "cjson" - ltn12 = require "ltn12" - https = require "ssl.https" - https.TIMEOUT = 5 + local json = require "cjson" + local ltn12 = require "ltn12" + local https = require "ssl.https" + https.TIMEOUT = 30 local req = { username = request.user, @@ -16,8 +16,7 @@ function auth_password_verify(request, password) } req.protocol[request.service] = true local req_json = json.encode(req) - local res = {} - + local res = {} local b, c = https.request { method = "POST", url = "https://nginx:9082", @@ -29,11 +28,16 @@ function auth_password_verify(request, password) sink = ltn12.sink.table(res), insecure = true } + + if c ~= 200 then + dovecot.i_info("HTTP request failed with " .. c .. " for user " .. request.user) + return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "Upstream error" + end + local api_response = json.decode(table.concat(res)) if api_response.success == true then return dovecot.auth.PASSDB_RESULT_OK, "" end - return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Failed to authenticate" end From 65d872cc1487380e488e26d27a26154a12753f5f Mon Sep 17 00:00:00 2001 From: Bruno Antunes Date: Thu, 27 Mar 2025 20:21:25 +0000 Subject: [PATCH 02/16] Fix tiny typo --- helper-scripts/backup_and_restore.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/backup_and_restore.sh b/helper-scripts/backup_and_restore.sh index 0cb37fce3..c7615c294 100755 --- a/helper-scripts/backup_and_restore.sh +++ b/helper-scripts/backup_and_restore.sh @@ -236,7 +236,7 @@ function restore() { if [[ $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') == "" ]]; then echo -e "\e[33mCould not find a architecture signature of the loaded backup... Maybe the backup was done before the multiarch update?" sleep 2 - echo -e "Continuing anyhow. If rspamd is crashing opon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m" + echo -e "Continuing anyhow. If rspamd is crashing upon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m" sleep 2 docker stop $(docker ps -qf name=rspamd-mailcow) docker run -i --name mailcow-backup --rm \ From 0157cbddafe59b253b8186d7e29a63da85a964d7 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 31 Mar 2025 10:36:20 +0200 Subject: [PATCH 03/16] [Netfilter] Downgrade to 1.61 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 2d68b80ce..4907b592d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -477,7 +477,7 @@ services: - acme netfilter-mailcow: - image: ghcr.io/mailcow/netfilter:1.62 + image: ghcr.io/mailcow/netfilter:1.61 stop_grace_period: 30s restart: always privileged: true From f37961b7d06b1e0f0fdb2f893f5dfa295c00f86f Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 31 Mar 2025 11:32:01 +0200 Subject: [PATCH 04/16] [SOGo] Use JS for mailcow logout --- data/Dockerfiles/sogo/navMailcowBtns.diff | 6 +----- data/conf/sogo/custom-sogo.js | 10 ++++++++++ docker-compose.yml | 2 +- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/data/Dockerfiles/sogo/navMailcowBtns.diff b/data/Dockerfiles/sogo/navMailcowBtns.diff index 1b469aa60..563818fb6 100644 --- a/data/Dockerfiles/sogo/navMailcowBtns.diff +++ b/data/Dockerfiles/sogo/navMailcowBtns.diff @@ -7,14 +7,10 @@ < < ng-show="::activeUser.path.logoff.length" 85c78 < ng-href="#"> --- > ng-href="{{::activeUser.path.logoff}}"> -89,91d81 -<
-< -<
diff --git a/data/conf/sogo/custom-sogo.js b/data/conf/sogo/custom-sogo.js index e1f27e8ff..d3b90b085 100644 --- a/data/conf/sogo/custom-sogo.js +++ b/data/conf/sogo/custom-sogo.js @@ -5,6 +5,16 @@ document.addEventListener('DOMContentLoaded', function () { window.location.href = '/user'; } }); +// logout function +function mc_logout() { + fetch("/", { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded" + }, + body: "logout=1" + }).then(() => window.location.href = '/'); +} // Custom SOGo JS diff --git a/docker-compose.yml b/docker-compose.yml index 2d68b80ce..dea033a11 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -199,7 +199,7 @@ services: - phpfpm sogo-mailcow: - image: ghcr.io/mailcow/sogo:1.131 + image: ghcr.io/mailcow/sogo:1.133 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} From e452917de9786663dd9eb0af371dd916ab6d63be Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 31 Mar 2025 12:14:43 +0200 Subject: [PATCH 05/16] [SOGo] Show mailcow Settings Button to SOGoSuperUsers --- data/Dockerfiles/sogo/navMailcowBtns.diff | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/data/Dockerfiles/sogo/navMailcowBtns.diff b/data/Dockerfiles/sogo/navMailcowBtns.diff index 563818fb6..2107b5b1f 100644 --- a/data/Dockerfiles/sogo/navMailcowBtns.diff +++ b/data/Dockerfiles/sogo/navMailcowBtns.diff @@ -1,9 +1,8 @@ -59,65d58 -< ng-show="::!activeUser.isSuperUser" +60,65d58 < var:ng-click="navButtonClick" < ng-href="/user"> < build -< +< mailcow <
< Date: Tue, 1 Apr 2025 16:39:15 +0200 Subject: [PATCH 06/16] [Web] Fix password reset --- data/web/reset-password.php | 1 + 1 file changed, 1 insertion(+) diff --git a/data/web/reset-password.php b/data/web/reset-password.php index 7544d40c3..d717d9d8b 100644 --- a/data/web/reset-password.php +++ b/data/web/reset-password.php @@ -1,5 +1,6 @@ Date: Tue, 1 Apr 2025 22:00:11 +0200 Subject: [PATCH 07/16] update postscreen_access.cidr (#6443) --- data/conf/postfix/postscreen_access.cidr | 83 +++++++++++++++++++++--- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index c6ed2be93..36c7e9fca 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,6 +1,6 @@ -# Whitelist generated by Postwhite v3.4 on Sat Mar 1 00:19:29 UTC 2025 +# Whitelist generated by Postwhite v3.4 on Tue Apr 1 00:20:51 UTC 2025 # https://github.com/stevejenkins/postwhite/ -# 2000 total rules +# 2067 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit 2a01:111:f403:8000::/50 permit @@ -26,7 +26,12 @@ 8.20.114.31 permit 8.25.194.0/23 permit 8.25.196.0/23 permit +8.39.54.0/23 permit +8.39.54.250/31 permit +8.40.222.0/23 permit +8.40.222.250/31 permit 12.130.86.238 permit +13.107.246.59 permit 13.110.208.0/21 permit 13.110.209.0/24 permit 13.110.216.0/22 permit @@ -60,8 +65,6 @@ 20.59.80.4/30 permit 20.63.210.192/28 permit 20.69.8.108/30 permit -20.70.246.20 permit -20.76.201.171 permit 20.83.222.104/30 permit 20.88.157.184/30 permit 20.94.180.64/28 permit @@ -70,14 +73,11 @@ 20.98.194.68/30 permit 20.105.209.76/30 permit 20.107.239.64/30 permit -20.112.250.133 permit 20.118.139.208/30 permit 20.141.10.196 permit 20.185.214.0/27 permit 20.185.214.32/27 permit 20.185.214.64/27 permit -20.231.239.246 permit -20.236.44.162 permit 23.103.224.0/19 permit 23.249.208.0/20 permit 23.251.224.0/19 permit @@ -103,6 +103,24 @@ 27.123.206.80/28 permit 31.25.48.222 permit 31.47.251.17 permit +34.2.64.0/22 permit +34.2.68.0/23 permit +34.2.70.0/23 permit +34.2.71.64/26 permit +34.2.72.0/22 permit +34.2.75.0/26 permit +34.2.78.0/23 permit +34.2.80.0/23 permit +34.2.82.0/23 permit +34.2.84.0/24 permit +34.2.84.64/26 permit +34.2.85.0/24 permit +34.2.85.64/26 permit +34.2.86.0/23 permit +34.2.88.0/23 permit +34.2.90.0/23 permit +34.2.92.0/23 permit +34.2.94.0/23 permit 34.195.217.107 permit 34.212.163.75 permit 34.215.104.144 permit @@ -215,7 +233,6 @@ 52.95.49.88/29 permit 52.96.91.34 permit 52.96.111.82 permit -52.96.172.98 permit 52.96.214.50 permit 52.96.222.194 permit 52.96.222.226 permit @@ -255,6 +272,7 @@ 54.244.54.130 permit 54.244.242.0/24 permit 54.255.61.23 permit +56.124.6.228 permit 57.103.64.0/18 permit 62.13.128.0/24 permit 62.13.129.128/25 permit @@ -341,6 +359,7 @@ 65.110.161.77 permit 65.123.29.213 permit 65.123.29.220 permit +65.154.166.0/24 permit 65.212.180.36 permit 66.102.0.0/20 permit 66.119.150.192/26 permit @@ -1304,6 +1323,9 @@ 117.120.16.0/21 permit 119.42.242.52/31 permit 119.42.242.156 permit +121.244.91.48 permit +121.244.91.52 permit +122.15.156.182 permit 123.126.78.64/29 permit 124.108.96.24/31 permit 124.108.96.28/31 permit @@ -1366,7 +1388,21 @@ 134.170.141.64/26 permit 134.170.143.0/24 permit 134.170.174.0/24 permit +135.84.80.0/24 permit +135.84.81.0/24 permit +135.84.82.0/24 permit +135.84.83.0/24 permit 135.84.216.0/22 permit +136.143.160.0/24 permit +136.143.161.0/24 permit +136.143.162.0/24 permit +136.143.176.0/24 permit +136.143.177.0/24 permit +136.143.178.49 permit +136.143.182.0/23 permit +136.143.184.0/24 permit +136.143.188.0/24 permit +136.143.190.0/23 permit 136.147.128.0/20 permit 136.147.135.0/24 permit 136.147.176.0/20 permit @@ -1381,6 +1417,7 @@ 139.138.46.219 permit 139.138.57.55 permit 139.138.58.119 permit +139.167.79.86 permit 139.180.17.0/24 permit 140.238.148.191 permit 141.148.159.229 permit @@ -1498,6 +1535,9 @@ 163.114.135.16 permit 164.152.23.32 permit 164.177.132.168/30 permit +165.173.128.0/24 permit +165.173.180.250/31 permit +165.173.182.250/31 permit 166.78.68.0/22 permit 166.78.68.221 permit 166.78.69.169 permit @@ -1526,6 +1566,12 @@ 168.245.12.252 permit 168.245.46.9 permit 168.245.127.231 permit +169.148.129.0/24 permit +169.148.131.0/24 permit +169.148.142.10 permit +169.148.144.0/25 permit +169.148.144.10 permit +169.148.146.0/23 permit 170.10.128.0/24 permit 170.10.129.0/24 permit 170.10.132.56/29 permit @@ -1667,6 +1713,14 @@ 198.61.254.231 permit 198.178.234.57 permit 198.244.48.0/20 permit +198.244.56.107 permit +198.244.56.108 permit +198.244.56.109 permit +198.244.56.111 permit +198.244.56.112 permit +198.244.56.113 permit +198.244.56.114 permit +198.244.56.115 permit 198.244.59.30 permit 198.244.59.33 permit 198.244.59.35 permit @@ -1679,7 +1733,15 @@ 199.16.156.0/22 permit 199.33.145.1 permit 199.33.145.32 permit +199.34.22.36 permit 199.59.148.0/22 permit +199.67.80.2 permit +199.67.80.20 permit +199.67.82.2 permit +199.67.82.20 permit +199.67.84.0/24 permit +199.67.86.0/24 permit +199.67.88.0/24 permit 199.101.161.130 permit 199.101.162.0/25 permit 199.122.120.0/21 permit @@ -1736,6 +1798,8 @@ 204.92.114.187 permit 204.92.114.203 permit 204.92.114.204/31 permit +204.141.32.0/23 permit +204.141.42.0/23 permit 204.220.160.0/21 permit 204.220.168.0/21 permit 204.220.176.0/20 permit @@ -1988,6 +2052,9 @@ 2603:1030:20e:3::23c permit 2603:1030:b:3::152 permit 2603:1030:c02:8::14 permit +2607:13c0:0001:0000:0000:0000:0000:7000/116 permit +2607:13c0:0002:0000:0000:0000:0000:1000/116 permit +2607:13c0:0004:0000:0000:0000:0000:0000/116 permit 2607:f8b0:4000::/36 permit 2620:109:c003:104::/64 permit 2620:109:c003:104::215 permit From a92832d115922cb11b2387c25919da804f708c4d Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 2 Apr 2025 14:39:24 +0200 Subject: [PATCH 08/16] update README.md to include first 50 and 100$ monthly sponsors --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index dc9b76be0..40288f10e 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,22 @@ You can also [get a SAL](https://www.servercow.de/mailcow?lang=en#sal) which is Or just spread the word: moo. +## Many thanks to our GitHub Sponsors ❤️ +A big thank you to everyone supporting us on GitHub Sponsors—your contributions mean the world to us! Special thanks to the following amazing supporters: + +### 100$/Month Sponsors + + + +### 50$/Month Sponsors + + ## Info, documentation and support Please see [the official documentation](https://docs.mailcow.email/) for installation and support instructions. 🐄 From 805634f9a94529a2c611100aed22f5c0b2d11b34 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 3 Apr 2025 10:19:30 +0200 Subject: [PATCH 09/16] Fix sasl_logs --- data/conf/dovecot/auth/mailcowauth.php | 15 ++++--- data/conf/dovecot/auth/passwd-verify.lua | 9 ++-- data/web/inc/functions.auth.inc.php | 50 ++++++++++++++-------- data/web/inc/functions.inc.php | 28 ++++++++++++ data/web/js/site/user.js | 6 --- data/web/templates/user/tab-user-auth.twig | 3 +- 6 files changed, 74 insertions(+), 37 deletions(-) diff --git a/data/conf/dovecot/auth/mailcowauth.php b/data/conf/dovecot/auth/mailcowauth.php index fc17df724..667419c57 100644 --- a/data/conf/dovecot/auth/mailcowauth.php +++ b/data/conf/dovecot/auth/mailcowauth.php @@ -69,29 +69,34 @@ require_once 'functions.acl.inc.php'; $isSOGoRequest = $post['real_rip'] == getenv('IPV4_NETWORK') . '.248'; $result = false; -$protocol = $post['protocol']; if ($isSOGoRequest) { - $protocol = null; // This is a SOGo Auth request. First check for SSO password. $sogo_sso_pass = file_get_contents("/etc/sogo-sso/sogo-sso.pass"); if ($sogo_sso_pass === $post['password']){ error_log('MAILCOWAUTH: SOGo SSO auth for user ' . $post['username']); + set_sasl_log($post['username'], $post['real_rip'], "SOGO"); $result = true; } } if ($result === false){ - $result = apppass_login($post['username'], $post['password'], $protocol, array( + $result = apppass_login($post['username'], $post['password'], array($post['service'] => true), array( 'is_internal' => true, 'remote_addr' => $post['real_rip'] )); - if ($result) error_log('MAILCOWAUTH: App auth for user ' . $post['username']); + if ($result) { + error_log('MAILCOWAUTH: App auth for user ' . $post['username']); + set_sasl_log($post['username'], $post['real_rip'], $post['service']); + } } if ($result === false){ // Init Identity Provider $iam_provider = identity_provider('init'); $iam_settings = identity_provider('get'); $result = user_login($post['username'], $post['password'], array('is_internal' => true)); - if ($result) error_log('MAILCOWAUTH: User auth for user ' . $post['username']); + if ($result) { + error_log('MAILCOWAUTH: User auth for user ' . $post['username']); + set_sasl_log($post['username'], $post['real_rip'], $post['service']); + } } if ($result) { diff --git a/data/conf/dovecot/auth/passwd-verify.lua b/data/conf/dovecot/auth/passwd-verify.lua index cb2e928d0..a6cb988d7 100644 --- a/data/conf/dovecot/auth/passwd-verify.lua +++ b/data/conf/dovecot/auth/passwd-verify.lua @@ -12,12 +12,11 @@ function auth_password_verify(request, password) username = request.user, password = password, real_rip = request.real_rip, - protocol = {} + service = request.service } - req.protocol[request.service] = true local req_json = json.encode(req) - local res = {} - + local res = {} + local b, c = https.request { method = "POST", url = "https://nginx:9082", @@ -33,7 +32,7 @@ function auth_password_verify(request, password) if api_response.success == true then return dovecot.auth.PASSDB_RESULT_OK, "" end - + return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Failed to authenticate" end diff --git a/data/web/inc/functions.auth.inc.php b/data/web/inc/functions.auth.inc.php index f432c3834..30d5943c4 100644 --- a/data/web/inc/functions.auth.inc.php +++ b/data/web/inc/functions.auth.inc.php @@ -9,25 +9,51 @@ function check_login($user, $pass, $app_passwd_data = false, $extra = null) { // Try validate admin if (!isset($role) || $role == "admin") { $result = admin_login($user, $pass); - if ($result !== false) return $result; + if ($result !== false){ + return $result; + } } // Try validate domain admin if (!isset($role) || $role == "domain_admin") { $result = domainadmin_login($user, $pass); - if ($result !== false) return $result; + if ($result !== false) { + return $result; + } } // Try validate user if (!isset($role) || $role == "user") { $result = user_login($user, $pass); - if ($result !== false) return $result; + if ($result !== false) { + if ($app_passwd_data['eas'] === true) { + $service = 'EAS'; + } elseif ($app_passwd_data['dav'] === true) { + $service = 'DAV'; + } else { + $service = 'MAILCOWUI'; + } + $real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']); + set_sasl_log($user, $real_rip, $service); + return $result; + } } // Try validate app password if (!isset($role) || $role == "app") { $result = apppass_login($user, $pass, $app_passwd_data); - if ($result !== false) return $result; + if ($result !== false) { + if ($app_passwd_data['eas'] === true) { + $service = 'EAS'; + } elseif ($app_passwd_data['dav'] === true) { + $service = 'DAV'; + } else { + $service = 'NONE'; + } + $real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']); + set_sasl_log($user, $real_rip, $service, $pass); + return $result; + } } // skip log and only return false if it's an internal request @@ -415,21 +441,7 @@ function apppass_login($user, $pass, $app_passwd_data, $extra = null){ // verify password if (verify_hash($row['password'], $pass) !== false) { - if ($is_internal){ - $remote_addr = $extra['remote_addr']; - } else { - $remote_addr = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']); - } - - $service = strtoupper($is_app_passwd); - $stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)"); - $stmt->execute(array( - ':service' => $service, - ':app_id' => $row['app_passwd_id'], - ':username' => $user, - ':remote_addr' => $remote_addr - )); - + $_SESSION['app_passwd_id'] = $row['app_passwd_id']; unset($_SESSION['ldelay']); return "user"; } diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 6a70eb6e3..49e26b978 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -350,6 +350,34 @@ function last_login($action, $username, $sasl_limit_days = 7, $ui_offset = 1) { } } +function set_sasl_log($username, $real_rip, $service){ + global $pdo; + + try { + if (!empty($_SESSION['app_passwd_id'])) { + $app_password = $_SESSION['app_passwd_id']; + } else { + $app_password = 0; + } + + $stmt = $pdo->prepare('REPLACE INTO `sasl_log` (`username`, `real_rip`, `service`, `app_password`) VALUES (:username, :real_rip, :service, :app_password)'); + $stmt->execute(array( + ':username' => $username, + ':real_rip' => $real_rip, + ':service' => $service, + ':app_password' => $app_password + )); + } catch (PDOException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_data_log), + 'msg' => array('mysql_error', $e) + ); + return false; + } + + return true; +} function flush_memcached() { try { $m = new Memcached(); diff --git a/data/web/js/site/user.js b/data/web/js/site/user.js index 8f64d4e20..678e23b19 100644 --- a/data/web/js/site/user.js +++ b/data/web/js/site/user.js @@ -90,13 +90,7 @@ jQuery(function($){ console.log('error reading last logins'); }, success: function (data) { - $('.last-ui-login').html(''); $('.last-sasl-login').html(''); - if (data.ui.time) { - $('.last-ui-login').html(' ' + lang.last_ui_login + ': ' + unix_time_format(data.ui.time)); - } else { - $('.last-ui-login').text(lang.no_last_login); - } if (data.sasl) { $('.last-sasl-login').append('
    '); $.each(data.sasl, function (i, item) { diff --git a/data/web/templates/user/tab-user-auth.twig b/data/web/templates/user/tab-user-auth.twig index a7e025431..bace33489 100644 --- a/data/web/templates/user/tab-user-auth.twig +++ b/data/web/templates/user/tab-user-auth.twig @@ -184,7 +184,7 @@ {% endif %} -
    +
    {{ lang.user.recent_successful_connections }}
    @@ -192,7 +192,6 @@

    -
    {{ lang.user.clear_recent_successful_connections }} From ceeabded73c66c8022eeac69721908f3f1c90d46 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 3 Apr 2025 10:29:47 +0200 Subject: [PATCH 10/16] [Web] Fix transport routing test --- data/web/js/site/admin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js index 90c00002a..847c25aa8 100644 --- a/data/web/js/site/admin.js +++ b/data/web/js/site/admin.js @@ -681,7 +681,7 @@ jQuery(function($){ $(this).html('
    Loading...
    '); $.ajax({ type: 'GET', - url: 'inc/ajax/transport_check.php', + url: '/inc/ajax/transport_check.php', dataType: 'text', data: $('#test_transport_form').serialize(), complete: function (data) { From e65478076b48e6986f0bec0e8b5020697192340d Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 3 Apr 2025 11:58:35 +0200 Subject: [PATCH 11/16] [Web] Prevent user sync for mismatched authsource --- data/conf/phpfpm/crons/keycloak-sync.php | 2 +- data/conf/phpfpm/crons/ldap-sync.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/conf/phpfpm/crons/keycloak-sync.php b/data/conf/phpfpm/crons/keycloak-sync.php index c9655a8ec..f09a47d79 100644 --- a/data/conf/phpfpm/crons/keycloak-sync.php +++ b/data/conf/phpfpm/crons/keycloak-sync.php @@ -196,7 +196,7 @@ while (true) { logMsg("err", "Could not create user " . $user['email']); continue; } - } else if ($row && intval($iam_settings['periodic_sync']) == 1) { + } else if ($row && intval($iam_settings['periodic_sync']) == 1 && $row['authsource'] == "keycloak") { if ($mapper_key === false){ logMsg("warning", "No matching attribute mapping found for user " . $user['email']); continue; diff --git a/data/conf/phpfpm/crons/ldap-sync.php b/data/conf/phpfpm/crons/ldap-sync.php index 66b76e64a..32026c071 100644 --- a/data/conf/phpfpm/crons/ldap-sync.php +++ b/data/conf/phpfpm/crons/ldap-sync.php @@ -168,7 +168,7 @@ foreach ($response as $user) { logMsg("err", "Could not create user " . $user[$iam_settings['username_field']][0]); continue; } - } else if ($row && intval($iam_settings['periodic_sync']) == 1) { + } else if ($row && intval($iam_settings['periodic_sync']) == 1 && $row['authsource'] == "ldap") { if ($mapper_key === false){ logMsg("warning", "No matching attribute mapping found for user " . $user[$iam_settings['username_field']][0]); continue; From 62f816e64a964a0eb3c9243595b6ffedff897cc6 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 3 Apr 2025 12:19:04 +0200 Subject: [PATCH 12/16] [Web] Check app password before user password on web login --- data/web/inc/functions.auth.inc.php | 33 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/data/web/inc/functions.auth.inc.php b/data/web/inc/functions.auth.inc.php index 30d5943c4..994915efc 100644 --- a/data/web/inc/functions.auth.inc.php +++ b/data/web/inc/functions.auth.inc.php @@ -22,22 +22,6 @@ function check_login($user, $pass, $app_passwd_data = false, $extra = null) { } } - // Try validate user - if (!isset($role) || $role == "user") { - $result = user_login($user, $pass); - if ($result !== false) { - if ($app_passwd_data['eas'] === true) { - $service = 'EAS'; - } elseif ($app_passwd_data['dav'] === true) { - $service = 'DAV'; - } else { - $service = 'MAILCOWUI'; - } - $real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']); - set_sasl_log($user, $real_rip, $service); - return $result; - } - } // Try validate app password if (!isset($role) || $role == "app") { @@ -56,6 +40,23 @@ function check_login($user, $pass, $app_passwd_data = false, $extra = null) { } } + // Try validate user + if (!isset($role) || $role == "user") { + $result = user_login($user, $pass); + if ($result !== false) { + if ($app_passwd_data['eas'] === true) { + $service = 'EAS'; + } elseif ($app_passwd_data['dav'] === true) { + $service = 'DAV'; + } else { + $service = 'MAILCOWUI'; + } + $real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']); + set_sasl_log($user, $real_rip, $service); + return $result; + } + } + // skip log and only return false if it's an internal request if ($is_internal == true) return false; From 6794e6ff43449d34397e40931310169658c84ac4 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 3 Apr 2025 12:31:43 +0200 Subject: [PATCH 13/16] [Dovecot] Add service for authentication cache_key --- data/conf/dovecot/dovecot.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index 15be77fce..05d9264fa 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -53,7 +53,7 @@ mail_shared_explicit_inbox = yes mail_prefetch_count = 30 passdb { driver = lua - args = file=/etc/dovecot/auth/passwd-verify.lua blocking=yes cache_key=%u:%w + args = file=/etc/dovecot/auth/passwd-verify.lua blocking=yes cache_key=%s:%u:%w result_success = return-ok result_failure = continue result_internalfail = continue From 402bf53a5c24ac34ca7df63396640c9c0f2dc21c Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 4 Apr 2025 13:18:42 +0200 Subject: [PATCH 14/16] [Web] Improve clarity of LDAP SSL/TLS settings --- data/web/lang/lang.de-de.json | 4 ++- data/web/lang/lang.en-gb.json | 4 ++- .../admin/tab-config-identity-provider.twig | 28 +++++++++++++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 45c6e9f50..98d601738 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -238,7 +238,9 @@ "iam_username_field": "Username Feld", "iam_binddn": "Bind DN", "iam_use_ssl": "Benutze SSL", - "iam_use_tls": "Benutze TLS", + "iam_use_ssl_info": "TLS wird gegenüber SSL empfohlen. SSL gilt als veralteter Mechanismus für die sichere Ausführung von LDAP-Operationen.

    Wenn SSL aktiviert ist und der Port auf 389 gesetzt wurde, wird dieser automatisch auf 636 geändert.", + "iam_use_tls": "Benutze StartTLS", + "iam_use_tls_info": "Wenn TLS aktiviert wird, muss der Standardport deines LDAP-Servers (389) verwendet werden. SSL-Ports können dabei nicht verwendet werden.", "iam_version": "Version", "ignore_ssl_error": "Ignoriere SSL Fehler", "import": "Importieren", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 5d6911e91..9c1f30483 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -245,7 +245,9 @@ "iam_username_field": "Username Field", "iam_binddn": "Bind DN", "iam_use_ssl": "Use SSL", - "iam_use_tls": "Use TLS", + "iam_use_ssl_info": "TLS is recommended over SSL. SSL is labelled as a deprecated mechanism for securely running LDAP operations.

    If enabling SSL, and port is set to 389, it will be automatically overridden to use 636.", + "iam_use_tls": "Use StartTLS", + "iam_use_tls_info": "If enabling TLS, you must use the default port for your LDAP server (389). SSL ports cannot be used.", "iam_version": "Version", "ignore_ssl_error": "Ignore SSL Errors", "import": "Import", diff --git a/data/web/templates/admin/tab-config-identity-provider.twig b/data/web/templates/admin/tab-config-identity-provider.twig index 9d4dcd286..dce26f8c3 100644 --- a/data/web/templates/admin/tab-config-identity-provider.twig +++ b/data/web/templates/admin/tab-config-identity-provider.twig @@ -392,11 +392,11 @@
    - +
    - +
    @@ -409,21 +409,37 @@
    +
    -
    +
    - +
    +
    -
    +
    - +
    From 0eb8f3879264288c5d586f8086a419cd8d03c008 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 7 Apr 2025 07:59:43 +0200 Subject: [PATCH 15/16] [Web] Update LDAP SSL/TLS tooltips --- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 98d601738..f37c1d849 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -238,7 +238,7 @@ "iam_username_field": "Username Feld", "iam_binddn": "Bind DN", "iam_use_ssl": "Benutze SSL", - "iam_use_ssl_info": "TLS wird gegenüber SSL empfohlen. SSL gilt als veralteter Mechanismus für die sichere Ausführung von LDAP-Operationen.

    Wenn SSL aktiviert ist und der Port auf 389 gesetzt wurde, wird dieser automatisch auf 636 geändert.", + "iam_use_ssl_info": "Wenn SSL aktiviert ist und der Port auf 389 gesetzt wurde, wird dieser automatisch auf 636 geändert.", "iam_use_tls": "Benutze StartTLS", "iam_use_tls_info": "Wenn TLS aktiviert wird, muss der Standardport deines LDAP-Servers (389) verwendet werden. SSL-Ports können dabei nicht verwendet werden.", "iam_version": "Version", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 9c1f30483..3b5ff3fb4 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -245,7 +245,7 @@ "iam_username_field": "Username Field", "iam_binddn": "Bind DN", "iam_use_ssl": "Use SSL", - "iam_use_ssl_info": "TLS is recommended over SSL. SSL is labelled as a deprecated mechanism for securely running LDAP operations.

    If enabling SSL, and port is set to 389, it will be automatically overridden to use 636.", + "iam_use_ssl_info": "If enabling SSL, and port is set to 389, it will be automatically overridden to use 636.", "iam_use_tls": "Use StartTLS", "iam_use_tls_info": "If enabling TLS, you must use the default port for your LDAP server (389). SSL ports cannot be used.", "iam_version": "Version", From 2c10c39bc4def2ecde8c1df9cf40487a0a4c08dd Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 7 Apr 2025 08:06:43 +0200 Subject: [PATCH 16/16] [Web] Update 2FA Info tooltip --- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index f37c1d849..747f7cf84 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -1335,7 +1335,7 @@ "tag_in_subfolder": "In Unterordner", "tag_in_subject": "In Betreff", "text": "Text", - "tfa_info": "Zwei-Faktor-Authentifizierung hilft dabei, Ihr Konto zu schützen. Wenn Sie sie aktivieren, benötigen Sie möglicherweise App-Passwörter, um sich bei Apps oder Diensten anzumelden, die die Zwei-Faktor-Authentifizierung nicht unterstützen (z.B. Mailclients).", + "tfa_info": "Zwei-Faktor-Authentifizierung hilft dabei, Ihr Konto zu schützen. Wenn Sie sie aktivieren, benötigen Sie App-Passwörter, um sich bei Apps oder Diensten anzumelden, die die Zwei-Faktor-Authentifizierung nicht unterstützen (z.B. Mailclients).", "title": "Title", "tls_enforce_in": "TLS eingehend erzwingen", "tls_enforce_out": "TLS ausgehend erzwingen", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 3b5ff3fb4..ca8bb3adf 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -1357,7 +1357,7 @@ "tag_in_subfolder": "In subfolder", "tag_in_subject": "In subject", "text": "Text", - "tfa_info": "Two-factor authentication helps protect your account. If you enable it, you may need app passwords to log in to apps or services that don't support two-factor authentication (e.g. Mailclients).", + "tfa_info": "Two-factor authentication helps protect your account. If you enable it, you need app passwords to log in to apps or services that don't support two-factor authentication (e.g. Mailclients).", "title": "Title", "tls_enforce_in": "Enforce TLS incoming", "tls_enforce_out": "Enforce TLS outgoing",