develooper Front page | perl.cvs.qpsmtpd | Postings from February 2007

[svn:qpsmtpd] r715 - in contrib/hjp/require_resolvable_client: . config.sample plugins t t/plugin_tests

From:
hjp
Date:
February 24, 2007 11:46
Subject:
[svn:qpsmtpd] r715 - in contrib/hjp/require_resolvable_client: . config.sample plugins t t/plugin_tests
Message ID:
20070224204639.BF7BFCBA1B@x12.develooper.com
Author: hjp
Date: Sat Feb 24 12:46:38 2007
New Revision: 715

Added:
   contrib/hjp/require_resolvable_client/config.sample/
   contrib/hjp/require_resolvable_client/config.sample/plugins
   contrib/hjp/require_resolvable_client/plugins/
   contrib/hjp/require_resolvable_client/plugins/require_resolvable_client
   contrib/hjp/require_resolvable_client/t/
   contrib/hjp/require_resolvable_client/t/plugin_tests/
   contrib/hjp/require_resolvable_client/t/plugin_tests/require_resolvable_client
Removed:
   contrib/hjp/require_resolvable_client/require_resolvable_client
Modified:
   contrib/hjp/require_resolvable_client/Makefile
   contrib/hjp/require_resolvable_client/Makerules
   contrib/hjp/require_resolvable_client/qpsmtpd-plugin-require_resolvable_client.spec

Log:
r249@hjp:
Made forward lookup configurable (thanks to "m. allan noah"
<kitno455@gmail.com> for the suggestion and part of the patch).
Also added some tests.


Modified: contrib/hjp/require_resolvable_client/Makefile
==============================================================================
--- contrib/hjp/require_resolvable_client/Makefile	(original)
+++ contrib/hjp/require_resolvable_client/Makefile	Sat Feb 24 12:46:38 2007
@@ -2,12 +2,18 @@
 FILES = $(PKG).spec \
     Makefile \
     Makerules \
-    $(NAME) \
+    plugins/$(NAME) \
+    t/plugin_tests/$(NAME) \
+    config.sample/plugins \
 
+TEST_LIB=~/wrk/qpsmtpd/trunk/t 
 
 all:
 
 clean:
 	rm -f $(PKG).tar.gz *.tmp
 
+test:
+	perl -I $(TEST_LIB) t/01_basic.t
+
 include Makerules

Modified: contrib/hjp/require_resolvable_client/Makerules
==============================================================================
--- contrib/hjp/require_resolvable_client/Makerules	(original)
+++ contrib/hjp/require_resolvable_client/Makerules	Sat Feb 24 12:46:38 2007
@@ -8,7 +8,7 @@
 	cp -p $^ $@
 
 rpm: $(PKG).tar.gz
-	rpm -ta --clean --sign --rmsource $^
+	rpmbuild -ta --clean --sign --rmsource $^
 
 $(PKG).tar.gz: $(FILES)
 	tar cfz $@ $^

Added: contrib/hjp/require_resolvable_client/config.sample/plugins
==============================================================================
--- (empty file)
+++ contrib/hjp/require_resolvable_client/config.sample/plugins	Sat Feb 24 12:46:38 2007
@@ -0,0 +1 @@
+require_resolvable_client

