From 6dcd686701ef35d5f72fe7941028344a88f2f5cd Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 18 Oct 2023 15:12:14 +0200 Subject: [PATCH] also test that external addresses fail to be forged --- chatmaild/src/chatmaild/filtermail.py | 2 +- online-tests/conftest.py | 9 +++++++++ online-tests/test_0_basic.py | 21 +++++++++++++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/chatmaild/src/chatmaild/filtermail.py b/chatmaild/src/chatmaild/filtermail.py index f7dfa3a5..f830d0e7 100644 --- a/chatmaild/src/chatmaild/filtermail.py +++ b/chatmaild/src/chatmaild/filtermail.py @@ -80,7 +80,7 @@ def lmtp_handle_DATA(envelope): _, from_addr = parseaddr(message.get("from").strip().lower()) logging.info(f"mime-from: {from_addr} envelope-from: {envelope.mail_from}") if envelope.mail_from != from_addr: - res += [f"500 Invalid FROM <{envelope.mail_from}>"] + res += [f"500 Invalid FROM <{from_addr}> for <{envelope.mail_from}>"] continue if envelope.mail_from == recipient: diff --git a/online-tests/conftest.py b/online-tests/conftest.py index 7ec39bf0..fc3e29d4 100644 --- a/online-tests/conftest.py +++ b/online-tests/conftest.py @@ -84,6 +84,15 @@ class ImapConn: assert status == "OK" return results + def fetch_all_messages(self): + print("imap-fetch all messages") + results = self.fetch_all() + messages = [] + for item in results: + if len(item) == 2: + messages.append(item[1].decode()) + return messages + @pytest.fixture def smtp(maildomain): diff --git a/online-tests/test_0_basic.py b/online-tests/test_0_basic.py index c3c475cb..908b0fb0 100644 --- a/online-tests/test_0_basic.py +++ b/online-tests/test_0_basic.py @@ -19,13 +19,19 @@ def test_use_two_chatmailservers(cmfactory, maildomain2): assert domain1 != domain2 -def test_reject_internal_forged_from(cmsetup, mailgen, lp, remote): +@pytest.mark.parametrize("internal", [True, False]) +def test_reject_forged_from(cmsetup, mailgen, lp, remote, internal): user1, user2, user3 = cmsetup.gen_users(3) lp.sec("send encrypted message with forged from") print("envelope_from", user1.addr) + if internal: + user_to_forge = user2.addr + else: + user_to_forge = "someone@example.org" + print("message to inject:") - msg = mailgen.get_encrypted(from_addr=user2.addr, to_addr=user3.addr) + msg = mailgen.get_encrypted(from_addr=user_to_forge, to_addr=user3.addr) for line in msg.split("\n")[:4]: print(f" {line}") @@ -33,15 +39,14 @@ def test_reject_internal_forged_from(cmsetup, mailgen, lp, remote): user1.smtp.sendmail(from_addr=user1.addr, to_addrs=[user3.addr], msg=msg) for line in remote_log: - print(line) - if "500 invalid from" in line: + # print(line) + if "500 invalid from" in line and user3.addr in line: break else: pytest.fail("remote postfix/filtermail failed to reject message") # also check that the forging-user got a non-delivery notice - for flags, bmsg in user1.imap.fetch_all(): - message = bmsg.decode() - if "Invalid FROM" in message and user2.addr in message: + for message in user1.imap.fetch_all_messages(): + if "Invalid FROM" in message and user_to_forge in message: return - pytest.fail("forged From did not cause rejection") + pytest.fail(f"forged From={user_to_forge} did not cause non-delivery notice")