#!/usr/bin/perl # # xm-spf.pl by Davide Libenzi ( XMail Perl filter for SPF ) # Copyright (C) 2004 Davide Libenzi # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # Davide Libenzi # use strict; use Mail::SPF::Query; my $opt_file = undef; my $opt_ip = undef; my $opt_sender = undef; my $opt_helo = undef; my $opt_rcpt_to = undef; my $opt_local = undef; my $opt_trusted = undef; my $opt_guess = undef; my $opt_exp = undef; my $opt_max_lookup = undef; my $opt_sanitize = undef; my $opt_name = "spfquery"; my $opt_debug = 0; my $opt_keep_comments = 0; my $opt_fallback = undef; my $opt_override = undef; my $opt_dns = undef; my $opt_help = undef; my $opt_pcode = 0; my $opt_fcode = 19; my @opt_bypass = undef; my $i; for ($i = 0; $i <= $#ARGV; $i++) { if ($ARGV[$i] eq "--file") { if (++$i <= $#ARGV) { $opt_file = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--ip") { if (++$i <= $#ARGV) { $opt_ip = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--sender") { if (++$i <= $#ARGV) { $opt_sender = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--helo") { if (++$i <= $#ARGV) { $opt_helo = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--rcpt-to") { if (++$i <= $#ARGV) { $opt_rcpt_to = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--debug") { if (++$i <= $#ARGV) { $opt_debug = int($ARGV[$i]); } } elsif ($ARGV[$i] eq "--local") { if (++$i <= $#ARGV) { $opt_local = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--trusted") { if (++$i <= $#ARGV) { $opt_trusted = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--guess") { if (++$i <= $#ARGV) { $opt_guess = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--expl") { if (++$i <= $#ARGV) { $opt_exp = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--max-lookup") { if (++$i <= $#ARGV) { $opt_max_lookup = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--sanitize") { if (++$i <= $#ARGV) { $opt_sanitize = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--name") { if (++$i <= $#ARGV) { $opt_name = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--fallback") { if (++$i <= $#ARGV) { $opt_fallback = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--override") { if (++$i <= $#ARGV) { $opt_override = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--dns") { if (++$i <= $#ARGV) { $opt_dns = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--pcode") { if (++$i <= $#ARGV) { $opt_pcode = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--fcode") { if (++$i <= $#ARGV) { $opt_fcode = $ARGV[$i]; } } elsif ($ARGV[$i] eq "--bypass") { if (++$i <= $#ARGV) { push(@opt_bypass, $ARGV[$i]); } } elsif ($ARGV[$i] eq "--help") { $opt_help = 1; } } if ($opt_help) { exit($opt_pcode); } if (defined($opt_file)) { my $ln; my @hvars; if (!open(MFIL, "$opt_file")) { print STDERR "unable to open ${opt_file}\n"; exit($opt_pcode); } # Read message info $ln = ; chomp($ln); @hvars = split(/;/, $ln); # Discard SMTP domain $ln = ; # Discard message ID $ln = ; # Read MAIL FROM $ln = ; chomp($ln); close(MFIL); # Handle both cases of early message file and spool file ($opt_sender = $ln) =~ s/[^<]+<([^>]*)>.*/$1/; if ($#hvars > 3) { $opt_helo = $hvars[0]; ($opt_ip = $hvars[1]) =~ s/([^:]+):[0-9]+/$1/; } else { ($opt_ip = $hvars[0]) =~ s/([^:]+):[0-9]+/$1/; } } if (!defined($opt_helo) && ($opt_sender =~ /\@/)) { ($opt_helo = $opt_sender) =~ s/.*\@(.*)/$1/; } for ($i = 0; $i <= $#opt_bypass; $i++) { if ($opt_ip =~ /$opt_bypass[$i]/) { if ($opt_debug) { print "whitelist ip ${opt_ip}\n"; } exit($opt_pcode); } } my $query = new Mail::SPF::Query(ipv4 => $opt_ip, sender => $opt_sender, helo => $opt_helo, local => $opt_local, trusted => $opt_trusted, guess => $opt_guess, default_explanation => $opt_exp, max_lookup => $opt_max_lookup, sanitize => $opt_sanitize, myhostname => $opt_name, fallback => $opt_fallback, override => $opt_override, debug => $opt_debug, ); my $rcode = ($query->result eq "fail") ? $opt_fcode: $opt_pcode; if ($opt_debug) { print $query->result . "\n"; } exit($rcode);