summaryrefslogtreecommitdiff
path: root/src/legacy
diff options
context:
space:
mode:
Diffstat (limited to 'src/legacy')
-rwxr-xr-xsrc/legacy/vyatta-sg-blacklist.pl682
1 files changed, 682 insertions, 0 deletions
diff --git a/src/legacy/vyatta-sg-blacklist.pl b/src/legacy/vyatta-sg-blacklist.pl
new file mode 100755
index 000000000..4104ac266
--- /dev/null
+++ b/src/legacy/vyatta-sg-blacklist.pl
@@ -0,0 +1,682 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-sg-blacklist.pl
+#
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# 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.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2008-2009 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Stig Thormodsrud
+# Date: October 2008
+# Description: script to download/update free url blacklist.
+#
+# **** End License ****
+#
+
+use Getopt::Long;
+use POSIX;
+use IO::Prompt;
+use Sys::Syslog qw(:standard :macros);
+use File::Copy;
+use Fcntl qw(:flock);
+use base qw(Exporter);
+use File::Basename;
+use File::Compare;
+
+use lib "/opt/vyatta/share/perl5";
+use Vyatta::Config;
+use Vyatta::File;
+
+use warnings;
+use strict;
+
+#
+# Default blacklist
+#
+# Below are some free blacklists we've tried:
+#
+# http://squidguard.mesd.k12.or.us/blacklists.tgz
+# http://ftp.teledanmark.no/pub/www/proxy/squidguard/contrib/blacklists.tar.gz
+# ftp://ftp.univ-tlse1.fr/pub/reseau/cache/squidguard_contrib/blacklists.tar.gz
+#
+# Note: the auto install/update assumes that the blacklist url is a tar gz
+# file with the blacklist categorys in a "blacklist" directory. Some
+# of the commercially available blacklists are a cgi script instead, so
+# those blacklists will need a different install/update script. Of
+# course they can be manually installed/updated.
+#
+my $blacklist_url = 'ftp://ftp.univ-tlse1.fr/pub/reseau/cache/squidguard_contrib/blacklists.tar.gz';
+
+#squid globals
+my $squid_init = '/etc/init.d/squid';
+my $squid_mime_type = '/usr/share/squid/mime.conf';
+
+#squidGuard globals
+my $urlfilter_data_dir = '/opt/vyatta/etc/config/url-filtering';
+my $squidguard_blacklist_db = "$urlfilter_data_dir/squidguard/db";
+my $squidguard_log_dir = '/var/log/squid';
+my $squidguard_blacklist_log = "$squidguard_log_dir/blacklist.log";
+my $squidguard_safesearch = "/opt/vyatta/etc/safesearch_rewrites";
+
+#vyattaguard globals
+my $vyattaguard = '/opt/vyatta/sbin/vg';
+
+sub webproxy_get_global_data_dir {
+ return $urlfilter_data_dir;
+}
+
+my $global_data_dir = webproxy_get_global_data_dir();
+
+
+sub squid_get_mime {
+ my @mime_types = ();
+ open(my $FILE, "<", $squid_mime_type) or die "Error: read $!";
+ my @lines = <$FILE>;
+ close($FILE);
+ foreach my $line (@lines) {
+ next if $line =~ /^#/; # skip comments
+ if ($line =~ /^([\S]+)[\s]+([\S]+)[\s]+([\S]+)[\s]+([\S]+).*$/) {
+ my $type = $2;
+ push @mime_types, $type if $type =~ /\//;
+ }
+ }
+ return @mime_types;
+}
+
+sub squidguard_is_configured {
+ my $config = new Vyatta::Config;
+ $config->setLevel('service webproxy url-filtering');
+ # This checks the running config, so it is assumed
+ # to be called from op mode.
+ return 1 if $config->existsOrig('squidguard');
+ return 0;
+}
+
+sub squidguard_get_blacklist_dir {
+ return $squidguard_blacklist_db;
+}
+
+sub squidguard_get_blacklist_log {
+ return $squidguard_blacklist_log;
+}
+
+sub squidguard_get_safesearch_rewrites {
+ my @rewrites = ();
+ open(my $FILE, "<", $squidguard_safesearch) or die "Error: read $!";
+ my @lines = <$FILE>;
+ close($FILE);
+ chomp @lines;
+ foreach my $line (@lines) {
+ next if $line =~ /^#/; # skip comments
+ if ($line =~ /^s\@/) {
+ push @rewrites, $line;
+ }
+ }
+ return @rewrites;
+}
+
+sub squidguard_ec_get_categorys {
+ my %cat_hash;
+
+ die "Must enable vyattaguard" if ! squidguard_use_ec();
+ die "Missing vyattaguard package\n" if ! -e $vyattaguard;
+ exit 1 if ! -e "$urlfilter_data_dir/sitefilter/categories.txt";
+
+ my @lines = `$vyattaguard list`;
+ foreach my $line (@lines) {
+ my ($id, $category) = split ':', $line;
+ next if ! defined $category;
+ chomp $category;
+ $category =~ s/\s/\_/g;
+ $category =~ s/\&/\_and\_/g;
+ $cat_hash{$id} = $category;
+ }
+ return %cat_hash;
+}
+
+sub squidguard_ec_cat2name {
+ my ($cat) = @_;
+
+ my %cat_hash = squidguard_ec_get_categorys();
+ return $cat_hash{$cat} if defined $cat_hash{$cat};
+ return;
+}
+
+sub squidguard_ec_name2cat {
+ my ($name) = @_;
+
+ my %cat_hash = squidguard_ec_get_categorys();
+ foreach my $key (keys (%cat_hash)) {
+ if ($cat_hash{$key} eq $name) {
+ return $key;
+ }
+ }
+ return;
+}
+
+sub squidguard_use_ec {
+ my $rc = system("cli-shell-api inSession");
+ my ($exist_func, $value_func);
+ if ($rc == 0) {
+ $exist_func = 'exists';
+ $value_func = 'returnValue';
+ } else {
+ $exist_func = 'existsOrig';
+ $value_func = 'returnOrigValue';
+ }
+ my $config = new Vyatta::Config;
+ $config->setLevel('service webproxy url-filtering squidguard');
+ if ($config->$exist_func('vyattaguard')) {
+ return if ! -e $vyattaguard;
+ my $mode = $config->$value_func('vyattaguard mode');
+ return $mode;
+ }
+ return;
+}
+
+sub squidguard_get_blacklists {
+
+ my @blacklists = ();
+ if (squidguard_use_ec()) {
+ die "Missing vyattaguard package\n" if ! -e $vyattaguard;
+ my %cat_hash = squidguard_ec_get_categorys();
+ foreach my $key (keys (%cat_hash)) {
+ next if ! defined $cat_hash{$key};
+ push @blacklists, $cat_hash{$key};
+ }
+ } else {
+ my $dir = $squidguard_blacklist_db;
+ opendir(DIR, $dir) || die "can't opendir $dir: $!";
+ my @dirs = readdir(DIR);
+ closedir DIR;
+
+ foreach my $file (@dirs) {
+ next if $file eq '.';
+ next if $file eq '..';
+ if (-d "$dir/$file") {
+ push @blacklists, $file;
+ }
+ }
+ }
+ @blacklists = sort(@blacklists);
+ return @blacklists;
+}
+
+sub squidguard_generate_db {
+ my ($interactive, $category, $group) = @_;
+
+ my $db_dir = squidguard_get_blacklist_dir();
+ my $tmp_conf = "/tmp/sg.conf.$$";
+ my $output = "dbhome $db_dir\n";
+ $output .= squidguard_build_dest($category, 0, $group);
+ $output .= "\nacl {\n";
+ $output .= "\tdefault {\n";
+ $output .= "\t\tpass all\n";
+ $output .= "\t}\n}\n\n";
+ webproxy_write_file($tmp_conf, $output);
+
+ my $dir = "$db_dir/$category";
+ if ( -l $dir) {
+ print "Skip link for [$category] -> [", readlink($dir), "]\n"
+ if $interactive;
+ return;
+ }
+ foreach my $type ('domains', 'urls', 'expressions') {
+ my $path = "$category/$type";
+ my $file = "$db_dir/$path";
+ if (-e $file and -s _) { # check exists and non-zero
+ my $file_db = "$file.db";
+ if (! -e $file_db) {
+ #
+ # it appears that there is a bug in squidGuard that if
+ # the db file doesn't exist then running with -C leaves
+ # huge tmp files in /var/tmp.
+ #
+ system("touch $file.db");
+ system("chown -R proxy.proxy $file.db > /dev/null 2>&1");
+ }
+ my $wc = `cat $file| wc -l`; chomp $wc;
+ print "Building DB for [$path] - $wc entries\n" if $interactive;
+ my $cmd = "\"squidGuard -d -c $tmp_conf -C $path\"";
+ system("su - proxy -c $cmd > /dev/null 2>&1");
+ }
+ }
+ system("rm $tmp_conf");
+}
+
+sub squidguard_is_category_local {
+ my ($category) = @_;
+
+ my $db_dir = squidguard_get_blacklist_dir();
+ my $local_file = "$db_dir/$category/local";
+ return 1 if -e $local_file;
+ return 0;
+}
+
+sub squidguard_is_blacklist_installed {
+ if (squidguard_use_ec()) {
+ if (-e "$urlfilter_data_dir/sitefilter/urldb") {
+ return 1;
+ }
+ } else {
+ my @blacklists = squidguard_get_blacklists();
+ foreach my $category (@blacklists) {
+ next if squidguard_is_category_local($category);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub squidguard_get_blacklist_domains_urls_exps {
+ my ($list) = shift;
+
+ my $dir = $squidguard_blacklist_db;
+ my ($domains, $urls, $exps) = undef;
+ $domains = "$list/domains" if -f "$dir/$list/domains" && -s _;
+ $urls = "$list/urls" if -f "$dir/$list/urls" && -s _;
+ $exps = "$list/expressions" if -f "$dir/$list/expressions" && -s _;
+ return ($domains, $urls, $exps);
+}
+
+sub squidguard_get_blacklist_files {
+ my ($type, $category) = @_;
+
+ my @lists = squidguard_get_blacklists();
+ my @files = ();
+ foreach my $list (@lists) {
+ my ($domain, $url, $exp) = squidguard_get_blacklist_domains_urls_exps(
+ $list);
+ if ($type eq 'domains') {
+ next if !defined $domain;
+ if (defined $category) {
+ next if $domain ne "$category/domains";
+ }
+ $domain = "$squidguard_blacklist_db/$domain";
+ push @files, $domain;
+ }
+ if ($type eq 'urls') {
+ next if !defined $url;
+ if (defined $category) {
+ next if $url ne "$category/urls";
+ }
+ $url = "$squidguard_blacklist_db/$url";
+ push @files, $url;
+ }
+ if ($type eq 'expressions') {
+ next if !defined $exp;
+ if (defined $category) {
+ next if $url ne "$category/expressions";
+ }
+ $exp = "$squidguard_blacklist_db/$exp";
+ push @files, $exp;
+ }
+
+ }
+ @files = sort(@files);
+ return @files;
+}
+
+sub squidguard_get_log_files {
+ open(my $LS, "-|", "ls $squidguard_log_dir/bl*.log* 2> /dev/null | sort -nr ");
+ my @log_files = <$LS>;
+ close $LS;
+ chomp @log_files;
+ return @log_files;
+}
+
+sub squidguard_build_dest {
+ my ($category, $logging, $group, $ec) = @_;
+
+ my $output = '';
+ my ($domains, $urls, $exps);
+ if (squidguard_is_category_local("$category-$group")) {
+ ($domains, $urls, $exps) = squidguard_get_blacklist_domains_urls_exps(
+ "$category-$group");
+ } else {
+ ($domains, $urls, $exps) = squidguard_get_blacklist_domains_urls_exps(
+ $category);
+ }
+
+ my $ec_cat = undef;
+ if (defined $ec) {
+ $ec_cat = squidguard_ec_name2cat($category);
+ }
+
+ $output = "dest $category-$group {\n";
+ $output .= "\tdomainlist $domains\n" if defined $domains;
+ $output .= "\turllist $urls\n" if defined $urls;
+ $output .= "\texpressionlist $exps\n" if defined $exps;
+ $output .= "\teccategory $ec_cat\n" if defined $ec_cat;
+ if ($logging) {
+ my $log = basename($squidguard_blacklist_log);
+ $output .= "\tlog $log\n";
+ }
+ $output .= "}\n\n";
+ return $output;
+}
+
+sub webproxy_read_file {
+ my ($file) = @_;
+ my @lines;
+ if ( -e $file) {
+ open(my $FILE, '<', $file) or die "Error: read $!";
+ @lines = <$FILE>;
+ close($FILE);
+ chomp @lines;
+ }
+ return @lines;
+}
+
+sub is_same_as_file {
+ my ($file, $value) = @_;
+
+ return if ! -e $file;
+
+ my $mem_file = '';
+ open my $MF, '+<', \$mem_file or die "couldn't open memfile $!\n";
+ print $MF $value;
+ seek($MF, 0, 0);
+
+ my $rc = compare($file, $MF);
+ return 1 if $rc == 0;
+ return;
+}
+
+sub webproxy_write_file {
+ my ($file, $config) = @_;
+
+ # Avoid unnecessary writes. At boot the file will be the
+ # regenerated with the same content.
+ return if is_same_as_file($file, $config);
+
+ open(my $fh, '>', $file) || die "Couldn't open $file - $!";
+ print $fh $config;
+ close $fh;
+ return 1;
+}
+
+sub webproxy_append_file {
+ my ($dst, $src) = @_;
+
+ open(my $ih, '<', $src) || die "Couldn't open $src - $!";
+ open(my $oh, '>>', $dst) || die "Couldn't open $dst - $!";
+ for (<$ih>) {
+ print $oh $_;
+ }
+ close($oh);
+ close($ih);
+ return 1;
+}
+
+sub webproxy_delete_local_entry {
+ my ($file, $value) = @_;
+
+ my $db_dir = squidguard_get_blacklist_dir();
+ $file = "$db_dir/$file";
+ my @lines = webproxy_read_file($file);
+ my $config = '';
+ foreach my $line (@lines) {
+ $config .= "$line\n" if $line ne $value;
+ }
+ if ($config eq '') {
+ unlink($file);
+ } else {
+ webproxy_write_file($file, $config);
+ }
+ return;
+}
+
+sub webproxy_delete_all_local {
+ my $db_dir = squidguard_get_blacklist_dir();
+ my @categorys = squidguard_get_blacklists();
+ foreach my $category (@categorys) {
+ if (squidguard_is_category_local($category)) {
+ system("rm -rf $db_dir/$category");
+ }
+ }
+ return;
+}
+
+sub print_err {
+ my ($interactive, $msg) = @_;
+ if ($interactive) {
+ print "$msg\n";
+ } else {
+ syslog(LOG_ERR, $msg);
+ }
+}
+
+sub squidguard_count_blacklist_entries {
+ my $db_dir = squidguard_get_blacklist_dir();
+
+ my $total = 0;
+ my @categories = squidguard_get_blacklists();
+ foreach my $category (@categories) {
+ foreach my $type ('domains', 'urls') {
+ my $path = "$category/$type";
+ my $file = "$db_dir/$path";
+ if (-e $file) {
+ my $wc = `cat $file| wc -l`; chomp $wc;
+ $total += $wc;
+ }
+ }
+ }
+ return $total;
+}
+
+sub squidguard_clean_tmpfiles {
+ #
+ # workaround for squidguard
+ # bug http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=494281
+ #
+ my @tmpfiles = </var/tmp/*>;
+ foreach my $file (@tmpfiles) {
+ my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime,
+ $mtime, $ctime, $blksize, $blocks) = stat($file);
+ my $name = (getpwuid($uid))[0] if $uid;
+ unlink($file) if $name and $name eq 'proxy';
+ }
+}
+
+sub squidguard_auto_update {
+ my ($interactive, $file) = @_;
+
+ my $rc;
+ my $db_dir = squidguard_get_blacklist_dir();
+ my $tmp_blacklists = '/tmp/blacklists.gz';
+
+ if (!squidguard_is_blacklist_installed()) {
+ my ($disk_free, $disk_required);
+ $disk_required = (30 * 1024 * 1024); # 30MB
+ $disk_free = `df $db_dir | grep -v Filesystem | awk '{ print \$4 }'`;
+ chomp($disk_free);
+ $disk_free *= 1024;
+ if ($disk_free < $disk_required) {
+ die "Error: not enough disk space $disk_required\/$disk_free";
+ }
+ }
+
+ if (defined $file) {
+ # use existing file
+ $rc = copy($file, $tmp_blacklists);
+ if (!$rc) {
+ print_err($interactive, "Unable to copy [$file] $!");
+ return 1;
+ }
+ } else {
+ # get from net
+ my $opt = '';
+ $opt = "-q" if ! $interactive;
+ $rc = system("wget -O $tmp_blacklists $opt $blacklist_url");
+ if ($rc) {
+ print_err($interactive, "Unable to download [$blacklist_url] $!");
+ return 1;
+ }
+ }
+
+ print "Uncompressing blacklist...\n" if $interactive;
+ $rc = system("tar --directory /tmp -zxvf $tmp_blacklists > /dev/null");
+ if ($rc) {
+ print_err($interactive, "Unable to uncompress [$blacklist_url] $!");
+ return 1;
+ }
+ my $b4_entries = squidguard_count_blacklist_entries();
+ my $archive = "$global_data_dir/squidguard/archive";
+ mkdir_p($archive) if ! -d $archive;
+ system("rm -rf $archive/*");
+ system("mv $db_dir/* $archive 2> /dev/null");
+ $rc = system("mv /tmp/blacklists/* $db_dir");
+ if ($rc) {
+ print_err($interactive, "Unable to install [$blacklist_url] $!");
+ return 1;
+ }
+ system("mv $archive/local-* $db_dir 2> /dev/null");
+ rm_rf($tmp_blacklists);
+ rm_rf("/tmp/blacklists");
+
+ my $after_entries = squidguard_count_blacklist_entries();
+ my $mode = "auto-update";
+ $mode = "manual" if $interactive;
+ syslog(LOG_WARNING,
+ "blacklist entries updated($mode) ($b4_entries/$after_entries)");
+ return 0;
+}
+
+sub squidguard_install_blacklist_def {
+ squidguard_auto_update(1, undef);
+}
+
+sub squidguard_update_blacklist {
+ my ($interactive, $update_category) = @_;
+
+ my @blacklists = squidguard_get_blacklists();
+ print "Checking permissions...\n" if $interactive;
+ my $db_dir = squidguard_get_blacklist_dir();
+ system("chown -R proxy.proxy $db_dir > /dev/null 2>&1");
+ chmod(2770, $db_dir);
+
+ #
+ # generate temporary config for each category & generate DB
+ #
+ foreach my $category (@blacklists) {
+ next if defined $update_category and $update_category ne $category;
+ squidguard_generate_db($interactive, $category, 'default');
+ }
+}
+
+
+#
+# main
+#
+my ($update_bl, $update_bl_cat, $update_bl_file, $auto_update_bl);
+
+GetOptions("update-blacklist!" => \$update_bl,
+ "update-blacklist-category=s" => \$update_bl_cat,
+ "update-blacklist-file=s" => \$update_bl_file,
+ "auto-update-blacklist!" => \$auto_update_bl,
+);
+
+my $sg_updatestatus_file = "$global_data_dir/squidguard/updatestatus";
+if (! -e "$global_data_dir/squidguard") {
+ system("mkdir -p $global_data_dir/squidguard/db");
+ my ($login, $pass, $uid, $gid) = getpwnam('proxy')
+ or die "proxy not in passwd file";
+ chown $uid, $gid, "$global_data_dir/squidguard/db";
+}
+touch($sg_updatestatus_file);
+system("echo update failed at `date` > $sg_updatestatus_file");
+system("sudo rm -f /var/lib/sitefilter/updatestatus");
+
+my $lock_file = '/tmp/vyatta_bl_lock';
+open(my $lck, ">", $lock_file) || die "Lock failed\n";
+flock($lck, LOCK_EX);
+
+if (defined $update_bl_cat) {
+ squidguard_update_blacklist(1, $update_bl_cat);
+ if (squidguard_is_configured()) {
+ print "\nThe webproxy daemon must be restarted\n";
+ if ((defined($ENV{VYATTA_PROCESS_CLIENT}) && $ENV{VYATTA_PROCESS_CLIENT} eq 'gui2_rest') ||
+ prompt("Would you like to restart it now? [confirm]",-y1d=>"y")) {
+ squid_restart(1);
+ }
+ }
+ squidguard_clean_tmpfiles();
+}
+
+if (defined $update_bl) {
+ my $updated = 0;
+ if (!squidguard_is_blacklist_installed()) {
+ print "Warning: No url-filtering blacklist installed\n";
+ if ((defined($ENV{VYATTA_PROCESS_CLIENT}) && $ENV{VYATTA_PROCESS_CLIENT} eq 'gui2_rest') ||
+ prompt("Would you like to download a default blacklist? [confirm]",
+ -y1d=>"y")) {
+ exit 1 if squidguard_install_blacklist_def();
+ $updated = 1;
+ } else {
+ exit 1;
+ }
+ } else {
+ if ((defined($ENV{VYATTA_PROCESS_CLIENT}) && $ENV{VYATTA_PROCESS_CLIENT} eq 'gui2_rest') ||
+ prompt("Would you like to re-download the blacklist? [confirm]",
+ -y1d=>"y")) {
+ my $rc = squidguard_auto_update(1, undef);
+ $updated = 1 if ! $rc;
+ }
+ }
+ if (! $updated) {
+ print "No blacklist updated\n";
+ if ((defined($ENV{VYATTA_PROCESS_CLIENT}) && $ENV{VYATTA_PROCESS_CLIENT} eq 'gui2_rest') ||
+ !prompt("Do you still want to generate binary DB? [confirm]",
+ -y1d=>"y")) {
+ exit 1;
+ }
+ }
+ # if there was an update we need to re-gen the binary DBs
+ # and restart the daemon
+ squidguard_update_blacklist(1);
+ if (squidguard_is_configured()) {
+ print "\nThe webproxy daemon must be restarted\n";
+ if ((defined($ENV{VYATTA_PROCESS_CLIENT}) && $ENV{VYATTA_PROCESS_CLIENT} eq 'gui2_rest') ||
+ prompt("Would you like to restart it now? [confirm]",-y1d=>"y")) {
+ squid_restart(1);
+ }
+ }
+ squidguard_clean_tmpfiles();
+}
+
+if (defined $update_bl_file) {
+ if (! -e $update_bl_file) {
+ die "Error: file [$update_bl_file] doesn't exist";
+ }
+ my $rc = squidguard_auto_update(0, $update_bl_file);
+ exit 1 if $rc;
+ squidguard_update_blacklist(1);
+ squidguard_clean_tmpfiles();
+}
+
+if (defined $auto_update_bl) {
+ my $rc = squidguard_auto_update(0);
+ exit 1 if $rc;
+ squidguard_update_blacklist(0);
+ if (squidguard_is_configured()) {
+ squid_restart(0);
+ }
+ squidguard_clean_tmpfiles();
+}
+
+system("echo update succeeded at `date` > $sg_updatestatus_file");
+close($lck);
+exit 0;
+
+#end of file