Skip to content

Commit 57ee17b

Browse files
authored
Merge branch 'nightly' into staging
2 parents 76194be + 9b86ff7 commit 57ee17b

File tree

758 files changed

+47623
-9234
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

758 files changed

+47623
-9234
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ data/conf/rspamd/local.d/*
4444
data/conf/rspamd/override.d/*
4545
data/conf/sogo/custom-theme.js
4646
data/conf/sogo/plist_ldap
47+
data/conf/sogo/plist_ldap.sh
4748
data/conf/sogo/sieve.creds
4849
data/conf/sogo/sogo-full.svg
4950
data/gitea/
@@ -69,3 +70,4 @@ rebuild-images.sh
6970
refresh_images.sh
7071
update_diffs/
7172
create_cold_standby.sh
73+
!data/conf/nginx/mailcow_auth.conf

data/Dockerfiles/clamd/clamdcheck.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ if [ "${CLAMAV_NO_CLAMD:-}" != "false" ]; then
1111
echo "Clamd is up"
1212
fi
1313

14-
exit 0
14+
exit 0

data/Dockerfiles/dovecot/Dockerfile

+6-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ LABEL maintainer = "The Infrastructure Company GmbH <[email protected]>"
44

55
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
66
ARG GOSU_VERSION=1.16
7+
ENV LC_ALL C
78

8-
ENV LANG C.UTF-8
9-
ENV LC_ALL C.UTF-8
109

1110
# Add groups and users before installing Dovecot to not break compatibility
1211
RUN addgroup -g 5000 vmail \
@@ -34,9 +33,13 @@ RUN addgroup -g 5000 vmail \
3433
lua5.3-sql-mysql \
3534
icu-data-full \
3635
mariadb-connector-c \
36+
lua-sec \
37+
mariadb-dev \
38+
glib-dev \
3739
gcompat \
3840
mariadb-client \
3941
perl \
42+
perl-dev \
4043
perl-ntlm \
4144
perl-cgi \
4245
perl-crypt-openssl-rsa \
@@ -133,4 +136,4 @@ COPY repl_health.sh /usr/local/bin/repl_health.sh
133136
COPY optimize-fts.sh /usr/local/bin/optimize-fts.sh
134137

135138
ENTRYPOINT ["/docker-entrypoint.sh"]
136-
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
139+
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf

data/Dockerfiles/dovecot/docker-entrypoint.sh

+4-128
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ${REDIS_CMDLINE} SET DOVECOT_REPL_HEALTH 1 > /dev/null
2828

2929
# Create missing directories
3030
[[ ! -d /etc/dovecot/sql/ ]] && mkdir -p /etc/dovecot/sql/
31-
[[ ! -d /etc/dovecot/lua/ ]] && mkdir -p /etc/dovecot/lua/
31+
[[ ! -d /etc/dovecot/auth/ ]] && mkdir -p /etc/dovecot/auth/
3232
[[ ! -d /etc/dovecot/conf.d/ ]] && mkdir -p /etc/dovecot/conf.d/
3333
[[ ! -d /var/vmail/_garbage ]] && mkdir -p /var/vmail/_garbage
3434
[[ ! -d /var/vmail/sieve ]] && mkdir -p /var/vmail/sieve
@@ -136,116 +136,6 @@ user_query = SELECT CONCAT(JSON_UNQUOTE(JSON_VALUE(attributes, '$.mailbox_format
136136
iterate_query = SELECT username FROM mailbox WHERE active = '1' OR active = '2';
137137
EOF
138138

139-
cat <<EOF > /etc/dovecot/lua/passwd-verify.lua
140-
function auth_password_verify(req, pass)
141-
142-
if req.domain == nil then
143-
return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "No such user"
144-
end
145-
146-
if cur == nil then
147-
script_init()
148-
end
149-
150-
if req.user == nil then
151-
req.user = ''
152-
end
153-
154-
respbody = {}
155-
156-
-- check against mailbox passwds
157-
local cur,errorString = con:execute(string.format([[SELECT password FROM mailbox
158-
WHERE username = '%s'
159-
AND active = '1'
160-
AND domain IN (SELECT domain FROM domain WHERE domain='%s' AND active='1')
161-
AND IFNULL(JSON_UNQUOTE(JSON_VALUE(mailbox.attributes, '$.force_pw_update')), 0) != '1'
162-
AND IFNULL(JSON_UNQUOTE(JSON_VALUE(attributes, '$.%s_access')), 1) = '1']], con:escape(req.user), con:escape(req.domain), con:escape(req.service)))
163-
local row = cur:fetch ({}, "a")
164-
while row do
165-
if req.password_verify(req, row.password, pass) == 1 then
166-
con:execute(string.format([[REPLACE INTO sasl_log (service, app_password, username, real_rip)
167-
VALUES ("%s", 0, "%s", "%s")]], con:escape(req.service), con:escape(req.user), con:escape(req.real_rip)))
168-
cur:close()
169-
con:close()
170-
return dovecot.auth.PASSDB_RESULT_OK, ""
171-
end
172-
row = cur:fetch (row, "a")
173-
end
174-
175-
-- check against app passwds for imap and smtp
176-
-- app passwords are only available for imap, smtp, sieve and pop3 when using sasl
177-
if req.service == "smtp" or req.service == "imap" or req.service == "sieve" or req.service == "pop3" then
178-
local cur,errorString = con:execute(string.format([[SELECT app_passwd.id, %s_access AS has_prot_access, app_passwd.password FROM app_passwd
179-
INNER JOIN mailbox ON mailbox.username = app_passwd.mailbox
180-
WHERE mailbox = '%s'
181-
AND app_passwd.active = '1'
182-
AND mailbox.active = '1'
183-
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)))
184-
local row = cur:fetch ({}, "a")
185-
while row do
186-
if req.password_verify(req, row.password, pass) == 1 then
187-
-- if password is valid and protocol access is 1 OR real_rip matches SOGo, proceed
188-
if tostring(req.real_rip) == "__IPV4_SOGO__" then
189-
cur:close()
190-
con:close()
191-
return dovecot.auth.PASSDB_RESULT_OK, ""
192-
elseif row.has_prot_access == "1" then
193-
con:execute(string.format([[REPLACE INTO sasl_log (service, app_password, username, real_rip)
194-
VALUES ("%s", %d, "%s", "%s")]], con:escape(req.service), row.id, con:escape(req.user), con:escape(req.real_rip)))
195-
cur:close()
196-
con:close()
197-
return dovecot.auth.PASSDB_RESULT_OK, ""
198-
end
199-
end
200-
row = cur:fetch (row, "a")
201-
end
202-
end
203-
204-
cur:close()
205-
con:close()
206-
207-
return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Failed to authenticate"
208-
209-
-- PoC
210-
-- local reqbody = string.format([[{
211-
-- "success":0,
212-
-- "service":"%s",
213-
-- "app_password":false,
214-
-- "username":"%s",
215-
-- "real_rip":"%s"
216-
-- }]], con:escape(req.service), con:escape(req.user), con:escape(req.real_rip))
217-
-- http.request {
218-
-- method = "POST",
219-
-- url = "http://nginx:8081/sasl_log.php",
220-
-- source = ltn12.source.string(reqbody),
221-
-- headers = {
222-
-- ["content-type"] = "application/json",
223-
-- ["content-length"] = tostring(#reqbody)
224-
-- },
225-
-- sink = ltn12.sink.table(respbody)
226-
-- }
227-
228-
end
229-
230-
function auth_passdb_lookup(req)
231-
return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, ""
232-
end
233-
234-
function script_init()
235-
mysql = require "luasql.mysql"
236-
http = require "socket.http"
237-
http.TIMEOUT = 5
238-
ltn12 = require "ltn12"
239-
env = mysql.mysql()
240-
con = env:connect("__DBNAME__","__DBUSER__","__DBPASS__","localhost")
241-
return 0
242-
end
243-
244-
function script_deinit()
245-
con:close()
246-
env:close()
247-
end
248-
EOF
249139

250140
# Temporarily set FTS depending on user choice inside mailcow.conf. Will be removed as soon as Solr is dropped
251141
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
@@ -288,13 +178,6 @@ EOF
288178
fi
289179

290180

291-
# Replace patterns in app-passdb.lua
292-
sed -i "s/__DBUSER__/${DBUSER}/g" /etc/dovecot/lua/passwd-verify.lua
293-
sed -i "s/__DBPASS__/${DBPASS}/g" /etc/dovecot/lua/passwd-verify.lua
294-
sed -i "s/__DBNAME__/${DBNAME}/g" /etc/dovecot/lua/passwd-verify.lua
295-
sed -i "s/__IPV4_SOGO__/${IPV4_NETWORK}.248/g" /etc/dovecot/lua/passwd-verify.lua
296-
297-
298181
# Migrate old sieve_after file
299182
[[ -f /etc/dovecot/sieve_after ]] && mv /etc/dovecot/sieve_after /etc/dovecot/global_sieve_after
300183
# Create global sieve scripts
@@ -367,13 +250,6 @@ EOF
367250
# Create random master Password for SOGo SSO
368251
RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1)
369252
echo -n ${RAND_PASS} > /etc/phpfpm/sogo-sso.pass
370-
cat <<EOF > /etc/dovecot/sogo-sso.conf
371-
# Autogenerated by mailcow
372-
passdb {
373-
driver = static
374-
args = allow_real_nets=${IPV4_NETWORK}.248/32 password={plain}${RAND_PASS}
375-
}
376-
EOF
377253

378254
if [[ "${MASTER}" =~ ^([nN][oO]|[nN])+$ ]]; then
379255
# Toggling MASTER will result in a rebuild of containers, so the quota script will be recreated
@@ -409,8 +285,8 @@ sievec /usr/lib/dovecot/sieve/report-ham.sieve
409285

410286
# Fix permissions
411287
chown root:root /etc/dovecot/sql/*.conf
412-
chown root:dovecot /etc/dovecot/sql/dovecot-dict-sql-sieve* /etc/dovecot/sql/dovecot-dict-sql-quota* /etc/dovecot/lua/passwd-verify.lua
413-
chmod 640 /etc/dovecot/sql/*.conf /etc/dovecot/lua/passwd-verify.lua
288+
chown root:dovecot /etc/dovecot/sql/dovecot-dict-sql-sieve* /etc/dovecot/sql/dovecot-dict-sql-quota* /etc/dovecot/auth/passwd-verify.lua
289+
chmod 640 /etc/dovecot/sql/*.conf /etc/dovecot/auth/passwd-verify.lua
414290
chown -R vmail:vmail /var/vmail/sieve
415291
chown -R vmail:vmail /var/volatile
416292
chown -R vmail:vmail /var/vmail_index
@@ -480,7 +356,7 @@ done
480356

481357
# For some strange, unknown and stupid reason, Dovecot may run into a race condition, when this file is not touched before it is read by dovecot/auth
482358
# May be related to something inside Docker, I seriously don't know
483-
touch /etc/dovecot/lua/passwd-verify.lua
359+
touch /etc/dovecot/auth/passwd-verify.lua
484360

485361
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
486362
cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf

data/Dockerfiles/dovecot/trim_logs.sh

+1
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ catch_non_zero "${REDIS_CMDLINE} LTRIM AUTODISCOVER_LOG 0 ${LOG_LINES}"
2323
catch_non_zero "${REDIS_CMDLINE} LTRIM API_LOG 0 ${LOG_LINES}"
2424
catch_non_zero "${REDIS_CMDLINE} LTRIM RL_LOG 0 ${LOG_LINES}"
2525
catch_non_zero "${REDIS_CMDLINE} LTRIM WATCHDOG_LOG 0 ${LOG_LINES}"
26+
catch_non_zero "${REDIS_CMDLINE} LTRIM CRON_LOG 0 ${LOG_LINES}"

data/Dockerfiles/rspamd/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ARG RSPAMD_VER=rspamd_3.9.1-1~82f43560f
66
ARG CODENAME=bookworm
77
ENV LC_ALL=C
88

9-
RUN apt-get update && apt-get install -y \
9+
RUN apt-get update && apt-get install -y --no-install-recommends \
1010
tzdata \
1111
ca-certificates \
1212
gnupg2 \

data/Dockerfiles/sogo/bootstrap-sogo.sh

+1-105
Original file line numberDiff line numberDiff line change
@@ -24,110 +24,6 @@ while [[ "${DBV_NOW}" != "${DBV_NEW}" ]]; do
2424
done
2525
echo "DB schema is ${DBV_NOW}"
2626

27-
# Recreate view
28-
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
29-
echo "We are master, preparing sogo_view..."
30-
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
31-
while [[ ${VIEW_OK} != 'OK' ]]; do
32-
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
33-
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) AS
34-
SELECT
35-
mailbox.username,
36-
mailbox.domain,
37-
mailbox.username,
38-
IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) = '0', IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.sogo_access')) = 1, password, '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'), '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'),
39-
mailbox.name,
40-
mailbox.username,
41-
IFNULL(GROUP_CONCAT(ga.aliases ORDER BY ga.aliases SEPARATOR ' '), ''),
42-
IFNULL(gda.ad_alias, ''),
43-
IFNULL(external_acl.send_as_acl, ''),
44-
mailbox.kind,
45-
mailbox.multiple_bookings
46-
FROM
47-
mailbox
48-
LEFT OUTER JOIN
49-
grouped_mail_aliases ga
50-
ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
51-
LEFT OUTER JOIN
52-
grouped_domain_alias_address gda
53-
ON gda.username = mailbox.username
54-
LEFT OUTER JOIN
55-
grouped_sender_acl_external external_acl
56-
ON external_acl.username = mailbox.username
57-
WHERE
58-
mailbox.active = '1'
59-
GROUP BY
60-
mailbox.username;
61-
EOF
62-
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
63-
VIEW_OK=OK
64-
else
65-
echo "Will retry to setup SOGo view in 3s..."
66-
sleep 3
67-
fi
68-
done
69-
else
70-
while [[ ${VIEW_OK} != 'OK' ]]; do
71-
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
72-
VIEW_OK=OK
73-
else
74-
echo "Waiting for SOGo view to be created by master..."
75-
sleep 3
76-
fi
77-
done
78-
fi
79-
80-
# Wait for static view table if missing after update and update content
81-
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
82-
echo "We are master, preparing _sogo_static_view..."
83-
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
84-
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
85-
STATIC_VIEW_OK=OK
86-
echo "Updating _sogo_static_view content..."
87-
# If changed, also update init_db.inc.php
88-
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) SELECT c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings from sogo_view;"
89-
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')"
90-
else
91-
echo "Waiting for database initialization..."
92-
sleep 3
93-
fi
94-
done
95-
else
96-
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
97-
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
98-
STATIC_VIEW_OK=OK
99-
else
100-
echo "Waiting for database initialization by master..."
101-
sleep 3
102-
fi
103-
done
104-
fi
105-
106-
107-
# Recreate password update trigger
108-
if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
109-
echo "We are master, preparing update trigger..."
110-
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password"
111-
while [[ ${TRIGGER_OK} != 'OK' ]]; do
112-
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
113-
DELIMITER -
114-
CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view
115-
FOR EACH ROW
116-
BEGIN
117-
UPDATE mailbox SET password = NEW.c_password WHERE NEW.c_uid = username;
118-
END;
119-
-
120-
DELIMITER ;
121-
EOF
122-
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'sogo_update_password'") ]]; then
123-
TRIGGER_OK=OK
124-
else
125-
echo "Will retry to setup SOGo password update trigger in 3s"
126-
sleep 3
127-
fi
128-
done
129-
fi
130-
13127
# cat /dev/urandom seems to hang here occasionally and is not recommended anyway, better use openssl
13228
RAND_PASS=$(openssl rand -base64 16 | tr -dc _A-Z-a-z-0-9)
13329

@@ -213,7 +109,7 @@ while read -r line gal
213109
</dict>" >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
214110
# Generate alternative LDAP authentication dict, when SQL authentication fails
215111
# This will nevertheless read attributes from LDAP
216-
line=${line} envsubst < /etc/sogo/plist_ldap >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
112+
/etc/sogo/plist_ldap.sh ${line} ${gal} >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
217113
echo " </array>
218114
</dict>" >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
219115
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain, CASE gal WHEN '1' THEN 'YES' ELSE 'NO' END AS gal FROM domain;" -B -N)

data/Dockerfiles/solr/Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
FROM solr:7.7-slim
2+
LABEL maintainer "The Infrastructure Company GmbH <[email protected]>"
23

34
USER root
45

0 commit comments

Comments
 (0)