From c11ed5dd1e899173500161ebf52e572de42917ca Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:34:20 +0100 Subject: [PATCH 1/4] Prevent duplicate/plaintext login announcement rendering (#6963) * Initial plan * Fix duplicate login announcement display Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> --- data/web/templates/base.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/templates/base.twig b/data/web/templates/base.twig index a8d0f6f39..98fdd86e4 100644 --- a/data/web/templates/base.twig +++ b/data/web/templates/base.twig @@ -144,7 +144,7 @@
-{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri %} +{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri and mailcow_cc_username %}
{{ ui_texts.ui_announcement_text }}
From e76f5237edcccd8fdcc613e22f9d9b84265459db Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 11 Dec 2025 13:29:11 +0100 Subject: [PATCH 2/4] ofelia: revert fixed cron syntax for sa-rules download --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 75d00af34..ae9a18d98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -321,7 +321,7 @@ services: ofelia.job-exec.dovecot_clean_q_aged.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/clean_q_aged.sh || exit 0\"" ofelia.job-exec.dovecot_maildir_gc.schedule: "0 */30 * * * *" ofelia.job-exec.dovecot_maildir_gc.command: "/bin/bash -c \"source /source_env.sh ; /usr/local/bin/gosu vmail /usr/local/bin/maildir_gc.sh\"" - ofelia.job-exec.dovecot_sarules.schedule: "0 0 0 * * *" + ofelia.job-exec.dovecot_sarules.schedule: "@every 24h" ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\"" ofelia.job-exec.dovecot_fts.schedule: "0 0 0 * * *" ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\"" From d977ddb5017e27f817f09310dcb7056449cb88fd Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 10 Dec 2025 08:43:04 +0100 Subject: [PATCH 3/4] backup: add image prefetch function to verify latest image is used --- helper-scripts/backup_and_restore.sh | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/helper-scripts/backup_and_restore.sh b/helper-scripts/backup_and_restore.sh index 7b75272cf..2e65f1343 100755 --- a/helper-scripts/backup_and_restore.sh +++ b/helper-scripts/backup_and_restore.sh @@ -91,6 +91,44 @@ if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then exit 1 fi +# Add image prefetch function +function prefetch_image() { + echo "Checking Docker image: ${DEBIAN_DOCKER_IMAGE}" + + # Get local image digest if it exists + local local_digest=$(docker image inspect ${DEBIAN_DOCKER_IMAGE} --format='{{index .RepoDigests 0}}' 2>/dev/null | cut -d'@' -f2) + + # Get remote image digest without pulling + local remote_digest=$(docker manifest inspect ${DEBIAN_DOCKER_IMAGE} 2>/dev/null | grep -oP '"digest":\s*"\K[^"]+' | head -1) + + if [[ -z "${remote_digest}" ]]; then + echo "Warning: Unable to check remote image" + if [[ -n "${local_digest}" ]]; then + echo "Using cached version" + echo + return 0 + else + echo "Error: Image ${DEBIAN_DOCKER_IMAGE} not found locally or remotely" + exit 1 + fi + fi + + if [[ "${local_digest}" != "${remote_digest}" ]]; then + echo "Image update available, pulling ${DEBIAN_DOCKER_IMAGE}" + if docker pull ${DEBIAN_DOCKER_IMAGE} 2>/dev/null; then + echo "Successfully pulled ${DEBIAN_DOCKER_IMAGE}" + else + echo "Error: Failed to pull ${DEBIAN_DOCKER_IMAGE}" + exit 1 + fi + else + echo "Image is up to date (${remote_digest:0:12}...)" + fi + echo +} + +# Prefetch the image early in the script +prefetch_image function backup() { DATE=$(date +"%Y-%m-%d-%H-%M-%S") From e8d9315d4ad6ae886b8146f618df1813db546254 Mon Sep 17 00:00:00 2001 From: Ashitaka <65665184+Ashitaka57@users.noreply.github.com> Date: Wed, 10 Dec 2025 11:41:06 +0100 Subject: [PATCH 4/4] Merge pull request #6905 from Ashitaka57/6646-pbkdf2-sha512-verify-hash Support for PBKDF2-SHA512 hash algorithm in verify_hash() (FreeIPA compatibility) (issue 6646) --- data/web/inc/functions.inc.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 81b3f7e08..1947ec465 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -814,6 +814,32 @@ function verify_hash($hash, $password) { $hash = $components[4]; return hash_equals(hash_pbkdf2('sha1', $password, $salt, $rounds), $hash); + case "PBKDF2-SHA512": + // Handle FreeIPA-style hash: {PBKDF2-SHA512}10000$$ + $components = explode('$', $hash); + if (count($components) !== 3) return false; + + // 1st part: iteration count (integer) + $iterations = intval($components[0]); + if ($iterations <= 0) return false; + + // 2nd part: salt (base64-encoded) + $salt = $components[1]; + // 3rd part: hash (base64-encoded) + $stored_hash_b64 = $components[2]; + + // Decode salt and hash from base64 + $salt_bin = base64_decode($salt, true); + $hash_bin = base64_decode($stored_hash_b64, true); + if ($salt_bin === false || $hash_bin === false) return false; + // Get length of hash in bytes + $hash_len = strlen($hash_bin); + if ($hash_len === 0) return false; + + // Calculate PBKDF2-SHA512 hash for provided password + $test_hash = hash_pbkdf2('sha512', $password, $salt_bin, $iterations, $hash_len, true); + return hash_equals($hash_bin, $test_hash); + case "PLAIN-MD4": return hash_equals(hash('md4', $password), $hash);