diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e980c413..00000000 --- a/.travis.yml +++ /dev/null @@ -1,11 +0,0 @@ -language: perl -perl: - - "5.18" - - "5.16" - - "5.8" - -before_install: - - cpanm -n Devel::Cover::Report::Coveralls - -after_script: - - cover -test -report coveralls diff --git a/MANIFEST b/MANIFEST index 6ad35735..25245fcc 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,8 +1,8 @@ .gitignore -.travis.yml bin/geolite-mirror-simple.pl bin/install_deps.pl Changes +config.sample/add_geoip_headers config.sample/badhelo config.sample/badmailfrom config.sample/badrcptto @@ -12,6 +12,7 @@ config.sample/dnsbl_zones config.sample/flat_auth_pw config.sample/invalid_resolvable_fromhost config.sample/IP +config.sample/karma_tlds config.sample/log2sql config.sample/logging config.sample/loglevel @@ -42,6 +43,9 @@ lib/Qpsmtpd/Config.pm lib/Qpsmtpd/ConfigServer.pm lib/Qpsmtpd/Connection.pm lib/Qpsmtpd/Constants.pm +lib/Qpsmtpd/DB.pm +lib/Qpsmtpd/DB/File/DBM.pm +lib/Qpsmtpd/DB/Redis.pm lib/Qpsmtpd/DSN.pm lib/Qpsmtpd/Plugin.pm lib/Qpsmtpd/Postfix.pm @@ -64,6 +68,7 @@ META.yml Module meta-data (added by MakeMaker) plugins/auth/auth_checkpassword plugins/auth/auth_cvm_unix_local plugins/auth/auth_flat_file +plugins/auth/auth_imap plugins/auth/auth_ldap_bind plugins/auth/auth_vpopmail plugins/auth/auth_vpopmail_sql @@ -149,8 +154,10 @@ run.tcpserver STATUS t/addresses.t t/auth.t +t/config/add_geoip_headers t/config/badhelo t/config/badrcptto +t/config/content_log_enabled t/config/dnsbl_allow t/config/dnsbl_zones t/config/flat_auth_pw @@ -169,6 +176,7 @@ t/misc.t t/plugin_tests.t t/plugin_tests/auth/auth_checkpassword t/plugin_tests/auth/auth_flat_file +t/plugin_tests/auth/auth_imap t/plugin_tests/auth/auth_vpopmail t/plugin_tests/auth/auth_vpopmail_sql t/plugin_tests/auth/auth_vpopmaild @@ -177,11 +185,13 @@ t/plugin_tests/auth/authnull t/plugin_tests/badmailfrom t/plugin_tests/badmailfromto t/plugin_tests/badrcptto +t/plugin_tests/content_log t/plugin_tests/count_unrecognized_commands t/plugin_tests/dmarc t/plugin_tests/dnsbl t/plugin_tests/dspam t/plugin_tests/earlytalker +t/plugin_tests/fcrdns t/plugin_tests/greylisting t/plugin_tests/headers t/plugin_tests/helo @@ -197,6 +207,10 @@ t/plugin_tests/virus/clamdscan t/qpsmtpd-address.t t/qpsmtpd-base.t t/qpsmtpd-config.t +t/qpsmtpd-db-file-dbm.t +t/qpsmtpd-db-redis.t +t/qpsmtpd-db.t +t/qpsmtpd-plugin.t t/qpsmtpd-smtp.t t/qpsmtpd.t t/rset.t diff --git a/MANIFEST.SKIP b/MANIFEST.SKIP index 6cbde865..a467db85 100644 --- a/MANIFEST.SKIP +++ b/MANIFEST.SKIP @@ -14,6 +14,7 @@ output/.* ^sqlite/ ^output/ ^tmp/ +^t/tmp/ ^blib/ ^blibdirs$ ^Makefile$ @@ -36,3 +37,4 @@ packaging ^supervise/ ^ssl/ ^t/config/greylist +^.github diff --git a/lib/Qpsmtpd/TcpServer.pm b/lib/Qpsmtpd/TcpServer.pm deleted file mode 100644 index 81b7b7ae..00000000 --- a/lib/Qpsmtpd/TcpServer.pm +++ /dev/null @@ -1,215 +0,0 @@ -package Qpsmtpd::TcpServer; -use strict; - -use POSIX (); -use Socket; - -use lib 'lib'; -use Qpsmtpd::Base; -use Qpsmtpd::Constants; -use parent 'Qpsmtpd::SMTP'; - -my $base = Qpsmtpd::Base->new(); - -my $has_ipv6 = 0; -if ( - eval { require Socket6; } && - eval { require IO::Socket::INET6; IO::Socket::INET6->VERSION('2.51'); } - ) -{ - Socket6->import('inet_ntop'); - $has_ipv6 = 1; -} - -sub has_ipv6 { - return $has_ipv6; -} - -my $first_0; - -sub conn_info_tcpserver { - - # started from tcpserver (or some other superserver which - # exports the TCPREMOTE* variables. - - my $r_host = $ENV{TCPREMOTEHOST} || '[' . $ENV{TCPREMOTEIP} . ']'; - return ( - local_ip => $ENV{TCPLOCALIP}, - local_host => $ENV{TCPLOCALHOST}, - local_port => $ENV{TCPLOCALPORT}, - remote_ip => $ENV{TCPREMOTEIP}, - remote_host => $r_host, - remote_info => $ENV{TCPREMOTEINFO} ? "$ENV{TCPREMOTEINFO}\@$r_host" : $r_host, - remote_port => $ENV{TCPREMOTEPORT}, - ) -} - -sub conn_info_inetd { - my $self = shift; - - # 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 ($r_port, $iaddr) = sockaddr_in($hersockaddr); - my $r_ip = inet_ntoa($iaddr); - my ($r_host) = $base->resolve_ptr($r_ip) || "[$r_ip]"; - - return ( - local_ip => '', - local_host => '', - local_port => '', - remote_ip => $r_ip, - remote_host => $r_host, - remote_info => $r_host, - remote_port => $r_port, - ) -} - -sub start_connection { - my $self = shift; - - my %info; - if ($ENV{TCPREMOTEIP}) { - %info = $self->conn_info_tcpserver(); - } - else { - %info = $self->conn_info_inetd(); - } - $self->log(LOGNOTICE, "Connection from $info{remote_info} [$info{remote_ip}]"); - - # 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. - $info{remote_host} =~ tr/a-zA-Z\.\-0-9\[\]//cd; - - $first_0 = $0 unless $first_0; - my $now = POSIX::strftime("%H:%M:%S %Y-%m-%d", localtime); - $0 = "$first_0 [$info{remote_ip} : $info{remote_host} : $now]"; - - $self->SUPER::connection->start(%info, @_); -} - -sub run { - my ($self, $client) = @_; - -# Set local client_socket to passed client object for testing socket state on writes - $self->{__client_socket} = $client; - - $self->load_plugins if !$self->{hooks}; - - my $rc = $self->start_conversation; - return if $rc != DONE; - -# this should really be the loop and read_input should just get one line; I think - $self->read_input; -} - -sub read_input { - my $self = shift; - - my $timeout = $self->config('timeoutsmtpd') # qmail smtpd control file - || $self->config('timeout') # qpsmtpd control file - || 1200; # default value - - alarm $timeout; - while () { - alarm 0; - $_ =~ s/\r?\n$//s; # advanced chomp - my $log = $_; - $log =~ s/AUTH PLAIN (.*)/AUTH PLAIN / - unless ($self->config('loglevel') || '6') >= 7; - $self->log(LOGINFO, "dispatching $log"); - $self->connection->notes('original_string', $_); - defined $self->dispatch(split / +/, $_, 2) - or $self->respond(502, "command unrecognized: '$_'"); - alarm $timeout; - } - alarm(0); - return if $self->connection->notes('disconnected'); - $self->reset_transaction; - $self->run_hooks('disconnect'); - $self->connection->notes(disconnected => 1); -} - -sub respond { - my ($self, $code, @messages) = @_; - my $buf = ''; - - if (!$self->check_socket()) { - $self->log(LOGERROR, - "Lost connection to client, cannot send response."); - return 0; - } - - while (my $msg = shift @messages) { - my $line = $code . (@messages ? "-" : " ") . $msg; - $self->log(LOGINFO, $line); - $buf .= "$line\r\n"; - } - print $buf - or ($self->log(LOGERROR, "Could not print [$buf]: $!"), return 0); - return 1; -} - -sub disconnect { - my $self = shift; - $self->log(LOGINFO, "click, disconnecting"); - $self->SUPER::disconnect(@_); - $self->run_hooks("post-connection"); - $self->connection->reset; - exit; -} - -# local/remote port and ip address -sub lrpip { - my ($self, $server, $client, $hisaddr) = @_; - - my $localsockaddr = getsockname($client); - my ($port, $iaddr, $lport, $laddr, $nto_iaddr, $nto_laddr); - - if ($server->sockdomain == AF_INET6) { # IPv6 - ($port, $iaddr) = sockaddr_in6($hisaddr); - ($lport, $laddr) = sockaddr_in6($localsockaddr); - $nto_iaddr = inet_ntop(AF_INET6(), $iaddr); - $nto_laddr = inet_ntop(AF_INET6(), $laddr); - } - else { # IPv4 - ($port, $iaddr) = sockaddr_in($hisaddr); - ($lport, $laddr) = sockaddr_in($localsockaddr); - $nto_iaddr = inet_ntoa($iaddr); - $nto_laddr = inet_ntoa($laddr); - } - - $nto_iaddr =~ s/::ffff://; - $nto_laddr =~ s/::ffff://; - - return $port, $iaddr, $lport, $laddr, $nto_iaddr, $nto_laddr; -} - -sub tcpenv { - my ($self, $TCPLOCALIP, $TCPREMOTEIP, $no_rdns) = @_; - - if ($no_rdns) { - return $TCPLOCALIP, $TCPREMOTEIP, - $TCPREMOTEIP ? "[$ENV{TCPREMOTEIP}]" : "[noip!]"; - } - my ($TCPREMOTEHOST) = $base->resolve_ptr($TCPREMOTEIP); - $TCPREMOTEHOST ||= 'Unknown'; - - return $TCPLOCALIP, $TCPREMOTEIP, $TCPREMOTEHOST; -} - -sub check_socket() { - my $self = shift; - - return 1 if ($self->{__client_socket}->connected); - - return 0; -} - -1; diff --git a/qpsmtpd b/qpsmtpd deleted file mode 100755 index b1b89ae1..00000000 --- a/qpsmtpd +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/perl -Tw -# Copyright (c) 2001-2010 Ask Bjoern Hansen. See the LICENSE file for details. -# The "command dispatch" system was taken from colobus - http://trainedmonkey.com/colobus/ -# -# this is designed to be run under tcpserver (http://cr.yp.to/ucspi-tcp.html) -# or inetd if you're into that sort of thing -# -# For more information see http://smtpd.github.io/qpsmtpd/ -# - -use lib 'lib'; -use Qpsmtpd::TcpServer; -use strict; -$| = 1; - -delete $ENV{ENV}; -$ENV{PATH} = '/bin:/usr/bin:/var/qmail/bin'; - -my $qpsmtpd = Qpsmtpd::TcpServer->new(); -$qpsmtpd->load_plugins(); -$qpsmtpd->start_connection(); -$qpsmtpd->run(\*STDIN); # pass the "socket" like -forkserver -$qpsmtpd->run_hooks("post-connection"); -$qpsmtpd->connection->reset; - -# needed for Qpsmtpd::TcpServer::check_socket(): -# emulate IO::Socket::connected on STDIN. STDIN was used instead of STDOUT -# because the other code also calls getpeername(STDIN). -sub IO::Handle::connected { return getpeername(shift) } - -__END__ - - -1;