2002-07-03 15:10:44 +02:00
|
|
|
package Qpsmtpd::TcpServer;
|
2002-09-24 12:56:35 +02:00
|
|
|
use Qpsmtpd::SMTP;
|
2003-04-15 19:01:43 +02:00
|
|
|
use Qpsmtpd::Constants;
|
2006-12-16 10:30:32 +01:00
|
|
|
use Socket;
|
2003-04-15 19:01:43 +02:00
|
|
|
|
2002-09-24 12:56:35 +02:00
|
|
|
@ISA = qw(Qpsmtpd::SMTP);
|
2002-07-03 15:10:44 +02:00
|
|
|
use strict;
|
|
|
|
|
2004-06-05 12:06:44 +02:00
|
|
|
use POSIX ();
|
|
|
|
|
|
|
|
my $first_0;
|
|
|
|
|
2002-07-03 15:10:44 +02:00
|
|
|
sub start_connection {
|
|
|
|
my $self = shift;
|
|
|
|
|
2006-12-16 10:30:32 +01:00
|
|
|
my ($remote_host, $remote_info, $remote_ip);
|
2002-08-06 14:34:03 +02:00
|
|
|
|
2006-12-16 10:30:32 +01:00
|
|
|
if ($ENV{TCPREMOTEIP}) {
|
|
|
|
# started from tcpserver (or some other superserver which
|
|
|
|
# exports the TCPREMOTE* variables.
|
|
|
|
$remote_ip = $ENV{TCPREMOTEIP};
|
|
|
|
$remote_host = $ENV{TCPREMOTEHOST} || "[$remote_ip]";
|
|
|
|
$remote_info = $ENV{TCPREMOTEINFO} ? "$ENV{TCPREMOTEINFO}\@$remote_host" : $remote_host;
|
|
|
|
} else {
|
|
|
|
# Started from inetd or similar.
|
|
|
|
# get info on the remote host from the socket.
|
|
|
|
# ignore ident/tap/...
|
|
|
|
my $hersockaddr = getpeername(STDIN)
|
|
|
|
or die "getpeername failed: $0 must be called from tcpserver, (x)inetd or a similar program which passes a socket to stdin";
|
|
|
|
my ($port, $iaddr) = sockaddr_in($hersockaddr);
|
|
|
|
$remote_ip = inet_ntoa($iaddr);
|
|
|
|
$remote_host = gethostbyaddr($iaddr, AF_INET) || "[$remote_ip]";
|
|
|
|
$remote_info = $remote_host;
|
|
|
|
}
|
2004-08-01 08:56:33 +02:00
|
|
|
$self->log(LOGNOTICE, "Connection from $remote_info [$remote_ip]");
|
2002-07-03 15:10:44 +02:00
|
|
|
|
2003-04-21 10:28:12 +02:00
|
|
|
# if the local dns resolver doesn't filter it out we might get
|
|
|
|
# ansi escape characters that could make a ps axw do "funny"
|
|
|
|
# things. So to be safe, cut them out.
|
|
|
|
$remote_host =~ tr/a-zA-Z\.\-0-9//cd;
|
|
|
|
|
2004-06-05 12:06:44 +02:00
|
|
|
$first_0 = $0 unless $first_0;
|
|
|
|
my $now = POSIX::strftime("%H:%M:%S %Y-%m-%d", localtime);
|
|
|
|
$0 = "$first_0 [$remote_ip : $remote_host : $now]";
|
2003-04-16 18:35:14 +02:00
|
|
|
|
2002-07-03 15:10:44 +02:00
|
|
|
$self->SUPER::connection->start(remote_info => $remote_info,
|
|
|
|
remote_ip => $remote_ip,
|
|
|
|
remote_host => $remote_host,
|
|
|
|
@_);
|
|
|
|
}
|
|
|
|
|
|
|
|
sub run {
|
|
|
|
my $self = shift;
|
|
|
|
|
2002-07-06 09:16:23 +02:00
|
|
|
# should be somewhere in Qpsmtpd.pm and not here...
|
2005-09-22 19:14:20 +02:00
|
|
|
$self->load_plugins unless $self->{hooks};
|
2002-07-06 09:16:23 +02:00
|
|
|
|
2003-04-15 19:01:43 +02:00
|
|
|
my $rc = $self->start_conversation;
|
|
|
|
return if $rc != DONE;
|
2002-07-03 15:10:44 +02:00
|
|
|
|
|
|
|
# this should really be the loop and read_input should just get one line; I think
|
2002-09-12 09:31:56 +02:00
|
|
|
|
2002-07-03 15:10:44 +02:00
|
|
|
$self->read_input;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub read_input {
|
|
|
|
my $self = shift;
|
2002-09-12 09:31:56 +02:00
|
|
|
|
2004-11-25 20:50:18 +01:00
|
|
|
my $timeout =
|
|
|
|
$self->config('timeoutsmtpd') # qmail smtpd control file
|
|
|
|
|| $self->config('timeout') # qpsmtpd control file
|
|
|
|
|| 1200; # default value
|
|
|
|
|
2002-07-06 09:16:23 +02:00
|
|
|
alarm $timeout;
|
2002-07-03 15:10:44 +02:00
|
|
|
while (<STDIN>) {
|
|
|
|
alarm 0;
|
|
|
|
$_ =~ s/\r?\n$//s; # advanced chomp
|
2004-03-05 13:46:24 +01:00
|
|
|
$self->log(LOGDEBUG, "dispatching $_");
|
2005-01-30 06:40:24 +01:00
|
|
|
$self->connection->notes('original_string', $_);
|
2006-04-07 20:58:02 +02:00
|
|
|
defined $self->dispatch(split / +/, $_, 2)
|
2002-07-03 15:10:44 +02:00
|
|
|
or $self->respond(502, "command unrecognized: '$_'");
|
2002-07-06 09:16:23 +02:00
|
|
|
alarm $timeout;
|
2002-07-03 15:10:44 +02:00
|
|
|
}
|
2004-11-19 09:44:24 +01:00
|
|
|
alarm(0);
|
2002-07-03 15:10:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub respond {
|
|
|
|
my ($self, $code, @messages) = @_;
|
2006-10-04 15:49:49 +02:00
|
|
|
my $buf = '';
|
2002-07-03 15:10:44 +02:00
|
|
|
while (my $msg = shift @messages) {
|
|
|
|
my $line = $code . (@messages?"-":" ").$msg;
|
2004-08-01 08:56:33 +02:00
|
|
|
$self->log(LOGDEBUG, $line);
|
2006-10-04 15:49:49 +02:00
|
|
|
$buf .= "$line\r\n";
|
2002-07-03 15:10:44 +02:00
|
|
|
}
|
2006-10-04 15:49:49 +02:00
|
|
|
print $buf or ($self->log(LOGERROR, "Could not print [$buf]: $!"), return 0);
|
2002-07-03 15:10:44 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-07-15 13:49:49 +02:00
|
|
|
sub disconnect {
|
|
|
|
my $self = shift;
|
2004-11-27 07:41:06 +01:00
|
|
|
$self->log(LOGDEBUG,"click, disconnecting");
|
2002-07-15 13:49:49 +02:00
|
|
|
$self->SUPER::disconnect(@_);
|
2006-01-11 17:21:08 +01:00
|
|
|
$self->run_hooks("post-connection");
|
2002-07-15 13:49:49 +02:00
|
|
|
exit;
|
|
|
|
}
|
2002-07-03 15:10:44 +02:00
|
|
|
|
|
|
|
1;
|