From f5799faf6d283b8479484ac3b789117e68816360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9?= Date: Thu, 4 Oct 2018 14:38:12 +0200 Subject: [PATCH] [Web] Feature: TLS policy maps [Web] Avoid php extensions in links [Web] Minor fixes --- data/web/edit.php | 65 ++++- .../inc/functions.address_rewriting.inc.php | 198 +++++-------- .../web/inc/functions.tls_policy_maps.inc.php | 157 +++++++++++ data/web/inc/header.inc.php | 266 +++++++++--------- data/web/inc/init_db.inc.php | 22 +- data/web/inc/prerequisites.inc.php | 1 + data/web/index.php | 6 +- data/web/js/admin.js | 4 +- data/web/js/mailbox.js | 91 +++++- data/web/js/user.js | 2 +- data/web/json_api.php | 34 +++ data/web/lang/lang.de.php | 27 +- data/web/lang/lang.en.php | 22 +- data/web/mailbox.php | 29 ++ data/web/modals/mailbox.php | 56 ++++ data/web/user.php | 2 +- 16 files changed, 690 insertions(+), 292 deletions(-) create mode 100644 data/web/inc/functions.tls_policy_maps.inc.php diff --git a/data/web/edit.php b/data/web/edit.php index a2eb4fb7..d97b0ffa 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -731,7 +731,9 @@ if (isset($_SESSION['mailcow_cc_role'])) { +

:

+
+
+ +
+ +
+ + +
+
+
+ +
+ +
+
+
+ +
+ + +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+ + + prepare("INSERT INTO `bcc_maps` (`local_dest`, `bcc_dest`, `domain`, `active`, `type`) VALUES - (:local_dest, :bcc_dest, :domain, :active, :type)"); - $stmt->execute(array( - ':local_dest' => $local_dest_sane, - ':bcc_dest' => $bcc_dest, - ':domain' => $domain, - ':active' => $active, - ':type' => $type - )); - } - catch (PDOException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("INSERT INTO `bcc_maps` (`local_dest`, `bcc_dest`, `domain`, `active`, `type`) VALUES + (:local_dest, :bcc_dest, :domain, :active, :type)"); + $stmt->execute(array( + ':local_dest' => $local_dest_sane, + ':bcc_dest' => $bcc_dest, + ':domain' => $domain, + ':active' => $active, + ':type' => $type + )); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), @@ -155,37 +145,27 @@ function bcc($_action, $_data = null, $attr = null) { ); continue; } - try { - $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps` - WHERE `local_dest` = :local_dest AND `type` = :type"); - $stmt->execute(array(':local_dest' => $local_dest, ':type' => $type)); - $id_now = $stmt->fetch(PDO::FETCH_ASSOC)['id']; + $stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps` + WHERE `local_dest` = :local_dest AND `type` = :type"); + $stmt->execute(array(':local_dest' => $local_dest, ':type' => $type)); + $id_now = $stmt->fetch(PDO::FETCH_ASSOC)['id']; - if (isset($id_now) && $id_now != $id) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('bcc_exists', htmlspecialchars($local_dest), $type) - ); - continue; - } - - $stmt = $pdo->prepare("UPDATE `bcc_maps` SET `bcc_dest` = :bcc_dest, `active` = :active, `type` = :type WHERE `id`= :id"); - $stmt->execute(array( - ':bcc_dest' => $bcc_dest, - ':active' => $active, - ':type' => $type, - ':id' => $id - )); - } - catch (PDOException $e) { + if (isset($id_now) && $id_now != $id) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => array('bcc_exists', htmlspecialchars($local_dest), $type) ); continue; } + + $stmt = $pdo->prepare("UPDATE `bcc_maps` SET `bcc_dest` = :bcc_dest, `active` = :active, `type` = :type WHERE `id`= :id"); + $stmt->execute(array( + ':bcc_dest' => $bcc_dest, + ':active' => $active, + ':type' => $type, + ':id' => $id + )); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), @@ -246,29 +226,20 @@ function bcc($_action, $_data = null, $attr = null) { if (!is_numeric($id)) { return false; } - try { - $stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id"); - $stmt->execute(array(':id' => $id)); - $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain']; - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => 'access_denied' - ); - continue; - } - $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `id`= :id"); - $stmt->execute(array(':id' => $id)); - } - catch (PDOException $e) { + $stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id"); + $stmt->execute(array(':id' => $id)); + $domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain']; + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) + 'msg' => 'access_denied' ); continue; } + $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `id`= :id"); + $stmt->execute(array(':id' => $id)); + $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), @@ -317,33 +288,22 @@ function recipient_map($_action, $_data = null, $attr = null) { } $rmaps = recipient_map('get'); foreach ($rmaps as $rmap) { - $old_dests_existing[] = recipient_map('details', $rmap)['recipient_map_old']; - } - if (in_array($old_dest_sane, $old_dests_existing)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest)) - ); - return false; - } - try { - $stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES - (:old_dest, :new_dest, :active)"); - $stmt->execute(array( - ':old_dest' => $old_dest_sane, - ':new_dest' => $new_dest, - ':active' => $active - )); - } - catch (PDOException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane)) + ); + return false; + } } + $stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES + (:old_dest, :new_dest, :active)"); + $stmt->execute(array( + ':old_dest' => $old_dest_sane, + ':new_dest' => $new_dest, + ':active' => $active + )); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), @@ -384,7 +344,6 @@ function recipient_map($_action, $_data = null, $attr = null) { ); continue; } - $active = intval($_data['active']); if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) { $_SESSION['return'][] = array( 'type' => 'danger', @@ -395,38 +354,27 @@ function recipient_map($_action, $_data = null, $attr = null) { } $rmaps = recipient_map('get'); foreach ($rmaps as $rmap) { - $old_dests_existing[] = recipient_map('details', $rmap)['recipient_map_old']; - } - if (in_array($old_dest_sane, $old_dests_existing) && - recipient_map('details', $id)['recipient_map_old'] != $old_dest_sane) { + if ($rmap == $id) { continue; } + if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane)) ); - continue; - } - try { - $stmt = $pdo->prepare("UPDATE `recipient_maps` SET - `old_dest` = :old_dest, - `new_dest` = :new_dest, - `active` = :active - WHERE `id`= :id"); - $stmt->execute(array( - ':old_dest' => $old_dest_sane, - ':new_dest' => $new_dest, - ':active' => $active, - ':id' => $id - )); - } - catch (PDOException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; + return false; + } } + $stmt = $pdo->prepare("UPDATE `recipient_maps` SET + `old_dest` = :old_dest, + `new_dest` = :new_dest, + `active` = :active + WHERE `id`= :id"); + $stmt->execute(array( + ':old_dest' => $old_dest_sane, + ':new_dest' => $new_dest, + ':active' => $active, + ':id' => $id + )); $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_data, $_attr), @@ -471,24 +419,14 @@ function recipient_map($_action, $_data = null, $attr = null) { if (!is_numeric($id)) { return false; } - try { - $stmt = $pdo->prepare("DELETE FROM `recipient_maps` WHERE `id`= :id"); - $stmt->execute(array(':id' => $id)); - } - catch (PDOException $e) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_data, $_attr), - 'msg' => array('mysql_error', $e) - ); - return false; - } + $stmt = $pdo->prepare("DELETE FROM `recipient_maps` WHERE `id`= :id"); + $stmt->execute(array(':id' => $id)); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('recipient_map_entry_deleted', htmlspecialchars($id)) + ); } - $_SESSION['return'][] = array( - 'type' => 'success', - 'msg' => array('recipient_map_entry_deleted', htmlspecialchars($old_dest)) - ); - return true; break; } } diff --git a/data/web/inc/functions.tls_policy_maps.inc.php b/data/web/inc/functions.tls_policy_maps.inc.php new file mode 100644 index 00000000..6581b60d --- /dev/null +++ b/data/web/inc/functions.tls_policy_maps.inc.php @@ -0,0 +1,157 @@ + 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => 'tls_policy_map_parameter_invalid' + ); + return false; + } + } + } + $active = intval($_data['active']); + $tls_policy_maps = tls_policy_maps('get'); + foreach ($tls_policy_maps as $tls_policy_map) { + if (tls_policy_maps('details', $tls_policy_map)['dest'] == $dest) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('tls_policy_map_entry_exists', htmlspecialchars($dest)) + ); + return false; + } + } + $stmt = $pdo->prepare("INSERT INTO `tls_policy_override` (`dest`, `policy`, `parameters`, `active`) VALUES + (:dest, :policy, :parameters, :active)"); + $stmt->execute(array( + ':dest' => $dest, + ':policy' => $policy, + ':parameters' => $parameters, + ':active' => $active + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('tls_policy_map_entry_saved', htmlspecialchars($dest)) + ); + break; + case 'edit': + $ids = (array)$_data['id']; + foreach ($ids as $id) { + $is_now = tls_policy_maps('details', $id); + if (!empty($is_now)) { + $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int']; + $dest = (!empty($_data['dest'])) ? $_data['dest'] : $is_now['dest']; + $policy = (!empty($_data['policy'])) ? $_data['policy'] : $is_now['policy']; + $parameters = (isset($_data['parameters'])) ? $_data['parameters'] : $is_now['parameters']; + } + else { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => 'access_denied' + ); + continue; + } + if (!empty($parameters)) { + foreach (explode(' ', $parameters) as $parameter) { + if (!preg_match('/(.+)\=(.+)/i', $parameter)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => 'tls_policy_map_parameter_invalid' + ); + return false; + } + } + } + $tls_policy_maps = tls_policy_maps('get'); + foreach ($tls_policy_maps as $tls_policy_map) { + if ($tls_policy_map == $id) { continue; } + if (tls_policy_maps('details', $tls_policy_map)['dest'] == $dest) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('recipient_map_entry_exists', htmlspecialchars($dest)) + ); + return false; + } + } + $stmt = $pdo->prepare("UPDATE `tls_policy_override` SET + `dest` = :dest, + `policy` = :policy, + `parameters` = :parameters, + `active` = :active + WHERE `id`= :id"); + $stmt->execute(array( + ':dest' => $dest, + ':policy' => $policy, + ':parameters' => $parameters, + ':active' => $active, + ':id' => $id + )); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('tls_policy_map_entry_saved', htmlspecialchars($dest)) + ); + } + break; + case 'details': + $mapdata = array(); + $id = intval($_data); + $stmt = $pdo->prepare("SELECT `id`, + `dest`, + `policy`, + `parameters`, + `active` AS `active_int`, + CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, + `created`, + `modified` FROM `tls_policy_override` + WHERE `id` = :id"); + $stmt->execute(array(':id' => $id)); + $mapdata = $stmt->fetch(PDO::FETCH_ASSOC); + return $mapdata; + break; + case 'get': + $mapdata = array(); + $all_items = array(); + $id = intval($_data); + $stmt = $pdo->query("SELECT `id` FROM `tls_policy_override`"); + $all_items = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($all_items as $i) { + $mapdata[] = $i['id']; + } + $all_items = null; + return $mapdata; + break; + case 'delete': + $ids = (array)$_data['id']; + foreach ($ids as $id) { + if (!is_numeric($id)) { + return false; + } + $stmt = $pdo->prepare("DELETE FROM `tls_policy_override` WHERE `id`= :id"); + $stmt->execute(array(':id' => $id)); + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_data, $_attr), + 'msg' => array('tls_policy_map_entry_deleted', htmlspecialchars($id)) + ); + } + break; + } +} diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php index 46384b7b..15dc4f02 100644 --- a/data/web/inc/header.inc.php +++ b/data/web/inc/header.inc.php @@ -1,145 +1,145 @@ - - - - - -<?=$UI_TEXTS['title_name'];?> - - - - - - - - - - - - - - - - - -' : null; ?> -' : null; ?> -' : null; ?> -' : null; ?> -' : null; ?> -' : null; ?> - - + + + + + + <?=$UI_TEXTS['title_name'];?> + + + + + + + + + + + + + + + + + + ' : null; ?> + ' : null; ?> + ' : null; ?> + ' : null; ?> + ' : null; ?> + ' : null; ?> + + -
- -
+ + +
  • + +
  • ()
  • + + + + + +
    diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 571713be..8ece2544 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "21092018_1902"; + $db_version = "03102018_1502"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -192,6 +192,26 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "tls_policy_override" => array( + "cols" => array( + "id" => "INT NOT NULL AUTO_INCREMENT", + "dest" => "VARCHAR(255) NOT NULL", + "policy" => "ENUM('none', 'may', 'encrypt', 'dane', 'dane-only', 'fingerprint', 'verify', 'secure') NOT NULL", + "parameters" => "VARCHAR(255) DEFAULT ''", + "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", + "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", + "active" => "TINYINT(1) NOT NULL DEFAULT '1'" + ), + "keys" => array( + "primary" => array( + "" => array("id") + ), + "unique" => array( + "dest" => array("dest") + ), + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "quarantine" => array( "cols" => array( "id" => "INT NOT NULL AUTO_INCREMENT", diff --git a/data/web/inc/prerequisites.inc.php b/data/web/inc/prerequisites.inc.php index 209c7184..4cb742af 100644 --- a/data/web/inc/prerequisites.inc.php +++ b/data/web/inc/prerequisites.inc.php @@ -146,6 +146,7 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fwdhost.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.relayhost.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rsettings.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.docker.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php'; diff --git a/data/web/index.php b/data/web/index.php index 47339923..07fb4497 100644 --- a/data/web/index.php +++ b/data/web/index.php @@ -2,15 +2,15 @@ require_once 'inc/prerequisites.inc.php'; if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') { - header('Location: /admin.php'); + header('Location: /admin'); exit(); } elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') { - header('Location: /mailbox.php'); + header('Location: /mailbox'); exit(); } elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') { - header('Location: /user.php'); + header('Location: /user'); exit(); } require_once 'inc/header.inc.php'; diff --git a/data/web/js/admin.js b/data/web/js/admin.js index 17df1cf0..d8f1e0ad 100644 --- a/data/web/js/admin.js +++ b/data/web/js/admin.js @@ -121,7 +121,7 @@ jQuery(function($){ $.each(data, function (i, item) { item.action = '
    ' + ' Test' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; @@ -144,7 +144,7 @@ jQuery(function($){ item.selected_domains = escapeHtml(item.selected_domains.toString().replace(/,/g, " ")); item.chkbox = ''; item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + ' Login' + '
    '; diff --git a/data/web/js/mailbox.js b/data/web/js/mailbox.js index 836ec872..8894e995 100644 --- a/data/web/js/mailbox.js +++ b/data/web/js/mailbox.js @@ -300,11 +300,11 @@ jQuery(function($){ item.chkbox = ''; item.action = '
    '; if (role == "admin") { - item.action += ' ' + lang.edit + '' + + item.action += ' ' + lang.edit + '' + ' ' + lang.remove + ''; } else { - item.action += ' ' + lang.edit + ''; + item.action += ' ' + lang.edit + ''; } item.action += ' DNS
    '; }); @@ -353,6 +353,8 @@ jQuery(function($){ }, }, {"name":"spam_aliases","filterable": false,"title":lang.spam_aliases,"breakpoints":"xs sm md"}, + {"name":"tls_enforce_in","filterable": false,"title":lang.tls_enforce_in,"breakpoints":"all"}, + {"name":"tls_enforce_out","filterable": false,"title":lang.tls_enforce_out,"breakpoints":"all"}, {"name":"in_use","filterable": false,"type":"html","title":lang.in_use,"sortValue": function(value){ return Number($(value).find(".progress-bar").attr('aria-valuenow')); }, @@ -382,16 +384,18 @@ jQuery(function($){ }).join('/1'); } item.chkbox = ''; + item.tls_enforce_in = ''; + item.tls_enforce_out = ''; if (acl_data.login_as === 1) { item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '' + '
    '; } else { item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; } @@ -412,6 +416,7 @@ jQuery(function($){ "delay": 100, "position": "left", "connectors": false, + //"container": "#tab-mailboxes.panel", "placeholder": lang.filter_table }, "components": { @@ -459,7 +464,7 @@ jQuery(function($){ item.multiple_bookings = '' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')'; } item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; @@ -518,7 +523,7 @@ jQuery(function($){ success: function (data) { $.each(data, function (i, item) { item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; @@ -581,7 +586,7 @@ jQuery(function($){ item.recipient_map_old = escapeHtml(item.recipient_map_old); item.recipient_map_new = escapeHtml(item.recipient_map_new); item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; @@ -614,6 +619,69 @@ jQuery(function($){ } }); } + function draw_tls_policy_table() { + ft_tls_policy_table = FooTable.init('#tls_policy_table', { + "columns": [ + {"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"}, + {"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}}, + {"name":"dest","title":lang.tls_map_dest}, + {"name":"policy","title":lang.tls_map_policy}, + {"name":"parameters","title":lang.tls_map_parameters}, + {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active}, + {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"} + ], + "empty": lang.empty, + "rows": $.ajax({ + dataType: 'json', + url: '/api/v1/get/tls-policy-map/all', + jsonp: false, + error: function () { + console.log('Cannot draw tls policy map table'); + }, + success: function (data) { + if (role == "admin") { + $.each(data, function (i, item) { + item.dest = escapeHtml(item.dest); + item.policy = '' + escapeHtml(item.policy) + ''; + if (item.parameters == '') { + item.parameters = '-'; + } else { + item.parameters = '' + escapeHtml(item.parameters) + ''; + } + item.action = '
    ' + + ' ' + lang.edit + '' + + ' ' + lang.remove + '' + + '
    '; + item.chkbox = ''; + }); + } + } + }), + "paging": { + "enabled": true, + "limit": 5, + "size": pagination_size + }, + "filtering": { + "enabled": true, + "delay": 100, + "position": "left", + "connectors": false, + "placeholder": lang.filter_table + }, + "sorting": { + "enabled": true + }, + "on": { + "ready.ft.table": function(e, ft){ + table_mailbox_ready(ft, 'tls_policy_table'); + }, + "after.ft.paging": function(e, ft){ + paging_mailbox_after(ft, 'tls_policy_table'); + } + } + }); + } function draw_alias_table() { ft_alias_table = FooTable.init('#alias_table', { "columns": [ @@ -636,7 +704,7 @@ jQuery(function($){ success: function (data) { $.each(data, function (i, item) { item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; @@ -711,7 +779,7 @@ jQuery(function($){ success: function (data) { $.each(data, function (i, item) { item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + ' DNS
    ' + ''; @@ -779,7 +847,7 @@ jQuery(function($){ } item.server_w_port = escapeHtml(item.user1) + '@' + item.host1 + ':' + item.port1; item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; @@ -850,7 +918,7 @@ jQuery(function($){ item.script_data = '
    ' + escapeHtml(item.script_data) + '
    ' item.filter_type = '
    ' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '
    ' item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = '' @@ -892,5 +960,6 @@ jQuery(function($){ draw_filter_table(); draw_bcc_table(); draw_recipient_map_table(); + draw_tls_policy_table(); }); diff --git a/data/web/js/user.js b/data/web/js/user.js index 5649d6c6..2c960e82 100644 --- a/data/web/js/user.js +++ b/data/web/js/user.js @@ -122,7 +122,7 @@ jQuery(function($){ item.server_w_port = escapeHtml(item.user1 + '@' + item.host1 + ':' + item.port1); if (acl_data.syncjobs === 1) { item.action = '
    ' + - ' ' + lang.edit + '' + + ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; item.chkbox = ''; diff --git a/data/web/json_api.php b/data/web/json_api.php index adeb162e..d1f6a979 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -153,6 +153,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u case "recipient_map": process_add_return(recipient_map('add', $attr)); break; + case "tls-policy-map": + process_add_return(tls_policy_maps('add', $attr)); + break; } break; case "get": @@ -662,6 +665,31 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u break; } break; + case "tls-policy-map": + switch ($object) { + case "all": + $tls_policy_maps_items = tls_policy_maps('get'); + if (!empty($tls_policy_maps_items)) { + foreach ($tls_policy_maps_items as $tls_policy_maps_item) { + if ($details = tls_policy_maps('details', $tls_policy_maps_item)) { + $data[] = $details; + } + else { + continue; + } + } + } + process_get_return($data); + break; + default: + $data = tls_policy_maps('details', $object); + if (!empty($data)) { + $data[] = $details; + } + process_get_return($data); + break; + } + break; case "policy_wl_mailbox": switch ($object) { default: @@ -919,6 +947,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u case "recipient_map": process_delete_return(recipient_map('delete', array('id' => $items))); break; + case "tls-policy-map": + process_delete_return(tls_policy_maps('delete', array('id' => $items))); + break; case "fwdhost": process_delete_return(fwdhost('delete', array('forwardinghost' => $items))); break; @@ -991,6 +1022,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u case "recipient_map": process_edit_return(recipient_map('edit', array_merge(array('id' => $items), $attr))); break; + case "tls-policy-map": + process_edit_return(tls_policy_maps('edit', array_merge(array('id' => $items), $attr))); + break; case "alias": process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr))); break; diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php index 4cb2e789..9392f346 100644 --- a/data/web/lang/lang.de.php +++ b/data/web/lang/lang.de.php @@ -240,6 +240,17 @@ $lang['header']['mailcow_settings'] = 'Konfiguration'; $lang['header']['administration'] = 'Administration'; $lang['header']['mailboxes'] = 'Mailboxen'; $lang['header']['user_settings'] = 'Benutzereinstellungen'; +$lang['mailbox']['tls_policy_maps'] = 'TLS-Richtlinien'; +$lang['mailbox']['tls_policy_maps_long'] = 'Ausgehende TLS-Richtlinien'; +$lang['mailbox']['tls_policy_maps_info'] = 'Nachstehende Richtlinien erzwingen TLS-Transportregeln unabhängig von TLS-Richtlinieneinstellungen eines Benutzers.
    + Für weitere Informationen zur Syntax sollte die "smtp_tls_policy_maps" Dokumentation konsultiert werden.'; +$lang['mailbox']['tls_enforce_in'] = 'Enforce TLS incoming'; +$lang['mailbox']['tls_enforce_out'] = 'Enforce TLS outgoing'; +$lang['mailbox']['tls_map_dest'] = 'Ziel'; +$lang['mailbox']['tls_map_dest_info'] = 'Beispiele: example.org, .example.org, mail@example.org, [mail.example.org]:25'; +$lang['mailbox']['tls_map_policy'] = 'Richtlinie'; +$lang['mailbox']['tls_map_parameters'] = 'Parameter'; +$lang['mailbox']['tls_map_parameters_info'] = 'Leer oder Parameter, Beispiele: protocols=!SSLv2 ciphers=medium exclude=3DES'; $lang['mailbox']['booking_0'] = 'Immer als verfügbar anzeigen'; $lang['mailbox']['booking_lt0'] = 'Unbegrenzt, jedoch anzeigen, wenn gebucht'; $lang['mailbox']['booking_custom'] = 'Benutzerdefiniertes Limit'; @@ -666,9 +677,13 @@ $lang['mailbox']['recipient_map_new_info'] = 'Der neue Empfänger muss eine E-Ma $lang['mailbox']['recipient_map_old'] = 'Original Empfänger'; $lang['mailbox']['recipient_map_new'] = 'Neuer Empfänger'; $lang['mailbox']['add_recipient_map_entry'] = 'Empfängerumschreibung hinzufügen'; -$lang['danger']['invalid_recipient_map_new'] = 'Neuer Empfänger %s ist ungültig'; -$lang['danger']['invalid_recipient_map_old'] = 'Originaler Empfänger %s ist ungültig'; -$lang['danger']['recipient_map_entry_exists'] = 'Eine Empfängerumschreibung für %s existiert bereits'; -$lang['success']['recipient_map_entry_saved'] = 'Empfängerumschreibung für Objekt %s wurde gespeichert'; -$lang['success']['recipient_map_entry_deleted'] = 'Empfängerumschreibung für Objekt %s wurde gelöscht'; - +$lang['danger']['invalid_recipient_map_new'] = 'Neuer Empfänger "%s" ist ungültig'; +$lang['danger']['invalid_recipient_map_old'] = 'Originaler Empfänger "%s" ist ungültig'; +$lang['danger']['recipient_map_entry_exists'] = 'Eine Empfängerumschreibung für Objekt "%s" existiert bereits'; +$lang['success']['recipient_map_entry_saved'] = 'Empfängerumschreibung für Objekt "%s" wurde gespeichert'; +$lang['success']['recipient_map_entry_deleted'] = 'Empfängerumschreibung mit der ID %s wurde gelöscht'; +$lang['danger']['tls_policy_map_entry_exists'] = 'Eine TLS-Richtlinie "%s" existiert bereits'; +$lang['success']['tls_policy_map_entry_saved'] = 'TLS-Richtlinieneintrag "%s" wurde gespeichert'; +$lang['success']['tls_policy_map_entry_deleted'] = 'TLS-Richtlinie mit der ID %s wurde gelöscht'; +$lang['mailbox']['add_tls_policy_map'] = "TLS-Richtlinieneintrag hinzufügen"; +$lang['danger']['tls_policy_map_parameter_invalid'] = "Parameter ist ungültig"; diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php index 9e5dc9ec..195bceb2 100644 --- a/data/web/lang/lang.en.php +++ b/data/web/lang/lang.en.php @@ -242,6 +242,17 @@ $lang['header']['mailcow_settings'] = 'Configuration'; $lang['header']['administration'] = 'Administration'; $lang['header']['mailboxes'] = 'Mailboxes'; $lang['header']['user_settings'] = 'User settings'; +$lang['mailbox']['tls_policy_maps'] = 'TLS policy maps'; +$lang['mailbox']['tls_policy_maps_long'] = 'Outgoing TLS policy map overrides'; +$lang['mailbox']['tls_policy_maps_info'] = 'This policy map overrides outgoing TLS transport rules independently of a users TLS policy settings.
    + Please check the "smtp_tls_policy_maps" docs for further information.'; +$lang['mailbox']['tls_enforce_in'] = 'Enforce TLS incoming'; +$lang['mailbox']['tls_enforce_out'] = 'Enforce TLS outgoing'; +$lang['mailbox']['tls_map_dest'] = 'Destination'; +$lang['mailbox']['tls_map_dest_info'] = 'Examples: example.org, .example.org, mail@example.org, [mail.example.org]:25'; +$lang['mailbox']['tls_map_policy'] = 'Policy'; +$lang['mailbox']['tls_map_parameters'] = 'Parameters'; +$lang['mailbox']['tls_map_parameters_info'] = 'Empty or parameters, for example: protocols=!SSLv2 ciphers=medium exclude=3DES'; $lang['mailbox']['booking_0'] = 'Always show as free'; $lang['mailbox']['booking_lt0'] = 'Unlimited, but show as busy when booked'; $lang['mailbox']['booking_custom'] = 'Hard-limit to a custom amount of bookings'; @@ -667,6 +678,7 @@ $lang['mailbox']['bcc_maps'] = "BCC maps"; $lang['mailbox']['bcc_to_sender'] = "Switch to sender map type"; $lang['mailbox']['bcc_to_rcpt'] = "Switch to recipient map type"; $lang['mailbox']['add_bcc_entry'] = "Add BCC map"; +$lang['mailbox']['add_tls_policy_map'] = "Add TLS policy map"; $lang['mailbox']['bcc_info'] = "BCC maps are used to silently forward copies of all messages to another address. A recipient map type entry is used, when the local destination acts as recipient of a mail. Sender maps conform to the same principle.
    The local destination will not be informed about a failed delivery."; $lang['mailbox']['address_rewriting'] = 'Address rewriting'; @@ -679,10 +691,14 @@ $lang['mailbox']['recipient_map_old'] = 'Original recipient'; $lang['mailbox']['recipient_map_new'] = 'New recipient'; $lang['danger']['invalid_recipient_map_new'] = 'Invalid new recipient specified: %s'; $lang['danger']['invalid_recipient_map_old'] = 'Invalid original recipient specified: %s'; -$lang['danger']['recipient_map_entry_exists'] = 'A Recipient map entry for %s exists'; -$lang['success']['recipient_map_entry_saved'] = 'Recipient map entry for %s has been saved'; -$lang['success']['recipient_map_entry_deleted'] = 'Recipient map entry for %s has been deleted'; +$lang['danger']['recipient_map_entry_exists'] = 'A Recipient map entry "%s" exists'; +$lang['success']['recipient_map_entry_saved'] = 'Recipient map entry "%s" has been saved'; +$lang['success']['recipient_map_entry_deleted'] = 'Recipient map ID %s has been deleted'; +$lang['danger']['tls_policy_map_entry_exists'] = 'A TLS policy map entry "%s" exists'; +$lang['success']['tls_policy_map_entry_saved'] = 'TLS policy map entry "%s" has been saved'; +$lang['success']['tls_policy_map_entry_deleted'] = 'TLS policy map ID %s has been deleted'; $lang['mailbox']['add_recipient_map_entry'] = 'Add recipient map'; +$lang['danger']['tls_policy_map_parameter_invalid'] = "Policy parameter is invalid"; $lang['oauth2']['scope_ask_permission'] = 'An application asked for the following permissions'; $lang['oauth2']['profile'] = 'Profile'; diff --git a/data/web/mailbox.php b/data/web/mailbox.php index 70d8dbb6..fd21d26d 100644 --- a/data/web/mailbox.php +++ b/data/web/mailbox.php @@ -22,6 +22,7 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
  • +
  • @@ -287,6 +288,34 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
    + +
    " id="tab-tls-policy"> +
    +
    + +
    + +
    +
    +

    +
    +
    +
    +
    +
    + + + + +
    +
    +
    +
    diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php index fe99bc6d..107df71a 100644 --- a/data/web/modals/mailbox.php +++ b/data/web/modals/mailbox.php @@ -692,6 +692,62 @@ if (!isset($_SESSION['mailcow_cc_role'])) { + +