Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: add config option to require d=... signing domain to be either the FROM domain, or a subdomain of it #232

Open
ell1e opened this issue Oct 25, 2024 · 12 comments

Comments

@ell1e
Copy link

ell1e commented Oct 25, 2024

Feature request: I would like to make OpenDKIM set Authentication-Results to some kind of failure mode if the d=... domain entry doesn't match the FROM or a subdomain of it. For example, if a mail comes from @gmail.com, I would like it to not mark that as a pass unless the valid DKIM signature uses either the domain gmail.com or any.sub.domain.of.gmail.com. It would be nice to have a config option for this, and from reading the manual it seems like currently there isn't one.

Alternatives considered: I'm guessing OpenDKIM's Lua scripting API might allow this, but I couldn't find a good example of this in the wild and it seems like an easy thing to do incorrectly. Therefore, doing this with a config switch would be safer and less error prone for the user.

Reasoning, or why I consider this useful: I've only seen meaningless third-party signatures use other domains, e.g. mailing lists that aren't inherently trustworthy and of which the signature doesn't indicate to me the original e-mail wasn't spoofed.

I understand a mailing list's DKIM signature from a sender-unrelated domain might still indicate the e-mail has at least been unaltered from the mailing list server to me, but 1. I personally don't consider that worthwhile the risk that addons like "DKIM Verifier" might make the user believe the e-mail isn't spoofed when to my understanding, it often still have might been. Also, 2. it seems to me like security aware mailing lists will often rewrite FROM to themselves anyway and e.g. put the receiver into Reply-To, in which case they can sign with the actual origin domain.

Therefore, in practice any signatures not relating to the FROM domain in any meaningful matter seem to be at best not of much use for figuring out if an e-mail was spoofed, and at worst may confuse and mislead users about the actual security level present.

@futatuki
Copy link

futatuki commented Oct 26, 2024

I don't think it is good idea to use (modifying the meaning of) Authentication-Results: header for this purpose even if the feature is off by default, because it is not compliant to RFCs. I think the porpose of this feature request is to make it easy to rejector to quarantine the message by the local policy that described above, and it can be accomplished by other ways, by rejecting or quaranting directly in the milter, or by adding some X-foo header.
(2024-10-26T17:04UTC correction: "Authentication-Result" -> "Authentication-Results")

(This is my subjective opinion, and does not intend to deny the idea itself.)

@ell1e
Copy link
Author

ell1e commented Oct 26, 2024

I do however not wish to reject or quarantine, what I want is to have a clear indication on the client side that this e-mail may not in fact have a trustworthy DKIM signature (which, in my opinion, is usually going to be true for these cases, whether the RFC allows them or not). An X-foo header won't be shown by common DKIM-aware e-mail clients, sadly.

Perhaps an example Lua script for this purpose could be added to OpenDKIM? While I can figure out this specific check in Lua, I don't trust myself to set up the script such that all other behavior remains as before.

@futatuki
Copy link

A small example of screen script which is described in opendkim-lua(3) can be implemented like:

fdomain = string.lower(odkim.get_fromdomain(ctx))
for idx = 0, odkim.get_sigcount(ctx) - 1 do
    sig = odkim.get_sighandle(ctx, idx)
    if string.lower(odkim.sig_getdomain(sig)) ~= fdomain then
        odkim.sig_ignore(sig)
    end
end
return nil

It seems this is almost what you want, except the condition when the milter ignores a signature. As far as I tried, the result of dkim verification on the signature ignored by the milter is recoreded as 'dkim=fail'.

@ell1e
Copy link
Author

ell1e commented Oct 27, 2024

Thanks for the idea! Wouldn't I need to add extra code below to invoke the normal verification after that? The example scripts seem to always do that, it looks fairly complicated. That's why I think a config option would be ideal, since this seems like a rather common sense use case to me.

@futatuki
Copy link

I found almost same code I wrote above, but more robust, is already in OpenDKIM source tree as opendkim/screen.lua.sample.

I need to add extra code below to invoke the normal verification after that? The example scripts seem to always do that, it looks fairly complicated.

The section about screen script in opendkim-lua(3) says:

.I screen
The screen script is run after the DKIM verification context has been
established. The main purpose of this script is to give the user an
opportunity to examine the message header fields compared to the available
DKIM signatures and determine which, if any, should be ignored during
verification. For example, the user might decide only signatures added by
domains exactly matching that in the From: domain are acceptable, and the
rest should be ignored.

Isn't this the answer of your question?

@ell1e
Copy link
Author

ell1e commented Oct 27, 2024

Good find! As far as I can tell, this script doesn't allow subdomains: https://github.com/trusteddomainproject/OpenDKIM/blob/develop/opendkim/screen.lua.sample From my test of real world e-mails, subdomain signatures aren't uncommon. So it's somewhat close.

@futatuki
Copy link

As far as I can tell, this script doesn't allow subdomains

Yes, so I wrote the condition differs what you want. To accomplish it you need to write a new condition to compaire fdomain and sdomain, by using Lua's string manipulation functions (This link is for Lua 5.4).

@ell1e
Copy link
Author

ell1e commented Oct 27, 2024

Interesting! Isn't this type of check also a common DMARC policy? However, to my understanding mailing lists mean that in practice that's often not used in strict mode. But in my opinion it suggests there might be demand for this check as an easily available thing.

@futatuki
Copy link

Isn't this type of check also a common DMARC policy?

Yes, and it is not a part of (current version of) DKIM specification. That is why I'm not positive to add it as a config option, and try to treating as a part of local policy script.

By the way, the result of "ignore" some signatures above are "dkim=fail" in AR header on current code, but I think it is incorrect and should not included in AR header (as I described in issue #233). How do you think about it? Do you want "dkim=fail" result for this policy, or is it acceptable to exclude from AR header?

@ell1e
Copy link
Author

ell1e commented Oct 28, 2024

I usually use the option to always include an Authentication-Results header because otherwise, improperly written e-mail clients may assume an attacker-specified header farther down in the return path is a trustworthy one. (E.g. "DKIM Verifier" for Thunderbird by default might pick up on any header.) In that scenario, there would need to be some sort of dkim= entry, and I assume dkim=none might confuse some clients even more if there is actually a DKIM signature present. But I don't really care what value it would be set to, as long as it's not dkim=pass.

@futatuki
Copy link

Per RFC8601 Sec 2.7.1., it seems that we should use dkim=policy in such a case. I'll comment it to issue #233 and make a PR.

@ell1e
Copy link
Author

ell1e commented Oct 28, 2024

dkim=policy seems like a good choice 😊 thank you so much for looking into this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants