#!/usr/bin/perl
#
# This cgi script displays a page when a user accesses a blocked site.
# If a user repeatedly tries to access blocked sites they get barred.
# The script then emails the sysop to tell them who was blocked and
# how to unblock them. Users are allowed to hit $blocklimit blocked
# sites per day before getting barred. This is to allow for false hits.
# Once they get barred their internet access is blocked until the sysop
# manually unblocks them.
#
require Mail::Send;
$allow_html_code = 0;
&ReadEnvs;

$deniedurl = $in{'DENIEDURL'};
$reason = $in{'REASON'};
$user = $in{'USER'};
$ip = $in{'IP'};
$logfile = '/var/log/dansguardian/access.log';
$templog = '/tmp/dansguardian.log';
$prog = '/usr/sbin/dansguardian';
# who to send mail to when a user is blocked
$sysop = 'phil';
# limit of blocked accesses per day
$blocklimit = 20;

print "Content-type: text/html\n\n";
print" <table width=\"700\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\" align=\"center\">";
print"  <tr>";
print"    <td align=\"center\" colspan=\"3\"><img src=\"/dansguardian/stop.gif\"></td>";
print"  </tr>";
print"      </table>";
print '<HTML><HEAD><TITLE>DansGuardian - Access Denied</TITLE></HEAD>';
print '<BODY><CENTER><H2>ACCESS HAS BEEN DENIED</H2>';
if (length($user) > 1) {
  print "<em>$user</em>, access to the page:<P>";
}
else {
  print 'Access to the page:<P>';
}
print "<strong><a href=\"$deniedurl\">$deniedurl</a></strong>";
print '<P>... has been denied for the following reason:<P>';
print "<strong><font color=\"#ff0000\">$reason</font></strong>";
print '<P>Your username, IP address, date, time and URL have been logged.';
print '<P><table border=1 bgcolor="#FFEE00" style="width: 90%; text-align: center" ><tr><td>You are seeing this error because the page';
print ' you attempted to access contains, or is labelled as containing, material that has been deemed';
print ' inappropriate, or you have mis-typed the URL</td></tr></table>';
print '<table border=1 bgcolor="#44dd44" style="width: 90%; text-align: center"><tr><td>If you think this page has been blocked ';
print 'by mistake, please contact the Network Manager.</td></tr>';
print '</table>';
&BlockThem;
print '<P><font size=-3>Powered by <a href="http://dansguardian.org" target="_blank">DansGuardian</a></font>';
print '</center></BODY></HTML>';

exit;

sub BlockThem {
# Can't get read access to the log unless root or nobody, so copy with system call
# Needs apache to be able to use sudo without a password...

unlink ("$templog");
@args = ("sudo cp $logfile $templog");
    system(@args);
if ($? == -1) {
        print "Copy failed to execute: $!\n";
    }
else
{
	$thismonth = (localtime)[4] + 1;
	$thisday = (localtime)[3];
	$thisyear = (localtime)[5];
	if ($thisyear > 98) {
	  $thisyear += 1900;
	}
	else {
	  $thisyear += 2000;
	}
	$datestring = "$thisyear.$thismonth.$thisday";
	open(OUTFILE, ">>/etc/dansguardian/bannediplist")   or print "Can't open output file: $!";
	$user = $ip;
	$matches = 0;       

	open(INFILE,  "<$templog")   or print "Can't open input file: $!";
	while (<INFILE>) {     # assigns each line in turn to $_ 
	  if(/$datestring/) {
	    if(/$user/) {
	      if(/DENIED/) {
	  	$matches += 1 };
            }
	  }
        }
	close INFILE;
        unlink ("$templog");
	if($matches > $blocklimit) {
	  use Socket;
	  $ipaddr = inet_aton("$user");
	  $username = gethostbyaddr ($ipaddr, AF_INET);
	  print '<table border=1 bgcolor="#FF0000" style="width: 90%; text-align: center"><tr><td>';
	  print "You have attempted to access too many banned sites and are now BLOCKED.<br>";
          print "Please ask the Network Manager nicely to get unblocked.";
	  print '</table>';
	  print OUTFILE "$user\n";
	  @args = ("sudo $prog -r");
	    system(@args);
	  $msg = new Mail::Send Subject=>'Dansguardian Blocker', To=>"$sysop";
	  $fh = $msg->open;
	  print $fh "$username has tried to access $matches banned sites today ($datestring)\n";
	  print $fh "Their IP address ($user) has been added to /etc/dansguardian/bannediplist\n";
	  print $fh "To unblock them, remove their entry from the file and run dansguardian -r\n";
	  $fh->close;         # complete the message and send it
	}
	else
	{
	  print '<table border=1 bgcolor="#FF0000" style="width: 90%; text-align: center"><tr><td>';
	  print "You have attempted to access $matches banned sites.";
    	  print '</table>';	  
	}
      close OUTFILE;
      }
}
sub ReadEnvs {
  local($cl, @clp, $pair, $name, $value);
  if ( $ENV{'REQUEST_METHOD'} eq 'POST' ) {
    read(STDIN, $cl, $ENV{'CONTENT_LENGTH'} );
  }
  else {
    $cl = $ENV{'QUERY_STRING'};
  }
  @clp = split(/::/, $cl);
  foreach $pair (@clp) {
    ($name, $value) = split(/==/, $pair);
    $value =~ tr/+/ /;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    $value =~ s/<!--(.|\n)*-->//g;
    if ($allow_html_code != 1) {
      $value =~ s/<([^>]|\n)*>//g;
    }
    $in{$name} = $value;
  }
}




