diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 6382a1c2..4ff41b75 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,7 +15,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} - name: download filtermail - run: curl -L https://github.com/chatmail/filtermail/releases/download/v0.3.0/filtermail-x86_64 -o /usr/local/bin/filtermail && chmod +x /usr/local/bin/filtermail + run: curl -L https://github.com/chatmail/filtermail/releases/download/v0.5.1/filtermail-x86_64 -o /usr/local/bin/filtermail && chmod +x /usr/local/bin/filtermail - name: run chatmaild tests working-directory: chatmaild run: pipx run tox diff --git a/chatmaild/src/chatmaild/tests/test_filtermail_blackbox.py b/chatmaild/src/chatmaild/tests/test_filtermail_blackbox.py index 85718890..c8766656 100644 --- a/chatmaild/src/chatmaild/tests/test_filtermail_blackbox.py +++ b/chatmaild/src/chatmaild/tests/test_filtermail_blackbox.py @@ -47,6 +47,8 @@ def test_one_mail( make_config, make_popen, smtpserver, maildata, filtermail_mode, monkeypatch ): monkeypatch.setenv("PYTHONUNBUFFERED", "1") + # DKIM is tested by cmdeploy tests. + monkeypatch.setenv("FILTERMAIL_SKIP_DKIM", "1") smtp_inject_port = 20025 if filtermail_mode == "outgoing": settings = dict( @@ -64,6 +66,10 @@ def test_one_mail( popen = make_popen(["filtermail", path, filtermail_mode]) line = popen.stderr.readline().strip() + + # skip a warning that FILTERMAIL_SKIP_DKIM shouldn't be used in prod + if b"DKIM verification DISABLED!" in line: + line = popen.stderr.readline().strip() if b"loop" not in line: print(line.decode("ascii"), file=sys.stderr) pytest.fail("starting filtermail failed") diff --git a/cmdeploy/src/cmdeploy/filtermail/deployer.py b/cmdeploy/src/cmdeploy/filtermail/deployer.py index f18b0c9a..0cd66211 100644 --- a/cmdeploy/src/cmdeploy/filtermail/deployer.py +++ b/cmdeploy/src/cmdeploy/filtermail/deployer.py @@ -14,10 +14,10 @@ class FiltermailDeployer(Deployer): def install(self): arch = host.get_fact(facts.server.Arch) - url = f"https://github.com/chatmail/filtermail/releases/download/v0.3.0/filtermail-{arch}" + url = f"https://github.com/chatmail/filtermail/releases/download/v0.5.1/filtermail-{arch}" sha256sum = { - "x86_64": "f14a31323ae2dad3b59d3fdafcde507521da2f951a9478cd1f2fe2b4463df71d", - "aarch64": "933770d75046c4fd7084ce8d43f905f8748333426ad839154f0fc654755ef09f", + "x86_64": "adce2ddb461c5fd744df699f3b0b3c33b6d52413c641f18695b93826e5e0d234", + "aarch64": "b51cf4248c6c443308f21b1811da1cc919b98b719a2138f4b60940ea093a5422", }[arch] self.need_restart |= files.download( name="Download filtermail", diff --git a/cmdeploy/src/cmdeploy/opendkim/deployer.py b/cmdeploy/src/cmdeploy/opendkim/deployer.py index 8fd12995..54b95024 100644 --- a/cmdeploy/src/cmdeploy/opendkim/deployer.py +++ b/cmdeploy/src/cmdeploy/opendkim/deployer.py @@ -37,21 +37,15 @@ class OpendkimDeployer(Deployer): ) need_restart |= main_config.changed - screen_script = files.put( - src=get_resource("opendkim/screen.lua"), - dest="/etc/opendkim/screen.lua", - user="root", - group="root", - mode="644", + screen_script = files.file( + path="/etc/opendkim/screen.lua", + present=False, ) need_restart |= screen_script.changed - final_script = files.put( - src=get_resource("opendkim/final.lua"), - dest="/etc/opendkim/final.lua", - user="root", - group="root", - mode="644", + final_script = files.file( + path="/etc/opendkim/final.lua", + present=False, ) need_restart |= final_script.changed diff --git a/cmdeploy/src/cmdeploy/opendkim/final.lua b/cmdeploy/src/cmdeploy/opendkim/final.lua deleted file mode 100644 index 2779e38d..00000000 --- a/cmdeploy/src/cmdeploy/opendkim/final.lua +++ /dev/null @@ -1,42 +0,0 @@ -mtaname = odkim.get_mtasymbol(ctx, "{daemon_name}") -if mtaname == "ORIGINATING" then - -- Outgoing message will be signed, - -- no need to look for signatures. - return nil -end - -nsigs = odkim.get_sigcount(ctx) -if nsigs == nil then - return nil -end - -local valid = false -local error_msg = "No valid DKIM signature found." -for i = 1, nsigs do - sig = odkim.get_sighandle(ctx, i - 1) - sigres = odkim.sig_result(sig) - - -- All signatures that do not correspond to From: - -- were ignored in screen.lua and return sigres -1. - -- - -- Any valid signature that was not ignored like this - -- means the message is acceptable. - if sigres == 0 then - valid = true - else - error_msg = "DKIM signature is invalid, error code " .. tostring(sigres) .. ", search https://github.com/trusteddomainproject/OpenDKIM/blob/master/libopendkim/dkim.h#L108" - end -end - -if valid then - -- Strip all DKIM-Signature headers after successful validation - -- Delete in reverse order to avoid index shifting. - for i = nsigs, 1, -1 do - odkim.del_header(ctx, "DKIM-Signature", i) - end -else - odkim.set_reply(ctx, "554", "5.7.1", error_msg) - odkim.set_result(ctx, SMFIS_REJECT) -end - -return nil diff --git a/cmdeploy/src/cmdeploy/opendkim/opendkim.conf b/cmdeploy/src/cmdeploy/opendkim/opendkim.conf index cfa654b4..e1a3e1b2 100644 --- a/cmdeploy/src/cmdeploy/opendkim/opendkim.conf +++ b/cmdeploy/src/cmdeploy/opendkim/opendkim.conf @@ -45,12 +45,6 @@ SignHeaders *,+autocrypt,+content-type # Default is empty. OversignHeaders from,reply-to,subject,date,to,cc,resent-date,resent-from,resent-sender,resent-to,resent-cc,in-reply-to,references,list-id,list-help,list-unsubscribe,list-subscribe,list-post,list-owner,list-archive,autocrypt -# Script to ignore signatures that do not correspond to the From: domain. -ScreenPolicyScript /etc/opendkim/screen.lua - -# Script to reject mails without a valid DKIM signature. -FinalPolicyScript /etc/opendkim/final.lua - # In Debian, opendkim runs as user "opendkim". A umask of 007 is required when # using a local socket with MTAs that access the socket as a non-privileged # user (for example, Postfix). You may need to add user "postfix" to group diff --git a/cmdeploy/src/cmdeploy/opendkim/screen.lua b/cmdeploy/src/cmdeploy/opendkim/screen.lua deleted file mode 100644 index 0f083e2d..00000000 --- a/cmdeploy/src/cmdeploy/opendkim/screen.lua +++ /dev/null @@ -1,21 +0,0 @@ --- Ignore signatures that do not correspond to the From: domain. - -from_domain = odkim.get_fromdomain(ctx) -if from_domain == nil then - return nil -end - -n = odkim.get_sigcount(ctx) -if n == nil then - return nil -end - -for i = 1, n do - sig = odkim.get_sighandle(ctx, i - 1) - sig_domain = odkim.sig_getdomain(sig) - if from_domain ~= sig_domain then - odkim.sig_ignore(sig) - end -end - -return nil diff --git a/cmdeploy/src/cmdeploy/postfix/master.cf.j2 b/cmdeploy/src/cmdeploy/postfix/master.cf.j2 index 3f3a3a07..4914767c 100644 --- a/cmdeploy/src/cmdeploy/postfix/master.cf.j2 +++ b/cmdeploy/src/cmdeploy/postfix/master.cf.j2 @@ -86,7 +86,6 @@ filter unix - n n - - lmtp # Local SMTP server for reinjecting incoming filtered mail 127.0.0.1:{{ config.postfix_reinject_port_incoming }} inet n - n - 100 smtpd -o syslog_name=postfix/reinject_incoming - -o smtpd_milters=unix:opendkim/opendkim.sock # Cleanup `Received` headers for authenticated mail # to avoid leaking client IP. diff --git a/cmdeploy/src/cmdeploy/tests/online/test_1_basic.py b/cmdeploy/src/cmdeploy/tests/online/test_1_basic.py index 26691f8f..7ff23b5b 100644 --- a/cmdeploy/src/cmdeploy/tests/online/test_1_basic.py +++ b/cmdeploy/src/cmdeploy/tests/online/test_1_basic.py @@ -147,7 +147,7 @@ def test_reject_missing_dkim(cmsetup, maildata, from_addr): conn.starttls() with conn as s: - with pytest.raises(smtplib.SMTPDataError, match="No valid DKIM signature"): + with pytest.raises(smtplib.SMTPDataError, match="No DKIM signature found"): s.sendmail(from_addr=from_addr, to_addrs=recipient.addr, msg=msg)