Hello community, here is the log from the commit of package postgrey for openSUSE:Factory checked in at 2016-10-20 23:09:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/postgrey (Old) and /work/SRC/openSUSE:Factory/.postgrey.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "postgrey" Changes: -------- --- /work/SRC/openSUSE:Factory/postgrey/postgrey.changes 2016-05-23 16:39:07.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.postgrey.new/postgrey.changes 2016-10-20 23:09:50.000000000 +0200 @@ -1,0 +2,17 @@ +Thu Oct 13 23:25:32 UTC 2016 - [email protected] + +- Update to 1.37: + * added initial test suite + * testing using travis-ci (https://travis-ci.org/schweikert/postgrey) + * removed IP pool-detection code for --lookup-by-net, because it matched + also the naming of some big hosters like facebook (#32, Michal Petrucha, + Andrew Ayer, Jon Sailor) + * fix early logging of errors and warnings to syslog + * simplified IP matching code + * added support for IPv6 whitelists with netmask + * add network-range based whitelist for Office 365 (Holger Stember) + * updated whitelist +- postgrey-1.36-config.patch renamed to postgrey-1.37-config.patch + and rebased to new version. + +------------------------------------------------------------------- Old: ---- postgrey-1.36-config.patch postgrey-1.36.tar.gz New: ---- postgrey-1.37-config.patch postgrey-1.37.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ postgrey.spec ++++++ --- /var/tmp/diff_new_pack.zdza1l/_old 2016-10-20 23:09:51.000000000 +0200 +++ /var/tmp/diff_new_pack.zdza1l/_new 2016-10-20 23:09:51.000000000 +0200 @@ -17,7 +17,7 @@ Name: postgrey -Version: 1.36 +Version: 1.37 Release: 0 Summary: Postfix greylisting policy server License: GPL-2.0+ @@ -34,7 +34,7 @@ # PATCH-FIX-OPENSUSE -- Adapt default config and documentation to pathnames for openSUSE # /etc/postfix => /etc/postgrey # /var/spool/postfix/postgrey => /var/lib/postgrey -Patch0: %{name}-1.36-config.patch +Patch0: %{name}-%{version}-config.patch # PATCH-FIX-OPENSUSE -- run postgrey under the same groupid as postfix: postfix Patch1: %{name}-groupid.patch # PATCH-FIX-OPENSUSE -- patch SOURCE5 to run under openSUSE ++++++ postgrey-1.36-config.patch -> postgrey-1.37-config.patch ++++++ --- /work/SRC/openSUSE:Factory/postgrey/postgrey-1.36-config.patch 2016-01-07 00:24:48.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.postgrey.new/postgrey-1.37-config.patch 2016-10-20 23:09:50.000000000 +0200 @@ -1,8 +1,19 @@ -Index: README -=================================================================== ---- README.orig -+++ README -@@ -21,7 +21,7 @@ Documentation +diff -rNU 15 ../postgrey-1.37-o/README ./README +--- ../postgrey-1.37-o/README 2015-07-23 23:04:07.000000000 +0200 ++++ ./README 2016-10-14 01:33:15.000000000 +0200 +@@ -9,31 +9,31 @@ + + - Perl >= 5.6.0 + - Net::Server (Perl Module) + - IO::Multiplex (Perl Module) + - BerkeleyDB (Perl Module) + - Berkeley DB >= 4.1 (Library) + - Digest::SHA (Perl Module, only for --privacy option) + - NetAddr::IP + + + Documentation + ------------- See POD documentation in postgrey. Execute: @@ -11,11 +22,34 @@ See also Postgrey's homepage: -Index: contrib/postgreyreport -=================================================================== ---- contrib/postgreyreport.orig -+++ contrib/postgreyreport -@@ -24,7 +24,7 @@ select((select(STDOUT), $| = 1)[0]); # + http://postgrey.schweikert.ch/ + + + Mailing-List and getting Help + ----------------------------- + + There is a mailing-list for the discussion of postgrey, where you can + also ask for help in case of trouble. To subscribe, send a mail with + subject 'subscribe' to: + + [email protected] + +diff -rNU 15 ../postgrey-1.37-o/contrib/postgreyreport ./contrib/postgreyreport +--- ../postgrey-1.37-o/contrib/postgreyreport 2013-12-12 11:32:41.000000000 +0100 ++++ ./contrib/postgreyreport 2016-10-14 01:34:27.000000000 +0200 +@@ -12,31 +12,31 @@ + #use Net::RBLClient; + my $VERSION='1.14.3 (20100321)'; + + # used in maillog processing + my $RE_revdns_ip = qr/ ([^\[\s]+)\[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]/; # ptr[1.2.3.4] + my $RE_reject = qr/reject: /; + my $RE_triplet = qr/$RE_revdns_ip: 450 .+from=<([^>]+)> to=<([^>]+)>/; + + my $dns; my %dns_cache; # used for --check_sender + my $rbl = undef; # Net::RBLClient object + select((select(STDOUT), $| = 1)[0]); # Unbuffer standard output. + # default options, override via command line my %opt = ( user => 'postgrey', @@ -24,7 +58,31 @@ delay => 300, return_string => 'Greylisted', # match on this string -@@ -594,7 +594,7 @@ B<postgreyreport> [I<options>...] + check_sender => '', # = mx,a,mx/24,a/24 # todo=spf - uses Net::DNS + show_tries => 0, # number of greylist attempts within --delay + separate_by_subnet => '', # if not blank output this string for every new /24 + separate_by_ip => '', # if not blank output this string for every new IP + single_line => 1, # output everything on a single line? (grouping enabled if false ) + tab => 0, # use tabs as separators, not spaces (only in single line mode) + show_time => 0, # show entry time in maillog + + skip_dnsbl => [], # list of DNSBL servers to check and skip reporting for + skip_clients => [], # files of clients to skip reporting + skip_pool => 0, # skip entries that appear to be a provider pool (last 2 ips in ptr) + match_clients => [], # files of ONLY clients to report on +@@ -582,31 +582,31 @@ + + + + =head1 NAME + + postgreyreport - Fatal report for Postfix Greylisting Policy Server + + =head1 SYNOPSIS + + B<postgreyreport> [I<options>...] + + -h, --help display this help and exit --version display version and exit --user=USER run as USER (default: postgrey) @@ -33,22 +91,69 @@ --delay=N report triplets that did not try again after N seconds (default: 300) --greylist-text=TXT text to match on for greylist maillog lines -Index: postgrey -=================================================================== ---- postgrey.orig -+++ postgrey -@@ -24,8 +24,8 @@ use vars qw(@ISA); + --skip_pool Skip report for 'subscriber pools' ( last 2 octets of IP found in PTR name ) + --skip_dnsbl=RBL RBL server to query and skip reporting for any listed hosts (SLOW!!) + --skip_clients=FILE PTR or IP or REGEXP of clients to skip in report + --match_clients=FILE *ONLY* report if fatal *AND* PTR/IP of client matches + + --show_tries display the number of attempts failed triplets made in first column + --show_time show entry time in maillog (single line only) + --tab use tabs as separators for easy cut(1)ting + + --nosingle_line display sender/recipients grouped by ptr - ip + --separate_by_subnet=TXT display TXT for every new /24 (ex: "=================\n" ) + --separate_by_ip=TXT display TXT for every new IP (ex: "\n") +diff -rNU 15 ../postgrey-1.37-o/postgrey ./postgrey +--- ../postgrey-1.37-o/postgrey 2016-09-22 10:09:38.000000000 +0200 ++++ ./postgrey 2016-10-14 01:50:20.000000000 +0200 +@@ -12,32 +12,32 @@ + use Pod::Usage; + use Getopt::Long 2.25 qw(:config posix_default no_ignore_case); + use NetAddr::IP; + use Net::Server; # used only to find out which version we use + use Net::Server::Multiplex; + use BerkeleyDB; + use Fcntl ':flock'; # import LOCK_* constants + use Sys::Hostname; + use Sys::Syslog; # used only to find out which version we use + use POSIX qw(strftime setlocale LC_ALL); + + use vars qw(@ISA); @ISA = qw(Net::Server::Multiplex); - my $VERSION = '1.36'; + my $VERSION = '1.37'; -my $DEFAULT_DBDIR = '/var/spool/postfix/postgrey'; -my $CONFIG_DIR = '/etc/postfix'; +my $DEFAULT_DBDIR = '/var/lib/postgrey'; +my $CONFIG_DIR = '/etc/postgrey'; - sub cidr_parse($) + sub read_clients_whitelists($) { -@@ -644,10 +644,10 @@ sub main() + my ($self) = @_; + + my @whitelist_clients = (); + my @whitelist_ips = (); + for my $f (@{$self->{postgrey}{whitelist_clients_files}}) { + if(open(CLIENTS, $f)) { + while(<CLIENTS>) { + s/#.*$//; s/^\s+//; s/\s+$//; next if $_ eq ''; + if(/^\/(\S+)\/$/) { + # regular expression + push @whitelist_clients, qr{$1}i; + } +@@ -613,34 +613,34 @@ + postgrey => { + delay => $opt{delay} || 300, + max_age => $opt{'max-age'} || 35, + last_maint => time, + last_maint_keys => 0, # do it on the first night + lookup_by_host => $opt{'lookup-by-host'}, + ipv4cidr => $opt{'ipv4cidr'} || 24, + ipv6cidr => $opt{'ipv6cidr'} || 64, + awl_clients => defined $opt{'auto-whitelist-clients'} ? + ($opt{'auto-whitelist-clients'} ne '' ? + $opt{'auto-whitelist-clients'} : 5) : 5, + retry_window => $retry_window, greylist_action => $opt{'greylist-action'} || 'DEFER_IF_PERMIT', greylist_text => $opt{'greylist-text'} || 'Greylisted, see http://postgrey.schweikert.ch/help/%r.html', whitelist_clients_files => $opt{'whitelist-clients'} || @@ -62,7 +167,31 @@ privacy => defined $opt{'privacy'}, hostname => defined $opt{hostname} ? $opt{hostname} : hostname, exim => defined $opt{'exim'}, -@@ -831,7 +831,7 @@ B<postgrey> [I<options>...] + x_greylist_header => $opt{'x-greylist-header'} || 'X-Greylist: delayed %t seconds by postgrey-%v at %h; %d', + }, + }, 'postgrey'; + + # max_age is in days + $server->{postgrey}{max_age}*=3600*24; + + # be sure to put in syslog any warnings / fatal errors + if(defined $server->{server}{log_file} and $server->{server}{log_file} eq 'Sys::Syslog') { + $SIG{__WARN__} = sub { Sys::Syslog::syslog('warning', '%s', "WARNING: $_[0]") }; + $SIG{__DIE__} = sub { Sys::Syslog::syslog('crit', '%s', "FATAL: $_[0]"); die @_; }; + } +@@ -800,126 +800,126 @@ + + B<postgrey> [I<options>...] + + -h, --help display this help and exit + --version output version information and exit + -v, --verbose increase verbosity level + --syslog-facility Syslog facility to use (default mail) + -q, --quiet decrease verbosity level + -u, --unix=PATH listen on unix socket PATH + --socketmode=MODE unix socket permission (default 0666) + -i, --inet=[HOST:]PORT listen on PORT, localhost if HOST is not specified + -d, --daemonize run in the background --pidfile=PATH put daemon pid into this file --user=USER run as USER (default: postgrey) --group=GROUP run as group GROUP (default: nogroup) @@ -71,27 +200,56 @@ --delay=N greylist for N seconds (default: 300) --max-age=N delete entries older than N days since the last time that they have been seen (default: 35) -@@ -847,8 +847,8 @@ B<postgrey> [I<options>...] + --retry-window=N allow only N days for the first retrial (default: 2) + append 'h' if you want to specify it in hours + --greylist-action=A if greylisted, return A to Postfix (default: DEFER_IF_PERMIT) + --greylist-text=TXT response when a mail is greylisted + (default: Greylisted + help url, see below) + --lookup-by-subnet strip the last N bits from IP addresses, determined by ipv4cidr and ipv6cidr (default) + --ipv4cidr=N What cidr to use for the subnet on IPv4 addresses when using lookup-by-subnet (default: 24) + --ipv6cidr=N What cidr to use for the subnet on IPv6 addresses when using lookup-by-subnet (default: 64) + --lookup-by-host do not strip the last 8 bits from IP addresses --privacy store data using one-way hash functions --hostname=NAME set the hostname (default: `hostname`) --exim don't reuse a socket for more than one query (exim compatible) - --whitelist-clients=FILE default: /etc/postfix/postgrey_whitelist_clients - --whitelist-recipients=FILE default: /etc/postfix/postgrey_whitelist_recipients -+ --whitelist-clients=FILE default: /etc/postgrey/whitelist_clients -+ --whitelist-recipients=FILE default: /etc/postgrey/whitelist_recipients ++ --whitelist-clients=FILE default: /etc/postfix/whitelist_clients ++ --whitelist-recipients=FILE default: /etc/postfix/whitelist_recipients --auto-whitelist-clients=N whitelist host after first successful delivery N is the minimal count of mails before a client is whitelisted (turned on by default with value 5) -@@ -858,7 +858,7 @@ B<postgrey> [I<options>...] + specify N=0 to disable. + --listen-queue-size=N allow for N waiting connections to our socket + --x-greylist-header=TXT header when a mail was delayed by greylisting default: X-Greylist: delayed <seconds> seconds by postgrey-<version> at <server>; <date> Note that the --whitelist-x options can be specified multiple times, - and that per default /etc/postfix/postgrey_whitelist_clients.local is -+ and that per default /etc/postgrey/whitelist_clients.local is ++ and that per default /etc/postfix/whitelist_clients.local is also read, so that you can put there local entries. =head1 DESCRIPTION -@@ -885,7 +885,7 @@ doing lookups in the database. + + Postgrey is a Postfix policy server implementing greylisting. + + When a request for delivery of a mail is received by Postfix via SMTP, the + triplet C<CLIENT_IP> / C<SENDER> / C<RECIPIENT> is built. If it is the first + time that this triplet is seen, or if the triplet was first seen less than + I<delay> seconds (300 is the default), then the mail gets rejected with a + temporary error. Hopefully spammers or viruses will not try again later, as it + is however required per RFC. + + Note that you shouldn't use the --lookup-by-host option unless you know what + you are doing: there are a lot of mail servers that use a pool of addresses to + send emails, so that they can change IP every time they try again. That's why + without this option postgrey will strip the last byte of the IP address when + doing lookups in the database. + + =head2 Installation + + =over 4 + =item * Create a C<postgrey> user and the directory where to put the database I<dbdir> @@ -100,7 +258,22 @@ =item * -@@ -908,12 +908,12 @@ Put something like this in /etc/main.cf: + Write an init script to start postgrey at boot and start it. Like this for example: + + postgrey --inet=10023 -d + + F<contrib/postgrey.init> in the postgrey source distribution includes a + LSB-compliant init script by Adrian von Bidder for the Debian system. + + =item * + + Put something like this in /etc/main.cf: + + smtpd_recipient_restrictions = + permit_mynetworks + ... + reject_unauth_destination + check_policy_service inet:127.0.0.1:10023 =item * @@ -116,7 +289,10 @@ greylisting. =back -@@ -924,9 +924,9 @@ Whitelists allow you to specify client addresses or recipient address, for + + =head2 Whitelists + + Whitelists allow you to specify client addresses or recipient address, for which no greylisting should be done. Per default postgrey will read the following files: @@ -129,29 +305,45 @@ You can specify alternative paths with the --whitelist-x options. -Index: postgrey_whitelist_clients -=================================================================== ---- postgrey_whitelist_clients.orig -+++ postgrey_whitelist_clients -@@ -2,3 +2,3 @@ + Postgrey whitelists follow similar syntax rules as Postfix access tables. + The following can be specified for B<recipient addresses>: + + =over 10 + + =item domain.addr + + C<domain.addr> domain and subdomains. + + =item name@ + + C<name@.*> and extended addresses C<name+blabla@.*>. +diff -rNU 15 ../postgrey-1.37-o/postgrey_whitelist_clients ./postgrey_whitelist_clients +--- ../postgrey-1.37-o/postgrey_whitelist_clients 2016-09-22 10:09:38.000000000 +0200 ++++ ./postgrey_whitelist_clients 2016-10-14 01:43:55.000000000 +0200 +@@ -1,18 +1,18 @@ + # postgrey whitelist for mail client hostnames # -------------------------------------------- -# put this file in /etc/postfix or specify its path +# put this file in /etc/postgrey or specify its path # with --whitelist-clients=xxx -@@ -19,8 +19,6 @@ vger.kernel.org - karger.ch - # 2004-06-02: lilys.ch, (slow: 4 hours) - server-x001.hostpoint.ch --# 2004-06-09: roche.com (no retry) --gw.bas.roche.com - # 2004-06-09: newsletter (no retry) - mail.hhlaw.com - # 2004-06-09: no retry (reported by Ralph Hildebrandt) -Index: postgrey_whitelist_recipients -=================================================================== ---- postgrey_whitelist_recipients.orig -+++ postgrey_whitelist_recipients -@@ -1,6 +1,6 @@ + # + # postgrey version: 1.37, build date: 2016-09-22 + + # greylisting.org: Southwest Airlines (unique sender, no retry) + southwest.com + # greylisting.org: isp.belgacom.be (wierd retry pattern) + isp.belgacom.be + # greylisting.org: Ameritrade (no retry) + ameritradeinfo.com + # greylisting.org: Amazon.com (unique sender with letters) + amazon.com + # 2004-05-20: Linux kernel mailing-list (unique sender with letters) + vger.kernel.org + # 2004-06-02: karger.ch, no retry +diff -rNU 15 ../postgrey-1.37-o/postgrey_whitelist_recipients ./postgrey_whitelist_recipients +--- ../postgrey-1.37-o/postgrey_whitelist_recipients 2016-09-22 10:09:38.000000000 +0200 ++++ ./postgrey_whitelist_recipients 2016-10-14 01:44:27.000000000 +0200 +@@ -1,7 +1,7 @@ # postgrey whitelist for mail recipients # -------------------------------------- -# put this file in /etc/postfix or specify its path @@ -159,3 +351,4 @@ # with --whitelist-recipients=xxx postmaster@ + abuse@ ++++++ postgrey-1.36.tar.gz -> postgrey-1.37.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/Changes new/postgrey-1.37/Changes --- old/postgrey-1.36/Changes 2015-09-01 21:43:05.000000000 +0200 +++ new/postgrey-1.37/Changes 2016-09-22 10:00:54.000000000 +0200 @@ -1,3 +1,15 @@ +* 2016-09-22: version 1.37 + - added initial test suite + - testing using travis-ci (https://travis-ci.org/schweikert/postgrey) + - removed IP pool-detection code for --lookup-by-net, because it matched + also the naming of some big hosters like facebook (#32, Michal Petrucha, + Andrew Ayer, Jon Sailor) + - fix early logging of errors and warnings to syslog + - simplified IP matching code + - added support for IPv6 whitelists with netmask + - add network-range based whitelist for Office 365 (Holger Stember) + - updated whitelist + * 2015-09-01: version 1.36 - improved support for IPv6 addresses: new --ipv4cidr and --ipv6cidr options for proper subnetting of IPv6 (HÃ¥vard Moen, BenediktS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/README.md new/postgrey-1.37/README.md --- old/postgrey-1.36/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/postgrey-1.37/README.md 2016-09-20 10:48:23.000000000 +0200 @@ -0,0 +1,37 @@ +[](https://travis-ci.org/schweikert/postgrey) + +# Postgrey - a Postfix policy server for greylisting + +## Requirements + +- Perl >= 5.6.0 +- Net::Server (Perl Module) +- IO::Multiplex (Perl Module) +- BerkeleyDB (Perl Module) +- Berkeley DB >= 4.1 (Library) +- Digest::SHA (Perl Module, only for --privacy option) +- NetAddr::IP + + +## Documentation + +See POD documentation in postgrey. Execute: + + perldoc postgrey + +See also Postgrey's homepage: + + http://postgrey.schweikert.ch/ + + +## Mailing-List and getting Help + +There is a mailing-list for the discussion of postgrey, where you can +also ask for help in case of trouble. To subscribe, send a mail with +subject 'subscribe' to: + + [email protected] + +There is also a mailing-list archive, where you might find answers: + + http://lists.ee.ethz.ch/wws/arc/postgrey diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/postgrey new/postgrey-1.37/postgrey --- old/postgrey-1.36/postgrey 2015-09-01 21:44:46.000000000 +0200 +++ new/postgrey-1.37/postgrey 2016-09-22 10:09:38.000000000 +0200 @@ -23,39 +23,16 @@ use vars qw(@ISA); @ISA = qw(Net::Server::Multiplex); -my $VERSION = '1.36'; +my $VERSION = '1.37'; my $DEFAULT_DBDIR = '/var/spool/postfix/postgrey'; my $CONFIG_DIR = '/etc/postfix'; -sub cidr_parse($) -{ - defined $_[0] or return undef; - $_[0] =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)\/(\d+)$/ or return undef; - $1 < 256 and $2 < 256 and $3 < 256 and $4 < 256 and $5 <= 32 and $5 > 0 - or return undef; - my $net = ($1<<24)+($2<<16)+($3<<8)+$4; - my $mask = ~((1<<(32-$5))-1); - return ($net & $mask, $mask); -} - -sub cidr_match($$$) -{ - my ($net, $mask, $addr) = @_; - return undef unless defined $net and defined $mask and defined $addr; - return undef if ($addr =~ /:.*:/); # ignore IPv6 addresses - if($addr =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { - $addr = ($1<<24)+($2<<16)+($3<<8)+$4; - } - return ($addr & $mask) == $net; -} - sub read_clients_whitelists($) { my ($self) = @_; my @whitelist_clients = (); my @whitelist_ips = (); - my @whitelist_cidr = (); for my $f (@{$self->{postgrey}{whitelist_clients_files}}) { if(open(CLIENTS, $f)) { while(<CLIENTS>) { @@ -64,22 +41,25 @@ # regular expression push @whitelist_clients, qr{$1}i; } - elsif(/^\d{1,3}(?:\.\d{1,3}){0,3}$/) { - # IP address or part of it - push @whitelist_ips, qr{^\Q$_\E\b}; - } - elsif(/^.*\:.*\:.*$/) { - # IPv6? - push @whitelist_ips, qr{^\Q$_\E\b}; - } - elsif(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}$/) { - my ($net, $mask) = cidr_parse($_); - if(defined $mask) { - push @whitelist_cidr, [ $net, $mask ]; - } - else { - warn "$f line $.: invalid cidr address\n"; - } + elsif(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:\/\d{1,2})?$/) { + # IPv4 address (with or without netmask) + my $ip = NetAddr::IP->new($_); + push @whitelist_ips, $ip if defined $ip; + } + elsif(/^\d{1,3}\.\d{1,3}\.\d{1,3}$/) { + # Partial IPv4 address (/24) + my $ip = NetAddr::IP->new($_, 24); + push @whitelist_ips, $ip if defined $ip; + } + elsif(/^\d{1,3}\.\d{1,3}$/) { + # Partial IPv4 address (/16) + my $ip = NetAddr::IP->new($_, 24); + push @whitelist_ips, $ip if defined $ip; + } + elsif(/^.*\:.*\:.*(?:\/\d{1,3})?$/) { + # IPv6 address (with or without netmask) + my $ip = NetAddr::IP->new($_); + push @whitelist_ips, $ip if defined $ip; } # note: we had ^[^\s\/]+$ but it triggers a bug in perl 5.8.0 elsif(/^\S+$/) { @@ -98,7 +78,6 @@ } $self->{postgrey}{whitelist_clients} = \@whitelist_clients; $self->{postgrey}{whitelist_ips} = \@whitelist_ips; - $self->{postgrey}{whitelist_cidr} = \@whitelist_cidr; } sub read_recipients_whitelists($) @@ -183,25 +162,17 @@ } my $ipaddr; - if($ip =~ /\./) { - # IPv4 - my @ip=split(/\./, $ip); - return ($ip, undef) unless defined $ip[3]; - # skip if it contains the last two IP numbers in the hostname - # (we assume it is a pool of dialup addresses of a provider) - return ($ip, undef) if $revdns =~ /$ip[2]/ and $revdns =~ /$ip[3]/; - - $ipaddr = NetAddr::IP->new($ip, $self->{postgrey}{ipv4cidr}); - } - elsif($ip =~ /:/) { - # IPv6 - $ipaddr = NetAddr::IP->new($ip, $self->{postgrey}{ipv6cidr}); + if($ip->bits() == 32) { + $ipaddr = NetAddr::IP->new($ip->addr, $self->{postgrey}{ipv4cidr}); + } + elsif($ip->bits() == 128) { + $ipaddr = NetAddr::IP->new($ip->addr, $self->{postgrey}{ipv6cidr}); } else { - warn "doesn't look like an IP address: $ipaddr\n"; + warn "NetAddr::IP->bits() neither 32 nor 128???\n"; return ($ip, undef); } - return ($ipaddr->network, undef); + return ($ipaddr->network()->addr(), undef); } sub mylog($$$) @@ -358,25 +329,39 @@ # not in a regular postfix query connection if(defined $attr->{policy_test_time}) { $now = $attr->{policy_test_time} } - # whitelists + # make sure that important attributes are defined + for my $a (qw(client_address client_name recipient sender)) { + defined $attr->{$a} or do { + warn "attribute missing: $a\n"; + return 'DUNNO'; + }; + } + + # parse "client_address" into a NetAddr::IP object + my $ip = NetAddr::IP->new($attr->{client_address}); + defined $attr->{client_address} or do { + warn "can't parse client_address from postfix: $attr->{client_address}\n"; + return 'DUNNO'; + }; + $attr->{client_address_ip} = $ip; + + # whitelists: client name for my $w (@{$self->{postgrey}{whitelist_clients}}) { if($attr->{client_name} =~ $w) { $self->mylog_action($attr, 'pass', 'client whitelist'); return 'DUNNO'; } } + + # whitelists: client ip for my $w (@{$self->{postgrey}{whitelist_ips}}) { - if($attr->{client_address} =~ $w) { - $self->mylog_action($attr, 'pass', 'client whitelist'); - return 'DUNNO'; - } - } - for my $w (@{$self->{postgrey}{whitelist_cidr}}) { - if(cidr_match($w->[0], $w->[1], $attr->{client_address})) { + if($attr->{client_address_ip}->within($w)) { $self->mylog_action($attr, 'pass', 'client whitelist'); return 'DUNNO'; } } + + # whitelists: recipient for my $w (@{$self->{postgrey}{whitelist_recipients}}) { if($attr->{recipient} =~ $w) { $self->mylog_action($attr, 'pass', 'recipient whitelist'); @@ -388,7 +373,7 @@ my ($cawl_db, $cawl_key, $cawl_count, $cawl_last); if($self->{postgrey}{awl_clients}) { $cawl_db = $self->{postgrey}{db_cawl}; - $cawl_key = $attr->{client_address}; + $cawl_key = $attr->{client_address_ip}->addr(); if ($self->{postgrey}{privacy}) { $cawl_key = Digest::SHA::sha1_hex($cawl_key); } @@ -410,7 +395,7 @@ # lookup my $sender = $self->do_sender_substitutions($attr->{sender}); my ($client_net, $client_host) = - $self->do_client_substitutions($attr->{client_address}, $attr->{client_name}); + $self->do_client_substitutions($attr->{client_address_ip}, $attr->{client_name}); my $key = lc "$client_net/$sender/$attr->{recipient}"; if ($self->{postgrey}{privacy}) { $key = Digest::SHA::sha1_hex($key); @@ -465,8 +450,8 @@ $cawl_count++; $cawl_db->{$cawl_key}=$cawl_count.','.$now; my $client = $attr->{client_name} ? - $attr->{client_name}.'['.$attr->{client_address}.']' : - $attr->{client_address}; + $attr->{client_name}.'['.$attr->{client_address_ip}->addr().']' : + $attr->{client_address_ip}->addr(); $self->mylog(1, "whitelisted: $client") if $cawl_count==$self->{postgrey}{awl_clients}; } @@ -494,10 +479,6 @@ # X-Greylist header: if(!$last_was_successful and $self->is_new_instance($attr->{instance})) { - # syslog - my $client = ($attr->{client_name} and $attr->{client_name} ne 'unknown') ? - $attr->{client_name} : $attr->{client_address}; - # add X-Greylist header my $date = strftime("%a, %d %b %Y %T %Z", localtime); my $delay = $now-$first; @@ -658,6 +639,12 @@ # max_age is in days $server->{postgrey}{max_age}*=3600*24; + # be sure to put in syslog any warnings / fatal errors + if(defined $server->{server}{log_file} and $server->{server}{log_file} eq 'Sys::Syslog') { + $SIG{__WARN__} = sub { Sys::Syslog::syslog('warning', '%s', "WARNING: $_[0]") }; + $SIG{__DIE__} = sub { Sys::Syslog::syslog('crit', '%s', "FATAL: $_[0]"); die @_; }; + } + # read whitelist $server->read_clients_whitelists(); $server->read_recipients_whitelists(); @@ -699,12 +686,6 @@ { my ($self) = @_; - # be sure to put in syslog any warnings / fatal errors - if($self->{server}{log_file} eq 'Sys::Syslog') { - $SIG{__WARN__} = sub { Sys::Syslog::syslog('warning', '%s', "WARNING: $_[0]") }; - $SIG{__DIE__} = sub { Sys::Syslog::syslog('crit', '%s', "FATAL: $_[0]"); die @_; }; - } - # write files with mode 600 umask 0077; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/postgrey_whitelist_clients new/postgrey-1.37/postgrey_whitelist_clients --- old/postgrey-1.36/postgrey_whitelist_clients 2015-09-01 21:44:54.000000000 +0200 +++ new/postgrey-1.37/postgrey_whitelist_clients 2016-09-22 10:09:38.000000000 +0200 @@ -3,7 +3,7 @@ # put this file in /etc/postfix or specify its path # with --whitelist-clients=xxx # -# postgrey version: 1.36, build date: 2015-09-01 +# postgrey version: 1.37, build date: 2016-09-22 # greylisting.org: Southwest Airlines (unique sender, no retry) southwest.com @@ -196,6 +196,8 @@ yahoo.com # 2008-11-07: facebook (no retry, reported by Tim Freeman) /^outmail\d+\.sctm\.tfbnw\.net$/ +# 2016-09-13: facebook (updated names, github #30) +outmail.facebook.com # 2009-02-10: server14.cyon.ch (long retry, reported by Alex Beckert) server14.cyon.ch # 2009-08-19: 126.com (big pool) @@ -225,8 +227,6 @@ mout-xforward.web.de mout-xforward.kundenserver.de mout-xforward.perfora.net -# 2014-02-01: startcom.org (long retry, reported by jweiher) -gateway.startcom.org # 2014-12-18: mail.ru (retries from fallback*.mail.ru, reported by Andriy Yurchuk) /^fallback\d+\.mail\.ru$/ # French tax authority, no retry @@ -235,5 +235,40 @@ /^o\d+\.ntdc\.magisto\.com$/ # 2015-07-23: outlook.com (github #20) outlook.com -# 2015-08-19 (the retrying is failing) +# 2015-08-19 (big pool) mail.alibaba.com +mail.aliyun.com +# 2016-09-13: amazonses.com (github #35, #37) +smtp-out.amazonses.com +# 2016-09-13: startcom.org (github #7) +startcom.org +# 2016-09-20: Microsoft Exchange Online (Office 365) +23.103.132.0/22 +23.103.136.0/21 +23.103.144.0/20 +23.103.198.0/23 +23.103.200.0/21 +40.92.0.0/14 +40.107.0.0/16 +65.55.88.0/24 +65.55.169.0/24 +94.245.120.64/26 +104.47.0.0/17 +134.170.101.0/24 +134.170.140.0/24 +134.170.171.0/24 +157.55.133.0/25 +157.56.87.192/26 +157.56.110.0/23 +157.56.112.0/24 +157.56.116.0/25 +157.56.120.0/25 +207.46.51.64/26 +207.46.100.0/24 +207.46.108.0/25 +207.46.163.0/24 +213.199.154.0/24 +213.199.180.128/26 +216.32.180.0/23 +2a01:111:f400:7c00::/54 +2a01:111:f400:fc00::/54 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/test/PostgreyTestClient.pm new/postgrey-1.37/test/PostgreyTestClient.pm --- old/postgrey-1.36/test/PostgreyTestClient.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/postgrey-1.37/test/PostgreyTestClient.pm 2016-09-20 16:45:24.000000000 +0200 @@ -0,0 +1,62 @@ +package PostgreyTestClient; + +use strict; +use IO::Socket::INET; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT_OK = qw(request); + +sub new +{ + my ($class, $path) = @_; + defined $path or die "ERROR: must define path"; + my $self = { + path => $path, + time => time, + }; + return bless $self, $class; +} + +sub advance_time +{ + my ($self, $seconds) = @_; + $self->{time}+=$seconds; +} + +sub request +{ + my ($self, $attrs) = @_; + + # creating a listening socket + my $socket = new IO::Socket::UNIX ( + Type => SOCK_STREAM(), + Peer => $self->{path}, + ); + defined $socket or do { + warn "ERROR: can't create socket: $!\n"; + return undef; + }; + + print $socket "request=smtpd_access_policy\n"; + print $socket "policy_test_time=$self->{time}\n"; + for my $key (keys %$attrs) { + print $socket "$key=$attrs->{$key}\n"; + } + print $socket "\n"; + + my $reply = ''; + while(my $line = readline($socket)) { + chomp($line); + last if $line eq ''; + $reply .= $line; + } + $reply =~ /^action=(.*)/ or do { + warn "unexpected reply: $reply\n"; + return undef; + }; + + return $1; +} + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/test/Test_Greylist.pm new/postgrey-1.37/test/Test_Greylist.pm --- old/postgrey-1.36/test/Test_Greylist.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/postgrey-1.37/test/Test_Greylist.pm 2016-09-22 09:46:35.000000000 +0200 @@ -0,0 +1,68 @@ +package Test_Greylist; + +use strict; +use Test::More; +use Time::HiRes; +use BerkeleyDB; + +our $tests = 8; + +sub run_tests { + my ($client) = @_; + + # Make first request (should be greylisted) + { + my $reply = $client->request({ + client_name => 'test1.example.com', + client_address => '192.168.0.1', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + is($reply, "DEFER_IF_PERMIT Greylisted, see http://postgrey.schweikert.ch/help/example.org.html", "verify greylisted"); + } + + $client->advance_time(310); + + { + my $reply = $client->request({ + client_name => 'test1.example.com', + client_address => '192.168.0.1', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + like($reply, qr{PREPEND X-Greylist: delayed 31[0123] seconds}, "verify pass"); + } + + # We should also pass when coming from different IP but same /24 network + { + my $reply = $client->request({ + client_name => 'test1.example.com', + client_address => '192.168.0.2', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + is($reply, 'DUNNO', 'verify pass (same subnet)'); + } + + # We should not pass when coming from a completely different IP + { + my $reply = $client->request({ + client_name => 'test1.example.com', + client_address => '10.1.50.2', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + like($reply, qr{^DEFER_IF_PERMIT}, 'verify greylist (different ip)'); + } +} + +sub run_tests_post_stop { + # verify content of db + +} + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/test/Test_Whitelists.pm new/postgrey-1.37/test/Test_Whitelists.pm --- old/postgrey-1.36/test/Test_Whitelists.pm 1970-01-01 01:00:00.000000000 +0100 +++ new/postgrey-1.37/test/Test_Whitelists.pm 2016-09-22 09:57:21.000000000 +0200 @@ -0,0 +1,68 @@ +package Test_Whitelists; + +use strict; +use Test::More; +use BerkeleyDB; + +our $tests = 8; + +sub run_tests { + my ($client) = @_; + + { + my $reply = $client->request({ + client_name => 'mail-xn1nam02ob0613.outbound.protection.outlook.com', + client_address => '2a01:222:f400:fe44::613', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + is($reply, 'DUNNO', "whitelisted: outlook.com"); + } + + # Verify whitelist entry: 195.235.39 + { + my $reply = $client->request({ + client_name => 'blabla.example.com', + client_address => '195.235.39.10', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + is($reply, 'DUNNO', "whitelisted: 195.235.39.10"); + } + + # Verify whitelist entry: 2a01:111:f400:7c00::10 + { + my $reply = $client->request({ + client_name => 'blabla.example.com', + client_address => '2a01:111:f400:7c00::10', + sender => '[email protected]', + recipient => '[email protected]', + }); + ok(defined $reply, 'send request'); + is($reply, 'DUNNO', "whitelisted: 2a01:111:f400:7c00::10"); + } +} + +sub run_tests_post_stop { + my ($client, $tmpdir) = @_; + + my $dbenv = BerkeleyDB::Env->new( + -Home => $tmpdir, + -Flags => DB_INIT_TXN|DB_INIT_MPOOL|DB_INIT_LOG, + ) or die "ERROR: can't open DB environment: $!\n"; + + my %db; + tie(%db, 'BerkeleyDB::Btree', + -Filename => 'postgrey.db', + -Flags => DB_RDONLY, + -Env => $dbenv, + ) or die "ERROR: can't open database postgrey.db: $!\n"; + + my $key = '10.1.50.0/[email protected]/[email protected]'; + ok(defined $db{$key}, "verify db entry exists"); + like($db{$key}, qr{^\d+,\d+$}, "verify db entry value"); +} + +1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/test/test-wrapper.sh new/postgrey-1.37/test/test-wrapper.sh --- old/postgrey-1.36/test/test-wrapper.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/postgrey-1.37/test/test-wrapper.sh 2016-09-16 14:50:19.000000000 +0200 @@ -0,0 +1,24 @@ +#!/bin/sh + +# we need a wrapper to allow loading of modules from a non-system path, and we can't use PERL5LIB because of taint mode (-T) + +GID=`id -g` +UID=`id -u` +OPTS="--user=$UID --group=$GID" +DEFAULT_LIB_ROOT="$HOME/perl5" + +# note that this script assumes that we are run in the test directory and that postgrey is in ../postgrey +if [ ! -f ../postgrey ]; then + echo "ERROR: ../postgrey not found. are you running this script from the test directory?" >&2 + exit 1 +fi + +[ -d $DBDIR ] || mkdir $DBDIR + +if [ -n "$PERL_LOCAL_LIB_ROOT" ]; then + LIB_ROOT=$PERL_LOCAL_LIB_ROOT +else + LIB_ROOT=$DEFAULT_LIB_ROOT +fi + +exec perl -T -I$LIB_ROOT/lib/perl5 ../postgrey $OPTS "$@" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/postgrey-1.36/test/test.pl new/postgrey-1.37/test/test.pl --- old/postgrey-1.36/test/test.pl 1970-01-01 01:00:00.000000000 +0100 +++ new/postgrey-1.37/test/test.pl 2016-09-22 09:53:59.000000000 +0200 @@ -0,0 +1,59 @@ +#!/usr/bin/perl -w + +use lib '.'; +use lib "$ENV{HOME}/perl5/lib/perl5"; + +use strict; +use Test::More; +use File::Temp; +use File::Slurper; + +use PostgreyTestClient; +use Test_Greylist; +use Test_Whitelists; + +plan tests => 4 + $Test_Greylist::tests + $Test_Whitelists::tests; + +my $tmpdir = File::Temp->newdir(); +my $sock_path = "$tmpdir/postgrey.sock"; +my $pid_path = "$tmpdir/postgrey.pid"; + +# Are we started in the root directory of the project? chdir to 'test' +if(-d 'test') { + chdir('test') or die "ERROR: can't chdir to test: $!\n"; +} + +# Start postgrey +system("./test-wrapper.sh -d --pidfile=$pid_path " . + "--dbdir=$tmpdir --unix=$sock_path " . + "--whitelist-clients=../postgrey_whitelist_clients " . + "--whitelist-recipients=../postgrey_whitelist_recipients " . + "--delay=1", + ); +ok($? == 0, "start postgrey"); +sleep(1); + +# Verify that it is running +my $pid; open(PID, $pid_path) and $pid = <PID>; close(PID); +ok(defined $pid, "pid file generated") or done_testing, exit; +chomp($pid); +ok(kill(0, $pid), "postgrey is running") or done_testing, exit; + +# Initialize test client +my $client = PostgreyTestClient->new($sock_path); + +# Run tests in modules +Test_Greylist::run_tests($client); +Test_Whitelists::run_tests($client); + +# Stop postgrey and verify that it stopped +kill('TERM', $pid); +for(my $i=0; $i<10; $i++) { + if(kill(0, $pid)==0) { last; } + kill('TERM', $pid); + print "# waiting for postgrey to stop (pid=$pid)\n"; + sleep(1); +} +ok(kill(0, $pid) == 0, "postgrey is stopped"); + +Test_Whitelists::run_tests_post_stop($client, $tmpdir);
