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},
pgpLWTPdk0v9P.pgp
Description: PGP signature
