[Rspamd] Fix map permissions for www
[Web] Allow to manage global maps in UI (WIP)master
parent
2b477e338f
commit
b52ee0a706
|
@ -8,6 +8,8 @@ touch /etc/rspamd/rspamd.conf.local \
|
||||||
|
|
||||||
chmod 755 /var/lib/rspamd
|
chmod 755 /var/lib/rspamd
|
||||||
|
|
||||||
|
addgroup --system --gid 82 www-access
|
||||||
|
|
||||||
[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated by mailcow' > /etc/rspamd/override.d/worker-controller-password.inc
|
[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Autogenerated by mailcow' > /etc/rspamd/override.d/worker-controller-password.inc
|
||||||
|
|
||||||
DOVECOT_V4=
|
DOVECOT_V4=
|
||||||
|
@ -49,8 +51,10 @@ touch /etc/rspamd/custom/global_mime_from_blacklist.map \
|
||||||
/etc/rspamd/custom/bad_words_de.map
|
/etc/rspamd/custom/bad_words_de.map
|
||||||
|
|
||||||
# www-data (82) group needs to write to these files
|
# www-data (82) group needs to write to these files
|
||||||
chown -R _rspamd:82 /etc/rspamd/custom
|
chown root:root /etc/rspamd/custom/
|
||||||
chmod -R g+w /etc/rspamd/custom
|
chmod 0755 /etc/rspamd/custom/
|
||||||
|
chown -R _rspamd:www-access /etc/rspamd/custom/*
|
||||||
|
chmod -R 664 /etc/rspamd/custom/*
|
||||||
|
|
||||||
# Run hooks
|
# Run hooks
|
||||||
for file in /hooks/*; do
|
for file in /hooks/*; do
|
||||||
|
|
|
@ -17,6 +17,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
|
||||||
<li role="presentation"><a href="#tab-routing" aria-controls="tab-config" role="tab" data-toggle="tab"><?=$lang['admin']['routing'];?></a></li>
|
<li role="presentation"><a href="#tab-routing" aria-controls="tab-config" role="tab" data-toggle="tab"><?=$lang['admin']['routing'];?></a></li>
|
||||||
<li role="presentation"><a href="#tab-sys-mails" aria-controls="tab-sys-mails" role="tab" data-toggle="tab"><?=$lang['admin']['sys_mails'];?></a></li>
|
<li role="presentation"><a href="#tab-sys-mails" aria-controls="tab-sys-mails" role="tab" data-toggle="tab"><?=$lang['admin']['sys_mails'];?></a></li>
|
||||||
<li role="presentation"><a href="#tab-mailq" aria-controls="tab-mailq" role="tab" data-toggle="tab"><?=$lang['admin']['queue_manager'];?></a></li>
|
<li role="presentation"><a href="#tab-mailq" aria-controls="tab-mailq" role="tab" data-toggle="tab"><?=$lang['admin']['queue_manager'];?></a></li>
|
||||||
|
<li role="presentation"><a href="#tab-rspamdmaps" aria-controls="tab-rspamdmaps" role="tab" data-toggle="tab"><?=$lang['admin']['rspamd_global_filters'];?></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -1136,6 +1137,49 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div role="tabpanel" class="tab-pane" id="tab-rspamdmaps">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<?=$lang['admin']['rspamd_global_filters'];?>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<p><?=$lang['admin']['rspamd_global_filters_info'];?></p>
|
||||||
|
<div id="confirm_show_rspamd_global_filters" class="<?=($_SESSION['show_rspamd_global_filters'] === true) ? 'hidden' : '';?>">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="show_rspamd_global_filters"> <?=$lang['admin']['rspamd_global_filters_agree'];?>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="rspamd_global_filters" class="<?=($_SESSION['show_rspamd_global_filters'] !== true) ? 'hidden' : '';?>">
|
||||||
|
<?php
|
||||||
|
foreach ($RSPAMD_MAPS as $rspamd_map):
|
||||||
|
?>
|
||||||
|
<hr>
|
||||||
|
<form class="form-horizontal" data-id="<?=$rspamd_map;?>" role="form" method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-3" for="<?=$rspamd_map;?>"><code><?=$rspamd_map;?></code>:</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<textarea id="<?=$rspamd_map;?>" spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control textarea-code" rows="10" name="rspamd_map_data" required><?=file_get_contents('/rspamd_custom_maps/' . $rspamd_map);?></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-3 col-sm-9">
|
||||||
|
<button class="btn btn-xs btn-default validate_rspamd_regex" data-regex-map="<?=$rspamd_map;?>" href="#"><?=$lang['add']['validate'];?></button>
|
||||||
|
<button class="btn btn-xs btn-success submit_rspamd_regex" data-action="edit_selected" data-id="<?=$rspamd_map;?>" data-item="<?=htmlspecialchars($rspamd_map);?>" data-api-url='edit/rspamd-map' data-api-attr='{}' href="#" disabled><?=$lang['edit']['save'];?></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php
|
||||||
|
endforeach;
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div> <!-- /tab-content -->
|
</div> <!-- /tab-content -->
|
||||||
</div> <!-- /col-md-12 -->
|
</div> <!-- /col-md-12 -->
|
||||||
</div> <!-- /row -->
|
</div> <!-- /row -->
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
if (!isset($_SESSION['mailcow_cc_role'])) {
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
if (isset($_GET['regex'])) {
|
||||||
|
$regex_lines = preg_split("/(\r\n|\n|\r)/", $_GET['regex']);
|
||||||
|
foreach ($regex_lines as $line => $regex) {
|
||||||
|
if (empty($regex) || substr($regex, 0, 1) == "#") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (empty($regex) || substr($regex, 0, 1) != "/") {
|
||||||
|
echo json_encode(array('type' => 'danger', 'msg' => 'Line ' . ($line + 1) . ': Invalid regex'));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
if (@preg_match($regex, 'Lorem Ipsum') === false) {
|
||||||
|
echo json_encode(array('type' => 'danger', 'msg' => 'Line ' . ($line + 1) . ': Invalid regex "' . $regex . '"'));
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
echo json_encode(array('type' => 'success', 'msg' => $lang['add']['validation_success']));
|
||||||
|
}
|
||||||
|
?>
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
$_SESSION['show_rspamd_global_filters'] = true;
|
|
@ -32,7 +32,7 @@ function fail2ban($_action, $_data = null) {
|
||||||
$tmp_wl_data[] = $key;
|
$tmp_wl_data[] = $key;
|
||||||
}
|
}
|
||||||
if (isset($tmp_wl_data)) {
|
if (isset($tmp_wl_data)) {
|
||||||
sort($tmp_wl_data);
|
natsort($tmp_wl_data);
|
||||||
$f2b_options['whitelist'] = implode(PHP_EOL, $tmp_wl_data);
|
$f2b_options['whitelist'] = implode(PHP_EOL, $tmp_wl_data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -48,7 +48,7 @@ function fail2ban($_action, $_data = null) {
|
||||||
$tmp_bl_data[] = $key;
|
$tmp_bl_data[] = $key;
|
||||||
}
|
}
|
||||||
if (isset($tmp_bl_data)) {
|
if (isset($tmp_bl_data)) {
|
||||||
sort($tmp_bl_data);
|
natsort($tmp_bl_data);
|
||||||
$f2b_options['blacklist'] = implode(PHP_EOL, $tmp_bl_data);
|
$f2b_options['blacklist'] = implode(PHP_EOL, $tmp_bl_data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
<?php
|
|
||||||
function rsettings($_action, $_data = null) {
|
|
||||||
global $pdo;
|
|
||||||
global $lang;
|
|
||||||
$_data_log = $_data;
|
|
||||||
switch ($_action) {
|
|
||||||
case 'add':
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => 'access_denied'
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$content = $_data['content'];
|
|
||||||
$desc = $_data['desc'];
|
|
||||||
$active = intval($_data['active']);
|
|
||||||
if (empty($content)) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => 'map_content_empty'
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO `settingsmap` (`content`, `desc`, `active`)
|
|
||||||
VALUES (:content, :desc, :active)");
|
|
||||||
$stmt->execute(array(
|
|
||||||
':content' => $content,
|
|
||||||
':desc' => $desc,
|
|
||||||
':active' => $active
|
|
||||||
));
|
|
||||||
}
|
|
||||||
catch (PDOException $e) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => array('mysql_error', $e)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'success',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => 'settings_map_added'
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'edit':
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => 'access_denied'
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$ids = (array)$_data['id'];
|
|
||||||
foreach ($ids as $id) {
|
|
||||||
$is_now = rsettings('details', $id);
|
|
||||||
if (!empty($is_now)) {
|
|
||||||
$content = (!empty($_data['content'])) ? $_data['content'] : $is_now['content'];
|
|
||||||
$desc = (!empty($_data['desc'])) ? $_data['desc'] : $is_now['desc'];
|
|
||||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => array('settings_map_invalid', $id)
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$content = trim($content);
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->prepare("UPDATE `settingsmap` SET
|
|
||||||
`content` = :content,
|
|
||||||
`desc` = :desc,
|
|
||||||
`active` = :active
|
|
||||||
WHERE `id` = :id");
|
|
||||||
$stmt->execute(array(
|
|
||||||
':content' => $content,
|
|
||||||
':desc' => $desc,
|
|
||||||
':active' => $active,
|
|
||||||
':id' => $id
|
|
||||||
));
|
|
||||||
}
|
|
||||||
catch (PDOException $e) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => array('mysql_error', $e)
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'success',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => array('object_modified', htmlspecialchars($ids))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => 'access_denied'
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$ids = (array)$_data['id'];
|
|
||||||
foreach ($ids as $id) {
|
|
||||||
try {
|
|
||||||
$stmt = $pdo->prepare("DELETE FROM `settingsmap` WHERE `id`= :id");
|
|
||||||
$stmt->execute(array(':id' => $id));
|
|
||||||
}
|
|
||||||
catch (PDOException $e) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => array('mysql_error', $e)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'success',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
|
||||||
'msg' => array('settings_map_removed', htmlspecialchars($id))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'get':
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$settingsmaps = array();
|
|
||||||
$stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`");
|
|
||||||
$settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
return $settingsmaps;
|
|
||||||
break;
|
|
||||||
case 'details':
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$settingsmapdata = array();
|
|
||||||
$stmt = $pdo->prepare("SELECT `id`,
|
|
||||||
`desc`,
|
|
||||||
`content`,
|
|
||||||
`active` AS `active_int`,
|
|
||||||
CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
|
|
||||||
FROM `settingsmap`
|
|
||||||
WHERE `id` = :id");
|
|
||||||
$stmt->execute(array(':id' => $_data));
|
|
||||||
$settingsmapdata = $stmt->fetch(PDO::FETCH_ASSOC);
|
|
||||||
return $settingsmapdata;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,311 @@
|
||||||
|
<?php
|
||||||
|
function rsettings($_action, $_data = null) {
|
||||||
|
global $pdo;
|
||||||
|
global $lang;
|
||||||
|
$_data_log = $_data;
|
||||||
|
switch ($_action) {
|
||||||
|
case 'add':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$content = $_data['content'];
|
||||||
|
$desc = $_data['desc'];
|
||||||
|
$active = intval($_data['active']);
|
||||||
|
if (empty($content)) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'map_content_empty'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `settingsmap` (`content`, `desc`, `active`)
|
||||||
|
VALUES (:content, :desc, :active)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':content' => $content,
|
||||||
|
':desc' => $desc,
|
||||||
|
':active' => $active
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('mysql_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'settings_map_added'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ids = (array)$_data['id'];
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$is_now = rsettings('details', $id);
|
||||||
|
if (!empty($is_now)) {
|
||||||
|
$content = (!empty($_data['content'])) ? $_data['content'] : $is_now['content'];
|
||||||
|
$desc = (!empty($_data['desc'])) ? $_data['desc'] : $is_now['desc'];
|
||||||
|
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('settings_map_invalid', $id)
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$content = trim($content);
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("UPDATE `settingsmap` SET
|
||||||
|
`content` = :content,
|
||||||
|
`desc` = :desc,
|
||||||
|
`active` = :active
|
||||||
|
WHERE `id` = :id");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':content' => $content,
|
||||||
|
':desc' => $desc,
|
||||||
|
':active' => $active,
|
||||||
|
':id' => $id
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('mysql_error', $e)
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('object_modified', htmlspecialchars($ids))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ids = (array)$_data['id'];
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM `settingsmap` WHERE `id`= :id");
|
||||||
|
$stmt->execute(array(':id' => $id));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('mysql_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('settings_map_removed', htmlspecialchars($id))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'get':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$settingsmaps = array();
|
||||||
|
$stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`");
|
||||||
|
$settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $settingsmaps;
|
||||||
|
break;
|
||||||
|
case 'details':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$settingsmapdata = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT `id`,
|
||||||
|
`desc`,
|
||||||
|
`content`,
|
||||||
|
`active` AS `active_int`,
|
||||||
|
CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
|
||||||
|
FROM `settingsmap`
|
||||||
|
WHERE `id` = :id");
|
||||||
|
$stmt->execute(array(':id' => $_data));
|
||||||
|
$settingsmapdata = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
return $settingsmapdata;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function rspamd($_action, $_data = null) {
|
||||||
|
global $pdo;
|
||||||
|
global $lang;
|
||||||
|
global $RSPAMD_MAPS;
|
||||||
|
$_data_log = $_data;
|
||||||
|
switch ($_action) {
|
||||||
|
case 'add':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$content = $_data['content'];
|
||||||
|
$desc = $_data['desc'];
|
||||||
|
$active = intval($_data['active']);
|
||||||
|
if (empty($content)) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'map_content_empty'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `settingsmap` (`content`, `desc`, `active`)
|
||||||
|
VALUES (:content, :desc, :active)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':content' => $content,
|
||||||
|
':desc' => $desc,
|
||||||
|
':active' => $active
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('mysql_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'settings_map_added'
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'edit':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$maps = (array)$_data['map'];
|
||||||
|
foreach ($maps as $map) {
|
||||||
|
if (!in_array($map, $RSPAMD_MAPS)) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('global_map_invalid', $map)
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (file_exists('/rspamd_custom_maps/' . $map)) {
|
||||||
|
$map_content = trim($_data['rspamd_map_data']);
|
||||||
|
$map_handle = fopen('/rspamd_custom_maps/' . $map, 'w');
|
||||||
|
if (!$map_handle) {
|
||||||
|
throw new Exception('File cannot be opened for writing.');
|
||||||
|
}
|
||||||
|
fwrite($map_handle, $map_content . PHP_EOL);
|
||||||
|
fclose($map_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('global_map_write_error', htmlspecialchars($map), htmlspecialchars($e->getMessage()))
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('object_modified', htmlspecialchars($map))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$ids = (array)$_data['id'];
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM `settingsmap` WHERE `id`= :id");
|
||||||
|
$stmt->execute(array(':id' => $id));
|
||||||
|
}
|
||||||
|
catch (PDOException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('mysql_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||||
|
'msg' => array('settings_map_removed', htmlspecialchars($id))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'get':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$settingsmaps = array();
|
||||||
|
$stmt = $pdo->query("SELECT `id`, `desc`, `active` FROM `settingsmap`");
|
||||||
|
$settingsmaps = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
return $settingsmaps;
|
||||||
|
break;
|
||||||
|
case 'details':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin" || !isset($_data)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$settingsmapdata = array();
|
||||||
|
$stmt = $pdo->prepare("SELECT `id`,
|
||||||
|
`desc`,
|
||||||
|
`content`,
|
||||||
|
`active` AS `active_int`,
|
||||||
|
CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`
|
||||||
|
FROM `settingsmap`
|
||||||
|
WHERE `id` = :id");
|
||||||
|
$stmt->execute(array(':id' => $_data));
|
||||||
|
$settingsmapdata = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
return $settingsmapdata;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -209,7 +209,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailq.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.oauth2.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.oauth2.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.transports.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.transports.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rsettings.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rspamd.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.tls_policy_maps.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.tls_policy_maps.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php';
|
||||||
|
|
|
@ -156,7 +156,7 @@ $MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'] = 'hourly';
|
||||||
$MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format'] = 'maildir:';
|
$MAILBOX_DEFAULT_ATTRIBUTES['mailbox_format'] = 'maildir:';
|
||||||
|
|
||||||
// Set visible Rspamd maps in mailcow UI, do not change unless you know what you are doing
|
// Set visible Rspamd maps in mailcow UI, do not change unless you know what you are doing
|
||||||
$RSPAM_MAPS = array(
|
$RSPAMD_MAPS = array(
|
||||||
'global_mime_from_blacklist.map',
|
'global_mime_from_blacklist.map',
|
||||||
'global_mime_from_whitelist.map',
|
'global_mime_from_whitelist.map',
|
||||||
'global_rcpt_blacklist.map',
|
'global_rcpt_blacklist.map',
|
||||||
|
|
|
@ -3,6 +3,7 @@ var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456
|
||||||
jQuery(function($){
|
jQuery(function($){
|
||||||
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
|
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
|
||||||
var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
|
var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="};
|
||||||
|
function jq(myid) {return "#" + myid.replace( /(:|\.|\[|\]|,|=|@)/g, "\\$1" );}
|
||||||
function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
|
function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
|
||||||
function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]}
|
function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]}
|
||||||
function hashCode(t){for(var n=0,r=0;r<t.length;r++)n=t.charCodeAt(r)+((n<<5)-n);return n}
|
function hashCode(t){for(var n=0,r=0;r<t.length;r++)n=t.charCodeAt(r)+((n<<5)-n);return n}
|
||||||
|
@ -29,6 +30,33 @@ jQuery(function($){
|
||||||
$("#mass_exclude").change(function(){ $("#mass_include").selectpicker('deselectAll'); });
|
$("#mass_exclude").change(function(){ $("#mass_include").selectpicker('deselectAll'); });
|
||||||
$("#mass_include").change(function(){ $("#mass_exclude").selectpicker('deselectAll'); });
|
$("#mass_include").change(function(){ $("#mass_exclude").selectpicker('deselectAll'); });
|
||||||
$("#mass_disarm").click(function() { $("#mass_send").attr("disabled", !this.checked); });
|
$("#mass_disarm").click(function() { $("#mass_send").attr("disabled", !this.checked); });
|
||||||
|
$(".validate_rspamd_regex").click(function( event ) {
|
||||||
|
event.preventDefault();
|
||||||
|
var regex_map_id = $(this).data('regex-map');
|
||||||
|
var regex_data = $(jq(regex_map_id)).val();
|
||||||
|
$.ajax({
|
||||||
|
dataType: 'json',
|
||||||
|
url: "/inc/ajax/regex_validation.php",
|
||||||
|
type: "get",
|
||||||
|
data: { regex: regex_data },
|
||||||
|
complete: function(data) {
|
||||||
|
var response = (data.responseText);
|
||||||
|
response_obj = JSON.parse(response);
|
||||||
|
if (response_obj.type == "success") {
|
||||||
|
$('button[data-id="' + regex_map_id + '"]').attr({"disabled": false});
|
||||||
|
}
|
||||||
|
mailcow_alert_box(response_obj.msg, response_obj.type);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$('.textarea-code').on('keyup', function() {
|
||||||
|
$('.submit_rspamd_regex').attr({"disabled": true});
|
||||||
|
});
|
||||||
|
$("#show_rspamd_global_filters").click(function() {
|
||||||
|
$.get("inc/ajax/show_rspamd_global_filters.php");
|
||||||
|
$("#confirm_show_rspamd_global_filters").hide();
|
||||||
|
$("#rspamd_global_filters").removeClass("hidden");
|
||||||
|
});
|
||||||
$("#super_delete").click(function() { return confirm(lang.queue_ays); });
|
$("#super_delete").click(function() { return confirm(lang.queue_ays); });
|
||||||
$(".refresh_table").on('click', function(e) {
|
$(".refresh_table").on('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
|
@ -133,16 +133,15 @@ $(document).ready(function() {
|
||||||
$(e.currentTarget).find('#sieveDataText').html('<pre style="font-size:14px;line-height:1.1">' + sieveScript + '</pre>');
|
$(e.currentTarget).find('#sieveDataText').html('<pre style="font-size:14px;line-height:1.1">' + sieveScript + '</pre>');
|
||||||
});
|
});
|
||||||
// Disable submit button on script change
|
// Disable submit button on script change
|
||||||
$('#script_data').on('keyup', function() {
|
$('.textarea-code').on('keyup', function() {
|
||||||
$('#add_filter_btns > #add_sieve_script').attr({"disabled": true});
|
$('#add_filter_btns > #add_sieve_script').attr({"disabled": true});
|
||||||
$('#validation_msg').html('-');
|
|
||||||
});
|
});
|
||||||
// Validate script data
|
// Validate script data
|
||||||
$("#validate_sieve").click(function( event ) {
|
$("#validate_sieve").click(function( event ) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var script = $('#script_data').val();
|
var script = $('#script_data').val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
dataType: 'jsonp',
|
dataType: 'json',
|
||||||
url: "/inc/ajax/sieve_validation.php",
|
url: "/inc/ajax/sieve_validation.php",
|
||||||
type: "get",
|
type: "get",
|
||||||
data: { script: script },
|
data: { script: script },
|
||||||
|
|
|
@ -1245,6 +1245,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
||||||
case "alias":
|
case "alias":
|
||||||
process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr)));
|
process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr)));
|
||||||
break;
|
break;
|
||||||
|
case "rspamd-map":
|
||||||
|
process_edit_return(rspamd('edit', array_merge(array('map' => $items), $attr)));
|
||||||
|
break;
|
||||||
case "app_links":
|
case "app_links":
|
||||||
process_edit_return(customize('edit', 'app_links', $attr));
|
process_edit_return(customize('edit', 'app_links', $attr));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -71,6 +71,8 @@ $lang['danger']['private_key_error'] = "Schlüsselfehler: %s";
|
||||||
$lang['danger']['map_content_empty'] = "Inhalt darf nicht leer sein";
|
$lang['danger']['map_content_empty'] = "Inhalt darf nicht leer sein";
|
||||||
$lang['success']['settings_map_added'] = "Regel wurde gespeichert";
|
$lang['success']['settings_map_added'] = "Regel wurde gespeichert";
|
||||||
$lang['danger']['settings_map_invalid'] = "Regel ID %s ist ungültig";
|
$lang['danger']['settings_map_invalid'] = "Regel ID %s ist ungültig";
|
||||||
|
$lang['danger']['global_map_invalid'] = "Rspamd Map %s ist ungültig";
|
||||||
|
$lang['danger']['global_map_write_error'] = "Kann globale Map ID %s nicht schreiben: %s";
|
||||||
$lang['success']['settings_map_removed'] = "Regeln wurden entfernt: %s";
|
$lang['success']['settings_map_removed'] = "Regeln wurden entfernt: %s";
|
||||||
$lang['danger']['invalid_host'] = "Ungültiger Host: %s";
|
$lang['danger']['invalid_host'] = "Ungültiger Host: %s";
|
||||||
$lang['danger']['relayhost_invalid'] = "Mapeintrag %s ist ungültig";
|
$lang['danger']['relayhost_invalid'] = "Mapeintrag %s ist ungültig";
|
||||||
|
@ -915,5 +917,9 @@ $lang['mailbox']['alias_domain_backupmx'] = 'Alias-Domain für Relay-Domain inak
|
||||||
$lang['danger']['extra_acl_invalid'] = 'Externe Absenderadresse "%s" ist ungültig';
|
$lang['danger']['extra_acl_invalid'] = 'Externe Absenderadresse "%s" ist ungültig';
|
||||||
$lang['danger']['extra_acl_invalid_domain'] = 'Externe Absenderadresse "%s" verwendet eine ungültige Domain';
|
$lang['danger']['extra_acl_invalid_domain'] = 'Externe Absenderadresse "%s" verwendet eine ungültige Domain';
|
||||||
|
|
||||||
$lang['admin']['rspamd_global_filters'] = 'Globale Rspamd Filter';
|
$lang['admin']['rspamd_global_filters_agree'] = "Ich werde vorsichtig sein!";
|
||||||
$lang['admin']['rspamd_global_filters'] = 'Globale Rspamd Filter';
|
$lang['admin']['rspamd_global_filters'] = 'Globale Filter-Maps';
|
||||||
|
$lang['admin']['rspamd_global_filters_info'] = 'Globale Filter-Maps steuern globales White- und Blacklisting dieses Servers. Die akzeptierte Form für Einträge sind <b>ausschließlich</b> Regular Expressions.
|
||||||
|
Trotz rudimentärer Überprüfung der Map, kann es zu fehlerhaften Einträgen kommen, die Rspamd im schlechtesten Fall mit unvorhersehbarer Funktionalität bestraft.<br>
|
||||||
|
Das korrekte Format lautet "/pattern/options" (Beispiel: <code>/.+@domain\.tld/i</code>).<br>
|
||||||
|
Der Name der Map beschreibt die jeweilige Funktion.';
|
||||||
|
|
|
@ -72,6 +72,8 @@ $lang['danger']['private_key_error'] = "Private key error: %s";
|
||||||
$lang['danger']['map_content_empty'] = "Map content cannot be empty";
|
$lang['danger']['map_content_empty'] = "Map content cannot be empty";
|
||||||
$lang['success']['settings_map_added'] = "Added settings map entry";
|
$lang['success']['settings_map_added'] = "Added settings map entry";
|
||||||
$lang['danger']['settings_map_invalid'] = "Settings map ID %s invalid";
|
$lang['danger']['settings_map_invalid'] = "Settings map ID %s invalid";
|
||||||
|
$lang['danger']['global_map_invalid'] = "Global map ID %s invalid";
|
||||||
|
$lang['danger']['global_map_write_error'] = "Could not write global map ID %s: %s";
|
||||||
$lang['success']['settings_map_removed'] = "Removed settings map ID %s";
|
$lang['success']['settings_map_removed'] = "Removed settings map ID %s";
|
||||||
$lang['danger']['invalid_host'] = "Invalid host specified: %s";
|
$lang['danger']['invalid_host'] = "Invalid host specified: %s";
|
||||||
$lang['danger']['relayhost_invalid'] = "Map entry %s is invalid";
|
$lang['danger']['relayhost_invalid'] = "Map entry %s is invalid";
|
||||||
|
@ -940,5 +942,8 @@ $lang['mailbox']['alias_domain_backupmx'] = 'Alias domain inactive for relay dom
|
||||||
$lang['danger']['extra_acl_invalid'] = 'External sender address "%s" is invalid';
|
$lang['danger']['extra_acl_invalid'] = 'External sender address "%s" is invalid';
|
||||||
$lang['danger']['extra_acl_invalid_domain'] = 'External sender "%s" uses an invalid domain';
|
$lang['danger']['extra_acl_invalid_domain'] = 'External sender "%s" uses an invalid domain';
|
||||||
|
|
||||||
$lang['admin']['rspamd_global_filters'] = 'Global Rspamd filters';
|
$lang['admin']['rspamd_global_filters_agree'] = "I will be careful!";
|
||||||
$lang['admin']['rspamd_global_filters_info'] = 'Global Rspamd filters';
|
$lang['admin']['rspamd_global_filters'] = 'Global filter maps';
|
||||||
|
$lang['admin']['rspamd_global_filters_info'] = 'Global filter maps contain different kind of global black and whitelists. Their names explain their purpose. All content must contain valid regular expression in the format of "/pattern/options" (e.g. <code>/.+@domain\.tld/i</code>).<br>
|
||||||
|
Although rudimentary checks are being executed on each line of regex, Rspamds functionality can be broken, if it fails to read the syntax correctly.';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue