#!/usr/bin/perl # # This code is distributed under the terms of the GPL # # (c) 2006 marco.s # # $Id: updxlrator,v 1.0 2006/10/03 00:00:00 marco.s Exp $ # use strict; use IO::Socket; $|=1; my $swroot="/var/ipfire"; my $updcachedir="/srv/web/ipfire/html/updatecache"; my %netsettings=(); my %xlratorsettings=(); my $http_port="81"; my $logfile="/var/log/updatexlrator/cache.log"; my $logging=0; my $passive_mode=0; my $maxusage=0; my $nice=''; my @tmp=(); my $now=''; my $request=''; my $from_local_cache=0; my $dsturl=''; my $hostaddr=''; my $username=''; my $method=''; my @metadata=(); my $sfNoSource = "0"; my $sfOk = "1"; my $sfOutdated = "2"; unless (-d "$updcachedir/metadata") { unless (-d "$updcachedir") { mkdir "$updcachedir"; } mkdir "$updcachedir/metadata"; system("chown nobody.squid $updcachedir"); system("chmod 775 $updcachedir"); system("chown nobody.squid $updcachedir/metadata"); system("chmod 775 $updcachedir/metadata"); } readhash("${swroot}/ethernet/settings", \%netsettings); if (-e "$swroot/updatexlrator/settings") { &readhash("$swroot/updatexlrator/settings", \%xlratorsettings); if ($xlratorsettings{'ENABLE_LOG'} eq 'on') { $logging=1; }; if ($xlratorsettings{'PASSIVE_MODE'} eq 'on') { $passive_mode=1; }; $maxusage=$xlratorsettings{'MAX_DISK_USAGE'}; if ($xlratorsettings{'LOW_DOWNLOAD_PRIORITY'} eq 'on') { $nice='/bin/nice --adjustment=15 '; }; } if (!$maxusage) { $maxusage=75; }; while (<>) { $request=$_; $from_local_cache=0; @tmp=split(/ /,$request); chomp(@tmp); $dsturl =$tmp[0]; $hostaddr=$tmp[1]; while ($hostaddr =~ /.*\/$/) { chop $hostaddr; } $username=$tmp[2]; if ($username eq '') { $username='-'; }; $method =$tmp[3]; if (($method eq 'GET') || ($method eq 'HEAD')) { # ----------------------------------------------------------- # Section: Windows Update / Windows Downloads # ----------------------------------------------------------- if ( (($dsturl =~ m@^http://[^/]*\.microsoft\.com/.*\.(exe|psf|msi)$@i) || ($dsturl =~ m@^http://[^/]*\.windowsupdate\.com/.*\.(exe|psf|cab)$@i)) && ($dsturl !~ m@^http://[^/]*\.microsoft\.com/.*(/autoupd|selfupdate/).*\.cab@i) && ($dsturl !~ m@\&@) ) { $from_local_cache = &cache_access($dsturl,$hostaddr,$username,"Microsoft"); } # ----------------------------------------------------------- # Section: Adobe Downloads # ----------------------------------------------------------- if ($dsturl =~ m@^http://(ar)?download\.adobe\.com/.*\.(exe|bin|dmg|idx|gz)$@i) { $from_local_cache = &cache_access($dsturl,$hostaddr,$username,"Adobe"); } # ----------------------------------------------------------- # Section: Symantec Downloads # ----------------------------------------------------------- if ($dsturl =~ m@^[f|h]t?tp://[^/]*\.symantec(liveupdate)?\.com/.*\.(exe|zip|xdb)$@i) { $from_local_cache = &cache_access($dsturl,$hostaddr,$username,"Symantec"); } # ----------------------------------------------------------- # Section: Avira Downloads # ----------------------------------------------------------- if ($dsturl =~ m@^http://dl[0-9]\.avgate\.net/.*\.(htm|html|gz)$@i) { $from_local_cache = &cache_access($dsturl,$hostaddr,$username,"Avira"); } # ----------------------------------------------------------- # Section: Avast Downloads # ----------------------------------------------------------- if ($dsturl =~ m@^http://download[0-99]\.avast\.com/.*\.(exe|zip|vps|stamp|vpu)$@i) { $from_local_cache = &cache_access($dsturl,$hostaddr,$username,"Avast"); } # ----------------------------------------------------------- } if ($from_local_cache) { $request="http://$netsettings{'GREEN_ADDRESS'}:$http_port/updatecache/".substr($dsturl,rindex($dsturl,"/")+1)." $hostaddr $username $method\n"; } print $request; } # ------------------------------------------------------------------- sub readhash { my $filename = $_[0]; my $hash = $_[1]; my ($var, $val); if (-e $filename) { open(FILE, $filename) or die "Unable to read file $filename"; while () { chop; ($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 writelog { open(LOGFILE,">>$logfile"); print LOGFILE time." $_[0] $_[1] $_[2] $_[3] $_[4]\n"; close(LOGFILE); } # ------------------------------------------------------------------- sub diskfree { open(DF,"/bin/df --block-size=1 $_[0]|"); while() { unless ($_ =~ m/^Filesystem/ ) { my ($device,$size,$used,$free,$percent,$mount) = split; if ($free =~ m/^(\d+)$/) { close DF; return $free; } } } close DF; } # ------------------------------------------------------------------- sub diskusage { open(DF,"/bin/df $_[0]|"); while() { unless ($_ =~ m/^Filesystem/ ) { my ($device,$size,$used,$free,$percent,$mount) = split; if ($percent =~ m/^(\d+)%$/) { close DF; $percent =~ s/%$//; return $percent; } } } close DF; } # ------------------------------------------------------------------- sub getdownloadsize { my $remote=0; my @response=(); my $contentlength=0; my $url = $_[0]; $url =~ s@^(.*)://([^/]*)@@; my $proto = $1; my $fqhn = $2; if ((-e "$swroot/red/active") && ($proto eq 'http')) { $remote = IO::Socket::INET->new( PeerHost => $fqhn, PeerPort => 'http(80)', Timeout => 1 ); } if ($remote) { print $remote "HEAD $url HTTP/1.0\n"; print $remote "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\n"; print $remote "Host: $fqhn\n"; print $remote "Accept: */*\n\n"; while (<$remote>) { push(@response,$_); } close $remote; if ($response[0] =~ /^HTTP\/\d+\.\d+\s\d+\sOK\s*$/) { foreach (@response) { if (/^Content-Length: /i) { s/^Content-Length: //i; $contentlength=$_; } } } } return $contentlength; } # ------------------------------------------------------------------- sub cache_access { my $updsource="UPDCACHE"; my $updfile=''; my $do_redirect=0; $_[0] =~ s@\%2f@/@ig; $updfile = substr($_[0],rindex($_[0],"/")+1); if (!-e "$updcachedir/metadata/$updfile") { open(FILE,">$updcachedir/metadata/$updfile"); print FILE "$_[0]\n$_[3]\n$sfOutdated\n0\n"; close(FILE); } if (-e "$updcachedir/$updfile") { open(FILE,">>$updcachedir/metadata/$updfile"); print FILE time."\n"; close(FILE); $do_redirect=1; } else { $updsource="DLSOURCE"; if ((!$passive_mode) && (&diskusage($updcachedir) <= $maxusage) && (&getdownloadsize <= &diskfree($updcachedir)) && (!-e "$updcachedir/download/$updfile")) { system("$nice/var/ipfire/updatexlrator/bin/download $_[0] &"); } } if ($logging) { &writelog($_[1],$_[2],$_[3],$updsource,$_[0]); } return $do_redirect; } # -------------------------------------------------------------------