mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-02-18 15:16:25 +00:00
Compare commits
13 Commits
copilot/fi
...
copilot/fi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64fe2e6d0d | ||
|
|
f01ada9377 | ||
|
|
ae6420dc80 | ||
|
|
a1b0004be9 | ||
|
|
88376566f9 | ||
|
|
89b4676641 | ||
|
|
a710b0e580 | ||
|
|
b3e6891802 | ||
|
|
19225b223c | ||
|
|
3e5a58be8f | ||
|
|
1fe4cd03e9 | ||
|
|
12e02e67ff | ||
|
|
b6f57dfb78 |
@@ -2,7 +2,7 @@ FROM debian:trixie-slim
|
||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
ARG RSPAMD_VER=rspamd_3.14.1-1~46a758617
|
||||
ARG RSPAMD_VER=rspamd_3.14.2-82~90302bc
|
||||
ARG CODENAME=trixie
|
||||
ENV LC_ALL=C
|
||||
|
||||
|
||||
@@ -251,73 +251,6 @@ function password_check($password1, $password2) {
|
||||
|
||||
return true;
|
||||
}
|
||||
function generate_app_passwd($length = 32) {
|
||||
// Get password complexity requirements
|
||||
$password_complexity = password_complexity('get');
|
||||
|
||||
// Determine the actual length to use
|
||||
$required_length = max($length, intval($password_complexity['length']));
|
||||
|
||||
// Define character sets
|
||||
$lowercase = 'abcdefghijklmnopqrstuvwxyz';
|
||||
$uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$digits = '0123456789';
|
||||
$special = '!@#$%^&*()-_=+[]{}|;:,.<>?';
|
||||
|
||||
// Build the character pool and required chars based on policy
|
||||
$pool = '';
|
||||
$required_chars = '';
|
||||
|
||||
// Add digits to pool and ensure at least one if required
|
||||
if ($password_complexity['numbers'] == 1) {
|
||||
$pool .= $digits;
|
||||
$required_chars .= $digits[random_int(0, strlen($digits) - 1)];
|
||||
}
|
||||
|
||||
// Add alphabetic characters if required
|
||||
if ($password_complexity['chars'] == 1) {
|
||||
$pool .= $lowercase;
|
||||
// Only add required char if not already added by lowerupper requirement
|
||||
if ($password_complexity['lowerupper'] != 1) {
|
||||
$required_chars .= $lowercase[random_int(0, strlen($lowercase) - 1)];
|
||||
}
|
||||
}
|
||||
|
||||
// Add both uppercase and lowercase letters if lowerupper required
|
||||
if ($password_complexity['lowerupper'] == 1) {
|
||||
$pool .= $lowercase . $uppercase;
|
||||
$required_chars .= $uppercase[random_int(0, strlen($uppercase) - 1)];
|
||||
$required_chars .= $lowercase[random_int(0, strlen($lowercase) - 1)];
|
||||
}
|
||||
|
||||
// Add special characters if required
|
||||
if ($password_complexity['special_chars'] == 1) {
|
||||
$pool .= $special;
|
||||
$required_chars .= $special[random_int(0, strlen($special) - 1)];
|
||||
}
|
||||
|
||||
// If no requirements specified, use alphanumeric as default
|
||||
if (empty($pool)) {
|
||||
$pool = $lowercase . $uppercase . $digits;
|
||||
$required_chars .= $digits[random_int(0, strlen($digits) - 1)];
|
||||
}
|
||||
|
||||
// Ensure the password is at least as long as the required characters
|
||||
$final_length = max($required_length, strlen($required_chars));
|
||||
|
||||
// Generate remaining characters from the pool
|
||||
$remaining_length = $final_length - strlen($required_chars);
|
||||
$password = $required_chars;
|
||||
|
||||
for ($i = 0; $i < $remaining_length; $i++) {
|
||||
$password .= $pool[random_int(0, strlen($pool) - 1)];
|
||||
}
|
||||
|
||||
// Shuffle the password to mix required chars with random ones
|
||||
$password = str_shuffle($password);
|
||||
|
||||
return $password;
|
||||
}
|
||||
function last_login($action, $username, $sasl_limit_days = 7, $ui_offset = 1) {
|
||||
global $pdo;
|
||||
global $redis;
|
||||
@@ -3464,6 +3397,8 @@ function set_user_loggedin_session($user) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['mailcow_cc_username'] = $user;
|
||||
$_SESSION['mailcow_cc_role'] = 'user';
|
||||
// Update User-Agent after session regeneration to prevent validation errors
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
$sogo_sso_pass = file_get_contents("/etc/sogo-sso/sogo-sso.pass");
|
||||
$_SESSION['sogo-sso-user-allowed'][] = $user;
|
||||
$_SESSION['sogo-sso-pass'] = $sogo_sso_pass;
|
||||
|
||||
@@ -43,6 +43,9 @@ if (!isset($_SESSION['SESS_REMOTE_UA'])) {
|
||||
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > $SESSION_LIFETIME)) {
|
||||
session_unset();
|
||||
session_destroy();
|
||||
session_start();
|
||||
// After destroying session, we need to reset the User-Agent for the new session
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
}
|
||||
$_SESSION['LAST_ACTIVITY'] = time();
|
||||
|
||||
@@ -134,6 +137,12 @@ function session_check() {
|
||||
return true;
|
||||
}
|
||||
if (!isset($_SESSION['SESS_REMOTE_UA']) || ($_SESSION['SESS_REMOTE_UA'] != $_SERVER['HTTP_USER_AGENT'])) {
|
||||
// In development mode, allow User-Agent changes (e.g., for responsive testing in dev tools)
|
||||
// Validate UA is not empty and has reasonable length (most UAs are under 200 chars, 500 is safe upper limit)
|
||||
if (isset($GLOBALS['DEV_MODE']) && $GLOBALS['DEV_MODE'] && !empty($_SERVER['HTTP_USER_AGENT']) && strlen($_SERVER['HTTP_USER_AGENT']) < 500) {
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
return true;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'warning',
|
||||
'msg' => 'session_ua'
|
||||
|
||||
@@ -50,6 +50,8 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['mailcow_cc_username'] = $login_user;
|
||||
$_SESSION['mailcow_cc_role'] = "admin";
|
||||
// Update User-Agent after session regeneration to prevent validation errors
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
header("Location: /admin/dashboard");
|
||||
die();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ if (!empty($_GET['sso_token'])) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['mailcow_cc_username'] = $username;
|
||||
$_SESSION['mailcow_cc_role'] = 'domainadmin';
|
||||
// Update User-Agent after session regeneration to prevent validation errors
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
header('Location: /domainadmin/mailbox');
|
||||
}
|
||||
}
|
||||
@@ -61,6 +63,8 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['mailcow_cc_username'] = $login_user;
|
||||
$_SESSION['mailcow_cc_role'] = "domainadmin";
|
||||
// Update User-Agent after session regeneration to prevent validation errors
|
||||
$_SESSION['SESS_REMOTE_UA'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
header("Location: /domainadmin/mailbox");
|
||||
die();
|
||||
}
|
||||
|
||||
@@ -54,7 +54,16 @@ jQuery(function($){
|
||||
$.get("/inc/ajax/show_rspamd_global_filters.php");
|
||||
$("#confirm_show_rspamd_global_filters").hide();
|
||||
$("#rspamd_global_filters").removeClass("d-none");
|
||||
localStorage.setItem('rspamd_global_filters_confirmed', 'true');
|
||||
});
|
||||
|
||||
$(document).ready(function() {
|
||||
if (localStorage.getItem('rspamd_global_filters_confirmed') === 'true') {
|
||||
$("#confirm_show_rspamd_global_filters").hide();
|
||||
$("#rspamd_global_filters").removeClass("d-none");
|
||||
}
|
||||
});
|
||||
|
||||
$("#super_delete").click(function() { return confirm(lang.queue_ays); });
|
||||
|
||||
$(".refresh_table").on('click', function(e) {
|
||||
|
||||
@@ -1266,7 +1266,7 @@
|
||||
"no_last_login": "Aucune dernière information de connexion à l'interface",
|
||||
"no_record": "Pas d'enregistrement",
|
||||
"password": "Mot de passe",
|
||||
"password_now": "Mot de passe courant (confirmer les changements)",
|
||||
"password_now": "Mot de passe actuel (confirmer les changements)",
|
||||
"password_repeat": "Mot de passe (répéter)",
|
||||
"pushover_evaluate_x_prio": "Acheminement du courrier hautement prioritaire [<code>X-Priority: 1</code>]",
|
||||
"pushover_info": "Les paramètres de notification push s’appliqueront à tout le courrier propre (non spam) livré à <b>%s</b> y compris les alias (partagés, non partagés, étiquetés).",
|
||||
|
||||
@@ -240,7 +240,7 @@
|
||||
"generate": "Generuj",
|
||||
"guid": "GUID - unikalny identyfikator instancji",
|
||||
"guid_and_license": "GUID & licencja",
|
||||
"hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.<br>\n\n\n\n Każdy hash jest oznaczony indywidualnym kolorem.",
|
||||
"hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.<br> Każdy hash jest oznaczony indywidualnym kolorem.",
|
||||
"help_text": "Zastąp tekst pomocy poniżej maski logowania (dozwolone HTML)",
|
||||
"html": "HTML",
|
||||
"iam": "Dostawca tożsamości",
|
||||
@@ -683,7 +683,11 @@
|
||||
"mailbox_rename_agree": "Stworzyłem kopię zapasową.",
|
||||
"mailbox_rename_warning": "WAŻNE! Utwórz kopię zapasową przed zmianą nazwy skrzynki pocztowej.",
|
||||
"mailbox_rename_alias": "Tworzenie aliasów automatycznie",
|
||||
"mailbox_rename_title": "Nowa nazwa lokalnej skrzynki pocztowej"
|
||||
"mailbox_rename_title": "Nowa nazwa lokalnej skrzynki pocztowej",
|
||||
"mbox_rl_info": "Ten limit szybkości dotyczy nazwy logowania SASL i odpowiada dowolnemu adresowi „from” używanemu przez zalogowanego użytkownika. Limit szybkości dla skrzynki pocztowej nadpisuje limit szybkości dla całej domeny.",
|
||||
"nexthop": "Następny hop",
|
||||
"private_comment": "Prywatny komentarz",
|
||||
"public_comment": "Komentarz publiczny"
|
||||
},
|
||||
"footer": {
|
||||
"cancel": "Anuluj",
|
||||
@@ -1075,7 +1079,7 @@
|
||||
"spamfilter_table_remove": "Usuń",
|
||||
"spamfilter_table_rule": "Zasada",
|
||||
"spamfilter_wl": "Biała lista",
|
||||
"spamfilter_wl_desc": "Adresy e-mail znajdujące się na liście dozwolonych (allowlist) są zaprogramowane tak, aby <b> nigdy nie </b> były klasyfikowane jako spam.\nMożna używać symboli wieloznacznych (wildcardów).\nFiltr jest stosowany wyłącznie do bezpośrednich aliasów (aliasów wskazujących na jedną skrzynkę pocztową), z wyłączeniem aliasów typu „catch-all” oraz samej skrzynki pocztowej",
|
||||
"spamfilter_wl_desc": "Adresy e-mail znajdujące się na liście dozwolonych (allowlist) są zaprogramowane tak, aby <b> nigdy nie </b> były klasyfikowane jako spam. Można używać symboli wieloznacznych (wildcardów).Filtr jest stosowany wyłącznie do bezpośrednich aliasów (aliasów wskazujących na jedną skrzynkę pocztową), z wyłączeniem aliasów typu „catch-all” oraz samej skrzynki pocztowej",
|
||||
"spamfilter_yellow": "Żółty: ta wiadomość może być spamem, zostanie oznaczona jako spam i przeniesiona do folderu spam",
|
||||
"sync_jobs": "Zadania synchronizacji",
|
||||
"tag_handling": "Ustaw obsługę znaczników pocztowych",
|
||||
|
||||
@@ -340,7 +340,8 @@
|
||||
"tls_policy": "Política de TLS",
|
||||
"quarantine_attachments": "Anexos de quarentena",
|
||||
"filters": "Filtros",
|
||||
"smtp_ip_access": "Mudar anfitriões permitidos para SMTP"
|
||||
"smtp_ip_access": "Mudar anfitriões permitidos para SMTP",
|
||||
"app_passwds": "Gerenciar senhas de aplicativos"
|
||||
},
|
||||
"warning": {
|
||||
"no_active_admin": "Não é possível desactivar o último administrador activo"
|
||||
|
||||
@@ -52,7 +52,7 @@ if (isset($_GET['app_password'])) {
|
||||
else
|
||||
$platform = $_SERVER['HTTP_USER_AGENT'];
|
||||
|
||||
$password = generate_app_passwd();
|
||||
$password = bin2hex(openssl_random_pseudo_bytes(16));
|
||||
$attr = array(
|
||||
'app_name' => $platform,
|
||||
'app_passwd' => $password,
|
||||
|
||||
@@ -84,7 +84,7 @@ services:
|
||||
- clamd
|
||||
|
||||
rspamd-mailcow:
|
||||
image: ghcr.io/mailcow/rspamd:3.14.1
|
||||
image: ghcr.io/mailcow/rspamd:3.14.2
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
- dovecot-mailcow
|
||||
|
||||
Reference in New Issue
Block a user