Wietse Venema wrote:
If I understand things correctly, the solution is already available
in DKIM today. It involves signer configuration (sign for N+1
instances of each header that is covered by the signature) and
requires no change in protocol or semantics. It merely hardens the
DKIM signature and I see nothing wrong with doing so.
If I am mistaken then please correct me.
It depends on the Application implementation of DKIM.
How are you doing it or offering DKIM signer configuration in postfix?
Do you have a "Required Headers" to sign operation option?
Let me give you a summary background of events leading up to this.
We began to finally go full steam with DKIM integration into our
integrated mail framework.
I had explored the 2006 revision of the Alt-N open source API to
explore all this, and to begin the effort in earnest, I upgraded the
API to latest 2009 version which included ADSP support.
There were one thing I noticed when I did a diff between the two API
versions. The one that stood out was a new signer options:
int nAllowUnsignedFromHeaders; // 0 = From headers not included in
the
// signature are not allowed, 1 =
allowed
Note I wasn't aware of this multiple from issue yet, so I presumed
this was an implementator field experience after three years with a
need to relax the RFC 4871 requirement to hash the 5322.From. After
all, with the direction to disassociate the author and signer, it felt
that was all part of it.
There was another related header hashing option that was both in the
old and new versions:
char szRequiredHeaders[256]; // colon-separated list of headers that
// must be signed
The API also provides a callback where it passes each 5322 header as
it parsed the 5322 message where it wants a TRUE or FALSE function
response. This allows an application to prepare a callback to
determine what specific headers to sign.
The difference is:
With a CALL BACK, application be be specific with the headers to
sign and
only these headers appear in the tag h= values list.
With szRequireHeaaders defined, it was not exclusive but added headers
that by default the API didn't sign.
In other would, by default, the signing function signed ALL headers
excluding
X-*
Authentication-Results:
Return-Path:
Using szRequiredHeader, would allow you to sign other headers not
already signed.
But for the application which imports the API into a p-code language
for SMTP receiver (verify) and SMTP router (signing) shimming, I could
not use the call back method and I needed a way to give operators a
configuration method way to allow them which headers should be signed.
So I added an option:
int nUseRequiredHeadersOnly; // 1 - used szRequireHeaders and
exclude the rest
which says if szRequiredHeaders is set, then only those headers are
signed.
I then ask Alt-N about the nAllowUnsignedFromHeaders feature and to
inform them if the change I made with nUseRequiredHeadersOnly.
That is why I found out why they needed nAllowUnsignedFromHeaders
because a customer incident reported the multiple 5322.From issue.
I was able to confirm this and I traced the logic of
nAllowUnsignedFromHeaders and saw that it doesn't stop multiple
5322.From (N) but rather it enforces that each one was included in the
h= tag.
So while the trick to add N+1 "from" values to the h= tag would help
mitigate this, we don't know if most applications give an operators
option to set the exclusive headers to sign.
I did because I wanted to explore different h= headers signing setup
especially with integrated list operations. For example, the operator
configuration default:
#---------------------------------------------------------------------
# Signing Options for author-domain section
#
# Possible values for canon=
#
# DKIM_CANON_SIMPLE
# DKIM_CANON_NOWSP
# DKIM_CANON_RELAXED
# DKIM_SIGN_SIMPLE
# DKIM_SIGN_SIMPLE_RELAXED
# DKIM_SIGN_RELAXED
# DKIM_SIGN_RELAXED_SIMPLE
#
# [<AUTHOR-DOMAIN>]
# signer = <SIGNER-DOMAIN> # this is the signature
d= tag
# selector = <SELECTOR> # this is the signature
s= tag
# Canon = DKIM_SIGN_SIMPLE # canonization
# IncludeBodyLengthTag = 0 # opt, 1 - include l=
tag body size
# IncludeTimeStamp = 1 # opt, 1 - include t=
tag timestamp
# IncludeQueryMethod = 0 # opt, 1 - include q= tag
# Hash = 1 # req, 1 - SHA1, 2 - SHA256
# IncludeCopiedHeaders = 0 # opt, 1 - use z= tag
# Identity = # opt, i= tag
# ExpireTime = 0 # opt, days, adds x= tag
# UseRequiredHeadersOnly = 1 # opt, 1 - used
szRequireHeaders
# RequiredHeaders =
From:To:Date:Message-Id:Organization:Subject:List-ID
#---------------------------------------------------------------------
I wanted to ability to always have the List-ID to handle both type of
streams, private email and list email with one default setup. It
would also help to protect against replay by a foreign list server.
What I can do now with our setup is change the default to:
RequiredHeaders =
From:From:To:Date:Message-Id:Organization:Subject:List-ID
So the "kludge" idea is good, but we don't know if most other DKIM
application implementations offer this. I believe Levine is correct
on this point that most implementations may not be this flexible.
--
Hector Santos, CTO
http://www.santronics.com
http://santronics.blogspot.com
_______________________________________________
NOTE WELL: This list operates according to
http://mipassoc.org/dkim/ietf-list-rules.html