Replied inline and snipped.  Apologies if my mail.app gets this wrong.

> On Apr 1, 2021, at 7:49 PM, Simon Wilson <si...@simonandkate.net> wrote:
> 
> ----- Message from Dan Mahoney <d...@prime.gushi.org> ---------
>   Date: Thu, 1 Apr 2021 16:19:05 -0700
>   From: Dan Mahoney <d...@prime.gushi.org>
> Subject: Re: Milters and policy
>     To: si...@simonandkate.net
>     Cc: postfix-users@postfix.org
> 
> 
>>> On Mar 31, 2021, at 18:23, Simon Wilson <si...@simonandkate.net> wrote:
>>> 
>>> 
>>>> 
>>>>> ...if multiple milters are called are they run in order specified?
>>>>> 
>>>>> smtpd_milters           = inet:127.0.0.1:8891,inet:127.0.0.1:8893
>>>> 
>>>> yes
>>>> 
>>>>> I.e. in the example above if OpenDMARC is to see and trust an
>>>>> already-run OpenDKIM Authentication-Results header is the order of
>>>>> specifying the milters important?
>>>> 
>>>> yes opendkim need to run before opendmarc, and if you have openarc place 
>>>> that before opendkim, it can be messy if opendmarc checks openarc results, 
>>>> remeber it also need to trust AR headers to be considered good info
>>>> 
>>>> but i do not use milters self, only do all i need with fuglu
>>> 
>>> Thanks again Benny. I have policyd-spf set to insert an AR header, and 
>>> OpenDMARC set to trust the Authserv-Id added in Authentication-Results 
>>> headers by policyd-spf and OpenDKIM. All working nicely and good to 
>>> understand the sequence.
>> 
>> Please read CVE-2019-20790, and tell me you’ve found a way to tell PyPolicyd 
>> not to trust the SMTP HELO to generate a passing AR header.
>> 
>> -Dan
>> 
> 
> In the interests of open disclosure of your interests, I assume 
> d...@prime.gushi.org = https://github.com/thegushi = OpenDMARC developer?

Calling me a developer is a bit strong.  I’m a fairly new member of the team, 
mostly trying to do issue wrangling and patch management, and maybe get our 
mailing lists converted to something that isn’t dependent on an EOL python, but 
I don’t/didn’t write most of the code.  I’m mainly a sysadmin and network 
operator.  I am also (coincidentally) the maintainer for the FreeBSD opendmarc 
port, which might explain this journey.

> This is possibly off-topic for the Postfix list... maybe not.

…with tongue in cheek, I’ll take all the discussion about mail filtering over 
any about political correctness that’s happened this year.  That said, if 
people feel this is off topic, nudge me privately and I’ll take a hint.

> Re the risk from the CVE to my setup...
> 
> I run policyd-spf as a postfix check_policy with reject on fail (on both HELO 
> and MAILFROM), and assuming a mail gets past that (99% do), I then use that 
> Pass along with OpenDKIM and OpenDMARC to contribute to Spamassassin scoring. 
> My DMARC Spamassassin rules do not apply a -ve on a pass, only a +ve on a 
> fail.
> 
> The impact of a false pass from DMARC (particularly as our Webmail system - 
> Horde - does not show any added trust for a dmarc pass) would be failure to 
> apply a negative Spamassassin score from a the missed DMARC fail. With my 
> mail setup and users the impact of that is probably manageable... but agreed 
> it is not ideal.
> 
> What concerns me as much as anything is that each of the apps' devs in 
> question (pypolicyd-spf and opendmarc) are each pointing at each other :-/
> 
> https://bugs.launchpad.net/pypolicyd-spf/+bug/1838816/comments/4:
> "my belief that the issue here is a DMARC processor failing to do alignment 
> validation correctly"
> 
> https://github.com/trusteddomainproject/OpenDMARC/issues/49#issuecomment-802242666
> "Honestly, this CVE seems more to belong to py-policyd than OpenDMARC."
> 
> What would be nice would be if the two of you worked together on coming up 
> with a fix...

The upcoming 1.4.1 will have a more detailed explanation of the CVE in question 
as we go over the decisions that we made in taking action on this.

My logic in writing up the CVE summary was: OpenDMARC is following the 
protocols as designed.  If an earlier milter in the chain says SPF passed, it 
doesn’t feel right to pick that apart and say “but did it really?”

The CVE was not “All SPF milters in all configurations allow failed 
authentication with opendmarc" — py-policyd was one called out specifically.  
That says something to me.

> Anyways...
> 
> I see two possible workarounds (not fixes).
> 
> 1. Setting pypolicyd to HELO_Reject = No_Check. RFC7208 indicates that 
> MAILFROM and HELO are both equally valid for an SPF result, *BUT* the vast 
> majority of my SPF checks trigger pass or fail on MAILFROM (I've had 3 spf 
> HELO passes in 10 days on HELO, thousands on MAILFROM). Testing pypolicyd-spf 
> with HELO_reject = No_Check results in spf=none for those. Removing the HELO 
> check means that OpenDMARC can assume any spf result it is given is based on 
> MAILFROM.

RFC7489 Section 4.1:  "DMARC uses the result of SPF authentication of the MAIL 
FROM identity.”

If we’re processing SPF ourselves, this is true.  (The SPF RFC calls HELO 
checking optional).  If we’re parsing an earlier added header (perhaps added by 
a border MX), we prioritize spf=pass over other decisions.  (Perhaps this is 
wrong to do).

With regard to OpenDMARC, we *could* add a check on an earlier SPF header that 
checks *ONLY* the mail-from identity in a received-spf header.  This might be a 
better response to the CVE for future code, but at the very least right now a 
workaround and a statement is warranted.

In turn, that could lead users to point at an SPF=pass in a previous A/R or 
received-spf header, and complain that we’re still rejecting.  It could also 
lead OpenDMARC to add its own SPF A/R header with a different result than a 
previous one, which could greater complicate things down the chain.  Which 
header does a downstream filter (say, Spamd) believe?

> 2. Tell OpenDMARC to *NOT* trust any existing spf result and do its own. I.e. 
> SPFIgnoreResults true. This obviously doubles SPF processing time, and 
> relegates pypolicyd-spf to purely an inbound policy reject check. If one is 
> not using pypolicyd to reject then this would be pointless, and it could be 
> removed from the stack.

Rejecting based on an SPF policy such as -all is carefully cautioned when used 
with DMARC (RFC7489 10.1).  Since SPF is broken by pretty much every mailing 
list, and mailing lists are not SPF aware (but some ARE dmarc aware), using 
py-policyd to reject is probably not a great idea anyway, since as far as I 
know py-policyd doesn’t know how to check if a _dmarc record also exists.

Our advice to the administrators is to carefully evaluate the behavior of this 
software — be aware that this is a failure mode, and act accordingly.

I don’t use py-policyd, so I don’t know what else it can be used to do (for 
example, if it’s a general purpose wrapper like Amavis is).  I don’t feel that 
we should be writing documentation or suggesting specific configuration knobs 
for software we didn’t put out.

The CVE response is visible in the SECURITY folder in our github on the 
“develop” branch.  This specific callout will probably also be in the RELEASE 
NOTES, which we’re still writing.

Stay safe out there,

-Dan

> 
> Thoughts?
> 
>> 
>>> 
>>> Simon.
>>> 
>>> --
>>> Simon Wilson
>>> M: 0400 12 11 16
> 
> 
> ----- End message from Dan Mahoney <d...@prime.gushi.org> -----
> 
> 
> 
> -- 
> Simon Wilson
> M: 0400 12 11 16

Reply via email to