SPF: arrage flow so if a pass result is possible,

we will get it and set the note for DMARC plugin
This commit is contained in:
Matt Simerson 2013-04-24 03:09:02 -04:00
parent effb4e2269
commit c0210a7877
2 changed files with 43 additions and 38 deletions

View File

@ -296,9 +296,16 @@ sub get_organizational_domain {
# $self->log( LOGINFO, "i: $i, $tld" );
#warn "i: $i - tld: $tld\n";
if (grep /$tld/, $self->qp->config('public_suffix_list')) {
if (grep /^$tld/, $self->qp->config('public_suffix_list')) {
$greatest = $i + 1;
next;
}
# check for wildcards (ex: *.uk should match co.uk)
$tld = join '.', '\*', reverse((@labels)[0 .. $i-1]);
if (grep /^$tld/, $self->qp->config('public_suffix_list')) {
$greatest = $i + 1;
};
}
return $from_host if $greatest == scalar @labels; # same
@ -327,7 +334,16 @@ sub exists_in_dns {
# Since this search gets repeated for the Organizational Name, if it
# fails for the O.N., there's no delegation from the TLD.
my $res = $self->init_resolver(8);
my $query = $res->query($domain, 'NS') or do {
return 1 if $self->host_has_rr('NS', $res, $domain);
return 1 if $self->host_has_rr('MX', $res, $domain);
return 1 if $self->host_has_rr('A', $res, $domain);
return 1 if $self->host_has_rr('AAAA', $res, $domain);
}
sub host_has_rr {
my ($self, $type, $res, $domain) = @_;
my $query = $res->query($domain, $type) or do {
if ($res->errorstring eq 'NXDOMAIN') {
$self->log(LOGDEBUG, "fail, non-existent domain: $domain");
return;
@ -337,14 +353,14 @@ sub exists_in_dns {
};
my $matches = 0;
for my $rr ($query->answer) {
next if $rr->type !~ /(?:NS|MX|A|AAAA)/;
next if $rr->type ne $type;
$matches++;
}
if (0 == $matches) {
$self->log(LOGDEBUG, "fail, no records for $domain");
$self->log(LOGDEBUG, "no $type records for $domain");
}
return $matches;
}
};
sub fetch_dmarc_record {
my ($self, $zone) = @_;

View File

@ -96,24 +96,13 @@ sub mail_handler {
return (DECLINED, "SPF - null sender");
}
if ($self->qp->connection->relay_client) {
$self->log(LOGINFO, "skip, relay_client");
return (DECLINED, "SPF - relaying permitted");
}
if (!$self->{_args}{reject}) {
$self->log(LOGINFO, "skip, reject disabled");
return (DECLINED);
}
my $client_ip = $self->qp->connection->remote_ip;
my $from = $sender->user . '@' . lc($sender->host);
my $helo = $self->qp->connection->hello_host;
my $scope = $from ? 'mfrom' : 'helo';
my %req_params = (
versions => [1, 2], # optional
scope => $scope,
ip_address => $client_ip,
ip_address => $self->qp->connection->remote_ip,
);
if ($scope =~ /^mfrom|pra$/) {
@ -144,28 +133,24 @@ sub mail_handler {
return (DECLINED, "SPF - no response");
}
if (!$reject) {
$self->log(LOGINFO, "fail, no reject policy ($code: $why)");
return (DECLINED, "SPF - $code: $why");
}
# SPF result codes: pass fail softfail neutral none error permerror temperror
return $self->handle_code_none($reject, $why) if $code eq 'none';
if ($code eq 'fail') {
$self->adjust_karma(-1);
return $self->handle_code_fail($reject, $why);
}
elsif ($code eq 'softfail') {
$self->adjust_karma(-1);
return $self->handle_code_softfail($reject, $why);
}
elsif ($code eq 'pass') {
if ($code eq 'pass') {
$self->adjust_karma(1);
$transaction->notes('spf_pass_host', lc $sender->host);
$self->log(LOGINFO, "pass, $code: $why");
return (DECLINED);
}
elsif ($code eq 'neutral') {
if (!$reject) {
$self->log(LOGINFO, "skip, tolerated ($code: $why)");
return (DECLINED, "SPF - $code: $why");
}
# SPF result codes: pass fail softfail neutral none error permerror temperror
return $self->handle_code_none($reject, $why) if $code eq 'none';
return $self->handle_code_fail($reject, $why) if $code eq 'fail';
return $self->handle_code_softfail($reject, $why) if $code eq 'softfail';
if ($code eq 'neutral') {
$self->log(LOGINFO, "fail, $code, $why");
return (DENY, "SPF - $code: $why") if $reject >= 5;
}
@ -196,33 +181,37 @@ sub handle_code_none {
return (DENY, "SPF - none: $why");
}
$self->log(LOGINFO, "pass, none, $why");
$self->log(LOGINFO, "skip, tolerated, none, $why");
return DECLINED;
}
sub handle_code_fail {
my ($self, $reject, $why) = @_;
$self->adjust_karma(-1);
if ($reject >= 2) {
$self->log(LOGINFO, "fail, $why");
return (DENY, "SPF - forgery: $why") if $reject >= 3;
return (DENYSOFT, "SPF - fail: $why");
}
$self->log(LOGINFO, "pass, fail tolerated, $why");
$self->log(LOGINFO, "fail, tolerated, $why");
return DECLINED;
}
sub handle_code_softfail {
my ($self, $reject, $why) = @_;
$self->adjust_karma(-1);
if ($reject >= 3) {
$self->log(LOGINFO, "fail, soft, $why");
return (DENY, "SPF - fail: $why") if $reject >= 4;
return (DENYSOFT, "SPF - fail: $why") if $reject >= 3;
}
$self->log(LOGINFO, "pass, softfail tolerated, $why");
$self->log(LOGINFO, "fail, soft, tolerated, $why");
return DECLINED;
}