You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by jm...@apache.org on 2006/11/02 22:39:40 UTC

svn commit: r470533 - /spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm

Author: jm
Date: Thu Nov  2 13:39:39 2006
New Revision: 470533

URL: http://svn.apache.org/viewvc?view=rev&rev=470533
Log:
bug 5140: improvements to DomainKeys support, thanks to Mark Martinec: improve debugging; avoid fetching DK policy when the signature is valid (verifies), as required by draft-delany-domainkeys-base-06; avoid sanitizing header (stripping away trailing header fields likely to be inserted by LDA or MUA) when signature header contains a h tag, which explicitly lists header fields which were included in signature calculation.

Modified:
    spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm

Modified: spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm
URL: http://svn.apache.org/viewvc/spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm?view=diff&rev=470533&r1=470532&r2=470533
==============================================================================
--- spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm (original)
+++ spamassassin/trunk/lib/Mail/SpamAssassin/Plugin/DomainKeys.pm Thu Nov  2 13:39:39 2006
@@ -23,7 +23,22 @@
 
  loadplugin Mail::SpamAssassin::Plugin::DomainKeys [/path/to/DomainKeys.pm]
 
- full DOMAINKEY_DOMAIN eval:check_domainkeys_verified()
+Signature:
+ header DK_SIGNED                eval:check_domainkeys_signed()
+ header DK_VERIFIED              eval:check_domainkeys_verified()
+
+Policy:
+   Note that DK policy record is only fetched if DK_VERIFIED is false
+   to save signing domain from unnecessary DNS queries;
+   as recommended by draft-delany-domainkeys-base (SHOULD)!
+   Rules DK_POLICY_* will return false when DK_VERIFIED is true.
+ header DK_POLICY_TESTING        eval:check_domainkeys_testing()
+ header DK_POLICY_SIGNSOME       eval:check_domainkeys_signsome()
+ header DK_POLICY_SIGNALL        eval:check_domainkeys_signall()
+
+Whitelisting based on verified signature:
+ header USER_IN_DK_WHITELIST     eval:check_for_dk_whitelist_from()
+ header USER_IN_DEF_DK_WL        eval:check_for_def_dk_whitelist_from()
 
 =head1 DESCRIPTION
 
@@ -241,8 +256,11 @@
 
   my $header = $scan->{msg}->get_pristine_header();
   my $body = $scan->{msg}->get_body();
+  my $dksighdr = $scan->{msg}->get_header("DomainKey-Signature");
+  dbg("dk: signature: $dksighdr")  if defined $dksighdr;
 
-  $self->sanitize_header_for_dk(\$header);
+  $self->sanitize_header_for_dk(\$header)
+    if defined($dksighdr) && !grep {/^h=/i} split(/[ \t]*;[ \t]*/,$dksighdr);
 
   my $message = Mail::DomainKeys::Message->load(HeadString => $header,
 						 BodyReference => $body);
@@ -315,12 +333,17 @@
       $scan->{domainkeys_verified} = 1;
     }
   }
-
-  my $policy = Mail::DomainKeys::Policy->fetch(Protocol => 'dns',
-					       Domain => $domain);
-
+  my $policy;
+  if (!$scan->{domainkeys_verified}) {
+    # Recipient systems SHOULD not retrieve a policy TXT record
+    # for email that successfully verifies.
+    $policy = Mail::DomainKeys::Policy->fetch(Protocol => 'dns',
+					      Domain => $domain);
+    my($fetched_policy) = $policy ? $policy->as_string : 'NONE';
+    $fetched_policy = ''  if !defined $fetched_policy;
+    dbg ("dk: fetched policy for domain $domain: $fetched_policy");
+  }
   return unless $policy;
-  dbg ("dk: fetched policy");
 
   # not signed and domain doesn't sign all
   if ($policy->signsome()) {
@@ -346,10 +369,15 @@
   my ($self, $message) = @_;
   # try to use the signature() API if it exists (post-0.80)
   if ($message->can("signature")) {
+    my($sts,$msg);
     if (!$message->signed) {
-      return "no signature";
+      $sts = "no signature";
+    } else {
+      $sts = $message->signature->status;
+      $msg = $message->signature->errorstr;
     }
-    return $message->signature->status;
+    dbg("dk: $sts" . (defined $msg ? " ($msg)" : ''));
+    return $sts;
   } else {
     return $message->header->value;
   }
@@ -366,7 +394,7 @@
     return $message->signature->domain;
   } else {
     # otherwise parse it ourself
-    if ($scan->{msg}->get_header("DomainKey-Signature") =~ /d=(\S+);/) {
+    if ($scan->{msg}->get_header("DomainKey-Signature") =~ /d=([^;\s]+)/) {
       return $1;
     }
     return undef;
@@ -376,6 +404,7 @@
 sub sanitize_header_for_dk {
   my ($self, $ref) = @_;
 
+  dbg("dk: sanitizing header, no \"h\" tag in signature");
   # remove folding, in a HTML-escape data-preserving style, so we can
   # strip headers easily
   $$ref =~ s/!/!ex;/gs;