Skip to content

Commit

Permalink
- rename DKIM_* constants and description according to RFC 7601 2.7.1
Browse files Browse the repository at this point in the history
  DKIM_SUCCESS is now DKIM_PASS etc
  The old constants are still provided for compatibility
- release as 1.004
  • Loading branch information
noxxi committed Feb 20, 2019
1 parent 3307be2 commit ddbcdac
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 41 deletions.
6 changes: 5 additions & 1 deletion Changes
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
1.002 - 2019/02/10
1.004 - 2019/02/20
- rename DKIM_* constants and description according to RFC 7601 2.7.1
DKIM_SUCCESS is now DKIM_PASS etc
The old constants are still provided for compatibility
1.003 - 2019/02/10
- add Date to headers which should be signed by default
1.002 - 2018/11/15
- small fix authentication_results
Expand Down
76 changes: 48 additions & 28 deletions lib/Mail/DKIM/Iterator.pm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package Mail::DKIM::Iterator;
use v5.10.0;

our $VERSION = '1.003';
our $VERSION = '1.004';

use strict;
use warnings;
Expand All @@ -18,7 +18,26 @@ my $critical_headers_rx = do {
my @sign_headers = (@critical_headers, 'to', 'cc', 'date');

use Exporter 'import';
our @EXPORT =qw(
our @EXPORT = qw(
DKIM_POLICY
DKIM_PERMERROR
DKIM_NEUTRAL
DKIM_TEMPERROR
DKIM_FAIL
DKIM_PASS
);

use constant {
DKIM_POLICY => dualvar(-4,'policy'),
DKIM_PERMERROR => dualvar(-3,'permerror'),
DKIM_NEUTRAL => dualvar(-2,'neutral'),
DKIM_TEMPERROR => dualvar(-1,'temperror'),
DKIM_FAIL => dualvar( 0,'fail'),
DKIM_PASS => dualvar( 1,'pass'),
};

# compability to versions 1.003 and lower
push @EXPORT, qw(
DKIM_INVALID_HDR
DKIM_TEMPFAIL
DKIM_SOFTFAIL
Expand All @@ -27,13 +46,14 @@ our @EXPORT =qw(
);

use constant {
DKIM_INVALID_HDR => dualvar(-3,'invalid-header'),
DKIM_SOFTFAIL => dualvar(-2,'soft-fail'),
DKIM_TEMPFAIL => dualvar(-1,'temp-fail'),
DKIM_PERMFAIL => dualvar( 0,'perm-fail'),
DKIM_SUCCESS => dualvar( 1,'valid'),
DKIM_INVALID_HDR => DKIM_PERMERROR,
DKIM_TEMPFAIL => DKIM_TEMPERROR,
DKIM_SOFTFAIL => DKIM_NEUTRAL,
DKIM_PERMFAIL => DKIM_FAIL,
DKIM_SUCCESS => DKIM_PASS,
};


# create new object
sub new {
my ($class,%args) = @_;
Expand Down Expand Up @@ -182,8 +202,8 @@ sub _compute_result {
my $dkim_sig = sign($sig,$sig->{':key'},$self->{header},\$err);
push @rv, $sig->{':result'} =
Mail::DKIM::Iterator::SignRecord->new(
$dkim_sig ? ($sig,$dkim_sig,DKIM_SUCCESS)
: ($sig,undef,DKIM_PERMFAIL,$err)
$dkim_sig ? ($sig,$dkim_sig,DKIM_PASS)
: ($sig,undef,DKIM_FAIL,$err)
);
}
next;
Expand All @@ -195,7 +215,7 @@ sub _compute_result {
Mail::DKIM::Iterator::VerifyRecord->new(
$sig,
($sig->{s}//'UNKNOWN')."_domainkey".($sig->{d}//'UNKNOWN'),
DKIM_INVALID_HDR,
DKIM_PERMERROR,
$sig->{error}
);
next;
Expand All @@ -205,7 +225,7 @@ sub _compute_result {

if ($sig->{x} && $sig->{x} < time()) {
push @rv, $sig->{':result'} = Mail::DKIM::Iterator::VerifyRecord
->new($sig,$dns, DKIM_SOFTFAIL, "signature e[x]pired");
->new($sig,$dns, DKIM_POLICY, "signature e[x]pired");
next;
}

Expand Down Expand Up @@ -233,7 +253,7 @@ sub _compute_result {
} elsif (exists $self->{records}{$dns}) {
# cannot get DKIM record
push @rv, $sig->{':result'} = Mail::DKIM::Iterator::VerifyRecord
->new($sig,$dns, DKIM_TEMPFAIL, "dns lookup failed");
->new($sig,$dns, DKIM_TEMPERROR, "dns lookup failed");
} else {
# no DKIM record yet known for $dns - preliminary result
push @rv, Mail::DKIM::Iterator::VerifyRecord->new($sig,$dns);
Expand Down Expand Up @@ -475,14 +495,14 @@ sub sign {

# Verify a DKIM signature (hash from parse_signature) using a DKIM key (hash
# from parse_dkimkey). Output is (error_code,error_string) or simply
# (DKIM_SUCCESS) in case of no error.
# (DKIM_PASS) in case of no error.
sub _verify_sig {
my ($sig,$param) = @_;
return (DKIM_PERMFAIL,"none or invalid dkim record") if ! %$param;
return (DKIM_TEMPFAIL,$param->{tempfail}) if $param->{tempfail};
return (DKIM_PERMFAIL,$param->{permfail}) if $param->{permfail};
return (DKIM_PERMERROR,"none or invalid dkim record") if ! %$param;
return (DKIM_TEMPERROR,$param->{tempfail}) if $param->{tempfail};
return (DKIM_PERMERROR,$param->{permfail}) if $param->{permfail};

my $FAIL = $param->{t}{y} ? DKIM_SOFTFAIL : DKIM_PERMFAIL;
my $FAIL = $param->{t}{y} ? DKIM_NEUTRAL : DKIM_FAIL;
return ($FAIL,"key revoked") if ! $param->{p};

return ($FAIL,"hash algorithm not allowed")
Expand Down Expand Up @@ -516,7 +536,7 @@ sub _verify_sig {
# warn "encrypt="._encode64($bencrypt)."\n";
return ($FAIL,'header sig mismatch');
}
return (DKIM_SUCCESS, join(' + ', @{$sig->{':warning'} || []}));
return (DKIM_PASS, join(' + ', @{$sig->{':warning'} || []}));
}

# parse the header and extract
Expand Down Expand Up @@ -918,19 +938,19 @@ Mail::DKIM::Iterator - Iterative DKIM validation or signing.
# This final result consists of a VerifyRecord for each DKIM signature
# in the header, which provides access to the status. Status is one of
# of DKIM_SUCCESS, DKIM_PERMFAIL, DKIM_TEMPFAIL, DKIM_SOFTFAIL or
# DKIM_INVALID_HDR. In case of error $record->error contains a string
# of DKIM_FAIL, DKIM_FAIL, DKIM_PERMERROR, DKIM_TEMPERROR, DKIM_NEUTRAL or
# DKIM_POLICY. In case of error $record->error contains a string
# representation of the error.
for(@$rv) {
my $status = $_->status;
my $name = $_->domain;
if (!defined $status) {
print STDERR "$mailfile: $name UNKNOWN\n";
} elsif ($status == DKIM_SUCCESS) {
} elsif ($status == DKIM_PASS) {
# fully validated
print STDERR "$mailfile: $name OK ".$_->warning".\n";
} elsif ($status == DKIM_PERMFAIL) {
} elsif ($status == DKIM_FAIL) {
# hard error
print STDERR "$mailfile: $name FAIL ".$_->error."\n";
} else {
Expand Down Expand Up @@ -972,7 +992,7 @@ Mail::DKIM::Iterator - Iterative DKIM validation or signing.
my $name = $_->domain;
if (!defined $status) {
print STDERR "$mailfile: $name UNKNOWN\n";
} elsif (status != DKIM_SUCCESS) {
} elsif (status != DKIM_PASS) {
print STDERR "$mailfile: $name $status - ".$_->error."\n";
} else {
# show signature
Expand Down Expand Up @@ -1060,11 +1080,11 @@ Both VerifyRecord and SignRecord have the following methods:
=over 8
=item status - undef if no DKIM result is yet known for the record (preliminary
result). Otherwise any of DKIM_SUCCESS, DKIM_INVALID_HDR, DKIM_TEMPFAIL,
DKIM_SOFTFAIL, DKIM_PERMFAIL.
result). Otherwise any of DKIM_PASS, DKIM_FAIL, DKIM_NEUTRAL, DKIM_TEMPERROR,
DKIM_POLICY, DKIM_PERMERROR.
=item error - an error description in case the status shows an error, i.e. with
all status values except undef and DKIM_SUCCESS.
all status values except undef and DKIM_PASS.
=item sig - the DKIM signature as hash
Expand All @@ -1078,15 +1098,15 @@ A SignRecord has additionally the following methods:
=over 8
=item signature - the DKIM-Signature value, only if DKIM_SUCCESS
=item signature - the DKIM-Signature value, only if DKIM_PASS
=back
A VerifyRecord has additionally the following methods:
=over 8
=item warning - possible warnings if DKIM_SUCCESS
=item warning - possible warnings if DKIM_PASS
Currently this is used to provide information if critical header fields in
the mail are not convered by the signature and thus might have been changed
Expand Down
14 changes: 9 additions & 5 deletions misc/run-tests-mail-dkim.pl
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,17 @@
my ($name,$status,$error) = @$_;
if (!defined $status) {
print STDERR " U $name\n";
} elsif ($status == DKIM_PERMFAIL) {
} elsif ($status == DKIM_FAIL) {
print STDERR " F $name $error\n";
} elsif ($status == DKIM_SOFTFAIL) {
print STDERR " f $name $error\n";
} elsif ($status == DKIM_TEMPFAIL) {
} elsif ($status == DKIM_PERMERROR) {
print STDERR " E $name $error\n";
} elsif ($status == DKIM_TEMPERROR) {
print STDERR " T $name $error\n";
} elsif ($status == DKIM_SUCCESS) {
} elsif ($status == DKIM_POLICY) {
print STDERR " P $name $error\n";
} elsif ($status == DKIM_NEUTRAL) {
print STDERR " f $name $error\n";
} elsif ($status == DKIM_PASS) {
print STDERR " V $name\n";
} else {
die $status
Expand Down
2 changes: 1 addition & 1 deletion scripts/sign.pl
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ sub sign {
$rv || die "no result after end of mail\n";

@$rv == 1 or die "expected a single result, got ".int(@$rv)."\n";
$rv->[0]->status == DKIM_SUCCESS
$rv->[0]->status == DKIM_PASS
or die "unexpected status ".( $rv->[0]->status // '<undef>' )."\n";
my $dkim_sig = $rv->[0]->signature;
return $dkim_sig . $total_mail;
Expand Down
12 changes: 6 additions & 6 deletions t/sign-and-verify.t
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ for my $c (qw(
verify([$m],dns());
};
my $err = $@ || ($ok ? '':'unknown error');
is( $err,"status status=perm-fail error=header sig mismatch\n",
is( $err,"status status=fail error=header sig mismatch\n",
"wrong pubkey");
}

Expand All @@ -73,7 +73,7 @@ for my $c (qw(
verify([$m],dns());
};
my $err = $@ || ($ok ? '':'unknown error');
is( $err,"status status=soft-fail error=signature e[x]pired\n",
is( $err,"status status=policy error=signature e[x]pired\n",
"signature expired");
}

Expand All @@ -84,7 +84,7 @@ for my $c (qw(
verify([$m],dns());
};
my $err = $@ || ($ok ? '':'unknown error');
is( $err,"status status=temp-fail error=dns lookup failed\n",
is( $err,"status status=temperror error=dns lookup failed\n",
"DNS lookup failed");
}

Expand All @@ -95,7 +95,7 @@ for my $c (qw(
verify([$m],dns());
};
my $err = $@ || ($ok ? '':'unknown error');
is( $err,"status status=perm-fail error=invalid or empty DKIM record\n",
is( $err,"status status=permerror error=invalid or empty DKIM record\n",
"DKIM key invalid syntax");
}

Expand Down Expand Up @@ -132,7 +132,7 @@ sub sign {
$rv || die "no result after end of mail\n";

@$rv == 1 or die "expected a single result, got ".int(@$rv)."\n";
$rv->[0]->status == DKIM_SUCCESS
$rv->[0]->status == DKIM_PASS
or die "unexpected status ".( $rv->[0]->status // '<undef>' )."\n";
my $dkim_sig = $rv->[0]->signature;
return $dkim_sig . $total_mail;
Expand All @@ -159,7 +159,7 @@ sub verify {
@todo && die "still things to do at end of mail\n";
$rv || die "no result after end of mail\n";
@$rv == 1 or die "expected a single result, got ".int(@$rv)."\n";
$rv->[0]->status == DKIM_SUCCESS or die
$rv->[0]->status == DKIM_PASS or die
"status status=" . ($rv->[0]->status//'<undef>')
. " error=" . ($rv->[0]->error//'') . "\n";
$rv->[0]->warning eq ''
Expand Down

0 comments on commit ddbcdac

Please sign in to comment.