completed DKIM signing detection to A-R header

cleaning function, making it 'safe'

* added test coverage to authentication_results and clean_authentication_results
This commit is contained in:
Matt Simerson 2015-01-04 14:26:27 -08:00
parent 4226dfaa3e
commit 62a063b366
2 changed files with 92 additions and 14 deletions

View File

@ -767,9 +767,10 @@ sub data_respond {
return 1; return 1;
} }
$self->run_hooks("data_post_headers"); $self->run_hooks('data_post_headers');
$self->authentication_results(); $self->clean_authentication_results();
$self->received_line(); $self->received_line();
$self->authentication_results();
$self->run_hooks('data_post'); $self->run_hooks('data_post');
} }
@ -778,8 +779,6 @@ sub authentication_results {
my @auth_list = $self->config('me'); my @auth_list = $self->config('me');
#$self->clean_authentication_results();
if (!defined $self->{_auth}) { if (!defined $self->{_auth}) {
push @auth_list, 'auth=none'; push @auth_list, 'auth=none';
} }
@ -807,16 +806,23 @@ sub authentication_results {
sub clean_authentication_results { sub clean_authentication_results {
my $self = shift; my $self = shift;
# http://tools.ietf.org/html/draft-kucherawy-original-authres-00.html
# On messages received from the internet, move Authentication-Results headers # On messages received from the internet, move Authentication-Results headers
# to Original-AR, so our downstream can trust the A-R header we insert. # to Original-AR, so our downstream can trust the A-R header we insert.
# TODO: Do not invalidate DKIM signatures. # TODO: was A-R header added by a Trusted MTA? Remove otherwise. Maybe.
# if $self->transaction->header->get('DKIM-Signature') # See Also: RFC 5451, Removing The Header Field:
# Parse the DKIM signature(s) # http://tools.ietf.org/html/rfc5451#section-5
# return if A-R header is signed; # http://tools.ietf.org/html/draft-kucherawy-original-authres-00.html
# }
# Do not rename A-R header if DKIM signed
my $dkim_sig = $self->transaction->header->get('DKIM-Signature');
if ($dkim_sig) {
my %fields = map { split /=/ } split /;\s+/, $dkim_sig;
# print Data::Dumper::Dumper(\%fields);
if ($fields{h} && $fields{h} =~ /Authentication-Results/i) {
return;
}
}
my @ar_headers = $self->transaction->header->get('Authentication-Results'); my @ar_headers = $self->transaction->header->get('Authentication-Results');
for (my $i = 0 ; $i < scalar @ar_headers ; $i++) { for (my $i = 0 ; $i < scalar @ar_headers ; $i++) {

View File

@ -24,6 +24,8 @@ __helo_repeat_host();
__helo_respond('helo_respond'); __helo_respond('helo_respond');
__helo_respond('ehlo_respond'); __helo_respond('ehlo_respond');
__data_respond('data_respond'); __data_respond('data_respond');
__clean_authentication_results();
__authentication_results();
done_testing(); done_testing();
@ -161,6 +163,76 @@ sub __data_respond {
#is( $smtpd->data_respond(DECLINED), 1, 'data_respond, DECLINED' ); #is( $smtpd->data_respond(DECLINED), 1, 'data_respond, DECLINED' );
} }
sub __clean_authentication_results {
my $smtpd = _transaction_with_headers();
$smtpd->transaction->header->add('Authentication-Results', _test_ar_header());
$smtpd->clean_authentication_results();
ok(!$smtpd->transaction->header->get('Authentication-Results'), "clean_authentication_results removes A-R header");
ok($smtpd->transaction->header->get('Original-Authentication-Results'), "clean_authentication_results adds Original-A-R header");
# A-R header is _not_ DKIM signed
$smtpd = _transaction_with_headers();
$smtpd->transaction->header->add('Authentication-Results', _test_ar_header());
$smtpd->transaction->header->add('DKIM-Signature', _test_dkim_header());
$smtpd->clean_authentication_results();
ok(!$smtpd->transaction->header->get('Authentication-Results'), "clean_authentication_results removes non-DKIM-signed A-R header");
ok($smtpd->transaction->header->get('Original-Authentication-Results'), "clean_authentication_results adds non-DKIM-signed Original-A-R header");
# A-R header _is_ DKIM signed
$smtpd = _transaction_with_headers();
$smtpd->transaction->header->add('Authentication-Results', _test_ar_header());
$smtpd->transaction->header->add('DKIM-Signature', _test_dkim_sig_ar_signed());
$smtpd->clean_authentication_results();
ok($smtpd->transaction->header->get('Authentication-Results'), "clean_authentication_results removes non-DKIM-signed A-R header");
ok(!$smtpd->transaction->header->get('Original-Authentication-Results'), "clean_authentication_results adds non-DKIM-signed Original-A-R header");
}
sub _test_ar_header {
return 'mail.theartfarm.com; iprev=pass; spf=pass smtp.mailfrom=ietf.org; dkim=fail (body hash did not verify) header.i=@kitterman.com; dkim=pass header.i=@ietf.org';
}
sub _test_dkim_header {
return <<DKIM_HEADER
v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1; t=1420404573; bh=Tq5JynLUBXNqn1f+10W+MuPhq+XAbL4oLNfT+QPVK54=; h=From:To:Date:Message-ID:In-Reply-To:References:MIME-Version:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:Content-Type:Content-Transfer-Encoding:Sender; b=hsxkiq/cCNBJTOwv1wj+AA9w2ujXnpNVjpPREMSvidQQkDsnFPhASDi9hihEgEqo4LRMkbw/zHNyHBtF5TcT7WysNyItpmbnWiRksB9SuCBaqZMvqE/rNVca3goTgrb89O5SDZIWjcQ7rGvNqk/L+XL8VWCyNhOVlalnFMxKXyE=
DKIM_HEADER
}
sub _test_dkim_sig_ar_signed {
return <<DKIM_AR_SIGNED_HEADER
v=1; a=rsa-sha256; c=relaxed/simple; d=ietf.org; s=ietf1; t=1420404573; bh=Tq5JynLUBXNqn1f+10W+MuPhq+XAbL4oLNfT+QPVK54=; h=Authentication-Results:From:To:Date:Message-ID:In-Reply-To:References:MIME-Version:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:Content-Type:Content-Transfer-Encoding:Sender; b=hsxkiq/cCNBJTOwv1wj+AA9w2ujXnpNVjpPREMSvidQQkDsnFPhASDi9hihEgEqo4LRMkbw/zHNyHBtF5TcT7WysNyItpmbnWiRksB9SuCBaqZMvqE/rNVca3goTgrb89O5SDZIWjcQ7rGvNqk/L+XL8VWCyNhOVlalnFMxKXyE=
DKIM_AR_SIGNED_HEADER
}
sub _transaction_with_headers {
( $smtpd ) = Test::Qpsmtpd->new_conn();
$smtpd->transaction->header(
Mail::Header->new(Modify => 0, MailFrom => 'COERCE')
);
return $smtpd;
}
sub __authentication_results {
my $smtpd = _transaction_with_headers();
$smtpd->authentication_results();
my $ar = $smtpd->transaction->header->get('Authentication-Results'); chomp $ar;
ok($ar, "added A-R header: $ar");
$smtpd->{_auth} = OK;
$smtpd->{_auth_mechanism} = 'test_mech';
$smtpd->{_auth_user} = 'test@example';
$smtpd->authentication_results();
$ar = $smtpd->transaction->header->get('Authentication-Results'); chomp $ar;
ok($ar =~ /auth=pass/, "added A-R header with auth: $ar");
delete $smtpd->{_auth};
$smtpd->connection->notes('authentication_results', 'spf=pass smtp.mailfrom=ietf.org' );
$smtpd->authentication_results();
$ar = $smtpd->transaction->header->get('Authentication-Results'); chomp $ar;
ok($ar =~ /spf/, "added A-R header with SPF: $ar");
}
sub response_is { sub response_is {
my ( $expected, $descr ) = @_; my ( $expected, $descr ) = @_;
my $response; my $response;