1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2024-12-21 01:49:22 +02:00

Add ECDSA support

This is a squashed commit of the following:

commit db8051bc234c5fa67aa87a7a94f9e89eaf0e7dac
Merge: 2634fdf0 04020685
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Tue May 24 20:44:38 2022 +0200

    Merge branch 'master' into add-ecdsa-support

commit 2634fdf0e942c50220d6ea22319610327bd4127e
Merge: 0962b90d 116c7919
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Wed Nov 10 08:53:21 2021 +0100

    Merge branch 'master' into add-ecdsa-support

commit 0962b90db51586b30a20d8c5310c1b09dbfe96e3
Merge: 61522713 d90d4f96
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Wed Jun 9 11:33:34 2021 +0200

    Merge branch 'master' into add-ecdsa-support

commit 61522713f1916ac8062fd7b717984d142a395c26
Merge: 72261e60 64264767
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Fri Feb 26 18:20:30 2021 +0100

    Merge branch 'master' into add-ecdsa-support

commit 72261e60f0c147287fb312c51982030f69674e6a
Merge: 3a1cce21 0846013e
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Wed Dec 16 21:33:55 2020 +0100

    Merge branch 'master' into add-ecdsa-support

commit 3a1cce2105b377410a4c4aff00d44db7fea76e85
Merge: 6a01796e c1034b89
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Tue Sep 15 10:51:32 2020 +0200

    Merge branch 'master' into add-ecdsa-support

commit 6a01796e7ecbae78b89a2067080886bb59a394a1
Merge: 812adb0f 9685b4b5
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Tue Jul 21 14:07:56 2020 +0200

    Merge branch 'master' into add-ecdsa-support

commit 812adb0fe1bdb5d5d832bcaf09c2c8543c71914b
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sun Jul 5 00:12:21 2020 +0200

    Fix TLSA records for ECDSA and RSA certs in DNS diagnostics

    Disables TLS 1.3 for the test connection to limit to RSA or ECDSA ciphers.

commit 83c976999bf1da178ed9363f79ff772f9bffab93
Merge: 6fb29ab5 becc5059
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sat Jul 4 23:03:45 2020 +0200

    Merge branch 'master' into add-ecdsa-support

commit 6fb29ab554e55bac17fa3087da4580d224e95e6f
Merge: 3131e171 b933a309
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu May 21 11:34:30 2020 +0200

    Merge branch 'master' into add-ecdsa-support

commit 3131e1717f48488a81979206df6d67e6f55c10a7
Merge: 1929216e 7fa10cc3
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Apr 16 18:20:39 2020 +0200

    Merge branch 'master' into add-ecdsa-support

commit 1929216e6a8eff0a110bfc28425987c548e12fa0
Merge: a0edf841 a9947e99
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sat Mar 21 08:38:07 2020 +0100

    Merge branch 'master' into add-ecdsa-support

commit a0edf841427b093b03597ba231e5c6b228c0ee60
Merge: 6152b426 b5c844d7
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Feb 13 13:52:09 2020 +0100

    Merge branch 'master' into add-ecdsa-support

commit 6152b42616cfa9df483dee6047fdca2517b1b245
Merge: 85b791bf e6bb3069
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Wed Jan 15 10:14:18 2020 +0100

    Merge branch 'master' into add-ecdsa-support

commit 85b791bf07391217a1c00d957b6eb8eff091a7b0
Merge: c2339931 ff74b8aa
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Tue Dec 17 15:21:10 2019 +0100

    Merge branch 'master' into add-ecdsa-support

commit c2339931c5c8ec646e1ae8ebc148b75f06c904dc
Merge: eee0238b 4e8b2bfc
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sat Dec 7 17:17:05 2019 +0100

    Merge branch 'master' into add-ecdsa-support

commit eee0238b6b9c97bcfae2b4183ade3575d0b97563
Merge: 9e1ff332 1d1a9a27
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Fri Nov 8 12:53:51 2019 +0100

    Merge branch 'master' into add-ecdsa-support

commit 9e1ff332d163c9c2a9140bbe7388021a930dc759
Merge: ab164253 ea4da60c
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Fri Nov 1 16:06:41 2019 +0100

    Merge branch 'master' into add-ecdsa-support

