Signing all headers by default is not ideal

Bug #799175 reported by Scott Kitterman
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
dkimpy
Fix Released
Undecided
Stuart Gathman

Bug Description

Currently pydkim defaults to signing all headers. This is not a good default since some headers are more likely than others to be modified in transit. It makes pydkim's signatures more fragile than they need to be.

RFC 4871 5.4 and 5.5 has a long discussion about this with an explicit recommendation in 5.5. There are options and no single default setting is obviously correct. My suggestion is that pydkim provide a safe (does not sign headers likely to be modified in transit and does sign all header likely to be end user visible) default and API to adjust this.

Here is my suggestion for default (from 4871 5.5):

From (REQUIRED in all signatures)
Sender, Reply-To
Subject
Date, Message-ID
To, Cc
MIME-Version
Content-Type, Content-Transfer-Encoding, Content-ID, Content-Description
Resent-Date, Resent-From, Resent-Sender, Resent-To, Resent-Cc, Resent-Message-ID
In-Reply-To, References
List-Id, List-Help, List-Unsubscribe, List-Subscribe, List-Post, List-Owner, List-Archive

The default should 'sign' two From headers by default to prevent an additional From being added.

The API should only require From be signed (since it's a 4871 MUST). If someone wants to change from signing two Froms to one, I think that should be allowed, but if they want to not sign From at all then I think they can edit the code. Our API shoulnd't allow it.

Changed in pydkim:
milestone: none → 0.5
assignee: nobody → Stuart Gathman (stuart-gathman)
Revision history for this message
Stuart Gathman (stuart-gathman) wrote :

Verifying 2 froms was a hack - I'll have to be sure that signing 2 froms is compliant. That would require that the RFC specifies the equivalent of our dkim.select_headers(). Are there any other MUST headers? Off to read RFC.

Revision history for this message
Stuart Gathman (stuart-gathman) wrote :

After studying the RFC, this is what I'll do. DKIM class will have method to set

  SHOULD headers, which are signed as many times as present, and
  FROZEN headers which are mentioned once more than exist in h= to prevent the signature verifying if additional copied are added. (I was going to call this SINGLETON, but there could be more than one, but you don't want any more).

  There will be methods/properties to set SHOULD and FROZEN on a DKIM instance, which will adjust the default for messages signed with that instance.

  There is also a SHOULD_NOT list from the RFC is checked, and we throw an exception if you try to sign one. There will be a method to override the SHOULD_NOT list - with appropriate warnings in the docs. DKIM-Signature is in the SHOULD_NOT list. Nevertheless, we need to have test cases to work correctly if it is overridden and signed.

  By default, we sign everything in the SHOULD and FROZEN list as many times as they appear in the message, plus one more for FROZEN headers. (Thus, even if a frozen header doesn't exist in the signed message, verification will fail if it is subsequently added.)

  From gets special treatment. We throw an exception if from is not signed at least once when signing. In addition we keep this hack from bug#644046: if from is specified once in h= when verifying, make it twice so as to fail if an additional from was added. The signer could do this, and we will by default when signing, but from is considered important enough to force. If from appears 2 or more times, we don't add another because the message is already not rfc5322 compliant, and we can't guess what is really needed.

All this *still* doesn't handle signing a specified number of a repeated header. If a header occurs N times, the above options provide for signing 0, N or N+1 of the occurences. If you need 1 through N-1, then you have to use the include_headers parameter to specify the exact list. I can't see any use cases right now for supporting 1 through N-1 in a higher level way.

Revision history for this message
Stuart Gathman (stuart-gathman) wrote :

rfc5322 specifies these fields as occurring at most once:

  date from sender reply-to to cc bcc message-id in-reply-to references

We could make these all FROZEN by default. Is this too paranoid?

ScottK has said that it is not the job of pydkim to enforce rfc5322. If we simply sign these once, then any policy depending on the signature can know which copy was signed (the bottom copy), and MUAs *ought* to display only the signed copy. While bug#644046 was concerned with the from field, it seems the same consideration could apply to the others.

So, put in SHOULD - signature survives non-RFC field addition, and recipient knows which version of field was signed. *But* we all know how braindead MUAs can be. In fact, most recipient software is simply going to show a good signature and was never tested with multiple versions of such fields.

Or, put in FROZEN - non-RFC modification breaks signature. And recipient is advised in rfc4871 *not* to try and guess which fields broke sig (by for example removing later copies of singleton fields).

Or, keep current policy of FREEZING only from

Or, provide two high level options for default header freezing:
  Relaxed - from only
  Paranoid - all singleton headers

Note also that from is REQUIRED header in rfc5322, and so is date. So maybe both from and date should be frozen by default.

Changed in pydkim:
status: New → Fix Committed
Changed in pydkim:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.