git subrepo commit (merge) mailcow/src/mailcow-dockerized

subrepo: subdir:   "mailcow/src/mailcow-dockerized"
  merged:   "32243e56"
upstream: origin:   "https://github.com/mailcow/mailcow-dockerized.git"
  branch:   "master"
  commit:   "e2b4b6f6"
git-subrepo: version:  "0.4.3"
  origin:   "???"
  commit:   "???"
Change-Id: I51e2016ef5ab88a8b0bdc08551b18f48ceef0aa5
diff --git a/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/Dockerfile b/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/Dockerfile
index 1990097..1fc4000 100644
--- a/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/Dockerfile
+++ b/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/Dockerfile
@@ -2,7 +2,7 @@
 LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
 
 ARG DEBIAN_FRONTEND=noninteractive
-ARG DOVECOT=2.3.14.1
+ARG DOVECOT=2.3.17
 ENV LC_ALL C
 ENV GOSU_VERSION 1.12
 
diff --git a/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/docker-entrypoint.sh b/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/docker-entrypoint.sh
index 5ea1609..9ac2dc6 100755
--- a/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/docker-entrypoint.sh
+++ b/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/docker-entrypoint.sh
@@ -155,34 +155,47 @@
   local row = cur:fetch ({}, "a")
   while row do
     if req.password_verify(req, row.password, pass) == 1 then
-      cur:close()
       con:execute(string.format([[REPLACE INTO sasl_log (service, app_password, username, real_rip)
         VALUES ("%s", 0, "%s", "%s")]], con:escape(req.service), con:escape(req.user), con:escape(req.real_rip)))
+      cur:close()
+      con:close()
       return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass
     end
     row = cur:fetch (row, "a")
   end
 
-  -- check against app passwds
-  local cur,errorString = con:execute(string.format([[SELECT app_passwd.id, app_passwd.password FROM app_passwd
-    INNER JOIN mailbox ON mailbox.username = app_passwd.mailbox
-    WHERE mailbox = '%s'
-      AND IFNULL(JSON_UNQUOTE(JSON_VALUE(mailbox.attributes, '$.%s_access')), 1) = '1'
-      AND IFNULL(JSON_UNQUOTE(JSON_VALUE(mailbox.attributes, '$.force_pw_update')), 0) != '1'
-      AND app_passwd.active = '1'
-      AND mailbox.active = '1'
-      AND app_passwd.domain IN (SELECT domain FROM domain WHERE domain='%s' AND active='1')]], con:escape(req.user), con:escape(req.service), con:escape(req.domain)))
-  local row = cur:fetch ({}, "a")
-  while row do
-    if req.password_verify(req, row.password, pass) == 1 then
-      cur:close()
-      con:execute(string.format([[REPLACE INTO sasl_log (service, app_password, username, real_rip)
-        VALUES ("%s", %d, "%s", "%s")]], con:escape(req.service), row.id, con:escape(req.user), con:escape(req.real_rip)))
-      return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass
+  -- check against app passwds for imap and smtp
+  -- app passwords are only available for imap, smtp, sieve and pop3 when using sasl
+  if req.service == "smtp" or req.service == "imap" or req.service == "sieve" or req.service == "pop3" then
+    local cur,errorString = con:execute(string.format([[SELECT app_passwd.id, %s_access AS has_prot_access, app_passwd.password FROM app_passwd
+      INNER JOIN mailbox ON mailbox.username = app_passwd.mailbox
+      WHERE mailbox = '%s'
+        AND app_passwd.active = '1'
+        AND mailbox.active = '1'
+        AND app_passwd.domain IN (SELECT domain FROM domain WHERE domain='%s' AND active='1')]], con:escape(req.service), con:escape(req.user), con:escape(req.domain)))
+    local row = cur:fetch ({}, "a")
+    while row do
+      if req.password_verify(req, row.password, pass) == 1 then
+        -- if password is valid and protocol access is 1 OR real_rip matches SOGo, proceed
+        if tostring(req.real_rip) == "__IPV4_SOGO__" then
+          cur:close()
+          con:close()
+          return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass
+        elseif row.has_prot_access == "1" then
+          con:execute(string.format([[REPLACE INTO sasl_log (service, app_password, username, real_rip)
+            VALUES ("%s", %d, "%s", "%s")]], con:escape(req.service), row.id, con:escape(req.user), con:escape(req.real_rip)))
+          cur:close()
+          con:close()
+          return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass
+        end
+      end
+      row = cur:fetch (row, "a")
     end
-    row = cur:fetch (row, "a")
   end
 
+  cur:close()
+  con:close()
+
   return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Failed to authenticate"
 
   -- PoC
@@ -230,6 +243,7 @@
 sed -i "s/__DBUSER__/${DBUSER}/g" /etc/dovecot/lua/passwd-verify.lua
 sed -i "s/__DBPASS__/${DBPASS}/g" /etc/dovecot/lua/passwd-verify.lua
 sed -i "s/__DBNAME__/${DBNAME}/g" /etc/dovecot/lua/passwd-verify.lua
+sed -i "s/__IPV4_SOGO__/${IPV4_NETWORK}.248/g" /etc/dovecot/lua/passwd-verify.lua
 
 
 # Migrate old sieve_after file
diff --git a/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/imapsync_runner.pl b/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/imapsync_runner.pl
index 0f01a97..5b297ab 100644
--- a/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/imapsync_runner.pl
+++ b/mailcow/src/mailcow-dockerized/data/Dockerfiles/dovecot/imapsync_runner.pl
@@ -152,18 +152,28 @@
   '--noreleasecheck'];
 
   try {
-    $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1 WHERE id = ?");
+    $is_running = $dbh->prepare("UPDATE imapsync SET is_running = 1, success = NULL, exit_status = NULL WHERE id = ?");
     $is_running->bind_param( 1, ${id} );
     $is_running->execute();
-    
+
     run [@$generated_cmds, @$custom_params_ref], '&>', \my $stdout;
-    
-    $update = $dbh->prepare("UPDATE imapsync SET returned_text = ? WHERE id = ?");
+
+    # check exit code and status
+    ($exit_code, $exit_status) = ($stdout =~ m/Exiting\swith\sreturn\svalue\s(\d+)\s\(([^:)]+)/);
+
+    $success = 0;
+    if (defined $exit_code && $exit_code == 0) {
+      $success = 1;
+    }
+
+    $update = $dbh->prepare("UPDATE imapsync SET returned_text = ?, success = ?, exit_status = ? WHERE id = ?");
     $update->bind_param( 1, ${stdout} );
-    $update->bind_param( 2, ${id} );
+    $update->bind_param( 2, ${success} );
+    $update->bind_param( 3, ${exit_status} );
+    $update->bind_param( 4, ${id} );
     $update->execute();
   } catch {
-    $update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync' WHERE id = ?");
+    $update = $dbh->prepare("UPDATE imapsync SET returned_text = 'Could not start or finish imapsync', success = 0 WHERE id = ?");
     $update->bind_param( 1, ${id} );
     $update->execute();
   } finally {