[svn:qpsmtpd] r601 - branches/0.3x/plugins
[email protected] 11 Jan 2006 17:03:46 -0000
| Newsgroups | perl.cvs.qpsmtpd |
|---|---|
| Message-ID | <[email protected]> |
Author: jpeacock
Date: Wed Jan 11 09:03:45 2006
New Revision: 601
Added:
branches/0.3x/plugins/hosts_allow
Log:
Oops! Neglected to add this. Should have been part of r599.
Added: branches/0.3x/plugins/hosts_allow
==============================================================================
--- (empty file)
+++ branches/0.3x/plugins/hosts_allow Wed Jan 11 09:03:45 2006
@@ -0,0 +1,80 @@
+
+=head1 NAME
+
+hosts_allow - decide if a host is allowed to send mail
+
+=head1 DESCRIPTION
+
+The B<hosts_allow> module decides before the SMTP-Greeting if a host is
+allowed to connect. It checks for too many (running) connections from one
+host (see -m/--max-from-ip options in qpsmtpd-forkserver) and the config
+file I<hosts_allow>.
+The plugin takes no arguments.
+
+=head1 CONFIG
+
+The config file contains lines with two or three items. The first is either
+an IP address or a network/mask pair. The second is a (valid) return code
+from Qpsmtpd::Constants. The last is a comment which will be returned to the
+connecting client if the return code is DENY or DENYSOFT (and of course
+DENY_DISCONNECT and DENYSOFT_DISCONNECT).
+Example:
+
+ 192.168.3.4 DECLINED
+ 192.168.3.0/24 DENY Sorry, known spam only source
+
+This would exclude 192.168.3.4 from the DENY of 192.168.3.0/24.
+
+=cut
+
+use Qpsmtpd::Constants;
+use Socket;
+
+sub hook_pre_connection {
+ my ($self,$transaction,%args) = @_;
+
+ # remote_ip => inet_ntoa($iaddr),
+ # remote_port => $port,
+ # local_ip => inet_ntoa($laddr),
+ # local_port => $lport,
+ # max_conn_ip => $MAXCONNIP,
+ # child_addrs => [values %childstatus],
+
+ my $remote = $args{remote_ip};
+
+ if ($args{max_conn_ip}) {
+ my $num_conn = 1; # seed with current value
+ my $raddr = inet_aton($remote);
+ foreach my $rip (@{$args{child_addrs}}) {
+ ++$num_conn if (defined $rip && $rip eq $raddr);
+ }
+ if ($num_conn > $args{max_conn_ip}) {
+ $self->log(LOGINFO,
+ "Too many connections from $remote: "
+ . "$num_conn > " . $args{max_conn_ip}
+ . "Denying connection.");
+ return (DENYSOFT, "Sorry, too many connections from $remote, "
+ ."try again later");
+ }
+ }
+
+ foreach ($self->qp->config("hosts_allow")) {
+ s/^\s*//;
+ my ($ipmask, $const, $message) = split /\s+/, $_, 3;
+ next unless defined $const;
+
+ my ($net,$mask) = split '/', $ipmask, 2;
+ if (!defined $mask) {
+ $mask = 32;
+ }
+ $mask = pack "B32", "1"x($mask)."0"x(32-$mask);
+ if (join(".", unpack("C4", inet_aton($remote) & $mask)) eq $net) {
+ $const = Qpsmtpd::Constants::return_code($const) || DECLINED;
+ return($const, $message);
+ }
+ }
+
+ return (DECLINED);
+}
+
+# vim: sw=4 ts=4 expandtab syn=perl