ietf-dkim
[Top] [All Lists]

Re: [ietf-dkim] detecting header mutations after signing

2010-10-08 14:15:11
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

<Prev in Thread] Current Thread [Next in Thread>