On 2005-07-13 15:35:03 -0700, Ask Bjørn Hansen wrote:
> I tagged 0.31rc1.
[...]
> I figure we'll release 0.31 proper Friday or Monday if we get these  
> two things sorted and nothing else comes up.

The pre-connection and post-connection hooks are defined, but AFAICS
they aren't actually called anywhere. 

The attached patch calls the pre-connection hook in fork-server. It doesn't
touch tcpserver mode or Apache::Qpsmtp, and post-connection hook is
still missing, so this is just a quick and dirty patch, not a real fix.

        hp

PS: Look, Robert, no tabs :-)

-- 
   _  | Peter J. Holzer    | Ich sehe nun ein, dass Computer wenig
|_|_) | Sysadmin WSR       | geeignet sind, um sich was zu merken.
| |   | [EMAIL PROTECTED]         |
__/   | http://www.hjp.at/ |    -- Holger Lembke in dan-am
--- lib/Qpsmtpd/SMTP.pm.pre-connection  Mon Jul 11 14:24:26 2005
+++ lib/Qpsmtpd/SMTP.pm Sun Jul 17 17:16:36 2005
@@ -36,6 +36,9 @@
   # this list of valid commands should probably be a method or a set of methods
   $self->{_commands} = \%commands;
 
+  # should be somewhere in Qpsmtpd.pm and not here...
+  $self->load_plugins;
+
   $self;
 }
 
--- lib/Qpsmtpd/TcpServer.pm.pre-connection     Sun Jan 30 06:40:24 2005
+++ lib/Qpsmtpd/TcpServer.pm    Sun Jul 17 17:16:36 2005
@@ -38,9 +38,6 @@
 sub run {
     my $self = shift;
 
-    # should be somewhere in Qpsmtpd.pm and not here...
-    $self->load_plugins;
-
     my $rc = $self->start_conversation;
     return if $rc != DONE;
 
--- qpsmtpd-forkserver.pre-connection   Wed Jul  6 14:13:53 2005
+++ qpsmtpd-forkserver  Sun Jul 17 17:22:09 2005
@@ -30,7 +30,7 @@
 usage: qpsmtpd-forkserver [ options ]
  -l, --listen-address addr : listen on specific address(es); can be specified
                              multiple times for multiple bindings.  Default is
-                            0.0.0.0 (all interfaces).
+                             0.0.0.0 (all interfaces).
  -p, --port P              : listen on a specific port; default 2525
  -c, --limit-connections N : limit concurrent connections to N; default 15
  -u, --user U              : run as a particular user (default 'smtpd')
@@ -47,7 +47,7 @@
            'p|port=i' => \$PORT,
            'u|user=s' => \$USER,
            'pid-file=s' => \$PID_FILE,
-         ) || &usage;
+          ) || &usage;
 
 # detaint the commandline
 if ($PORT =~ /^(\d+)$/) { $PORT = $1 } else { &usage }
@@ -130,11 +130,11 @@
       die "unable to determine uid/gid for $USER\n";
 my $groups = "$qgid $qgid";
 while (my ($name,$passwd,$gid,$members) = getgrent()) {
-    my @m = split(/ /, $members);
-    if (grep {$_ eq $USER} @m) {
-       ::log(LOGINFO,"$USER is member of group $name($gid)");
-       $groups .= " $gid";
-    }
+  my @m = split(/ /, $members);
+  if (grep {$_ eq $USER} @m) {
+    ::log(LOGINFO,"$USER is member of group $name($gid)");
+    $groups .= " $gid";
+  }
 }
 $) = $groups;
 POSIX::setgid($qgid) or
@@ -145,9 +145,9 @@
 
 ::log(LOGINFO,"Listening on port $PORT");
 ::log(LOGINFO, 'Running as user '.
-       (getpwuid($>) || $>) .
-       ', group '.
-       (getgrgid($)) || $)));
+        (getpwuid($>) || $>) .
+        ', group '.
+        (getgrgid($)) || $)));
 
 while (1) {
   REAPER();
@@ -167,6 +167,10 @@
       next;
     }
     IO::Handle::blocking($client, 1);
+
+
+    # XXX this should probably be moved into a pre-connection hook
+    # {{{
     my ($port, $iaddr) = sockaddr_in($hisaddr);
     if ($MAXCONNIP) {
       my $num_conn = 1; # seed with current value
@@ -180,18 +184,55 @@
         ::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";
+        print $client "421 Sorry, too many connections from $rem_ip, try again 
later\r\n";
         close $client;
         next;
       }
     }
+    # }}}
+    
+    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);
+    $ENV{TCPREMOTEHOST} = gethostbyaddr($iaddr, AF_INET) || "Unknown";
+
+    ::log(LOGINFO, "Accepted connection $running/$MAXCONN from 
$ENV{TCPREMOTEIP} / $ENV{TCPREMOTEHOST}");
+    
+    # dup to STDIN/STDOUT
+    POSIX::dup2(fileno($client), 0);
+    POSIX::dup2(fileno($client), 1);
+    
+    my ($rc, $msg) = $qpsmtpd->run_hooks("pre-connection", $iaddr);
+    if ($rc == DENYSOFT) {
+      # RFC 2821: This may be a reply to any command if the service knows it 
must shut down.
+      # Connecting isn't really a command, as the greeting is a reply, it can 
be treated as
+      # one.
+      $client->autoflush(1);
+      print $client "421 ", ($msg || "Connection from you temporarily denied, 
bye bye."), "\r\n";
+      close $client;
+      next;
+    } elsif ($rc == DENY) {
+      # this is not correct according to RFC 2821: After a 554 response the
+      # channel must not be closed. So a pre-connection hook should never 
return
+      # DENY.
+      $client->autoflush(1);
+      print $client "554 ", ($msg || "Connection from you denied, bye bye."), 
"\r\n";
+      close $client;
+      next;
+    }
     my $pid = safe_fork();
     if ($pid) {
       # parent
-      $childstatus{$pid} = $iaddr;     # add to table
-      # $childstatus{$pid} = 1;        # add to table
+      $childstatus{$pid} = $iaddr;      # add to table
+      # $childstatus{$pid} = 1; # add to table
       $running++;
       close($client);
+      # redirect to something harmless.
+      # don't just close them to prevent something else to use stdin/out.
+      open(STDIN, "/dev/null");
+      open(STDOUT, ">/dev/null");
       next;
     }
     # otherwise child
@@ -207,22 +248,6 @@
        ::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);
-    $ENV{TCPREMOTEHOST} = gethostbyaddr($iaddr, AF_INET) || "Unknown";
-  
-    # don't do this!
-    #$0 = "qpsmtpd-forkserver: $ENV{TCPREMOTEIP} / $ENV{TCPREMOTEHOST}";
-  
-    ::log(LOGINFO, "Accepted connection $running/$MAXCONN from 
$ENV{TCPREMOTEIP} / $ENV{TCPREMOTEHOST}");
-    
-    # dup to STDIN/STDOUT
-    POSIX::dup2(fileno($client), 0);
-    POSIX::dup2(fileno($client), 1);
-    
     $qpsmtpd->start_connection
       (
        local_ip    => $ENV{TCPLOCALIP},

Attachment: pgpLWTPdk0v9P.pgp
Description: PGP signature

Reply via email to