From 1dc0c8d5d95093238280a2e333ffd44b6f90cba3 Mon Sep 17 00:00:00 2001 From: Dominik Chilla Date: Sun, 31 Jan 2021 17:08:05 +0100 Subject: [PATCH] DKIM alignment policy override --- app/exota-milter.py | 15 ++++++++--- app/policy.py | 59 +++++++++++++++++++++++++++++--------------- tests/miltertest.lua | 4 +-- tests/policy.json | 3 ++- 4 files changed, 54 insertions(+), 27 deletions(-) diff --git a/app/exota-milter.py b/app/exota-milter.py index 7951308..4d29a6f 100644 --- a/app/exota-milter.py +++ b/app/exota-milter.py @@ -353,10 +353,17 @@ class ExOTAMilter(Milter.Base): "/EOM: No aligned DKIM signatures found!" ) if g_milter_dkim_alignment_required: - return self.smfir_reject( - queue_id = self.getsymval('i'), - reason = 'DKIM alignment required!' - ) + if policy.is_dkim_alignment_required() == False: + logging.info(self.mconn_id + "/" + str(self.getsymval('i')) + + "/EOM: Policy overrides DKIM alignment requirement to '{0}'!".format( + policy.is_dkim_alignment_required() + ) + ) + else: + return self.smfir_reject( + queue_id = self.getsymval('i'), + reason = 'DKIM alignment required!' + ) else: logging.info(self.mconn_id + "/" + str(self.getsymval('i')) + "/EOM: No valid DKIM authentication result found" diff --git a/app/policy.py b/app/policy.py index 8d6c698..6f6b58a 100644 --- a/app/policy.py +++ b/app/policy.py @@ -16,7 +16,15 @@ class ExOTAPolicyInvalidException(ExOTAPolicyException): class ExOTAPolicy(): def __init__(self, policy_dict): self.tenant_id = policy_dict['tenant_id'] - self.dkim_enabled = policy_dict['dkim_enabled'] + if 'dkim_enabled' in policy_dict: + self.dkim_enabled = policy_dict['dkim_enabled'] + else: + self.dkim_enabled = True + if 'dkim_alignment_required' in policy_dict: + self.dkim_alignment_required = policy_dict['dkim_alignment_required'] + else: + # DKIM alignment per policy enabled by default + self.dkim_alignment_required = True def get_tenant_id(self): return self.tenant_id @@ -24,31 +32,42 @@ class ExOTAPolicy(): def is_dkim_enabled(self): return self.dkim_enabled + def is_dkim_alignment_required(self): + return self.dkim_alignment_required + @staticmethod def check_policy(policy_dict): if 'tenant_id' not in policy_dict: raise ExOTAPolicyInvalidException( - "Policy must have a 'tenant_id' attribute!" + "Policy must have a 'tenant_id' key!" ) - else: - try: - UUID(policy_dict['tenant_id']) - except ValueError as e: + for policy_key in policy_dict: + if policy_key == 'tenant_id': + try: + UUID(policy_dict[policy_key]) + except ValueError as e: + raise ExOTAPolicyInvalidException( + "Invalid 'tenant_id': {0}".format(str(e)) + ) from e + except Exception as e: + raise ExOTAPolicyInvalidException( + "Invalid 'tenant_id': {0}".format(traceback.format_exc()) + ) from e + elif policy_key == 'dkim_enabled': + if not isinstance(policy_dict[policy_key], bool): + raise ExOTAPolicyInvalidException( + "'dkim_enabled'({0}) must be boolean!".format(policy_dict['dkim_enabled']) + ) + elif policy_key == 'dkim_alignment_required': + if not isinstance(policy_dict[policy_key], bool): + raise ExOTAPolicyInvalidException( + "'dkim_alignment_required'({0}) must be boolean!".format( + policy_dict[policy_key] + ) + ) + else: raise ExOTAPolicyInvalidException( - "Invalid 'tenant_id': {0}".format(str(e)) - ) from e - except Exception as e: - raise ExOTAPolicyInvalidException( - "Invalid 'tenant_id': {0}".format(traceback.format_exc()) - ) from e - if 'dkim_enabled' not in policy_dict: - raise ExOTAPolicyInvalidException( - "Policy must have a 'dkim_enabled' attribute!" - ) - else: - if not isinstance(policy_dict['dkim_enabled'], bool): - raise ExOTAPolicyInvalidException( - "'dkim_enabled'({0}) must be boolean!".format(policy_dict['dkim_enabled']) + "Invalid policy_key '{0}'!".format(policy_key) ) class ExOTAPolicyBackend(): diff --git a/tests/miltertest.lua b/tests/miltertest.lua index e69eaa1..b65e0b0 100644 --- a/tests/miltertest.lua +++ b/tests/miltertest.lua @@ -30,7 +30,7 @@ if mt.getreply(conn) ~= SMFIR_CONTINUE then end -- HEADER -if mt.header(conn, "fRoM", '"Blah Blubb" ') ~= nil then +if mt.header(conn, "fRoM", '"Blah Blubb" ') ~= nil then error "mt.header(From) failed" end if mt.header(conn, "resent-fRoM", '"Blah Blubb" ') ~= nil then @@ -51,7 +51,7 @@ end if mt.header(conn, "Authentication-Results", "my-auth-serv-id;\n exota=pass") ~= nil then error "mt.header(Subject) failed" end -if mt.header(conn, "Authentication-RESULTS", "my-auth-serv-id;\n dkim=pass header.d=yad.onmicrosoft.com-blubb header.s=selector1-yad-onmicrosoft-com header.b=mmmjFpv8") ~= nil then +if mt.header(conn, "Authentication-RESULTS", "my-auth-serv-id;\n dkim=pass header.d=yad.onmicrosoft.comx header.s=selector1-yad-onmicrosoft-com header.b=mmmjFpv8") ~= nil then error "mt.header(Subject) failed" end if mt.header(conn, "Authentication-Results", "my-auth-serv-id;\n dkim=fail header.d=yad.onmicrosoft.com header.s=selector2-asdf header.b=mmmjFpv8") ~= nil then diff --git a/tests/policy.json b/tests/policy.json index d6a9b66..a3fc439 100644 --- a/tests/policy.json +++ b/tests/policy.json @@ -1,7 +1,8 @@ { "yad.onmicrosoft.com": { "tenant_id": "1234abcd-18c5-45e8-88de-123456789abc", - "dkim_enabled": true + "dkim_enabled": true, + "dkim_alignment_required": true }, "example.com": { "tenant_id": "abcd1234-18c5-45e8-88de-987654321cba",