Added: contrib/hjp/require_resolvable_client/plugins/require_resolvable_client
==============================================================================
--- (empty file)
+++ contrib/hjp/require_resolvable_client/plugins/require_resolvable_client	Sat Feb 24 12:46:38 2007
@@ -0,0 +1,140 @@
+=head1 NAME
+
+require_resolvable_client
+
+=head1 DESCRIPTION
+
+Plugin to reject mails if the IP address of the client doesn't resolve
+to a hostname.
+
+=head1 CONFIG
+
+The following parameters can be passed to require_resolvable_client:
+
+=over 4
+
+
+=item per_recipient <bool>
+
+Per recipient flag - if this is set, the plugin is only run for
+recipients which have recipient_option 'require_resolvable_client' set.
+This can be set by the aliases plugin.
+Default: 0.
+
+=item at_connect <bool>
+
+If this flag is set, the temporary failure will be generated immediately
+after the connect and the connection will be terminated. Otherwise, it
+will be generated in response to RCPT TO commands.
+Dropping the connection immediately saves resources and prevents address
+harvesting. On the other hand, it cannot be (de)activated per recipient.
+Default: 0
+
+=item permfail <bool>
+
+If this flag is set, a permanent failure is reported. Otherwise it is
+only a temporary failure, giving the admin of the client a chance to fix
+the problem before the user notices it.
+Default: 0
+
+=item forward_lookup <bool>
+
+If this flag is set, an additional forward DNS check (hostname to IP) is
+performed. Otherwise, only the reverse DNS check is performed.
+Default: 1
+
+=back
+
+=head1 NOTES
+
+This plugin makes use of the following connection notes:
+
+=over
+
+=item 'client_options'->{require_resolvable_client}{skip}
+
+If true, do nothing. This note is usually set by the 
+client_options plugin.
+
+=back
+
+and of the following transaction notes:
+
+=over
+
+=item 'recipient_options'->{require_resolvable_client}
+
+If true, per recipient checking is performed. This is only used if the
+per_recipient flag is set. This note is usually set by the aliases
+plugin.
+
+=back
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (c) 2006 Peter J. Holzer <hjp@hjp.at>. 
+
+This plugin is licensed under the same terms as the qpsmtpd package
+itself.
+Please see the LICENSE file included with qpsmtpd for details.
+
+=cut
+
+
+
+sub register {
+    my ($self, $qp, %arg) = @_;
+    $self->{_require_resolvable_client_per_recipient} = $arg{per_recipient};
+    $self->{_require_resolvable_client_permfail} = $arg{permfail};
+    $self->{_require_resolvable_client_forward_lookup}
+	= defined $arg{forward_lookup} ? $arg{forward_lookup} : 1;
+    if ($arg{at_connect}) {
+        $self->register_hook("connect", "handler");
+    } else {
+        $self->register_hook("rcpt", "handler");
+    }
+}
+
+sub handler {
+    my ($self, $transaction) = @_;
+
+    $self->log(LOGDEBUG, "in handler");
+    if (my $co = $self->qp->connection->notes('client_options')) {
+	if ($co->{require_resolvable_client}{skip}) {
+	    $self->log(LOGINFO, "client is whitelisted, skipping IP checks");
+	    return DECLINED 
+	}
+    }
+    my $forward_lookup = $self->{_require_resolvable_client_forward_lookup};
+    if ($self->{_require_resolvable_client_per_recipient}) {
+	my $ro = $transaction->notes('recipient_options');
+	return DECLINED unless ($ro && $ro->{require_resolvable_client});
+	$forward_lookup = $ro->{require_resolvable_client}{forward_lookup}
+	    if (ref $ro->{require_resolvable_client} eq 'HASH' 
+	        && exists $ro->{require_resolvable_client}{forward_lookup});
+    }
+    my $hostname = $self->connection->remote_host;
+    $self->log(LOGDEBUG, "hostname $hostname");
+    if ($hostname eq "Unknown" || $hostname =~ m /^\[[\d.]+\]$/ || $hostname =~ m /^[\d.]+$/ ) {
+	$self->log(LOGINFO, "$hostname not a FQDN, returning failure");
+	return $self->{_require_resolvable_client_permfail} ? DENY : DENYSOFT,
+	       "Reverse lookup for " . $self->connection->remote_ip . " failed";
+    }
+
+    if (!$forward_lookup) {
+        $self->log(LOGDEBUG, "skipping forward lookup of $hostname against " .  $self->connection->remote_ip);
+	return DECLINED;
+    }
+
+    $self->log(LOGDEBUG, "checking addresses of $hostname against " .  $self->connection->remote_ip);
+    my $ip = pack("C*", split(/\./, $self->connection->remote_ip));
+    my ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($hostname);
+    for (@addrs) {
+	$self->log(LOGDEBUG, "checking address " .  join(".", unpack("C4", $_)));
+	return DECLINED if ($ip eq $_);
+    }
+    $self->log(LOGINFO, "no address matches " .  $self->connection->remote_ip . ", returning failure");
+    return $self->{_require_resolvable_client_permfail} ? DENY : DENYSOFT,
+	   "Host name " . $self->connection->remote_host . " doesn't match IP address " . $self->connection->remote_ip;
+}
+

