develooper Front page | perl.cvs.qpsmtpd | Postings from January 2006

[svn:qpsmtpd] r599 - in branches/0.3x: . config.sample lib/Qpsmtpd

From:
jpeacock
Date:
January 11, 2006 08:21
Subject:
[svn:qpsmtpd] r599 - in branches/0.3x: . config.sample lib/Qpsmtpd
Message ID:
20060111162109.15386.qmail@x1.develooper.com
Author: jpeacock
Date: Wed Jan 11 08:21:08 2006
New Revision: 599

Modified:
   branches/0.3x/config.sample/plugins
   branches/0.3x/lib/Qpsmtpd/TcpServer.pm
   branches/0.3x/qpsmtpd-forkserver
Log:
the pre-connection and post-connection hooks are not working in
qpsmtpd-forkserver. This patch merges Peter's patch (with the possibilty
to DENY/DENSOFT the connection) and my first attempt. The --max-from-ip
check was moved from core to the hosts_allow plugin. 

Patch by: Hanno Hecker <hah@uu-x.de>

Modified: branches/0.3x/config.sample/plugins
==============================================================================
--- branches/0.3x/config.sample/plugins	(original)
+++ branches/0.3x/config.sample/plugins	Wed Jan 11 08:21:08 2006
@@ -6,6 +6,12 @@
 # plugins/http_config for details.
 #   http_config http://localhost/~smtpd/config/  http://www.example.com/smtp.pl?config=
 
+# The hosts_allow module must be loaded if you want the -m / --max-from-ip /
+# my $MAXCONNIP = 5; # max simultaneous connections from one IP
+# settings... without this it will NOT refuse more than $MAXCONNIP connections
+# from one IP!
+hosts_allow
+
 quit_fortune
 
 check_earlytalker

Modified: branches/0.3x/lib/Qpsmtpd/TcpServer.pm
==============================================================================
--- branches/0.3x/lib/Qpsmtpd/TcpServer.pm	(original)
+++ branches/0.3x/lib/Qpsmtpd/TcpServer.pm	Wed Jan 11 08:21:08 2006
@@ -84,6 +84,7 @@ sub disconnect {
   my $self = shift;
   $self->log(LOGDEBUG,"click, disconnecting");
   $self->SUPER::disconnect(@_);
+  $self->run_hooks("post-connection");
   exit;
 }
 

Modified: branches/0.3x/qpsmtpd-forkserver
==============================================================================
--- branches/0.3x/qpsmtpd-forkserver	(original)
+++ branches/0.3x/qpsmtpd-forkserver	Wed Jan 11 08:21:08 2006
@@ -192,23 +192,34 @@ while (1) {
     }
     IO::Handle::blocking($client, 1);
     my ($port, $iaddr) = sockaddr_in($hisaddr);
-    if ($MAXCONNIP) {
-      my $num_conn = 1; # seed with current value
-  
-      foreach my $rip (values %childstatus) {
-        ++$num_conn if (defined $rip && $rip eq $iaddr);
+    my $localsockaddr = getsockname($client);
+    my ($lport, $laddr) = sockaddr_in($localsockaddr);
+
+    my ($rc, @msg) = $qpsmtpd->run_hooks("pre-connection",
+                                         remote_ip    => inet_ntoa($iaddr),
+                                         remote_port  => $port,
+                                         local_ip     => inet_ntoa($laddr),
+                                         local_port   => $lport,
+                                         max_conn_ip  => $MAXCONNIP,
+                                         child_addrs  => [values %childstatus],
+                                        );
+    if ($rc == DENYSOFT || $rc == DENYSOFT_DISCONNECT) {
+      unless ($msg[0]) {
+        @msg = ("Sorry, try again later");
       }
-  
-      if ($num_conn > $MAXCONNIP) {
-        my $rem_ip = inet_ntoa($iaddr);
-        ::log(LOGINFO,"Too many connections from $rem_ip: "
-                     ."$num_conn > $MAXCONNIP. Denying connection.");
-        $client->autoflush(1);
-        print $client "451 Sorry, too many connections from $rem_ip, try again later\r\n";
-        close $client;
-        next;
+      &respond_client($client, 451, @msg);
+      close $client;
+      next;
+    } 
+    elsif ($rc == DENY || $rc == DENY_DISCONNECT) {
+      unless ($msg[0]) {
+        @msg = ("Sorry, service not available for you");
       }
+      &respond_client($client, 550, @msg);
+      close $client;
+      next;
     }
+
     my $pid = safe_fork();
     if ($pid) {
       # parent
@@ -231,8 +242,6 @@ while (1) {
        ::log(LOGINFO, "Connection Timed Out"); 
        exit; };
   
-    my $localsockaddr = getsockname($client);
-    my ($lport, $laddr) = sockaddr_in($localsockaddr);
     $ENV{TCPLOCALIP} = inet_ntoa($laddr);
     # my ($port, $iaddr) = sockaddr_in($hisaddr);
     $ENV{TCPREMOTEIP} = inet_ntoa($iaddr);
@@ -256,6 +265,7 @@ while (1) {
       );
     $qpsmtpd->run();
     
+    $qpsmtpd->run_hooks("post-connection");
     exit;                                   # child leaves
   }
 }
@@ -265,6 +275,18 @@ sub log {
   $qpsmtpd->log($level,$message);
 }
 
+sub respond_client {
+  my ($client, $code, @message) = @_;
+  $client->autoflush(1);
+  while (my $msg = shift @message) {
+    my $line = $code . (@message?"-":" ").$msg;
+    ::log(LOGDEBUG, $line);
+    print $client "$line\r\n" 
+      or (::log(LOGERROR, "Could not print [$line]: $!"), return 0);
+  }
+  return 1;
+}
+
 ### routine to protect process during fork
 sub safe_fork {
   



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