=head1 NAME check_rfc2821_strict_colon_param =head1 DESCRIPTION Plugin to optionally reject transactions where to client inserts extra whitespace between the colon and the path in MAIL and RCPT commands. The space isn't allowed by RFC (2)821, and is mostly inserted by worms and spamware. However, there are a few MTAs which have the same problem, so unconditionally rejecting such connections may not be feasible. Therefore the patch to Qpsmtpd::SMTP allows three actions, depending on config('rfc2821_strict_colon_param'): =over =item reject The erroneous request is rejected with a 503 (syntax error) response. =item note The erroneous request is accepted, but a transaction note ('extra_space_in_mail_from' or 'extra_space_in_rcpt_to') is added. A plugin (e.g., this one) can then decide whether to accept or reject the request. =item ignore (default) The erroneous request is accepted. =back This plugin hooks into the rcpt hook to allow per-user configuration of the behaviour. By default it rejects the command, but this can be overridden by setting client_options, sender_options or recipient_options. =head1 CONFIG =head1 NOTES This plugin makes use of the following connection notes: =over =item 'client_options'->{check_rfc2821_strict_colon_param}{skip} If true, checking the extra_space_in_mail_from and extra_space_in_rcpt_to transaction notes is skipped. This note is usually set by the client_options plugin. =back and of the following transaction notes: =over =item 'sender_options'->{check_rfc2821_strict_colon_param}{skip} If true, checking the extra_space_in_mail_from and extra_space_in_rcpt_to transaction notes is skipped. There is currently no plugin which sets this option, but it is intended for whitelisting based on the reverse path. =item 'recipient_options'->{check_rfc2821_strict_colon_param}{skip} If true, checking the extra_space_in_mail_from and extra_space_in_rcpt_to transaction notes is skipped. This note is usually set by the aliases plugin. =back =head1 BUGS =head1 AUTHOR Written by Peter J. Holzer . =cut use strict; use warnings; use Data::Dumper; my $VERSION = '0.01'; sub register { my ($self, $qp, %arg) = @_; $self->register_hook("rcpt", "rcpt_handler"); } sub rcpt_handler { my ($self, $transaction, $rcpt) = @_; if (my $co = $self->qp->connection->notes('client_options')) { my $d = Data::Dumper->new([$co], ['client_options']); $d->Indent(0); $self->log(LOGDEBUG, $d->Dump); if ($co->{check_rfc2821_strict_colon_param}{skip}) { $self->log(LOGINFO, "client is whitelisted, skipping rfc2821_strict_colon_param checks"); return DECLINED } } if (my $so = $transaction->notes('sender_options')) { if ($so->{check_rfc2821_strict_colon_param}{skip}) { $self->log(LOGINFO, "sender is whitelisted, skipping rfc2821_strict_colon_param checks"); return DECLINED } } if (my $ro = $transaction->notes('recipient_options')) { my $d = Data::Dumper->new([$ro], ['recipient_options']); $d->Indent(0); $self->log(LOGDEBUG, $d->Dump); if ($ro->{check_rfc2821_strict_colon_param}{skip}) { $self->log(LOGINFO, "recipient is whitelisted, skipping rfc2821_strict_colon_param checks"); return DECLINED } } if ($transaction->notes('extra_space_in_mail_from')) { $self->log(LOGNOTICE, "Syntax error in MAIL FROM (no space after colon allowed) detected."); return (DENY, "Syntax error in MAIL FROM (no space after colon allowed) detected."); } if ($transaction->notes('extra_space_in_rcpt_to')) { $self->log(LOGNOTICE, "Syntax error in RCPT TO (no space after colon allowed) detected."); return (DENY, "Syntax error in RCPT TO (no space after colon allowed) detected."); } } 1;