diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index 30a06d24..9d3965a7 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -49,4 +49,6 @@ COPY sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg COPY acl.diff /acl.diff CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf +VOLUME /usr/lib/GNUstep/SOGo/ + RUN rm -rf /tmp/* /var/tmp/* diff --git a/data/Dockerfiles/sogo/supervisord.conf b/data/Dockerfiles/sogo/supervisord.conf index 2a889560..1c1422b3 100644 --- a/data/Dockerfiles/sogo/supervisord.conf +++ b/data/Dockerfiles/sogo/supervisord.conf @@ -16,13 +16,6 @@ command=/usr/sbin/cron -f autorestart=true priority=2 -[program:sogo-webres] -command=/usr/bin/python -u -m SimpleHTTPServer 9192 -directory=/usr/lib/GNUstep/SOGo/ -user=sogo -autorestart=true -priority=4 - [program:bootstrap-sogo] command=/bootstrap-sogo.sh stdout_logfile=/dev/stdout diff --git a/data/Dockerfiles/watchdog/watchdog.sh b/data/Dockerfiles/watchdog/watchdog.sh index c06abbc2..ec3d5aca 100755 --- a/data/Dockerfiles/watchdog/watchdog.sh +++ b/data/Dockerfiles/watchdog/watchdog.sh @@ -59,10 +59,10 @@ function mail_error() { log_msg "Sent notification email to ${1}" } - get_container_ip() { # ${1} is container CONTAINER_ID=() + CONTAINER_IPS=() CONTAINER_IP= LOOP_C=1 until [[ ${CONTAINER_IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ ${LOOP_C} -gt 5 ]]; do @@ -72,15 +72,21 @@ get_container_ip() { # returned id can have multiple elements (if scaled), shuffle for random test CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf)) if [[ ! -z ${CONTAINER_ID} ]]; then - for matched_container in "${CONTAINER_ID[@]}"; do - CONTAINER_IP=$(curl --silent http://dockerapi:8080/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress') - # grep will do nothing if one of these vars is empty - [[ -z ${CONTAINER_IP} ]] && continue - [[ -z ${IPV4_NETWORK} ]] && continue - # only return ips that are part of our network - if ! grep -q ${IPV4_NETWORK} <(echo ${CONTAINER_IP}); then - CONTAINER_IP= - fi + for matched_container in "${CONTAINER_ID[@]}"; do + CONTAINER_IPS=($(curl --silent http://dockerapi:8080/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress')) + for ip_match in "${CONTAINER_IPS[@]}"; do + # grep will do nothing if one of these vars is empty + [[ -z ${ip_match} ]] && continue + [[ -z ${IPV4_NETWORK} ]] && continue + # only return ips that are part of our network + if ! grep -q ${IPV4_NETWORK} <(echo ${ip_match}); then + continue + else + CONTAINER_IP=${ip_match} + break + fi + done + [[ ! -z ${CONTAINER_IP} ]] && break done fi LOOP_C=$((LOOP_C + 1)) @@ -88,7 +94,6 @@ get_container_ip() { [[ ${LOOP_C} -gt 5 ]] && echo 240.0.0.0 || echo ${CONTAINER_IP} } -# Check functions nginx_checks() { err_count=0 diff_c=0 diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf index dd8db8a3..5fc0024d 100644 --- a/data/conf/dovecot/dovecot.conf +++ b/data/conf/dovecot/dovecot.conf @@ -175,7 +175,7 @@ namespace { type = shared separator = / prefix = Shared/%%u/ - location = maildir:%%h/:CONTROL=~/Shared/%%u:INDEXPVT=~/Shared/%%u + location = maildir:%%h/:INDEX=~/Shared/%%u;CONTROL=~/Shared/%%u subscriptions = no list = children } diff --git a/data/conf/nginx/site.conf b/data/conf/nginx/site.conf index d25d3b61..9ea4c385 100644 --- a/data/conf/nginx/site.conf +++ b/data/conf/nginx/site.conf @@ -156,44 +156,19 @@ server { } location /SOGo.woa/WebServerResources/ { - proxy_pass http://sogo:9192/WebServerResources/; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/WebServerResources/; - expires $expires; - allow all; + alias /usr/lib/GNUstep/SOGo/WebServerResources/; } location /.woa/WebServerResources/ { - proxy_pass http://sogo:9192/WebServerResources/; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/WebServerResources/; - expires $expires; - allow all; + alias /usr/lib/GNUstep/SOGo/WebServerResources/; } location /SOGo/WebServerResources/ { - proxy_pass http://sogo:9192/WebServerResources/; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/WebServerResources/; - allow all; + alias /usr/lib/GNUstep/SOGo/WebServerResources/; } location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) { - proxy_pass http://sogo:9192/$1.SOGo/Resources/$2; - proxy_set_header Host $http_host; - proxy_cache sogo; - proxy_cache_valid 200 1d; - proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; - #alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; + alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2; } include /etc/nginx/conf.d/site.*.custom; diff --git a/data/conf/rspamd/custom/bad_asn.map b/data/conf/rspamd/custom/bad_asn.map index 8b7a4407..bc9e10f6 100644 --- a/data/conf/rspamd/custom/bad_asn.map +++ b/data/conf/rspamd/custom/bad_asn.map @@ -1,11 +1,10 @@ # High spam networks, disabled by default #201942:5 #Soltia Consulting SL - ipinfo.io -#16276:5 #OVH -#12876:5 #ONLINE S.A.S -#31034:5 -#12874:5 -#30823:5 -#197071:5 +#16276:2 #OVH +#12876:2 #ONLINE S.A.S +#31034:5 #ARUBA-ASN, IT +#12874:5 #FASTWEB, IT +#30823:3 #PKV spam #42831:5 #UK Dedicated Servers Ltd #29119:5 #Aire Networks del Mediterraneo S.L.U. #13335:5 #Cloudflare @@ -17,7 +16,7 @@ #14061:4 #Digitalocean #55293:4 #A2 Hosting #63018:4 #US Dedicated -#197518:2 +#197518:2 #RACKMARKT #44493:2 #46606:2 #49505:2 @@ -25,3 +24,5 @@ #197695:2 #198068:2 #43146:2 +#49100:4 +#39364:4 diff --git a/data/conf/rspamd/local.d/multimap.conf b/data/conf/rspamd/local.d/multimap.conf index da4afaf2..c27a9d63 100644 --- a/data/conf/rspamd/local.d/multimap.conf +++ b/data/conf/rspamd/local.d/multimap.conf @@ -25,13 +25,6 @@ WHITELISTED_FWD_HOST { symbols_set = ["WHITELISTED_FWD_HOST"]; } -KEEP_SPAM { - type = "ip"; - map = "redis://KEEP_SPAM"; - action = "accept"; - symbols_set = ["KEEP_SPAM"]; -} - LOCAL_BL_ASN { require_symbols = "!MAILCOW_WHITE"; type = "asn"; @@ -40,11 +33,3 @@ LOCAL_BL_ASN { description = "Sender's ASN is on the local blacklist"; symbols_set = ["LOCAL_BL_ASN"]; } - -#SPOOFED_SENDER { -# type = "rcpt"; -# filter = "email:domain:tld"; -# map = "redis://DOMAIN_MAP"; -# require_symbols = "AUTH_NA | !RCVD_VIA_SMTP_AUTH"; -# symbols_set = ["SPOOFED_SENDER"]; -#} diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 7c9efbb4..92d223b1 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -7,6 +7,60 @@ rspamd_config.MAILCOW_AUTH = { end } +rspamd_config:register_symbol({ + name = 'KEEP_SPAM', + type = 'prefilter', + callback = function(task) + local util = require("rspamd_util") + local rspamd_logger = require "rspamd_logger" + local rspamd_ip = require 'rspamd_ip' + local uname = task:get_user() + if uname then + return false + end + local redis_params = rspamd_parse_redis_server('keep_spam') + local ip = task:get_from_ip() + local from_ip_string = ip:to_string() + ip_check_table = {from_ip_string} + local maxbits = 128 + local minbits = 32 + if ip:get_version() == 4 then + maxbits = 32 + minbits = 8 + end + for i=maxbits,minbits,-1 do + local nip = ip:apply_mask(i):to_string() .. "/" .. i + table.insert(ip_check_table, nip) + end + local function keep_spam_cb(err, data) + if err then + rspamd_logger.infox(rspamd_config, "keep_spam query request for ip %s returned invalid or empty data (\"%s\") or error (\"%s\")", ip, data, err) + return false + else + for k,v in pairs(data) do + if (v and v ~= userdata and v == '1') then + rspamd_logger.infox(rspamd_config, "found ip in keep_spam map, setting pre-result", v) + task:set_pre_result('accept', 'IP matched with forward hosts') + end + end + end + end + table.insert(ip_check_table, 1, 'KEEP_SPAM') + local redis_ret_user = rspamd_redis_make_request(task, + redis_params, -- connect params + 'KEEP_SPAM', -- hash key + false, -- is write + keep_spam_cb, --callback + 'HMGET', -- command + ip_check_table -- arguments + ) + if not redis_ret_user then + rspamd_logger.infox(rspamd_config, "cannot check keep_spam redis map") + end + end, + priority = 19 +}) + rspamd_config:register_symbol({ name = 'TAG_MOO', type = 'postfilter', diff --git a/data/web/admin.php b/data/web/admin.php index d2734431..749c96b6 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -29,7 +29,7 @@ $tfa_data = get_tfa();
- +
@@ -44,7 +44,7 @@ $tfa_data = get_tfa();
-
+
:
@@ -76,12 +76,10 @@ $tfa_data = get_tfa();
- - - - diff --git a/data/web/css/admin.css b/data/web/css/admin.css index a53d721c..bc89f1dd 100644 --- a/data/web/css/admin.css +++ b/data/web/css/admin.css @@ -65,12 +65,6 @@ body.modal-open { font-size:9pt; background:transparent; } -.bootstrap-select { - width: auto!important; -} .table-condensed .input-sm { width: 100%!important; } -.full-width-select { - width: 100%!important; -} diff --git a/data/web/css/mailbox.css b/data/web/css/mailbox.css index da2e96e3..488150d3 100644 --- a/data/web/css/mailbox.css +++ b/data/web/css/mailbox.css @@ -5,9 +5,6 @@ table.footable>tbody>tr.footable-empty>td { .pagination a { text-decoration: none !important; } -.panel panel-default { - overflow: visible !important; -} .btn-group { width: max-content; } diff --git a/data/web/css/mailcow.css b/data/web/css/mailcow.css index 374688a1..04d1b874 100644 --- a/data/web/css/mailcow.css +++ b/data/web/css/mailcow.css @@ -148,3 +148,13 @@ nav .glyphicon { color: #5a5a5a; white-space: nowrap; } +.haveibeenpwned { + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.full-width-select { + width: 100%!important; +} \ No newline at end of file diff --git a/data/web/edit.php b/data/web/edit.php index c4903c28..417f2a7c 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -92,7 +92,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- @@ -111,7 +111,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -140,6 +140,30 @@ if (isset($_SESSION['mailcow_cc_role'])) {
+
+
+
+

ACL

+
+
+
+ +
+
+ +
+
+
+
- +

@@ -278,14 +302,14 @@ if (isset($_SESSION['mailcow_cc_role'])) {
-
+
-
+
@@ -300,14 +324,14 @@ if (isset($_SESSION['mailcow_cc_role'])) {
-
+
-
+
@@ -474,7 +498,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -527,6 +551,30 @@ if (isset($_SESSION['mailcow_cc_role'])) {
+
+
+
+

ACL

+
+
+
+ +
+
+ +
+
+
+
- +
@@ -965,7 +1013,7 @@ else { + + diff --git a/data/web/modals/admin.php b/data/web/modals/admin.php index 7e8656e5..8bca0d87 100644 --- a/data/web/modals/admin.php +++ b/data/web/modals/admin.php @@ -67,7 +67,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
- ".htmlspecialchars($domain).""; @@ -79,7 +79,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
- +
diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php index b4a51893..160ab178 100644 --- a/data/web/modals/mailbox.php +++ b/data/web/modals/mailbox.php @@ -23,7 +23,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
- ".htmlspecialchars($domain).""; @@ -48,10 +48,9 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
- +
- - (Generate) +
diff --git a/data/web/modals/user.php b/data/web/modals/user.php index 62ccf1b1..5e0849e2 100644 --- a/data/web/modals/user.php +++ b/data/web/modals/user.php @@ -37,7 +37,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
- +
@@ -155,7 +155,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
- +
diff --git a/data/web/quarantine.php b/data/web/quarantine.php index 87f565a1..3e193586 100644 --- a/data/web/quarantine.php +++ b/data/web/quarantine.php @@ -18,7 +18,7 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
-
+
- +
-
+
@@ -299,9 +280,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
- +
@@ -309,7 +288,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
-

- +
-
- +

@@ -354,26 +329,22 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
- +
-
+
-
+
- +

@@ -381,28 +352,22 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
- +
-
+
-
+
- -
- +
@@ -411,11 +376,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
- +
-
+
- +
diff --git a/docker-compose.yml b/docker-compose.yml index 871961a8..cd0c69f8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -136,7 +136,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.34 + image: mailcow/sogo:1.36 build: ./data/Dockerfiles/sogo environment: - DBNAME=${DBNAME} @@ -264,6 +264,8 @@ services: - ./data/assets/ssl/:/etc/ssl/mail/:ro - ./data/conf/nginx/:/etc/nginx/conf.d/:rw - ./data/conf/rspamd/meta_exporter:/meta_exporter:ro + volumes_from: + - sogo-mailcow ports: - "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}" - "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}" @@ -328,7 +330,7 @@ services: - /lib/modules:/lib/modules:ro watchdog-mailcow: - image: mailcow/watchdog:1.19 + image: mailcow/watchdog:1.21 # Debug #command: /watchdog.sh build: ./data/Dockerfiles/watchdog