public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Commit
[Dovecot] Fix app passwds: allow multiple pass hashes by using LUA construct
afb43c9c
data/Dockerfiles/dovecot/Dockerfile | 1 +
data/Dockerfiles/dovecot/docker-entrypoint.sh | 56 +++++++++++++++++----------
data/conf/dovecot/dovecot.conf | 4 +-
3 files changed, 38 insertions(+), 23 deletions(-)
Diff
diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile
index e52f65d8..5279d0f3 100644
--- a/data/Dockerfiles/dovecot/Dockerfile
+++ b/data/Dockerfiles/dovecot/Dockerfile
@@ -69,6 +69,7 @@ RUN groupadd -g 5000 vmail \
libunicode-string-perl \
liburi-perl \
libwww-perl \
+ lua-sql-mysql \
mariadb-client \
procps \
python3-pip \
diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh
index 097895ab..3bba169d 100755
--- a/data/Dockerfiles/dovecot/docker-entrypoint.sh
+++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh
@@ -7,21 +7,6 @@ while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${D
sleep 2
done
-# Hard-code env vars to scripts due to cron not passing them to the scripts
-sed -i "s/__DBUSER__/${DBUSER}/g" /usr/local/bin/imapsync_cron.pl
-sed -i "s/__DBPASS__/${DBPASS}/g" /usr/local/bin/imapsync_cron.pl
-sed -i "s/__DBNAME__/${DBNAME}/g" /usr/local/bin/imapsync_cron.pl
-
-sed -i "s/__DBUSER__/${DBUSER}/g" /usr/local/bin/quarantine_notify.py
-sed -i "s/__DBPASS__/${DBPASS}/g" /usr/local/bin/quarantine_notify.py
-sed -i "s/__DBNAME__/${DBNAME}/g" /usr/local/bin/quarantine_notify.py
-
-sed -i "s/__DBUSER__/${DBUSER}/g" /usr/local/bin/clean_q_aged.sh
-sed -i "s/__DBPASS__/${DBPASS}/g" /usr/local/bin/clean_q_aged.sh
-sed -i "s/__DBNAME__/${DBNAME}/g" /usr/local/bin/clean_q_aged.sh
-
-sed -i "s/__LOG_LINES__/${LOG_LINES}/g" /usr/local/bin/trim_logs.sh
-
# Create missing directories
[[ ! -d /etc/dovecot/sql/ ]] && mkdir -p /etc/dovecot/sql/
[[ ! -d /var/vmail/_garbage ]] && mkdir -p /var/vmail/_garbage
@@ -127,12 +112,35 @@ default_pass_scheme = SSHA256
password_query = SELECT password FROM mailbox WHERE active = '1' AND username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_EXTRACT(attributes, '$.force_pw_update') NOT LIKE '%%1%%'
EOF
-cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-app-passdb.conf
-# Autogenerated by mailcow
-driver = mysql
-connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
-default_pass_scheme = SSHA256
-password_query = SELECT password FROM app_passwd WHERE active = '1' AND mailbox = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1')
+cat <<EOF > /var/lib/dovecot/app-passdb.lua
+function auth_password_verify(req, pass)
+ local cur,errorString = con:execute(string.format([[SELECT mailbox, password FROM app_passwd
+ WHERE mailbox = '%s'
+ AND active = '1'
+ AND domain IN (SELECT domain FROM domain WHERE domain='%s' AND active='1')]], 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
+ req.log_warning(req, string.format("User %s logged in with app password", row.mailbox))
+ cur:close()
+ return dovecot.auth.PASSDB_RESULT_OK, "password=" .. pass
+ end
+ row = cur:fetch (row, "a")
+ end
+ return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "no such user"
+end
+
+function script_init()
+ mysql = require "luasql.mysql"
+ env = mysql.mysql()
+ con = env:connect("__DBNAME__","__DBUSER__","__DBPASS__","mysql")
+ return 0
+end
+
+function script_deinit()
+ con:close()
+ env:close()
+end
EOF
# Migrate old sieve_after file
@@ -206,6 +214,12 @@ else
rm -f /etc/dovecot/sogo-sso.conf
fi
+# Hard-code env vars to scripts due to cron not passing them to the scripts
+sed -i "s/__DBUSER__/${DBUSER}/g" /usr/local/bin/imapsync_cron.pl /usr/local/bin/quarantine_notify.py /usr/local/bin/clean_q_aged.sh /var/lib/dovecot/app-passdb.lua
+sed -i "s/__DBPASS__/${DBPASS}/g" /usr/local/bin/imapsync_cron.pl /usr/local/bin/quarantine_notify.py /usr/local/bin/clean_q_aged.sh /var/lib/dovecot/app-passdb.lua
+sed -i "s/__DBNAME__/${DBNAME}/g" /usr/local/bin/imapsync_cron.pl /usr/local/bin/quarantine_notify.py /usr/local/bin/clean_q_aged.sh /var/lib/dovecot/app-passdb.lua
+sed -i "s/__LOG_LINES__/${LOG_LINES}/g" /usr/local/bin/trim_logs.sh
+
# 401 is user dovecot
if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then
openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem
diff --git a/data/conf/dovecot/dovecot.conf b/data/conf/dovecot/dovecot.conf
index 01243091..27fa834b 100644
--- a/data/conf/dovecot/dovecot.conf
+++ b/data/conf/dovecot/dovecot.conf
@@ -56,8 +56,8 @@ passdb {
}
# try an app passwd
passdb {
- args = /etc/dovecot/sql/dovecot-dict-sql-app-passdb.conf
- driver = sql
+ driver = lua
+ args = file=/var/lib/dovecot/app-passdb.lua blocking=yes
pass = yes
result_failure = continue
result_internalfail = continue