#!/usr/local/bin/perl use Fcntl; use DB_File; use DBI; use Digest::MD5 qw(md5_hex); use Sys::Hostname; use Sys::Syslog; my $whitelistdb="/usr/local/bastion/mailgrey/etc/whitelist.db"; my $configdir="/usr/local/bastion/mailgrey/etc"; our $dsn1; our $dsn1_user; our $dsn1_password; our $dsn2; our $dsn2_user; our $dsn2_password; require $configdir."/dsn.".hostname(); my $d_timeout=280; my %p; my %w; my $dbh1; my $dbh2; my $sth1; my $sth1_1; my $sth2; my $sth2_1; my $t0; my $t1; my $status; my $ts; my $waitperiod; my $nl; my $erg; my $erg1; my $erg2; my $failure; my $client_address; my $sender; my $recipient; my $hashstring; my $null=chr(0); my $changedate; sub getstat { my $filename=$_[0]; my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)=stat($filename); return $mtime; } sub initialize_db { $failure=0; $dbh1=DBI->connect($dsn1,$dsn1_user,$dsn1_password,{ RaiseError => 0, AutoCommit => 1, PrintError => 0 }); $dbh2=DBI->connect($dsn2,$dsn2_user,$dsn2_password,{ RaiseError => 0, AutoCommit => 1, PrintError => 0 }); if ($dbh1) { $sth1 =$dbh1->prepare("SELECT t0,t1,timeout FROM T_grey WHERE hash=?"); $sth1_1=$dbh1->prepare("INSERT INTO T_grey (hash,t0,t1,timeout) VALUES (?,?,?,?)"); $sth1_2=$dbh1->prepare("UPDATE T_grey SET t1=UNIX_TIMESTAMP() WHERE hash=?"); } if ($dbh2) { $sth2 =$dbh2->prepare("SELECT t0,t1,timeout FROM T_grey WHERE hash=?"); $sth2_1=$dbh2->prepare("INSERT INTO T_grey (hash,t0,t1,timeout) VALUES (?,?,?,?)"); $sth2_2=$dbh2->prepare("UPDATE T_grey SET t1=UNIX_TIMESTAMP() WHERE hash=?"); } if ((!$sth1)||(!$sth1_1)||(!$sth1_2)||(!$sth2)||(!$sth2_1)||(!$sth2_2)) { $failure=time(); } } sub cut_db1 { if ($failure==0) { $failure=time(); } undef $sth1,$sth1_1,$sth1_2,$dbh1; } sub cut_db2 { if ($failure==0) { $failure=time(); } undef $sth2,$sth2_1,$sth2_2,$dbh2; } $|=1; openlog("mailgrey-policy","","local0"); &initialize_db; tie %w,"DB_File",$whitelistdb,O_RDONLY,0400,$DB_HASH; $changedate=getstat($whitelistdb); while (true) { if (getstat($whitelistdb)!=$changedate) { untie %w; tie %w,"DB_File",$whitelistdb,O_RDONLY,0400,$DB_HASH; $changedate=getstat($whitelistdb); syslog("info","$whitelistdb reloaded."); } undef %p; while ($nl==0) { my $input=; if (!$input) { closelog(); exit; } chop $input; if (!($input =~ "=")) { $nl=1; } else { my ($lh,$rh) = split /=/,$input; $p{$lh}=lc($rh); } } $ts=time(); $client_address=substr($p{'client_address'},0,63); $sender=substr($p{'sender'},0,63); $recipient=substr($p{'recipient'},0,63); # Zuerst Whitelist if ($w{$p{'client_address'}.$null} eq '*'.$null) { print "action=OK\n\n"; } elsif ($w{$p{'client_address'}.$null} eq $sender.$null) { print "action=OK\n\n"; } # ansonsten Greylist else { $hashstring=md5_hex($client_address.$null.$sender.$null.$recipient); $status=0; $t0=0; $t1=0; $timeout=int(rand(300))+180; if ($sth1) { $sth1->bind_param(1,$hashstring); $erg1=$sth1->execute(); $sth1->bind_columns(\$t0,\$t1,\$timeout); $sth1->fetch(); if (!$erg1) { &cut_db1; } if ($erg1>0) { $status=1; } } if (($sth2) && ($status==0)) { $sth2->bind_param(1,$hashstring); $erg2=$sth2->execute(); $sth2->bind_columns(\$t0,\$t1,\$timeout); $sth2->fetch(); if (!$erg2) { &cut_db2; } if ($erg2>0) { $status=2; if ($sth1_1) { $sth1_1->bind_param(1,$hashstring); $sth1_1->bind_param(2,$t0); $sth1_1->bind_param(3,$t1); $sth1_1->bind_param(4,$timeout); $erg=$sth1_1->execute(); if (! $erg) { &cut_db1; } } } } $waitperiod=$timeout; if ($status>0) { if (($t0+$timeout) > $ts) { $status=-1; $waitperiod=$t0-$ts+$timeout; } } if ($status==0) { if ($sth1_1) { $sth1_1->bind_param(1,$hashstring); $sth1_1->bind_param(2,$ts); $sth1_1->bind_param(3,0); $sth1_1->bind_param(4,$timeout); $erg=$sth1_1->execute(); } if ($sth2_1) { $sth2_1->bind_param(1,$hashstring); $sth2_1->bind_param(2,$ts); $sth2_1->bind_param(3,0); $sth2_1->bind_param(4,$timeout); $erg2=$sth2_1->execute(); } if ((!$erg1) && (!$erg2)) { print "action=OK\n\n"; } else { print "action=420 4.7.1 You have been graylisted, next try in $waitperiod sec ($hashstring) [http://southbrain.com/graylisting]\n\n"; } } elsif ($status==-1) { print "action=420 4.7.1 You came again too early, next try in $waitperiod sec ($hashstring) [http://southbrain.com/graylisting]\n\n"; } else { if ($sth1_2) { $sth1_2->bind_param(1,$hashstring); $sth1_2->execute(); } if ($sth2_2) { $sth2_2->bind_param(1,$hashstring); $sth2_2->execute(); } print "action=OK\n\n"; } } if ( ($failure>0) && ( ($failure+60) < time()) ) { &initialize_db; } $nl=0; }