commit ab164253306e6bf696ef1cbf2235f2de3f05e9f5
Merge: c0499263 573e62f1
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Oct 31 13:57:01 2019 +0100

    Merge branch 'master' into add-ecdsa-support

commit c0499263455d49a807ff4d79b9d439dfd8e66137
Merge: 6a6d6c4a c4316150
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Oct 31 13:55:28 2019 +0100

    Merge pull request #1 from mhofer117/tls-sni-ecdsa

    Change line endings in functions.inc.php back to CRLF

commit c43161507bcb48750b865a657e6fe80c02812c83
Author: Marcel Hofer <m.hofer117@gmail.com>
Date:   Sun Oct 20 19:02:17 2019 +0200

    remove empty docker-entrypoint.sh

commit efd6cd1847f718900be72d20fa6361fda975bf1c
Merge: a2a0821a 6a6d6c4a
Author: Marcel Hofer <m.hofer117@gmail.com>
Date:   Sun Oct 20 19:00:07 2019 +0200

    Merge remote-tracking branch 'OpenLarry/add-ecdsa-support' into tls-sni-ecdsa

    # Conflicts:
    #	data/Dockerfiles/acme/docker-entrypoint.sh
    #	data/conf/dovecot/dovecot.conf
    #	data/conf/nginx/site.conf
    #	data/conf/postfix/main.cf
    #	data/web/inc/ajax/dns_diagnostics.php
    #	data/web/inc/functions.inc.php
    #	docker-compose.yml
    #	generate_config.sh
    #	update.sh

commit a2a0821a38a55cb99ba1dd32383344ed6504f451
Merge: 4a62809d 05e7c958
Author: Marcel Hofer <m.hofer117@gmail.com>
Date:   Sun Oct 20 18:50:16 2019 +0200

    Merge branch 'tls-sni' into tls-sni-ecdsa

commit 4a62809d33d1ef88c09f89cf1168a1f01f578e6f
Author: Marcel Hofer <m.hofer117@gmail.com>
Date:   Sat Oct 19 13:04:02 2019 +0200

    [SSL] add optional ecdsa certs in addition to rsa certs

commit 6a6d6c4a604cb5d310308e1adf1b709febe2460d
Merge: 351abd29 9f66b83a
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Tue Oct 1 11:01:28 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit 351abd29b2f41f97a57681dccb042d9c2321498d
Merge: eddb2693 04853794
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Mon Sep 9 17:40:47 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit eddb26938d04dee6e2dd29ab65a3fefd1d07732d
Merge: 9d13ead4 6e82a359
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Aug 29 11:36:03 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit 9d13ead450239a1408937e85aeed36afdd48631e
Merge: 478c4d1f f21cf134
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Aug 8 13:22:58 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit 478c4d1f6364d60e58205656e8d0dd784ce0f088
Merge: 46dbf3bc 7665cc2a
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Thu Jun 27 14:49:09 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit 46dbf3bc5e454b7bf74d1886f42e73b7d5b46d7b
Merge: 680a2726 69fb7f7a
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Fri May 31 12:33:32 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit 680a272664c451323dbc58f7dcbe17f96d387f1c
Merge: f69559f0 b20ff13e
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Tue May 7 12:29:34 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit f69559f03bd25752c2c526c1ac1b475a02508377
Merge: 3e8a9583 cd881652
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Mon Apr 15 12:55:41 2019 +0200

    Merge branch 'master' into add-ecdsa-support

commit 3e8a9583826d8e413e3f21c12fef0e116ad11b54
Merge: 956a487f 4aae7277
Author: Aaron <OpenLarry@users.noreply.github.com>
Date:   Mon Mar 18 16:52:37 2019 +0100

    Merge branch 'master' into add-ecdsa-support

commit 956a487f822580314186de7b0332e7f8ffaf289f
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sun Mar 17 12:34:56 2019 +0100

    Set SKIP_ECDSA_CERT to y by default

commit 7103fe7e89b8ba8d45d59e65a6823c7c160565c4
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sun Mar 17 11:05:05 2019 +0100

    Add SKIP_ECDSA_CERT config parameter

commit 91fca4fa3835f146571d9e5546c37fceffec2a42
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sat Mar 16 18:48:28 2019 +0100

    Show TLSA records for ECDSA certificates in DNS diagnostics

