Bei mir steht das drin:
#!/usr/bin/perl -w
#
# +-----------------------------------------------------------------------------+
# | Endian Firewall |
# +-----------------------------------------------------------------------------+
# | Copyright (c) 2005-2006 Endian |
# | Endian GmbH/Srl |
# | Bergweg 41 Via Monte |
# | 39057 Eppan/Appiano |
# | ITALIEN/ITALIA |
# | info@endian.it |
# | |
# | This program is free software; you can redistribute it and/or |
# | modify it under the terms of the GNU General Public License |
# | as published by the Free Software Foundation; either version 2 |
# | of the License, or (at your option) any later version. |
# | |
# | This program is distributed in the hope that it will be useful, |
# | but WITHOUT ANY WARRANTY; without even the implied warranty of |
# | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# | GNU General Public License for more details. |
# | |
# | You should have received a copy of the GNU General Public License |
# | along with this program; if not, write to the Free Software |
# | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
# | http://www.fsf.org/ |
# +-----------------------------------------------------------------------------+
#
use strict;
use CGI();
use Net::IPv4Addr qw (:all);
my %netsettings;
my %net_conf;
my $swroot = "/var/efw/";
my $ETHER_SETTINGS = $swroot."ethernet/settings";
my $routingfile = $swroot."routing/config";
my $custom_include = $swroot."proxy/proxy.custom.pac";
my $proxy_conffile = "${swroot}/proxy/settings";
my $proxy_conffile_default = "/usr/lib/efw/proxy/default/settings";
my $policyrules = "${swroot}/proxy/policyrules";
sub showhttpheaders() {
my $file = $ENV{'SCRIPT_NAME'};
$file =~ s/^[\/]*//;
print <<EOF
Cache-Control: no-cache
Connection: close
Content-Type: application/x-ns-proxy-autoconfig
Content-Disposition: attachement; filename="$file"
EOF
;
}
sub readhash($$) {
my $filename = shift;
my $hash = shift;
my ($var, $val);
open(FILE, $filename) or die "Unable to read file $filename";
while (<FILE>) {
chomp;
($var, $val) = split /=/, $_, 2;
if ($var) {
$val =~ s/^\'//g;
$val =~ s/\'$//g;
# Untaint variables read from hash
$var =~ /([A-Za-z0-9_-]*)/;
$var = $1;
$val =~ /([\w\W]*)/;
$val = $1;
$hash->{$var} = $val;
}
}
close FILE;
}
sub is_valid($) {
my $line = shift;
if ($line =~ /(?:(?:[^,]*),){9}/) {
return 1;
}
return 0;
}
sub read_config_file($) {
my $filename = shift;
my @lines;
open (FILE, "$filename");
foreach my $line (<FILE>) {
chomp($line);
$line =~ s/[\r\n]//g;
if (!is_valid($line)) {
next;
}
push(@lines, $line);
}
close (FILE);
return @lines;
}
sub read_config_line($$) {
my $line = shift;
my $file = shift;
my @lines = read_config_file($file);
return $lines[$line];
}
sub policy_line($) {
my $line = shift;
my %config;
$config{'valid'} = 0;
if (! is_valid($line)) {
return;
}
my @temp = split(/,/, $line);
$config{'enabled'} = $temp[0];
$config{'policy'} = $temp[1];
$config{'transparent'} = $temp[2];
$config{'auth'} = $temp[3];
$config{'auth_group'} = $temp[4];
$config{'time_restriction'} = $temp[5];
$config{'days'} = $temp[6];
$config{'starthour'} = $temp[7];
if ($config{'starthour'} eq "") {
$config{'starthour'} = "00";
}
$config{'startminute'} = $temp[8];
if ($config{'startminute'} eq "") {
$config{'startminute'} = "00";
}
$config{'stophour'} = $temp[9];
if ($config{'stophour'} eq "") {
$config{'stophour'} = "24";
}
$config{'stopminute'} = $temp[10];
if ($config{'stopminute'} eq "") {
$config{'stopminute'} = "00";
}
$config{'filtertype'} = $temp[11];
$config{'src_type'} = $temp[12];
$config{'src'} = $temp[13];
$config{'src'} =~ s/&/\|/g;
$config{'dst_type'} = $temp[14];
$config{'dst'} = $temp[15];
$config{'dst'} =~ s/&/\|/g;
$config{'mimetypes'} = $temp[16];
$config{'useragents'} = $temp[17];
$config{'useragents'} =~ s/&/\|/g;
$config{'valid'} = 1;
return %config;
}
sub read_settings() {
## -------------------------------------------------------------
## get settings and CGI parameters
## -------------------------------------------------------------
my %conf = ();
my %default_conf = ();
if ( -e $proxy_conffile_default ) {
&readhash( "$proxy_conffile_default", \%default_conf );
&readhash( "$proxy_conffile_default", \%conf );
}
if ( -e $proxy_conffile ) {
&readhash( "$proxy_conffile", \%conf );
}
return \%default_conf, \%conf;
}
(my $default_conf_ref, my $conf_ref) = read_settings();
my %default_conf = %$default_conf_ref;
my %conf = %$conf_ref;
readhash($ETHER_SETTINGS, \%net_conf);
sub get_zone($) {
my $ip = shift;
my @zones = ('GREEN', 'BLUE', 'ORANGE');
return '' if ($ip =~ /^$/);
foreach my $zone (@zones) {
if (! $net_conf{$zone.'_IPS'}) {
next;
}
foreach my $net (split(/,/, $net_conf{$zone.'_IPS'})) {
if (ipv4_in_network($net, "$ip/32")) {
return $zone;
}
}
}
return '';
}
sub get_port($) {
my $zone = shift;
$zone = uc($zone);
if ($conf{"PROXY_ENABLED"} eq "on") {
return $conf{'PROXY_PORT'};
}
return "";
}
sub get_ip($$) {
my $zone = shift;
my $ip = shift;
$zone = uc($zone);
foreach my $net (split(/,/, $net_conf{$zone.'_IPS'})) {
if (ipv4_in_network($net, "$ip/32")) {
my ($ip, $mask) = ipv4_parse($net);
return $ip;
}
}
return $net_conf{$zone.'_ADDRESS'}
}
sub search_route_subnet($) {
my $ip = shift;
return '' if (! -e "$routingfile");
open (F, "$routingfile") return '';
foreach my $line (<F>) {
my @token = split(/,/, $line);
next if ($token[0] eq 'off');
next if ($token[2] eq '');
next if ($token[3] =~ /^UPLINK/);
my @ipaddr = split(/\//, $token[2]);
if ($ipaddr[0]) {
if (ipv4_in_network($ipaddr[0],
"$ip/32"
)) {
close(F);
return $token[3];
}
}
}
close(F);
return '';
}
sub calculate_zone($) {
my $ip = shift;
my $zone = get_zone($ip);
return $zone if ($zone !~ /^$/);
my $gw = search_route_subnet($ip);
return get_zone($gw);
}
sub is_ip {
my $addr = shift;
my $withcidr = shift;
if (! $withcidr) {
$withcidr = 1;
}
if ($addr !~ /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})(?:\/(\d{1,2}))?$/) {
return 0;
}
my @parts = {$1, $2, $3, $4};
my $cidr = '';
if ($5) {
if ($withcidr eq 0) {
return 0;
}
$cidr = $5;
}
foreach my $number (@parts) {
$number = s/\D//;
if (($number < 0) ($number > 255)) {
return 0;
}
}
if ($cidr ne '') {
if (($cidr < 0) ($cidr > 32)) {
return 0;
}
}
return 1;
}
sub is_mask {
my $mask = $_[0];
# secord part an ip?
if (&is_ip($mask)) {
return 1;
}
# second part a number?
if (/^0/) {
return 0;
}
if (!($mask =~ /^\d+$/)) {
return 0;
}
if ($mask >= 0 && $mask <= 32) {
return 1;
}
return 0;
}
sub is_ipormask {
my $ipormask = $_[0];
# see if it is a IP only.
if (&is_ip($ipormask)) {
return 1;
}
# split it into number and mask.
if (!($ipormask =~ /^(.*?)\/(.*?)$/)) {
return 0;
}
my $ip = $1;
my $mask = $2;
# first part not a ip?
if (!(&is_ip($ip))) { return 0; }
return &is_mask($mask);
}
sub is_ipandmask {
my $ipandmask = $_[0];
# split it into number and mask.
if (!($ipandmask =~ /^(.*?)\/(.*?)$/)) {
return 0;
}
my $ip = $1;
my $mask = $2;
# first part not a ip?
if (!(&is_ip($ip, 0))) {
return 0;
}
return &is_mask($mask);
}
sub include_file($) {
my $file = shift;
open(F, $file);
print <F>;
close(F);
};
sub printpac($$$$) {
my $zone = shift;
my $ip = shift;
my $port = shift;
my $zone_nets = shift;
print <<END
function FindProxyForURL(url, host)
{
if (isPlainHostName(host) shExpMatch( url, "*$ip*" ) ) {
return "DIRECT";
}
else if (host == "127.0.0.1") {
return "DIRECT";
}
END
;
if (-f $custom_include) {
include_file($custom_include);
}
my @lines = read_config_file($policyrules);
my $num = 1;
my $any = 0;
if ($conf{"PROXY_ENABLED"} eq "on") {
# if ($conf{uc($zone) . "_ENABLED"} eq "transparent") {
# foreach my $net (split(/,/, $zone_nets)) {
# my ($netaddr, $netmask) = ipv4_network($net);
# $netmask = ipv4_cidr2msk($netmask);
# print <<END
# else if (isInNet(host, "$netaddr", "$netmask"))
# return "DIRECT";
# END
# ;
# }
# }
foreach my $thisline (@lines) {
chomp($thisline);
my %info = policy_line($thisline);
if ($info{"enabled"} ne "on") {
next;
}
elsif ($info{"src_type"} eq "any") {
$any = 1;
}
elsif ($info{"src_type"} eq "zone" && uc($info{"src"}) eq uc($zone)) {
foreach my $net (split(/,/, $zone_nets)) {
my ($netaddr, $netmask) = ipv4_network($net);
$netmask = ipv4_cidr2msk($netmask);
print <<END
else if (isInNet(host, "$netaddr", "$netmask") {
return "PROXY $ip:$port; DIRECT";
}
END
;
}
}
elsif ($info{"src_type"} eq "ip") {
foreach my $net (split(/\|/, $info{"src"})) {
if (is_ip($net)) {
print <<END
else if (host == "$net") {
return "PROXY $ip:$port; DIRECT";
}
END
;
}
elsif (is_ipandmask($net)) {
my ($netaddr, $netmask) = ipv4_network($net);
$netmask = ipv4_cidr2msk($netmask);
print <<END
else if (isInNet(host, "$netaddr", "$netmask") {
return "PROXY $ip:$port; DIRECT";
}
END
;
}
}
}
}
}
print <<END
else {
END
;
if ($ip eq '' $port eq '' $any eq 0) {
print <<END
return "DIRECT";
END
;
}
else {
print <<END
return "PROXY $ip:$port; DIRECT";
END
;
}
print <<END
}
}
END
;
}
my $zone = calculate_zone($ENV{'REMOTE_ADDR'});
showhttpheaders();
printpac($zone, get_ip($zone, $ENV{'REMOTE_ADDR'}), get_port($zone), $net_conf{$zone.'_IPS'});
exit(0);