Author: vetinari
Date: Thu Jan 24 10:43:34 2008
New Revision: 836
Added:
trunk/plugins/noop_counter
Modified:
trunk/docs/plugins.pod
trunk/lib/Qpsmtpd/Plugin.pm
trunk/lib/Qpsmtpd/SMTP.pm
Log:
Pluggable hook "noop" with example plugin (noop_counter) and doc update.
... now check_earlytalker can be expanded to VRFY and NOOP (see RFC 1854, #2.1)
Modified: trunk/docs/plugins.pod
==============================================================================
--- trunk/docs/plugins.pod (original)
+++ trunk/docs/plugins.pod Thu Jan 24 10:43:34 2008
@@ -1003,7 +1003,7 @@
my ($self, $transaction, $trace, $hook, $plugin, @log) = @_;
# $trace: level of message, for example
# LOGWARN, LOGDEBUG, ...
- # $hook: the hook in\/for which this logging
+ # $hook: the hook in/for which this logging
# was called
# $plugin: the plugin calling this hook
# @log: the log message
@@ -1174,6 +1174,37 @@
=pod
+=head2 hook_noop
+
+If the client sents the B<NOOP> command, this hook is called. Default is to
+return C<250 OK>.
+
+Allowed return codes are:
+
+=over 4
+
+=item DONE
+
+Plugin gave the answer
+
+=item DENY_DISCONNECT
+
+Return error code and disconnect client
+
+=item DENY
+
+Return error code.
+
+=item Anything Else...
+
+Give the default answer of B<250 OK>.
+
+=back
+
+Arguments are
+
+ my ($self,$transaction,@args) = @_;
+
=head2 hook_post_fork
B<NOTE:> This hook is only available in qpsmtpd-async.
Modified: trunk/lib/Qpsmtpd/Plugin.pm
==============================================================================
--- trunk/lib/Qpsmtpd/Plugin.pm (original)
+++ trunk/lib/Qpsmtpd/Plugin.pm Thu Jan 24 10:43:34 2008
@@ -7,7 +7,7 @@
logging config pre-connection connect ehlo_parse ehlo
helo_parse helo auth_parse auth auth-plain auth-login auth-cram-md5
rcpt_parse rcpt_pre rcpt mail_parse mail mail_pre
- data data_post queue_pre queue queue_post vrfy
+ data data_post queue_pre queue queue_post vrfy noop
quit reset_transaction disconnect post-connection
unrecognized_command deny ok received_line help
);
Modified: trunk/lib/Qpsmtpd/SMTP.pm
==============================================================================
--- trunk/lib/Qpsmtpd/SMTP.pm (original)
+++ trunk/lib/Qpsmtpd/SMTP.pm Thu Jan 24 10:43:34 2008
@@ -502,7 +502,22 @@
sub noop {
my $self = shift;
+ $self->run_hooks("noop");
+}
+
+sub noop_respond {
+ my ($self, $rc, $msg, $args) = @_;
+ return 1 if $rc == DONE;
+
+ if ($rc == DENY || $rc == DENY_DISCONNECT) {
+ $msg->[0] ||= "Stop wasting my time."; # FIXME: better default message?
+ $self->respond(500, @$msg);
+ $self->disconnect if $rc == DENY_DISCONNECT;
+ return 1;
+ }
+
$self->respond(250, "OK");
+ return 1;
}
sub vrfy {
Added: trunk/plugins/noop_counter
==============================================================================
--- (empty file)
+++ trunk/plugins/noop_counter Thu Jan 24 10:43:34 2008
@@ -0,0 +1,65 @@
+#
+#
+#
+
+=head1 NAME
+
+noop_counter - disconnect after too many consecutive NOOPs, example plugin for
the hook_noop()
+
+=head1 DESCRIPTION
+
+The B<noop_counter> counts the number of consecutive C<NOOP> commands given
+by a client and disconnects after a given number.
+
+Any other command than a C<NOOP> resets the counter.
+
+One argument may be given: the number of C<NOOP>s after which the client will
+be disconnected.
+
+=head1 NOTE
+
+This plugin should be loaded early to be able to reset the counter on any other
+command.
+
+=cut
+
+sub register {
+ my ($self, $qp, @args) = @_;
+ $self->{_noop_count} = 0;
+ $self->{_max_noop} = 3;
+ if ($args[0] && $args[0] =~ /^\d+$/) {
+ $self->{_max_noop} = shift @args;
+ }
+}
+
+sub hook_noop {
+ my ($self, $transaction, @args) = @_;
+ ++$self->{_noop_count};
+ ### the following block is not used, RFC 2821 says we SHOULD ignore
+ ### any arguments... so we MAY return an error if we want to :-)
+ # return (DENY, "Syntax error, NOOP does not take any arguments")
+ # if $args[0];
+
+ if ($self->{_noop_count} >= $self->{_max_noop}) {
+ return (DENY_DISCONNECT,
+ "Stop wasting my time, too many consecutive NOOPs");
+ }
+ return (DECLINED);
+}
+
+sub reset_noop_counter {
+ $_[0]->{_noop_count} = 0;
+ return (DECLINED);
+}
+
+# and bind the counter reset to the hooks, QUIT not useful here:
+*hook_helo = *hook_ehlo = # HELO / EHLO
+ *hook_mail = # MAIL FROM:
+ *hook_rcpt = # RCPT TO:
+ *hook_data = # DATA
+ *hook_reset_transaction = # RSET
+ *hook_vrfy = # VRFY
+ *hook_help = # HELP
+ \&reset_noop_counter;
+
+# vim: ts=4 sw=4 expandtab syn=perl