From c3dff626cbcd45b0f245c0dea790831ac4495c18 Mon Sep 17 00:00:00 2001 From: Matt Simerson Date: Sun, 10 Mar 2013 23:38:03 -0400 Subject: [PATCH] plugins/bogus_bounce: add Return-Path check make sure return path is empty, per RFC 3834 --- plugins/bogus_bounce | 47 ++++++++++++++++---------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/plugins/bogus_bounce b/plugins/bogus_bounce index 2a97472..79863a0 100644 --- a/plugins/bogus_bounce +++ b/plugins/bogus_bounce @@ -36,16 +36,11 @@ Deny with a soft error code. 2010 - Steve Kemp - http://steve.org.uk/Software/qpsmtpd/ -=cut - -=begin doc - -Look for our single expected argument and configure "action" appropriately. - -=end doc +2013 - Matt Simerson - added Return Path check =cut + sub register { my ($self, $qp) = (shift, shift); @@ -66,21 +61,11 @@ sub register { } } -=begin doc - -Handle the detection of bounces here. - -If we find a match then we'll react with our expected action. - -=end doc - -=cut - sub hook_data_post { my ($self, $transaction) = (@_); # - # Find the sender, and return unless it wasn't a bounce. + # Find the sender, quit processing if this isn't a bounce. # my $sender = $transaction->sender->address || undef; if ( $sender && $sender ne '<>') { @@ -88,22 +73,24 @@ sub hook_data_post { return DECLINED; }; + # at this point we know it is a bounce, via the null-envelope. # - # Get the recipients. + # Count the recipients. Valid bounces have a single recipient # my @to = $transaction->recipients || (); - if (scalar @to == 1) { - $self->log(LOGINFO, "pass, only 1 recipient"); - return DECLINED; + if (scalar @to != 1) { + $self->log(LOGINFO, "fail, bogus bounce to: " . join(',', @to)); + return $self->get_reject( "fail, this bounce message does not have 1 recipient" ); }; - # - # at this point we know: - # - # 1. It is a bounce, via the null-envelope. - # 2. It is a bogus bounce, because there are more than one recipients. - # - $self->log(LOGINFO, "fail, bogus bounce for :" . join(',', @to)); + # validate that Return-Path is empty, RFC 3834 - $self->get_reject( "fail, this is a bogus bounce" ); + my $rp = $transaction->header->get('Return-Path'); + if ( $rp && $rp ne '<>' ) { + $self->log(LOGINFO, "fail, bounce messages must not have a Return-Path"); + return $self->get_reject( "a bounce return path must be empty (RFC 3834)" ); + }; + + $self->log(LOGINFO, "pass, single recipient, empty Return-Path"); + return DECLINED; }