Hello,

On Mon, Mar 22, 2004 at 11:23:53PM -0500, Ari Jort wrote:
> I've been looking for a SA rule that will do something
> comparable to what postfix does with reject_unverified_sender.
> 
> The postfix address verification is described here:
> 
> http://www.porcupine.org/postfix-mirror/newdoc/ADDRESS_VERIFICATION_README.html
> 
> I'd like to use this technique, but would rather assign
> a score with SA, rather than make a reject/accept decision 
> based on the result.

I've implemented a verify_sender routine as inspired by 
the postfix address verification, noted above.  Patch
is attached.

This is a naive implementation in many ways.  

1) It assumes the envelope-from is retreivable from the 
Return-Path: header which is true in postfix-land.  I'm not
sure about elsewhere.

2) There's still a bunch of debugging code in here.  I thought
I'd leave it in in this patch, in case it helps anyone else
get it working.

3) It relies on 2 extra perl modules: Net::DNS and Net::SMTP
which might be better outside the spamd process space.  Maybe
a sender verification daemon?

4) It only checks with the highest priority mx record for a given
domain and does not move on to lower priority records.


I'd love some feedback or reports on whether anyone else
can get this working.

Thanks,

ari

-- 
Ari Jort
[EMAIL PROTECTED]
--- lib/Mail/SpamAssassin/EvalTests.pm.orig     Tue Mar 23 01:08:04 2004
+++ lib/Mail/SpamAssassin/EvalTests.pm  Tue Mar 23 18:39:28 2004
@@ -3595,6 +3595,89 @@
   return;
 }
 
+# return the value of the Return-Path: header
+sub get_return_path() {
+       my($self) = @_;
+       my($return_path) = $self->get('Return-Path');
+       chomp($return_path);
+       dbg(sprintf "raw return path %s", $return_path );
+       $return_path =~ s/^<//;
+       $return_path =~ s/>$//;
+       dbg(sprintf "adjusted return path %s", $return_path );
+       $self->{return_path} = $return_path;
+       return $return_path
+}
+
+# do address verification on mail Return-Path
+
+sub verify_sender() {
+       my($self) = @_;
+       use Net::SMTP;
+       use Net::DNS;
+
+       my($mailhost, $domain_part);
+       my($probefrom) = '[EMAIL PROTECTED]';
+       my(@mxs);
+
+       # question: which is best way to get $return_path, 
+       # from method or member var.  Both seem to work fine.
+       my($return_path) = $self->get_return_path();
+#      my($return_path_v) = $self->{return_path};
+#      my($return_path) = $return_path_m;
+#      dbg(sprintf "using return path from method %s", $return_path_m );
+#      dbg(sprintf "using return path from var %s", $return_path_v );
+       dbg(sprintf "using return path - %s -", $return_path );
+
+       # return_path looks like this: '[EMAIL PROTECTED]'
+       # we want to get the domain part, or 'speakeasy.net'
+       if ( $return_path =~ /([EMAIL PROTECTED])*\@([EMAIL PROTECTED])/ ) {
+               $domain_part = $2;
+       }
+       dbg(sprintf "using domain part - %s -", $domain_part );
+       # get mx from domain part
+       my($res) = Net::DNS::Resolver->new()
+               or die "cannot create resolver object\n";
+
+       unless ( @mxs = &mx($res, $domain_part) ) {
+               dbg ("cannot assign mx records: $?\n");
+               return 1;
+       }
+
+       # assumption: we only grab the first mx and try that
+       # in future we can cycle through lower priority mx's
+       $mailhost = $mxs[0];
+       dbg(sprintf "using mailhost %s", $mailhost->string );
+       my($rr) = $mailhost->exchange();
+       dbg(sprintf "using rr %s", $rr );
+
+       # must untaint rr record value
+       if ( $rr =~ /^([-A-Za-z0-9.]+)$/ ) {
+               # we check only for alphanumerics, dashes and periods
+               $rr = $1;
+               dbg(sprintf "rr successfully untainted: %s", $rr); 
+       } else {
+               dbg(sprintf "could not untaint rr: %s", $rr); 
+               return 1;
+       }
+       my($smtp_probe);
+       unless ( $smtp_probe = Net::SMTP->new($rr) ) {
+               dbg(sprintf "could not connect to mx: %s", $rr); 
+               return 1;
+       }
+       unless ( $smtp_probe->mail($probefrom) ) {
+               dbg(sprintf "MAIL FROM: %s was denied at mx: %s", $probefrom, 
$rr);
+               return 1; 
+       }
+       unless ( $smtp_probe->to( $self->get_return_path() ) ) {
+               dbg(sprintf "RCPT TO: %s was denied at mx: %s", $return_path, 
$rr);
+               return 1; 
+       }
+       $smtp_probe->reset();
+       $smtp_probe->quit();
+
+       dbg(sprintf "successfully verified sender %s", $return_path );
+       return 0;
+}
 ###########################################################################
 
 1;

Reply via email to