commit cc521b02501f03f692686f3dedc43339b342aa96
Author: Aaron Larisch <aaron-github@openlarry.de>
Date:   Sat Mar 16 13:04:03 2019 +0100

    Add ECDSA support

Co-authored-by: Marcel Hofer <m.hofer117@gmail.com>
This commit is contained in:
Aaron Larisch 2022-05-24 20:52:20 +02:00
parent deb6f0babc
commit dbfeed5c3a
14 changed files with 181 additions and 22 deletions

View File

@ -44,6 +44,17 @@ if [[ "${SKIP_LETS_ENCRYPT}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
exec $(readlink -f "$0")
fi
if [[ "${SKIP_ECDSA_CERT}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
SKIP_ECDSA_CERT=y
fi
ACME_BASE=/var/lib/acme
SSL_EXAMPLE=/var/lib/ssl-example
# Symlink ECDSA to RSA certificate if not present
[[ ! -f ${ACME_BASE}/ecdsa-cert.pem ]] && [[ ! -L ${ACME_BASE}/ecdsa-cert.pem ]] && ln -s cert.pem ${ACME_BASE}/ecdsa-cert.pem
[[ ! -f ${ACME_BASE}/ecdsa-key.pem ]] && [[ ! -L ${ACME_BASE}/ecdsa-key.pem ]] && ln -s key.pem ${ACME_BASE}/ecdsa-key.pem
log_f "Waiting for Docker API..."
until ping dockerapi -c1 > /dev/null; do
sleep 1
@ -62,9 +73,6 @@ until ping dovecot -c1 > /dev/null; do
done
log_f "Dovecot OK"
ACME_BASE=/var/lib/acme
SSL_EXAMPLE=/var/lib/ssl-example
mkdir -p ${ACME_BASE}/acme
# Migrate
@ -92,6 +100,18 @@ if [[ -f ${ACME_BASE}/cert.pem ]] && [[ -f ${ACME_BASE}/key.pem ]] && [[ $(stat
ISSUER=$(openssl x509 -in ${ACME_BASE}/cert.pem -noout -issuer)
if [[ ${ISSUER} != *"Let's Encrypt"* && ${ISSUER} != *"mailcow"* && ${ISSUER} != *"Fake LE Intermediate"* ]]; then
log_f "Found certificate with issuer other than mailcow snake-oil CA and Let's Encrypt, skipping ACME client..."
# Make sure we do not combine Letsencrypt ECDSA with another RSA certificate
# Remove ECDSA if that is the case
if [[ -f ${ACME_BASE}/ecdsa-cert.pem ]] && [[ -f ${ACME_BASE}/ecdsa-key.pem ]] && [[ ! -L ${ACME_BASE}/ecdsa-cert.pem ]] && [[ ! -L ${ACME_BASE}/ecdsa-key.pem ]]; then
ISSUER=$(openssl x509 -in ${ACME_BASE}/ecdsa-cert.pem -noout -issuer)
if [[ ${ISSUER} == *"Let's Encrypt"* || ${ISSUER} == *"mailcow"* || ${ISSUER} == *"Fake LE Intermediate"* ]]; then
log_f "Remove Let's Encrypt ECDSA certificate in favour of a custom RSA one"
ln -sf cert.pem ${ACME_BASE}/ecdsa-cert.pem
ln -sf key.pem ${ACME_BASE}/ecdsa-key.pem
fi
fi
sleep 3650d
exec $(readlink -f "$0")
fi
@ -100,17 +120,27 @@ else
log_f "Restoring previous acme certificate and restarting script..."
cp ${ACME_BASE}/${MAILCOW_HOSTNAME}/cert.pem ${ACME_BASE}/cert.pem
cp ${ACME_BASE}/${MAILCOW_HOSTNAME}/key.pem ${ACME_BASE}/key.pem
if [[ -f ${ACME_BASE}/${MAILCOW_HOSTNAME}/ecdsa-cert.pem ]] && [[ -f ${ACME_BASE}/${MAILCOW_HOSTNAME}/ecdsa-key.pem ]] && verify_hash_match ${ACME_BASE}/${MAILCOW_HOSTNAME}/ecdsa-cert.pem ${ACME_BASE}/${MAILCOW_HOSTNAME}/ecdsa-key.pem; then
# Remove symlink before copying
cp --remove-destination ${ACME_BASE}/${MAILCOW_HOSTNAME}/ecdsa-cert.pem ${ACME_BASE}/ecdsa-cert.pem
cp --remove-destination ${ACME_BASE}/${MAILCOW_HOSTNAME}/ecdsa-key.pem ${ACME_BASE}/ecdsa-key.pem
fi
# Restarting with env var set to trigger a restart,
exec env TRIGGER_RESTART=1 $(readlink -f "$0")
else
ISSUER="mailcow"
log_f "Restoring mailcow snake-oil certificates and restarting script..."
cp ${SSL_EXAMPLE}/cert.pem ${ACME_BASE}/cert.pem
cp ${SSL_EXAMPLE}/key.pem ${ACME_BASE}/key.pem
ln -sf cert.pem ${ACME_BASE}/ecdsa-cert.pem
ln -sf key.pem ${ACME_BASE}/ecdsa-key.pem
exec env TRIGGER_RESTART=1 $(readlink -f "$0")
fi
fi
chmod 600 ${ACME_BASE}/key.pem
chmod 600 ${ACME_BASE}/ecdsa-key.pem
log_f "Waiting for database..."
while ! mysqladmin status --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent > /dev/null; do
@ -142,10 +172,14 @@ log_f "OK" no_date
log_f "Initializing, please wait..."
while true; do
POSTFIX_CERT_SERIAL="$(echo | openssl s_client -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL="$(echo | openssl s_client -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL_NEW="$(echo | openssl s_client -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_NEW="$(echo | openssl s_client -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL="$(echo | openssl s_client -tls1_2 -cipher 'aRSA' -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL="$(echo | openssl s_client -tls1_2 -cipher 'aRSA' -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL_ECDSA="$(echo | openssl s_client -tls1_2 -cipher 'aECDSA' -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_ECDSA="$(echo | openssl s_client -tls1_2 -cipher 'aECDSA' -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL_NEW="$(echo | openssl s_client -tls1_2 -cipher 'aRSA' -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_NEW="$(echo | openssl s_client -tls1_2 -cipher 'aRSA' -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL_NEW_ECDSA="$(echo | openssl s_client -tls1_2 -cipher 'aECDSA' -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_NEW_ECDSA="$(echo | openssl s_client -tls1_2 -cipher 'aECDSA' -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
# Re-using previous acme-mailcow account and domain keys
if [[ ! -f ${ACME_BASE}/acme/key.pem ]]; then
log_f "Generating missing domain private rsa key..."
@ -153,6 +187,12 @@ while true; do
else
log_f "Using existing domain rsa key ${ACME_BASE}/acme/key.pem"
fi
if [[ ! -f ${ACME_BASE}/acme/ecdsa-key.pem ]]; then
log_f "Generating missing domain private ecdsa key..."
openssl ecparam -genkey -name secp384r1 -noout > ${ACME_BASE}/acme/ecdsa-key.pem
else
log_f "Using existing domain ecdsa key ${ACME_BASE}/acme/ecdsa-key.pem"
fi
if [[ ! -f ${ACME_BASE}/acme/account.pem ]]; then
log_f "Generating missing Lets Encrypt account key..."
if [[ ! -z ${ACME_CONTACT} ]]; then
@ -173,6 +213,7 @@ while true; do
fi
chmod 600 ${ACME_BASE}/acme/key.pem
chmod 600 ${ACME_BASE}/acme/ecdsa-key.pem
chmod 600 ${ACME_BASE}/acme/account.pem
unset EXISTING_CERTS
@ -309,6 +350,24 @@ while true; do
cp ${ACME_BASE}/${CERT_NAME}/cert.pem ${ACME_BASE}/cert.pem
cp ${ACME_BASE}/${CERT_NAME}/key.pem ${ACME_BASE}/key.pem
fi
if [[ "${SKIP_ECDSA_CERT}" != "y" ]]; then
DOMAINS=${SERVER_SAN_VALIDATED[@]} /srv/obtain-certificate.sh ecdsa
RETURN="$?"
if [[ "$RETURN" == "0" ]]; then # 0 = cert created successfully
CERT_AMOUNT_CHANGED=1
CERT_CHANGED=1
elif [[ "$RETURN" == "1" ]]; then # 1 = cert renewed successfully
CERT_CHANGED=1
elif [[ "$RETURN" == "2" ]]; then # 2 = cert not due for renewal
:
else
CERT_ERRORS=1
fi
# create relative symbolic link as server certificate
ln -sf ${CERT_NAME}/ecdsa-cert.pem ${ACME_BASE}/ecdsa-cert.pem
ln -sf ${CERT_NAME}/ecdsa-key.pem ${ACME_BASE}/ecdsa-key.pem
fi
fi
# individual certificates for SNI [@]
@ -345,6 +404,21 @@ while true; do
else
CERT_ERRORS=1
fi
if [[ "${SKIP_ECDSA_CERT}" != "y" ]]; then
DOMAINS=${VALIDATED_DOMAINS_SORTED[@]} /srv/obtain-certificate.sh ecdsa
RETURN="$?"
if [[ "$RETURN" == "0" ]]; then # 0 = cert created successfully
CERT_AMOUNT_CHANGED=1
CERT_CHANGED=1
elif [[ "$RETURN" == "1" ]]; then # 1 = cert renewed successfully
CERT_CHANGED=1
elif [[ "$RETURN" == "2" ]]; then # 2 = cert not due for renewal
:
else
CERT_ERRORS=1
fi
fi
fi
done
fi
@ -364,9 +438,19 @@ while true; do
DATE=$(date +%Y-%m-%d_%H_%M_%S)
log_f "Found orphaned certificate: ${EXISTING_CERT} - archiving it at ${ACME_BASE}/backups/${EXISTING_CERT}/"
BACKUP_DIR=${ACME_BASE}/backups/${EXISTING_CERT}/${DATE}
BACKUP_DIR_ECDSA=${ACME_BASE}/backups/${EXISTING_CERT}/ecdsa-${DATE}
# archive ecdsa cert (if exists)
mkdir -p ${BACKUP_DIR_ECDSA}/
[[ -f ${ACME_BASE}/${EXISTING_CERT}/ecdsa-cert.pem && -f ${ACME_BASE}/${EXISTING_CERT}/domains ]] && cp ${ACME_BASE}/${EXISTING_CERT}/domains ${BACKUP_DIR_ECDSA}/
[[ -f ${ACME_BASE}/${EXISTING_CERT}/ecdsa-cert.pem ]] && mv ${ACME_BASE}/${EXISTING_CERT}/ecdsa-cert.pem ${BACKUP_DIR_ECDSA}/
[[ -f ${ACME_BASE}/${EXISTING_CERT}/ecdsa-key.pem ]] && mv ${ACME_BASE}/${EXISTING_CERT}/ecdsa-key.pem ${BACKUP_DIR_ECDSA}/
[[ -f ${ACME_BASE}/${EXISTING_CERT}/ecdsa-acme.csr ]] && mv ${ACME_BASE}/${EXISTING_CERT}/ecdsa-acme.csr ${BACKUP_DIR_ECDSA}/
# archive rsa cert and any other files
mkdir -p ${ACME_BASE}/backups/${EXISTING_CERT}
mv ${ACME_BASE}/${EXISTING_CERT} ${BACKUP_DIR}
CERT_CHANGED=1
CERT_AMOUNT_CHANGED=1
fi
@ -377,7 +461,7 @@ while true; do
if [[ "${CERT_CHANGED}" == "1" ]]; then
rm -f "${ACME_BASE}/force_renew" 2> /dev/null
RELOAD_LOOP_C=1
while [[ "${POSTFIX_CERT_SERIAL}" == "${POSTFIX_CERT_SERIAL_NEW}" ]] || [[ "${DOVECOT_CERT_SERIAL}" == "${DOVECOT_CERT_SERIAL_NEW}" ]] || [[ ${#POSTFIX_CERT_SERIAL_NEW} -ne 36 ]] || [[ ${#DOVECOT_CERT_SERIAL_NEW} -ne 36 ]]; do
while [[ "${POSTFIX_CERT_SERIAL}" == "${POSTFIX_CERT_SERIAL_NEW}" ]] || [[ "${DOVECOT_CERT_SERIAL}" == "${DOVECOT_CERT_SERIAL_NEW}" ]] || [[ "${POSTFIX_CERT_SERIAL_ECDSA}" == "${POSTFIX_CERT_SERIAL_NEW_ECDSA}" ]] || [[ "${DOVECOT_CERT_SERIAL_ECDSA}" == "${DOVECOT_CERT_SERIAL_NEW_ECDSA}" ]] || [[ ${#POSTFIX_CERT_SERIAL_NEW} -ne 36 ]] || [[ ${#DOVECOT_CERT_SERIAL_NEW} -ne 36 ]] || [[ ${#POSTFIX_CERT_SERIAL_NEW_ECDSA} -ne 36 ]] || [[ ${#DOVECOT_CERT_SERIAL_NEW_ECDSA} -ne 36 ]]; do
log_f "Reloading or restarting services... (${RELOAD_LOOP_C})"
RELOAD_LOOP_C=$((RELOAD_LOOP_C + 1))
CERT_AMOUNT_CHANGED=${CERT_AMOUNT_CHANGED} /srv/reload-configurations.sh
@ -389,8 +473,10 @@ while true; do
until nc -z postfix 25; do
sleep 1
done
POSTFIX_CERT_SERIAL_NEW="$(echo | openssl s_client -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_NEW="$(echo | openssl s_client -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL_NEW="$(echo | openssl s_client -tls1_2 -cipher 'aRSA' -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_NEW="$(echo | openssl s_client -tls1_2 -cipher 'aRSA' -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
POSTFIX_CERT_SERIAL_NEW_ECDSA="$(echo | openssl s_client -tls1_2 -cipher 'aECDSA' -connect postfix:25 -starttls smtp 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
DOVECOT_CERT_SERIAL_NEW_ECDSA="$(echo | openssl s_client -tls1_2 -cipher 'aECDSA' -connect dovecot:143 -starttls imap 2>/dev/null | openssl x509 -inform pem -noout -serial | cut -d "=" -f 2)"
if [[ ${RELOAD_LOOP_C} -gt 3 ]]; then
log_f "Some services do return old end dates, something went wrong!"
${REDIS_CMDLINE} SET ACME_FAIL_TIME "$(date +%s)"

View File

@ -15,8 +15,9 @@ ACME_BASE=/var/lib/acme
TYPE=${1}
PREFIX=""
# only support rsa certificates for now
if [[ "${TYPE}" != "rsa" ]]; then
if [[ "${TYPE}" == "ecdsa" ]]; then
PREFIX="ecdsa-"
elif [[ "${TYPE}" != "rsa" ]]; then
log_f "Unknown certificate type '${TYPE}' requested"
exit 5
fi

View File

@ -274,6 +274,13 @@ for cert_dir in /etc/ssl/mail/*/ ; do
echo 'local_name '${domain}' {' >> /etc/dovecot/sni.conf;
echo ' ssl_cert = <'${cert_dir}'cert.pem' >> /etc/dovecot/sni.conf;
echo ' ssl_key = <'${cert_dir}'key.pem' >> /etc/dovecot/sni.conf;
if [[ -f ${cert_dir}ecdsa-cert.pem && -f ${cert_dir}ecdsa-key.pem ]]; then
echo ' ssl_alt_cert = <'${cert_dir}'ecdsa-cert.pem' >> /etc/dovecot/sni.conf;
echo ' ssl_alt_key = <'${cert_dir}'ecdsa-key.pem' >> /etc/dovecot/sni.conf;
else
echo ' ssl_alt_cert = <'${cert_dir}'cert.pem' >> /etc/dovecot/sni.conf;
echo ' ssl_alt_key = <'${cert_dir}'key.pem' >> /etc/dovecot/sni.conf;
fi
echo '}' >> /etc/dovecot/sni.conf;
done
done

View File

@ -36,6 +36,9 @@ else
IFS=" " read -r -a domains <<< "$(cat "${cert_dir}domains")"
for domain in "${domains[@]}"; do
echo -n "${domain} ${cert_dir}key.pem ${cert_dir}cert.pem" >> /opt/postfix/conf/sni.map;
if [[ -f ${cert_dir}ecdsa-cert.pem && -f ${cert_dir}ecdsa-key.pem ]]; then
echo -n " ${cert_dir}ecdsa-key.pem ${cert_dir}ecdsa-cert.pem" >> /opt/postfix/conf/sni.map;
fi
echo "" >> /opt/postfix/conf/sni.map;
done
done

View File

@ -0,0 +1 @@
cert.pem

View File

@ -0,0 +1 @@
key.pem

View File

@ -167,6 +167,8 @@ service lmtp {
listen = *,[::]
ssl_cert = </etc/ssl/mail/cert.pem
ssl_key = </etc/ssl/mail/key.pem
ssl_alt_cert = </etc/ssl/mail/ecdsa-cert.pem
ssl_alt_key = </etc/ssl/mail/ecdsa-key.pem
userdb {
driver = passwd-file
args = /etc/dovecot/dovecot-master.userdb

View File

@ -6,6 +6,8 @@ server {
ssl_certificate /etc/ssl/mail/cert.pem;
ssl_certificate_key /etc/ssl/mail/key.pem;
ssl_certificate /etc/ssl/mail/ecdsa-cert.pem;
ssl_certificate_key /etc/ssl/mail/ecdsa-key.pem;
include /etc/nginx/conf.d/server_name.active;
@ -29,6 +31,12 @@ server {
ssl_certificate '${cert_dir}'cert.pem;
ssl_certificate_key '${cert_dir}'key.pem;
';
if [[ -f ${cert_dir}ecdsa-cert.pem && -f ${cert_dir}ecdsa-key.pem ]]; then
echo -n '
ssl_certificate '${cert_dir}'ecdsa-cert.pem;
ssl_certificate_key '${cert_dir}'ecdsa-key.pem;
';
fi
echo -n '
server_name '${domains}';

View File

@ -5,6 +5,8 @@ biff = no
append_dot_mydomain = no
smtpd_tls_cert_file = /etc/ssl/mail/cert.pem
smtpd_tls_key_file = /etc/ssl/mail/key.pem
smtpd_tls_eccert_file = /etc/ssl/mail/ecdsa-cert.pem
smtpd_tls_eckey_file = /etc/ssl/mail/ecdsa-key.pem
tls_server_sni_maps = hash:/opt/postfix/conf/sni.map
smtpd_tls_received_header = yes
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache

View File

@ -97,11 +97,22 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
$mailcow_hostname
);
}
$records[] = array(
'_25._tcp.' . $autodiscover_config['smtp']['server'],
'TLSA',
generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1)
);
$digest = generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1, 'aRSA');
if($digest !== false) {
$records[] = array(
'_25._tcp.' . $autodiscover_config['smtp']['server'],
'TLSA',
$digest
);
}
$digest = generate_tlsa_digest($autodiscover_config['smtp']['server'], 25, 1, 'aECDSA');
if($digest !== false) {
$records[] = array(
'_25._tcp.' . $autodiscover_config['smtp']['server'],
'TLSA',
$digest
);
}
}
$records[] = array(
@ -340,7 +351,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
}
}
foreach ($currents as &$current) {
foreach ($currents as $i => &$current) {
if ($current['type'] == 'TXT' &&
stripos($current['txt'], 'v=dmarc') === 0 &&
$record[2] == $dmarc_link) {
@ -368,6 +379,21 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
}
elseif ($current['type'] != 'TXT' &&
isset($data_field[$current['type']]) && $state != state_good) {
// Ignore $current TLSA record if it already matches another one in $records.
// E.g. hide found TLSA records for an RSA certificate in the status column
// of missing TLSA records for an ECDSA certificate.
if($current['type'] == 'TLSA' && $record[1] == 'TLSA') {
foreach($records as $other_record) {
if($record != $other_record &&
$other_record[1] == 'TLSA' &&
$other_record[0] == $current['host'] &&
$other_record[2] == $current[$data_field[$current['type']]]) {
unset($currents[$i]);
continue 2;
}
}
}
$state = state_nomatch;
if ($current[$data_field[$current['type']]] == $record[2]) {
$state = state_good;

View File

@ -629,13 +629,16 @@ function expand_ipv6($ip) {
$ip = substr(preg_replace("/([A-f0-9]{4})/", "$1:", $hex['hex']), 0, -1);
return $ip;
}
function generate_tlsa_digest($hostname, $port, $starttls = null) {
function generate_tlsa_digest($hostname, $port, $starttls = null, $ciphers = 'DEFAULT') {
if (!is_valid_domain_name($hostname)) {
return "Not a valid hostname";
}
if (empty($starttls)) {
$context = stream_context_create(array("ssl" => array("capture_peer_cert" => true, 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)));
$stream = stream_socket_client('ssl://' . $hostname . ':' . $port, $error_nr, $error_msg, 5, STREAM_CLIENT_CONNECT, $context);
$context = stream_context_create(array("ssl" => array("ciphers" => $ciphers, "capture_peer_cert" => true, 'verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true)));
$stream = stream_socket_client('tcp://' . $hostname . ':' . $port, $error_nr, $error_msg, 5, STREAM_CLIENT_CONNECT, $context);
if(stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT) === false) {
return false; // negotiation failed
}
if (!$stream) {
$error_msg = isset($error_msg) ? $error_msg : '-';
return $error_nr . ': ' . $error_msg;
@ -674,7 +677,10 @@ function generate_tlsa_digest($hostname, $port, $starttls = null) {
stream_context_set_option($stream, 'ssl', 'verify_peer', false);
stream_context_set_option($stream, 'ssl', 'verify_peer_name', false);
stream_context_set_option($stream, 'ssl', 'allow_self_signed', true);
stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_ANY_CLIENT);
stream_context_set_option($stream, 'ssl', 'ciphers', $ciphers);
if(stream_socket_enable_crypto($stream, true, STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT) === false) {
return false; // negotiation failed
}
stream_set_blocking($stream, false);
}
$params = stream_context_get_params($stream);

View File

@ -414,6 +414,7 @@ services:
- COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME:-mailcow-dockerized}
- DIRECTORY_URL=${DIRECTORY_URL:-}
- ENABLE_SSL_SNI=${ENABLE_SSL_SNI:-n}
- SKIP_ECDSA_CERT=${SKIP_ECDSA_CERT:-y}
- SKIP_IP_CHECK=${SKIP_IP_CHECK:-n}
- SKIP_HTTP_VERIFICATION=${SKIP_HTTP_VERIFICATION:-n}
- ONLY_MAILCOW_HOSTNAME=${ONLY_MAILCOW_HOSTNAME:-n}

View File

@ -355,6 +355,10 @@ SKIP_LETS_ENCRYPT=n
# see https://doc.dovecot.org/admin_manual/ssl/sni_support
ENABLE_SSL_SNI=n
# Skip issuing Let's Encrypt ECDSA certificates - y/n
SKIP_ECDSA_CERT=n
# Skip IPv4 check in ACME container - y/n
SKIP_IP_CHECK=n

View File

@ -468,6 +468,7 @@ CONFIG_ARRAY=(
"SOLR_HEAP"
"SKIP_SOLR"
"ENABLE_SSL_SNI"
"SKIP_ECDSA_CERT"
"ALLOW_ADMIN_EMAIL_LOGIN"
"SKIP_HTTP_VERIFICATION"
"SOGO_EXPIRE_SESSION"
@ -614,6 +615,16 @@ for option in ${CONFIG_ARRAY[@]}; do
echo '# see https://wiki.dovecot.org/SSL/SNIClientSupport' >> mailcow.conf
echo "ENABLE_SSL_SNI=n" >> mailcow.conf
fi
elif [[ ${option} == "SKIP_ECDSA_CERT" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo "# Skip issuing Let's Encrypt ECDSA certificates - y/n" >> mailcow.conf
echo "# ECDSA certificates are disabled by default after upgrading." >> mailcow.conf
echo "# This should only be enabled if either" >> mailcow.conf
echo "# * you haven't set any TLSA DNS records or" >> mailcow.conf
echo "# * you will add additional TLSA DNS records for the ECDSA certificate. (See domain's DNS config in Mailcow UI after enabling.)" >> mailcow.conf
echo "SKIP_ECDSA_CERT=y" >> mailcow.conf
fi
elif [[ ${option} == "SKIP_SOGO" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"