Modified: contrib/hjp/require_resolvable_client/qpsmtpd-plugin-require_resolvable_client.spec
==============================================================================
--- contrib/hjp/require_resolvable_client/qpsmtpd-plugin-require_resolvable_client.spec	(original)
+++ contrib/hjp/require_resolvable_client/qpsmtpd-plugin-require_resolvable_client.spec	Sat Feb 24 12:46:38 2007
@@ -1,5 +1,5 @@
 Name: qpsmtpd-plugin-require_resolvable_client
-Version: 199
+Version: 248
 Release: 1
 Packager: hjp@hjp.at
 Summary: require_resolvable_client plugin for qpsmtpd
@@ -25,7 +25,7 @@
 %install
 rm -rf $RPM_BUILD_ROOT
 mkdir -p $RPM_BUILD_ROOT/usr/share/qpsmtpd/plugins
-cp require_resolvable_client $RPM_BUILD_ROOT/usr/share/qpsmtpd/plugins
+cp plugins/require_resolvable_client $RPM_BUILD_ROOT/usr/share/qpsmtpd/plugins
 
 [ -x /usr/lib/rpm/brp-compress ] && /usr/lib/rpm/brp-compress
 
@@ -35,6 +35,12 @@
 /usr/share/qpsmtpd/plugins/require_resolvable_client
 
 %changelog
+* Sat Feb 24 2007 <hjp@hjp.at> 248-1
+- r248: use rpmbuild instead of rpm.
+- r247: Made forward lookup per-recipient configurable.
+- r243: Patch by "m. allan noah" <kitno455@gmail.com> to make forward
+  lookup optional.
+
 * Fri Aug 11 2006 <hjp@hjp.at> 199-1
 - First RPM package.
 

Added: contrib/hjp/require_resolvable_client/t/plugin_tests/require_resolvable_client
==============================================================================
--- (empty file)
+++ contrib/hjp/require_resolvable_client/t/plugin_tests/require_resolvable_client	Sat Feb 24 12:46:38 2007
@@ -0,0 +1,31 @@
+sub register_tests {
+    my ($self) = @_;
+
+    $self->register_test("test", 5);
+}
+
+sub test {
+    my ($self) = @_;
+    my $connection = $self->qp->connection;
+    $connection->remote_host('example.com');
+    $connection->remote_ip('192.0.34.166');
+    my ($code, @strings) = $self->handler();
+    ok ($code == DECLINED, "example.com is 192.0.34.166");
+    $connection->remote_ip('127.0.0.2');
+    ($code, @strings) = $self->handler();
+    ok ($code == DENYSOFT, "example.com isn't 127.0.0.2");
+    $self->{_require_resolvable_client_forward_lookup} = 0;
+    ($code, @strings) = $self->handler();
+    ok ($code == DECLINED, "skipping forward check works");
+
+    $self->{_require_resolvable_client_forward_lookup} = 1;
+    $self->{_require_resolvable_client_per_recipient} = 1;
+    my $transaction = $self->transaction();
+    $transaction->notes('recipient_options', { require_resolvable_client => 1 });
+    ($code, @strings) = $self->handler($transaction);
+    cmp_ok($code, '==', DENYSOFT, "example.com isn't 127.0.0.2");
+    $transaction->notes('recipient_options',
+                        { require_resolvable_client => { forward_lookup => 0 } });
+    ($code, @strings) = $self->handler($transaction);
+    ok ($code == DECLINED, "skipping forward check works");
+}



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About