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); 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 }}
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\"" 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")