From dd2d691fc7becc8f23fa5674fc7d3dd401a4899d Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Wed, 16 Nov 2022 21:18:29 +0100 Subject: [PATCH 1/8] Replace opendkim with dkimpy --- api/mailinabox.yml | 4 +- management/dns_update.py | 53 ++++++++++++++-------- management/mail_log.py | 2 +- management/status_checks.py | 2 +- setup/dkim.sh | 88 +++++++++++++++++-------------------- setup/mail-postfix.sh | 6 ++- 6 files changed, 82 insertions(+), 73 deletions(-) diff --git a/api/mailinabox.yml b/api/mailinabox.yml index f3290fb91..2b45fbd18 100644 --- a/api/mailinabox.yml +++ b/api/mailinabox.yml @@ -1262,7 +1262,7 @@ paths: $ref: '#/components/schemas/MailUserAddResponse' example: | mail user added - updated DNS: OpenDKIM configuration + updated DNS: DKIM configuration 400: description: Bad request content: @@ -1863,7 +1863,7 @@ components: type: string example: | mail user added - updated DNS: OpenDKIM configuration + updated DNS: DKIM configuration description: | Mail user add response. diff --git a/management/dns_update.py b/management/dns_update.py index 2bfc104f2..f8c7edc8d 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -109,21 +109,22 @@ def do_dns_update(env, force=False): except: shell('check_call', ["/usr/sbin/service", "nsd", "restart"]) - # Write the OpenDKIM configuration tables for all of the mail domains. + # Write the DKIM configuration tables for all of the mail domains. from mailconfig import get_mail_domains - if write_opendkim_tables(get_mail_domains(env), env): - # Settings changed. Kick opendkim. - shell('check_call', ["/usr/sbin/service", "opendkim", "restart"]) + + if write_dkim_tables(get_mail_domains(env), env): + # Settings changed. Kick dkimpy. + shell('check_call', ["/usr/sbin/service", "dkimpy-milter", "restart"]) if len(updated_domains) == 0: # If this is the only thing that changed? - updated_domains.append("OpenDKIM configuration") + updated_domains.append("DKIM configuration") # Clear bind9's DNS cache so our own DNS resolver is up to date. # (ignore errors with trap=True) shell('check_call', ["/usr/sbin/rndc", "flush"], trap=True) if len(updated_domains) == 0: - # if nothing was updated (except maybe OpenDKIM's files), don't show any output + # if nothing was updated (except maybe DKIM's files), don't show any output return "" else: return "updated DNS: " + ",".join(updated_domains) + "\n" @@ -295,10 +296,18 @@ def has_rec(qname, rtype, prefix=None): if not has_rec(None, "TXT", prefix="v=spf1 "): records.append((None, "TXT", 'v=spf1 mx -all', "Recommended. Specifies that only the box is permitted to send @%s mail." % domain)) - # Append the DKIM TXT record to the zone as generated by OpenDKIM. + # Append the DKIM TXT record to the zone as generated by DKIMpy. # Skip if the user has set a DKIM record already. - opendkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/mail.txt') - with open(opendkim_record_file) as orf: + dkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-rsa.dns') + with open(dkim_record_file) as orf: + m = re.match(r'(\S+)\s+IN\s+TXT\s+\( ((?:"[^"]+"\s+)+)\)', orf.read(), re.S) + val = "".join(re.findall(r'"([^"]+)"', m.group(2))) + if not has_rec(m.group(1), "TXT", prefix="v=DKIM1; "): + records.append((m.group(1), "TXT", val, "Recommended. Provides a way for recipients to verify that this machine sent @%s mail." % domain)) + + # Also add a ed25519 DKIM record + dkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-ed25519.dns') + with open(dkim_record_file) as orf: m = re.match(r'(\S+)\s+IN\s+TXT\s+\( ((?:"[^"]+"\s+)+)\)', orf.read(), re.S) val = "".join(re.findall(r'"([^"]+)"', m.group(2))) if not has_rec(m.group(1), "TXT", prefix="v=DKIM1; "): @@ -760,14 +769,15 @@ def sign_zone(domain, zonefile, env): ######################################################################## -def write_opendkim_tables(domains, env): - # Append a record to OpenDKIM's KeyTable and SigningTable for each domain +def write_dkim_tables(domains, env): + # Append a record to DKIMpy's KeyTable and SigningTable for each domain # that we send mail from (zones and all subdomains). - opendkim_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/mail.private') + dkim_rsa_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-rsa.key') + dkim_ed_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-ed25519.key') - if not os.path.exists(opendkim_key_file): - # Looks like OpenDKIM is not installed. + if not os.path.exists(dkim_rsa_key_file) or not os.path.exists(dkim_ed_key_file): + # Looks like DKIMpy is not installed. return False config = { @@ -789,7 +799,12 @@ def write_opendkim_tables(domains, env): # signing domain must match the sender's From: domain. "KeyTable": "".join( - "{domain} {domain}:mail:{key_file}\n".format(domain=domain, key_file=opendkim_key_file) + "{domain} {domain}:box-rsa:{key_file}\n".format(domain=domain, key_file=dkim_rsa_key_file) + for domain in domains + ), + "KeyTableEd25519": + "".join( + "{domain} {domain}:box-ed25519:{key_file}\n".format(domain=domain, key_file=dkim_ed_key_file) for domain in domains ), } @@ -797,18 +812,18 @@ def write_opendkim_tables(domains, env): did_update = False for filename, content in config.items(): # Don't write the file if it doesn't need an update. - if os.path.exists("/etc/opendkim/" + filename): - with open("/etc/opendkim/" + filename) as f: + if os.path.exists("/etc/dkim/" + filename): + with open("/etc/dkim/" + filename) as f: if f.read() == content: continue # The contents needs to change. - with open("/etc/opendkim/" + filename, "w") as f: + with open("/etc/dkim/" + filename, "w") as f: f.write(content) did_update = True # Return whether the files changed. If they didn't change, there's - # no need to kick the opendkim process. + # no need to kick the dkimpy process. return did_update ######################################################################## diff --git a/management/mail_log.py b/management/mail_log.py index bdf757cc1..5fa278767 100755 --- a/management/mail_log.py +++ b/management/mail_log.py @@ -376,7 +376,7 @@ def scan_mail_log_line(line, collector): if SCAN_BLOCKED: scan_postfix_smtpd_line(date, log, collector) elif service in ("postfix/qmgr", "postfix/pickup", "postfix/cleanup", "postfix/scache", - "spampd", "postfix/anvil", "postfix/master", "opendkim", "postfix/lmtp", + "spampd", "postfix/anvil", "postfix/master", "dkimpy", "postfix/lmtp", "postfix/tlsmgr", "anvil"): # nothing to look at return True diff --git a/management/status_checks.py b/management/status_checks.py index 0d5554410..6f172eb45 100755 --- a/management/status_checks.py +++ b/management/status_checks.py @@ -28,7 +28,7 @@ def get_services(): { "name": "Dovecot LMTP LDA", "port": 10026, "public": False, }, { "name": "Postgrey", "port": 10023, "public": False, }, { "name": "Spamassassin", "port": 10025, "public": False, }, - { "name": "OpenDKIM", "port": 8891, "public": False, }, + { "name": "DKIMpy", "port": 8892, "public": False, }, { "name": "OpenDMARC", "port": 8893, "public": False, }, { "name": "Mail-in-a-Box Management Daemon", "port": 10222, "public": False, }, { "name": "SSH Login (ssh)", "port": get_ssh_port(), "public": True, }, diff --git a/setup/dkim.sh b/setup/dkim.sh index b2541a120..c9ba1e8bd 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -1,46 +1,43 @@ #!/bin/bash -# OpenDKIM +# DKIM # -------- # -# OpenDKIM provides a service that puts a DKIM signature on outbound mail. +# DKIMpy provides a service that puts a DKIM signature on outbound mail. # # The DNS configuration for DKIM is done in the management daemon. source setup/functions.sh # load our functions source /etc/mailinabox.conf # load global vars -# Install DKIM... -echo Installing OpenDKIM/OpenDMARC... -apt_install opendkim opendkim-tools opendmarc +# Remove openDKIM if present +apt-get purge -qq -y opendkim opendkim-tools + +# Install DKIMpy-Milter +echo Installing DKIMpy/OpenDMARC... +apt_install dkimpy-milter python3-dkim opendmarc # Make sure configuration directories exist. -mkdir -p /etc/opendkim; +mkdir -p /etc/dkim; mkdir -p $STORAGE_ROOT/mail/dkim # Used in InternalHosts and ExternalIgnoreList configuration directives. # Not quite sure why. -echo "127.0.0.1" > /etc/opendkim/TrustedHosts +echo "127.0.0.1" > /etc/dkim/TrustedHosts # We need to at least create these files, since we reference them later. -# Otherwise, opendkim startup will fail -touch /etc/opendkim/KeyTable -touch /etc/opendkim/SigningTable - -if grep -q "ExternalIgnoreList" /etc/opendkim.conf; then - true # already done #NODOC -else - # Add various configuration options to the end of `opendkim.conf`. - cat >> /etc/opendkim.conf << EOF; -Canonicalization relaxed/simple -MinimumKeyBits 1024 -ExternalIgnoreList refile:/etc/opendkim/TrustedHosts -InternalHosts refile:/etc/opendkim/TrustedHosts -KeyTable refile:/etc/opendkim/KeyTable -SigningTable refile:/etc/opendkim/SigningTable -Socket inet:8891@127.0.0.1 -RequireSafeKeys false -EOF -fi +touch /etc/dkim/KeyTable +touch /etc/dkim/SigningTable + +tools/editconf.py /etc/dkimpy-milter/dkimpy-milter.conf -s \ + "MacroList=daemon_name|ORIGINATING" \ + "MacroListVerify=daemon_name|VERIFYING" \ + "Canonicalization=relaxed/simple" \ + "MinimumKeyBits=1024" \ + "InternalHosts=refile:/etc/dkim/TrustedHosts" \ + "KeyTable=refile:/etc/dkim/KeyTable" \ + "KeyTableEd25519=refile:/etc/dkim/KeyTableEd25519" \ + "SigningTable=refile:/etc/dkim/SigningTable" \ + "Socket=inet:8892@127.0.0.1" # Create a new DKIM key. This creates mail.private and mail.txt # in $STORAGE_ROOT/mail/dkim. The former is the private key and @@ -48,16 +45,20 @@ fi # in our DNS setup. Note that the files are named after the # 'selector' of the key, which we can change later on to support # key rotation. -# -# A 1024-bit key is seen as a minimum standard by several providers -# such as Google. But they and others use a 2048 bit key, so we'll -# do the same. Keys beyond 2048 bits may exceed DNS record limits. -if [ ! -f "$STORAGE_ROOT/mail/dkim/mail.private" ]; then - opendkim-genkey -b 2048 -r -s mail -D $STORAGE_ROOT/mail/dkim +if [ ! -f "$STORAGE_ROOT/mail/dkim/box-rsa.key" ]; then + # All defaults are supposed to be ok, default key for rsa is 2048 bit + dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/box-rsa + dknewkey --ktype ed25519 $STORAGE_ROOT/mail/dkim/box-ed25519 + + # Force them into the format dns_update.py expects + sed -i 's/v=DKIM1;/box-rsa._domainkey IN TXT ( "v=DKIM1; s=email;/' $STORAGE_ROOT/mail/dkim/box-rsa.dns + echo '" )' >> $STORAGE_ROOT/mail/dkim/box-rsa.dns + sed -i 's/v=DKIM1;/box-ed25519._domainkey IN TXT ( "v=DKIM1; s=email;/' $STORAGE_ROOT/mail/dkim/box-ed25519.dns + echo '" )' >> $STORAGE_ROOT/mail/dkim/box-ed25519.dns fi -# Ensure files are owned by the opendkim user and are private otherwise. -chown -R opendkim:opendkim $STORAGE_ROOT/mail/dkim +# Ensure files are owned by the dkimpy-milter user and are private otherwise. +chown -R dkimpy-milter:dkimpy-milter $STORAGE_ROOT/mail/dkim chmod go-rwx $STORAGE_ROOT/mail/dkim tools/editconf.py /etc/opendmarc.conf -s \ @@ -88,29 +89,20 @@ tools/editconf.py /etc/opendmarc.conf -s \ tools/editconf.py /etc/opendmarc.conf -s \ "FailureReportsOnNone=true" -# AlwaysAddARHeader Adds an "Authentication-Results:" header field even to -# unsigned messages from domains with no "signs all" policy. The reported DKIM -# result will be "none" in such cases. Normally unsigned mail from non-strict -# domains does not cause the results header field to be added. This added header -# is used by spamassassin to evaluate the mail for spamminess. - -tools/editconf.py /etc/opendkim.conf -s \ - "AlwaysAddARHeader=true" - -# Add OpenDKIM and OpenDMARC as milters to postfix, which is how OpenDKIM +# Add DKIMpy and OpenDMARC as milters to postfix, which is how DKIMpy # intercepts outgoing mail to perform the signing (by adding a mail header) # and how they both intercept incoming mail to add Authentication-Results # headers. The order possibly/probably matters: OpenDMARC relies on the -# OpenDKIM Authentication-Results header already being present. +# DKIM Authentication-Results header already being present. # # Be careful. If we add other milters later, this needs to be concatenated # on the smtpd_milters line. # # The OpenDMARC milter is skipped in the SMTP submission listener by -# configuring smtpd_milters there to only list the OpenDKIM milter +# configuring smtpd_milters there to only list the DKIMpy milter # (see mail-postfix.sh). tools/editconf.py /etc/postfix/main.cf \ - "smtpd_milters=inet:127.0.0.1:8891 inet:127.0.0.1:8893"\ + "smtpd_milters=inet:127.0.0.1:8892 inet:127.0.0.1:8893"\ non_smtpd_milters=\$smtpd_milters \ milter_default_action=accept @@ -118,7 +110,7 @@ tools/editconf.py /etc/postfix/main.cf \ hide_output systemctl enable opendmarc # Restart services. -restart_service opendkim +restart_service dkimpy-milter restart_service opendmarc restart_service postfix diff --git a/setup/mail-postfix.sh b/setup/mail-postfix.sh index 5787e8c91..bcc6d092f 100755 --- a/setup/mail-postfix.sh +++ b/setup/mail-postfix.sh @@ -91,12 +91,14 @@ tools/editconf.py /etc/postfix/master.cf -s -w \ -o smtpd_tls_wrappermode=yes -o smtpd_sasl_auth_enable=yes -o syslog_name=postfix/submission - -o smtpd_milters=inet:127.0.0.1:8891 + -o smtpd_milters=inet:127.0.0.1:8892 + -o milter_macro_daemon_name=ORIGINATING -o cleanup_service_name=authclean" \ "submission=inet n - - - - smtpd -o smtpd_sasl_auth_enable=yes -o syslog_name=postfix/submission - -o smtpd_milters=inet:127.0.0.1:8891 + -o smtpd_milters=inet:127.0.0.1:8892 + -o milter_macro_daemon_name=ORIGINATING -o smtpd_tls_security_level=encrypt -o cleanup_service_name=authclean" \ "authclean=unix n - - - 0 cleanup From 4db591315b6759a580a1663578395bdd363a0581 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Wed, 28 Dec 2022 01:18:25 +0100 Subject: [PATCH 2/8] convert rsa key format --- setup/dkim.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup/dkim.sh b/setup/dkim.sh index c9ba1e8bd..35b059ada 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -48,6 +48,11 @@ tools/editconf.py /etc/dkimpy-milter/dkimpy-milter.conf -s \ if [ ! -f "$STORAGE_ROOT/mail/dkim/box-rsa.key" ]; then # All defaults are supposed to be ok, default key for rsa is 2048 bit dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/box-rsa + # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format + openssl pkey -in $STORAGE_ROOT/mail/dkim/box-rsa.key -traditional -out $STORAGE_ROOT/mail/dkim/box-rsa.key.1 + mv $STORAGE_ROOT/mail/dkim/box-rsa.key $STORAGE_ROOT/mail/dkim/box-rsa.key.8 + cp -f $STORAGE_ROOT/mail/dkim/box-rsa.key.1 $STORAGE_ROOT/mail/dkim/box-rsa.key + dknewkey --ktype ed25519 $STORAGE_ROOT/mail/dkim/box-ed25519 # Force them into the format dns_update.py expects From f797057c3d627853982b121686dd4db3a44c8462 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Thu, 29 Dec 2022 22:58:49 +0100 Subject: [PATCH 3/8] force move if necessary --- setup/dkim.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/dkim.sh b/setup/dkim.sh index 35b059ada..c1420bdfc 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -50,7 +50,7 @@ if [ ! -f "$STORAGE_ROOT/mail/dkim/box-rsa.key" ]; then dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/box-rsa # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format openssl pkey -in $STORAGE_ROOT/mail/dkim/box-rsa.key -traditional -out $STORAGE_ROOT/mail/dkim/box-rsa.key.1 - mv $STORAGE_ROOT/mail/dkim/box-rsa.key $STORAGE_ROOT/mail/dkim/box-rsa.key.8 + mv -f $STORAGE_ROOT/mail/dkim/box-rsa.key $STORAGE_ROOT/mail/dkim/box-rsa.key.8 cp -f $STORAGE_ROOT/mail/dkim/box-rsa.key.1 $STORAGE_ROOT/mail/dkim/box-rsa.key dknewkey --ktype ed25519 $STORAGE_ROOT/mail/dkim/box-ed25519 From ec2d38414d8122bc2582f4ae781e56112e9c4ea6 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Thu, 29 Dec 2022 23:05:08 +0100 Subject: [PATCH 4/8] document bug report --- setup/dkim.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/dkim.sh b/setup/dkim.sh index c1420bdfc..1ddc2dadd 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -49,6 +49,7 @@ if [ ! -f "$STORAGE_ROOT/mail/dkim/box-rsa.key" ]; then # All defaults are supposed to be ok, default key for rsa is 2048 bit dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/box-rsa # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format + # See bug https://bugs.launchpad.net/dkimpy/+bug/1978835 openssl pkey -in $STORAGE_ROOT/mail/dkim/box-rsa.key -traditional -out $STORAGE_ROOT/mail/dkim/box-rsa.key.1 mv -f $STORAGE_ROOT/mail/dkim/box-rsa.key $STORAGE_ROOT/mail/dkim/box-rsa.key.8 cp -f $STORAGE_ROOT/mail/dkim/box-rsa.key.1 $STORAGE_ROOT/mail/dkim/box-rsa.key From b5807fbf8e3ffd4e3079c3ca7fafba57e22cf7b8 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Fri, 30 Dec 2022 17:08:10 +0100 Subject: [PATCH 5/8] migrate existing rsa keys --- management/dns_update.py | 6 +++--- setup/dkim.sh | 39 ++++++++++++++++++++++++++------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/management/dns_update.py b/management/dns_update.py index f8c7edc8d..7549b0691 100755 --- a/management/dns_update.py +++ b/management/dns_update.py @@ -298,7 +298,7 @@ def has_rec(qname, rtype, prefix=None): # Append the DKIM TXT record to the zone as generated by DKIMpy. # Skip if the user has set a DKIM record already. - dkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-rsa.dns') + dkim_record_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/mail.dns') with open(dkim_record_file) as orf: m = re.match(r'(\S+)\s+IN\s+TXT\s+\( ((?:"[^"]+"\s+)+)\)', orf.read(), re.S) val = "".join(re.findall(r'"([^"]+)"', m.group(2))) @@ -773,7 +773,7 @@ def write_dkim_tables(domains, env): # Append a record to DKIMpy's KeyTable and SigningTable for each domain # that we send mail from (zones and all subdomains). - dkim_rsa_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-rsa.key') + dkim_rsa_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/mail.key') dkim_ed_key_file = os.path.join(env['STORAGE_ROOT'], 'mail/dkim/box-ed25519.key') if not os.path.exists(dkim_rsa_key_file) or not os.path.exists(dkim_ed_key_file): @@ -799,7 +799,7 @@ def write_dkim_tables(domains, env): # signing domain must match the sender's From: domain. "KeyTable": "".join( - "{domain} {domain}:box-rsa:{key_file}\n".format(domain=domain, key_file=dkim_rsa_key_file) + "{domain} {domain}:mail:{key_file}\n".format(domain=domain, key_file=dkim_rsa_key_file) for domain in domains ), "KeyTableEd25519": diff --git a/setup/dkim.sh b/setup/dkim.sh index 1ddc2dadd..979422fb8 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -39,26 +39,39 @@ tools/editconf.py /etc/dkimpy-milter/dkimpy-milter.conf -s \ "SigningTable=refile:/etc/dkim/SigningTable" \ "Socket=inet:8892@127.0.0.1" -# Create a new DKIM key. This creates mail.private and mail.txt +# Create a new DKIM key. This creates mail.key and mail.dns # in $STORAGE_ROOT/mail/dkim. The former is the private key and # the latter is the suggested DNS TXT entry which we'll include # in our DNS setup. Note that the files are named after the # 'selector' of the key, which we can change later on to support # key rotation. -if [ ! -f "$STORAGE_ROOT/mail/dkim/box-rsa.key" ]; then - # All defaults are supposed to be ok, default key for rsa is 2048 bit - dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/box-rsa - # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format - # See bug https://bugs.launchpad.net/dkimpy/+bug/1978835 - openssl pkey -in $STORAGE_ROOT/mail/dkim/box-rsa.key -traditional -out $STORAGE_ROOT/mail/dkim/box-rsa.key.1 - mv -f $STORAGE_ROOT/mail/dkim/box-rsa.key $STORAGE_ROOT/mail/dkim/box-rsa.key.8 - cp -f $STORAGE_ROOT/mail/dkim/box-rsa.key.1 $STORAGE_ROOT/mail/dkim/box-rsa.key - +if [ ! -f "$STORAGE_ROOT/mail/dkim/mail.key" ]; then + # Check if there is an existing rsa key + if [ -f "$STORAGE_ROOT/mail/dkim/mail.private" ]; then + # Re-use existing key + cp -f $STORAGE_ROOT/mail/dkim/mail.private $STORAGE_ROOT/mail/dkim/mail.key + cp -f $STORAGE_ROOT/mail/dkim/mail.txt $STORAGE_ROOT/mail/dkim/mail.dns + else + # All defaults are supposed to be ok, default key for rsa is 2048 bit + dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/mail + # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format + # See bug https://bugs.launchpad.net/dkimpy/+bug/1978835 + openssl pkey -in $STORAGE_ROOT/mail/dkim/mail.key -traditional -out $STORAGE_ROOT/mail/dkim/mail.key.1 + mv -f $STORAGE_ROOT/mail/dkim/mail.key $STORAGE_ROOT/mail/dkim/mail.key.8 + cp -f $STORAGE_ROOT/mail/dkim/mail.key.1 $STORAGE_ROOT/mail/dkim/mail.key + + # Force dns entry into the format dns_update.py expects + # We use selector mail for the rsa key, to be compatible with earlier installations of Mail-in-a-Box + sed -i 's/v=DKIM1;/mail._domainkey IN TXT ( "v=DKIM1; s=email;/' $STORAGE_ROOT/mail/dkim/mail.dns + echo '" )' >> $STORAGE_ROOT/mail/dkim/mail.dns + fi +fi + +if [ ! -f "$STORAGE_ROOT/mail/dkim/box-ed25519.key" ]; then + # Generate ed25519 key dknewkey --ktype ed25519 $STORAGE_ROOT/mail/dkim/box-ed25519 - # Force them into the format dns_update.py expects - sed -i 's/v=DKIM1;/box-rsa._domainkey IN TXT ( "v=DKIM1; s=email;/' $STORAGE_ROOT/mail/dkim/box-rsa.dns - echo '" )' >> $STORAGE_ROOT/mail/dkim/box-rsa.dns + # For the ed25519 dns entry, we use selector box-ed25519 sed -i 's/v=DKIM1;/box-ed25519._domainkey IN TXT ( "v=DKIM1; s=email;/' $STORAGE_ROOT/mail/dkim/box-ed25519.dns echo '" )' >> $STORAGE_ROOT/mail/dkim/box-ed25519.dns fi From d64f749e9a8dd384a9e417334b0b5bf0014767ed Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Thu, 16 Mar 2023 22:11:43 +0100 Subject: [PATCH 6/8] Also use pkcs#1 format for migrated key --- setup/dkim.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/setup/dkim.sh b/setup/dkim.sh index 979422fb8..9097e452a 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -54,17 +54,18 @@ if [ ! -f "$STORAGE_ROOT/mail/dkim/mail.key" ]; then else # All defaults are supposed to be ok, default key for rsa is 2048 bit dknewkey --ktype rsa $STORAGE_ROOT/mail/dkim/mail - # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format - # See bug https://bugs.launchpad.net/dkimpy/+bug/1978835 - openssl pkey -in $STORAGE_ROOT/mail/dkim/mail.key -traditional -out $STORAGE_ROOT/mail/dkim/mail.key.1 - mv -f $STORAGE_ROOT/mail/dkim/mail.key $STORAGE_ROOT/mail/dkim/mail.key.8 - cp -f $STORAGE_ROOT/mail/dkim/mail.key.1 $STORAGE_ROOT/mail/dkim/mail.key # Force dns entry into the format dns_update.py expects # We use selector mail for the rsa key, to be compatible with earlier installations of Mail-in-a-Box sed -i 's/v=DKIM1;/mail._domainkey IN TXT ( "v=DKIM1; s=email;/' $STORAGE_ROOT/mail/dkim/mail.dns echo '" )' >> $STORAGE_ROOT/mail/dkim/mail.dns fi + + # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format + # See bug https://bugs.launchpad.net/dkimpy/+bug/1978835 + openssl pkey -in $STORAGE_ROOT/mail/dkim/mail.key -traditional -out $STORAGE_ROOT/mail/dkim/mail.key.1 + mv -f $STORAGE_ROOT/mail/dkim/mail.key $STORAGE_ROOT/mail/dkim/mail.key.8 + cp -f $STORAGE_ROOT/mail/dkim/mail.key.1 $STORAGE_ROOT/mail/dkim/mail.key fi if [ ! -f "$STORAGE_ROOT/mail/dkim/box-ed25519.key" ]; then From dc6d66cc47f08d33a273a432fb64a9293c35718e Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Sat, 13 May 2023 17:32:08 +0200 Subject: [PATCH 7/8] change handling of pkcs key format --- setup/dkim.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/setup/dkim.sh b/setup/dkim.sh index 9097e452a..b4969ec38 100755 --- a/setup/dkim.sh +++ b/setup/dkim.sh @@ -63,9 +63,13 @@ if [ ! -f "$STORAGE_ROOT/mail/dkim/mail.key" ]; then # Change format from pkcs#8 to pkcs#1, dkimpy seemingly is not able to handle the #8 format # See bug https://bugs.launchpad.net/dkimpy/+bug/1978835 - openssl pkey -in $STORAGE_ROOT/mail/dkim/mail.key -traditional -out $STORAGE_ROOT/mail/dkim/mail.key.1 - mv -f $STORAGE_ROOT/mail/dkim/mail.key $STORAGE_ROOT/mail/dkim/mail.key.8 - cp -f $STORAGE_ROOT/mail/dkim/mail.key.1 $STORAGE_ROOT/mail/dkim/mail.key + line=$(head -n 1 mail.key) + if [ ! "$line" = "-----BEGIN RSA PRIVATE KEY-----" ]; then + # Generate pkcs#1 key from the pkcs#8 key + openssl pkey -in $STORAGE_ROOT/mail/dkim/mail.key -traditional -out $STORAGE_ROOT/mail/dkim/mail.key.1 + mv -f $STORAGE_ROOT/mail/dkim/mail.key $STORAGE_ROOT/mail/dkim/mail.key.8 + cp -f $STORAGE_ROOT/mail/dkim/mail.key.1 $STORAGE_ROOT/mail/dkim/mail.key + fi fi if [ ! -f "$STORAGE_ROOT/mail/dkim/box-ed25519.key" ]; then From 32cb954bb4c6e65096e31bb06dbac090431eb955 Mon Sep 17 00:00:00 2001 From: KiekerJan Date: Tue, 23 Jul 2024 20:22:28 +0200 Subject: [PATCH 8/8] missed a spot while merging --- management/mail_log.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/management/mail_log.py b/management/mail_log.py index 23d7b356c..62aff6b22 100755 --- a/management/mail_log.py +++ b/management/mail_log.py @@ -374,9 +374,9 @@ def scan_mail_log_line(line, collector): elif service == "postfix/smtpd": if SCAN_BLOCKED: scan_postfix_smtpd_line(date, log, collector) - elif service in ("postfix/qmgr", "postfix/pickup", "postfix/cleanup", "postfix/scache", + elif service in {"postfix/qmgr", "postfix/pickup", "postfix/cleanup", "postfix/scache", "spampd", "postfix/anvil", "postfix/master", "dkimpy", "postfix/lmtp", - "postfix/tlsmgr", "anvil"): + "postfix/tlsmgr", "anvil"}: # nothing to look at return True else: