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:
parent
effb4e2269
commit
c0210a7877
@ -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) = @_;
|
||||
|
@ -96,28 +96,17 @@ 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$/) {
|
||||
$req_params{identity} = $from;
|
||||
$req_params{identity} = $from;
|
||||
$req_params{helo_identity} = $helo if $helo;
|
||||
}
|
||||
elsif ($scope eq 'helo') {
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user