1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-07-30 08:33:51 +00:00

[Imapsync] fix custom params

This commit is contained in:
FreddleSpl0it
2026-07-21 17:13:33 +02:00
parent 6758999cf3
commit 52ca8f95c2
11 changed files with 161 additions and 137 deletions
+10 -8
View File
@@ -361,15 +361,15 @@ function imapsync_get_settings() {
}
function imapsync_normalize_custom_params($input) {
$pairs = json_decode((string)$input, true);
if (!is_array($pairs)) return '[]';
$allow = $GLOBALS['IMAPSYNC_OPTIONS']['whitelist'];
if (!is_array($input)) return '[]';
$pairs = $input;
$allow = $GLOBALS['IMAPSYNC_OPTIONS'];
$out = array();
foreach ($pairs as $p) {
if (!is_array($p)) continue;
$o = ltrim(strtolower(trim((string)($p['o'] ?? ''))), '-');
if ($o === '') continue;
if (!in_array($o, $allow, true)) return false; // disallowed option -> reject the whole set
if (!array_key_exists($o, $allow)) return false; // disallowed option -> reject the whole set
$out[] = array('o' => $o, 'v' => str_replace("\0", '', (string)($p['v'] ?? '')));
}
return json_encode($out);
@@ -484,7 +484,7 @@ function syncjob($_action, $_type, $_data = null, $_extra = null) {
$subfolder2 = $_data['subfolder2'];
$user1 = $_data['user1'];
$mins_interval = $_data['mins_interval'];
$custom_params = (empty(trim($_data['custom_params']))) ? '' : trim($_data['custom_params']);
$custom_params = $_data['custom_params'] ?? '';
// Resolve and authorize the chosen sync source. Visibility is enforced by syncjob('get', 'source').
$source = syncjob('get', 'source', array('id' => $source_id));
@@ -843,7 +843,8 @@ function syncjob($_action, $_type, $_data = null, $_extra = null) {
$subfolder2 = (isset($_data['subfolder2'])) ? $_data['subfolder2'] : $is_now['subfolder2'];
$mins_interval = (!empty($_data['mins_interval'])) ? $_data['mins_interval'] : $is_now['mins_interval'];
$exclude = (isset($_data['exclude'])) ? $_data['exclude'] : $is_now['exclude'];
$custom_params = (isset($_data['custom_params'])) ? $_data['custom_params'] : $is_now['custom_params'];
$custom_params_provided = isset($_data['custom_params']);
$custom_params = $custom_params_provided ? $_data['custom_params'] : $is_now['custom_params'];
$maxage = (isset($_data['maxage']) && $_data['maxage'] != "") ? intval($_data['maxage']) : $is_now['maxage'];
$maxbytespersecond = (isset($_data['maxbytespersecond']) && $_data['maxbytespersecond'] != "") ? intval($_data['maxbytespersecond']) : $is_now['maxbytespersecond'];
$timeout1 = (isset($_data['timeout1']) && $_data['timeout1'] != "") ? intval($_data['timeout1']) : $is_now['timeout1'];
@@ -873,8 +874,9 @@ function syncjob($_action, $_type, $_data = null, $_extra = null) {
$password1 = '';
}
// Structured custom params: validate option names against the allowlist, store as JSON pairs
$custom_params = imapsync_normalize_custom_params($custom_params);
if ($custom_params_provided) {
$custom_params = imapsync_normalize_custom_params($custom_params);
}
if ($custom_params === false) {
$_SESSION['return'][] = array(
'type' => 'danger',
+2 -2
View File
@@ -1535,7 +1535,7 @@ function init_db_schema()
// Syncjobs: migrate custom_params from raw imapsync string to structured JSON pairs.
// Old values could not contain spaces (they were rejected), so a whitespace split is safe.
$allow = $GLOBALS['IMAPSYNC_OPTIONS']['whitelist'];
$allow = $GLOBALS['IMAPSYNC_OPTIONS'];
$cp_upd = $pdo->prepare("UPDATE `imapsync` SET `custom_params` = :cp WHERE `id` = :id");
foreach ($pdo->query("SELECT `id`, `custom_params` FROM `imapsync`")->fetchAll(PDO::FETCH_ASSOC) as $r) {
$cp = trim((string)$r['custom_params']);
@@ -1548,7 +1548,7 @@ function init_db_schema()
$opt = ltrim($tokens[$i], '-'); $val = '';
if (strpos($opt, '=') !== false) { list($opt, $val) = explode('=', $opt, 2); }
elseif ($i + 1 < count($tokens) && strpos($tokens[$i + 1], '--') !== 0) { $val = $tokens[++$i]; }
if (!in_array(strtolower($opt), $allow)) continue; // drop options no longer allowed
if (!array_key_exists(strtolower($opt), $allow)) continue; // drop options no longer allowed
$pairs[] = array('o' => strtolower($opt), 'v' => $val);
}
}
+84 -91
View File
@@ -281,96 +281,89 @@ $RSPAMD_MAPS = array(
);
// Allowed imapsync options for a sync job's custom_params, mapped to whether they take a value:
// true = option takes a value
// false = pure flag, no value
// Anything not listed here is rejected.
// NEVER add (RCE): 'delete2foldersonly', 'delete2foldersbutnot', 'regexflag', 'regexmess', 'pipemess', 'regextrans2', 'maxlinelengthcmd'
$IMAPSYNC_OPTIONS = array(
'whitelist' => array(
'abort',
'authmd51',
'authuser1',
'debug',
'debugcontent',
'debugcrossduplicates',
'debugflags',
'debugfolders',
'debugimap',
'debugimap1',
'debugmemory',
'debugssl',
'delete1emptyfolders',
'delete2folders',
'disarmreadreceipts',
'domain1',
'domino1',
'errorsmax',
'exchange1',
'exitwhenover',
'expunge1',
'f1f2',
'filterbuggyflags',
'folder',
'folderfirst',
'folderlast',
'folderrec',
'gmail1',
'idatefromheader',
'include',
'inet4',
'inet6',
'justconnect',
'justfolders',
'justfoldersizes',
'justlogin',
'keepalive1',
'log',
'maxbytesafter',
'maxlinelength',
'maxmessagespersecond',
'maxsize',
'maxsleep',
'minage',
'minsize',
'noabletosearch',
'noabletosearch1',
'noexpunge1',
'nofoldersizesatend',
'noid',
'nolog',
'nomixfolders',
'noresyncflags',
'nossl1',
'nosyncacls',
'notls1',
'nousecache',
'office1',
'prefix1',
'resyncflags',
'resynclabels',
'search',
'search1',
'sep1',
'skipemptyfolders',
'subfolder1',
'subscribe',
'subscribed',
'syncacls',
'syncduplicates',
'syncinternaldates',
'synclabels',
'tests',
'testslive',
'testslive6',
'truncmess',
'usecache',
'useheader',
'useuid'
),
'blacklist' => array(
'skipmess',
'delete2foldersonly',
'delete2foldersbutnot',
'regexflag',
'regexmess',
'pipemess',
'regextrans2',
'maxlinelengthcmd'
)
'abort' => false,
'authmd51' => false,
'authuser1' => true,
'debug' => false,
'debugcontent' => false,
'debugcrossduplicates' => false,
'debugflags' => false,
'debugfolders' => false,
'debugimap' => false,
'debugimap1' => false,
'debugmemory' => false,
'debugssl' => true,
'delete1emptyfolders' => false,
'delete2folders' => false,
'disarmreadreceipts' => false,
'domain1' => true,
'domino1' => false,
'errorsmax' => true,
'exchange1' => false,
'exitwhenover' => true,
'expunge1' => false,
'f1f2' => true,
'filterbuggyflags' => false,
'folder' => true,
'folderfirst' => true,
'folderlast' => true,
'folderrec' => true,
'gmail1' => false,
'idatefromheader' => false,
'include' => true,
'inet4' => false,
'inet6' => false,
'justconnect' => false,
'justfolders' => false,
'justfoldersizes' => false,
'justlogin' => false,
'keepalive1' => false,
'log' => false,
'maxbytesafter' => true,
'maxlinelength' => true,
'maxmessagespersecond' => true,
'maxsize' => true,
'maxsleep' => true,
'minage' => true,
'minsize' => true,
'noabletosearch' => false,
'noabletosearch1' => false,
'noexpunge1' => false,
'nofoldersizesatend' => false,
'noid' => false,
'nolog' => false,
'nomixfolders' => false,
'noresyncflags' => false,
'nossl1' => false,
'nosyncacls' => false,
'notls1' => false,
'nousecache' => false,
'office1' => false,
'prefix1' => true,
'resyncflags' => false,
'resynclabels' => false,
'search' => true,
'search1' => true,
'sep1' => true,
'skipemptyfolders' => false,
'subfolder1' => true,
'subscribe' => false,
'subscribed' => false,
'syncacls' => false,
'syncduplicates' => false,
'syncinternaldates' => false,
'synclabels' => false,
'tests' => false,
'testslive' => false,
'testslive6' => false,
'truncmess' => true,
'usecache' => false,
'useheader' => true,
'useuid' => false,
);