From 5a00eccb3002d786493ce4b2771c11c8d9bbf7e7 Mon Sep 17 00:00:00 2001 From: Dexter Morgan Date: Thu, 2 Jun 2011 20:52:46 +0000 Subject: Branch for updates --- bin/.perl_checker | 1 + bin/drakguard | 782 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 783 insertions(+) create mode 100644 bin/.perl_checker create mode 100755 bin/drakguard (limited to 'bin') diff --git a/bin/.perl_checker b/bin/.perl_checker new file mode 100644 index 0000000..202e053 --- /dev/null +++ b/bin/.perl_checker @@ -0,0 +1 @@ +Basedir .. diff --git a/bin/drakguard b/bin/drakguard new file mode 100755 index 0000000..dfa7c3c --- /dev/null +++ b/bin/drakguard @@ -0,0 +1,782 @@ +#!/usr/bin/perl + +use lib qw(/usr/lib/libDrakX); +# i18n: IMPORTANT: to get correct namespace (drakguard instead of libDrakX) +BEGIN { unshift @::textdomains, 'drakguard' } +use strict; +use diagnostics; +use common; +use standalone; +use mygtk2; +use ugtk2 qw(:create :helpers :wrappers); +use Gtk2::SimpleList; +use interactive; +use network::shorewall; +use network::squid; +use services; +use Encode; + +my $dansguardian_main_file = "/etc/dansguardian/dansguardian.conf"; +my $dansguardian_filter_file = "/etc/dansguardian/dansguardianf1.conf"; +my $time_control_file = "/etc/shorewall/time_control"; +my $dansguardian_bannedsitelist = "/etc/dansguardian/lists/bannedsitelist"; +my $dansguardian_exceptionsitelist = "/etc/dansguardian/lists/exceptionsitelist"; +my $dansguardian_protected_program_list = "/etc/dansguardian/lists/blacklists/drakguard/protected_list"; +my $msec_conf = "/etc/security/msec/perms.conf"; +my $perms_orig = "/etc/security/msec/perms.orig"; +my $fstab_file = "/etc/fstab"; +my %dansguardian_levels = ( + 160 => N_("Low"), + 100 => N_("Normal"), + 50 => N_("High"), +); +my %dansguardian_langs = ( + arspanish => 'es_AR', + bulgarian => 'bg', + chinesebig5 => 'zh_TW', + chinesegb2312 => 'zh_CN', + czech => 'cs', + danish => 'da', + dutch => 'nl', + french => 'fr', + german => 'de', + hebrew => 'he', + hungarian => 'hu', + indonesian => 'id', + italian => 'it', + japanese => 'ja', + lithuanian => 'lt', + malay => 'ms', + mxspanish => 'es_MX', + polish => 'pl', + portuguese => 'pt', + ptbrazilian => 'pt_BR', + #russian-1251 + 'russian-koi8-r' => 'ru', + slovak => 'sk', + spanish => 'es', + swedish => 'sv', + turkish => 'tr', + ukenglish => 'en', +); + +my $blacklist_url_file = "/etc/dansguardian/lists/blacklists/drakguard/urls"; +my $whitelist_url_file = "/etc/dansguardian/lists/whitelists/drakguard/urls"; +my ($enable, $level, $time_control, $time_start_h, $time_start_m, $time_stop_h, $time_stop_m, $allow_time_change, $net_control, $not_net_control, $program_control, $net_control_state, $program_control_state, $acl_state); +my ($acl_active); +my $shorewall = network::shorewall::read(); +my $proxy_port = 3128; +my $proxy_user = 'squid'; +my $guardian_port = 8080; +my $guardian_user = 'dansguardian'; +load(); + + +my $toolname = 'drakguard'; +my $title = N("Parental Control"); +my $icon = 'drakguard'; + +$ugtk2::wm_icon = $icon; +my $w = ugtk2->new($title); +#- so that transient_for is defined, for wait messages and popups to be centered +$::main_window = $w->{real_window}; +my $in = interactive->vnew('su'); + +my $allusers_list = Gtk2::SimpleList->new(N("All users") => 'text'); +$allusers_list->get_selection->set_mode('multiple'); +@{$allusers_list->{data}} = sort(list_users()); + +my $allusers_program_list; +my $users_program_list; + +my $users_list = Gtk2::SimpleList->new(N("Allowed users") => 'text'); +$users_list->get_selection->set_mode('multiple'); +@{$users_list->{data}} = difference2($shorewall->{accept_local_users}{http}, [ $proxy_user ]); + +my @url_lists = ( + { + tab_title => N("Blacklist"), + list_title => N("Forbidden addresses"), + remove_text => N("Remove from blacklist"), + file => $blacklist_url_file, + apply => \&apply_blacklist, + }, + { + tab_title => N("Whitelist"), + list_title => N("Allowed addresses"), + remove_text => N("Remove from whitelist"), + file => $whitelist_url_file, + apply => \&apply_whitelist, + }, + { + tab_title => N("Block programs"), + list_title => N("Programs with blocked execution"), + remove_text => N("Remove from blocked execution list"), + file => $dansguardian_protected_program_list, + apply => \&apply_block_program, + } +); + +sub update_time_change() { + gtkval_modify(\$allow_time_change, $enable && $time_control); + gtkval_modify(\$net_control_state, $enable && $net_control); + gtkval_modify(\$not_net_control, $enable && !$net_control); + gtkval_modify(\$program_control_state, $enable && $program_control); + gtkval_modify(\$acl_state, $enable && $acl_active); +} + +sub update_network_change() { + gtkval_modify(\$not_net_control, $enable && !$net_control); + gtkval_modify(\$net_control_state, $enable && $net_control); +} + +sub update_program_state() { + gtkval_modify(\$program_control_state, $enable && $program_control); +} + +$w->{ok_clicked} = \&save; +$w->{cancel_clicked} = \&quit_gui; + +gtkadd($w->{window}, + gtknew('VBox', spacing => 5, children => [ + $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)), + 1, gtknew('Notebook', children => [ + gtknew('Label', text => N("Configuration")), + gtknew('VBox', spacing => 5, border_width => 5, children => [ + 0, gtknew('Label', text => N("This tool allows to configure parental control.\nIt can block access to web sites and restrict connection during a specified timeframe.")), + 0, gtknew('CheckButton', text => N("Enable parental control"), + active_ref => \$enable, toggled => \&update_time_change), + 1, gtknew('Label'), + 0, gtknew('Title2', label => N("Main options")), + 0, gtknew('HBox', children_tight => [ + gtknew('CheckButton', text => N("Block all network traffic"), + sensitive_ref => \$enable, active_ref => \$net_control, toggled => \&update_network_change), + ]), + 0, gtknew('HBox', children_tight => [ + gtknew('Label', sensitive_ref => \$enable, text_markup => N("Obscenity sensibility"), #Sensitivity to bad words + alignment => [ 0, 0.5 ]), + gtknew('ComboBox', + list => [ keys %dansguardian_levels ], + text_ref => \$level, + sensitive_ref => \$enable, + format => sub { translate($dansguardian_levels{$_[0]}) }), + ]), + 1, gtknew('Label'), + 0, gtknew('Title2', label => N("User access")), + 0, gtknew('HBox', spacing => 5, children_tight => [ + gtknew('ScrolledWindow', width => 220, height => 120, child => $allusers_list), + gtknew('VBox', spacing => 5, children_tight => [ + gtknew('Button', stock => "gtk-add", clicked => \&add_user), + gtknew('Button', stock => "gtk-remove", clicked => \&remove_user), + ]), + gtknew('ScrolledWindow', width => 220, height => 120, child => $users_list), + ]), + 1, gtknew('Label'), + 0, gtknew('Title2', label => N("Time control")), + 0, gtknew('CheckButton', text => N("Allow connections only between these times:"), + active_ref => \$time_control, sensitive_ref => \$enable, + toggled => \&update_time_change), + 0, gtknew('HBox', sensitive_ref => \$allow_time_change, spacing => 20, children_tight => [ + gtknew('Label', text => N("Start:")), + gtknew('HBox', spacing => 2, children_tight => [ + gtknew('SpinButton', lower => 0, upper => 23, step_increment => 1, value => $time_start_h, + value_changed => sub { $time_start_h = $_[0]->get_value } ), + gtknew('Label', text => ':'), + gtknew('SpinButton', lower => 0, upper => 59, step_increment => 1, value => $time_start_m, + value_changed => sub { $time_start_m = $_[0]->get_value } ), + ]), + gtknew('Label'), + gtknew('Label', text => N("End:")), + gtknew('HBox', spacing => 2, children_tight => [ + gtknew('SpinButton', lower => 0, upper => 23, step_increment => 1, value => $time_stop_h, + value_changed => sub { $time_stop_h = $_[0]->get_value } ), + gtknew('Label', text => ':'), + gtknew('SpinButton', lower => 0, upper => 59, step_increment => 1, value => $time_stop_m, + value_changed => sub { $time_stop_m = $_[0]->get_value } ), + ]), + ]), + ]), + (map { + my $url_list = $_; + $url_list->{list} = Gtk2::SimpleList->new($url_list->{list_title} => 'text'); + $url_list->{list}->get_selection->set_mode('multiple'); + if ($url_list->{tab_title} eq N("Block programs")){@{$url_list->{list}{data}} = read_program_list($url_list->{file}); } + else{@{$url_list->{list}{data}} = read_url_list($url_list->{file});} + + $allusers_program_list = Gtk2::SimpleList->new(N("Blocked users") => 'text'); + $allusers_program_list->get_selection->set_mode('multiple'); + @{$allusers_program_list->{data}} = sort(list_users()); + + $users_program_list = Gtk2::SimpleList->new(N("Allowed users") => 'text'); + $users_program_list->get_selection->set_mode('multiple'); + @{$users_program_list->{data}} = sort (read_program_user_list($url_list->{file})); + my $entry; + my $original_entry; + + ( + gtknew('Label', if_($url_list->{tab_title} eq N("Whitelist"), sensitive_ref => \$net_control_state), + if_($url_list->{tab_title} eq N("Blacklist"), sensitive_ref => \$not_net_control), + if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$acl_state), text => $url_list->{tab_title}), + gtknew('VBox', if_($url_list->{tab_title} eq N("Whitelist"), sensitive_ref => \$net_control_state), + if_($url_list->{tab_title} eq N("Blacklist"), sensitive_ref => \$not_net_control), spacing => 5, children => [ + 0, gtknew('HBox', children_tight => [ + if_($url_list->{tab_title} eq N("Block programs"),gtknew('CheckButton', text => N("Block defined applications"), + sensitive_ref => \$acl_state, active_ref => \$program_control, toggled => \&update_program_state)), + ]), + 0, gtknew('HBox', if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$program_control_state), border_width => 5, spacing => 5, children_loose => [ + $entry = gtknew('Entry'), + if_($url_list->{tab_title} eq N("Block programs"), gtknew('Button', text => N("..."), clicked => sub { + $entry->set_text($in->ask_file(N("Please select the program you want to control"), "/usr/bin")); + })), + 0, gtknew('Button', text => N("Add"), clicked => sub { + my $text = $entry->get_text; + my $exec; + my $args; + $text =~ s,^[^:]+://,,g; #- strip protocol + if ($url_list->{tab_title} eq N("Block programs")) { + $text =~ s,(\W?)$,,g; #- remove unknown caracters + $original_entry = ""; + $text = resolve_symlinks($text); + if ( (grep { $_ && m/^\[Desktop Entry\]\s*/g} chomp_(cat_($text))) || $text =~ m/\.desktop/g) {# make this only for application block + my @exec_line = grep { $_ && m/^Exec=(.*)\s*/g} chomp_(cat_($text)); + require lang; + my $locale = lang::read(); + $locale = lc($locale->{country}); + my @system_name = grep { $_ && m/^GenericName(\[$locale\])?=(.*)\s*/g} chomp_(cat_($text)); + foreach (@exec_line){ + ($exec, $text, $args) = /(^Exec=)(\w+)\s*(.*)/; + if ($text eq ""){ + ($exec, $text, $args) = /(^Exec=)(.*+)\s*(.*)/;} + } + foreach my $b (@system_name){ + $original_entry = $b; + $original_entry =~ s/^GenericName(\[$locale\])?=//g; + $original_entry = Encode::decode("utf8", $original_entry); + } + } + $text = `which $text 2> /dev/null` if $text ne ""; + $text =~ s/\n//g; + } + if ( $text eq "" && $url_list->{tab_title} eq N("Block programs")) { $in->ask_warn(N("Error"), N("Invalid Binary Name")) and return; } + else { if ($url_list->{tab_title} eq N("Block programs")) { + list_add_entry_program($url_list->{list}, $text. " ( $original_entry )") if $original_entry ne ""; + list_add_entry_program($url_list->{list}, $text) if $original_entry eq ""; + } + else { list_add_entry($url_list->{list}, $text); } + } + $entry->set_text(""); + }), + ]), + 1, gtknew('ScrolledWindow', if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$program_control_state), width => 500, height => 150, child => $url_list->{list}), + 0, gtknew('HButtonBox', if_($url_list->{tab_title} eq N("Block programs"), sensitive_ref => \$program_control_state), border_width => 5, layout => 'edge', children_loose => [ + gtknew('Button', text => $url_list->{remove_text}, clicked => sub { + list_remove_selected($url_list->{list}); + }), + ]), + if_($url_list->{tab_title} eq N("Block programs"), 1, gtknew('Label'), + 0, gtknew('Title2', label => N("Unblock users")), + 0, gtknew('HButtonBox', sensitive_ref => \$program_control_state, spacing => 5, children_tight => [ + gtknew('ScrolledWindow', width => 220, height => 120, child => $allusers_program_list), + gtknew('VBox', spacing => 5, children_tight => [ + gtknew('Button', stock => "gtk-add", clicked => \&add_user_program), + gtknew('Button', stock => "gtk-remove", clicked => \&remove_user_program), + ]), + gtknew('ScrolledWindow', width => 220, height => 120, child => $users_program_list), + ]), + 0, gtknew('HBox'), + ), + ]), + ); + } @url_lists), + ]), + 0, $w->create_okcancel( + undef, undef, undef, + [ N("Help"), sub { run_program::raw({ detach => 1 }, 'drakhelp', '--id', $toolname) } ]), + ]), +); + +$w->show; +if ( (grep {$_ && !/acl/} chomp_(cat_($fstab_file)) && grep {$_ && m/ext/} chomp_(cat_($fstab_file)))) { + $acl_active = 1; + $in->ask_yesorno(N("Warning"), N("The support for Access Control Lists must be enabled in order to use the Block programs feature.\nDo you want to enable it now?", $acl_active = 1)) or $acl_active = 0; + if ($acl_active) { + my @ext_lines = grep {$_ && m/ext/} chomp_(cat_($fstab_file)); + foreach my $line (@ext_lines){ + my ($id, $directory, $flag, $number) = $line=~ /^(.+)\s(.+)\s(ext(\w)\s(\w*))\s(.*)/ or next; + $line =~ s/ext(\w)\s(\w*)\s/$flag,acl /g; + subst_config_line($fstab_file,"$line\n"); #adds ,acl in the fstab file in the first run + # remount filesystem with acl parameter + } + $acl_active = 0; + $in->ask_warn(N("Warning"), N("The support for Access Control Lists was enabled.") . N("It is necessary to restart your computer to activate it.")); + } +} +else { + my @mount = `mount`; + if (grep (/,acl/, @mount)) { + $acl_active = 1; + } else { + $in->ask_warn(N("Warning"), N("The support for Access Control Lists, required by the Block programs feature, is enabled, but not yet activated.") . N("It is necessary to restart your computer to activate it."), $acl_active = 0);} +} +update_time_change; +Gtk2->main; + +$w->exit(0); + +sub list_add_entry { + my ($list, @addr) = @_; + foreach my $a (@addr) { + push @{$list->{data}}, $a + unless any { $_->[0] eq $a } @{$list->{data}}; + } +} + +sub list_add_entry_program { + my ($list, @addr) = @_; + foreach my $a (@addr) { + $b = $a; + $a =~ s/\s(.*)//g; + my @abc = map {$_->[0]} @{$list->{data}}; + push @{$list->{data}}, $b + unless (any { $_->[0] eq $b } @{$list->{data}}) || (grep {$_ && m/$a(.*)/g} @abc); + } +} + +sub list_remove_entry { + my ($list, @addr) = @_; + #- workaround buggy Gtk2::SimpleList array abstraction, it destroys references + @{$list->{data}} = map { member($_->[0], @addr) ? () : [ @$_ ] } @{$list->{data}}; +} + +sub list_get_selected { + my ($list) = @_; + uniq(map { $list->{data}[$_][0] } $list->get_selected_indices); +} + +sub list_remove_selected { + my ($list) = @_; + list_remove_entry($list, list_get_selected($list)); +} + +sub list_get_entries { + my ($list) = @_; + map { $_->[0] } @{$list->{data}}; +} + +sub add_user() { + list_add_entry($users_list, list_get_selected($allusers_list)); +} + +sub remove_user() { + list_remove_selected($users_list); +} + +sub add_user_program() { + list_add_entry($users_program_list, list_get_selected($allusers_program_list)); +} + +sub remove_user_program() { + list_remove_selected($users_program_list); +} + +sub quit_gui { + my ($o_code) = @_; + $w->exit($o_code); +} + +sub load() { + my $guardian = read_dansguardian(); + my $levelname = { %dansguardian_levels }->{$guardian->{naughtynesslimit}}; + $net_control = $guardian->{netblock}; + $program_control = $guardian->{programblock}; + gtkval_modify(\$not_net_control, $enable && !$net_control); + $level = { reverse %dansguardian_levels }->{$levelname} if $levelname; + $level ||= { reverse %dansguardian_levels }->{High}; + $enable = services::starts_on_boot('dansguardian'); + + $time_control = cat_($::prefix . "/etc/shorewall/start") =~ /^INCLUDE $time_control_file$/m; + my @time_control_settings = grep { /\bnet2fw\b/ } cat_($::prefix . $time_control_file); + my ($drop_start, $drop_stop); + if (my ($drop_start_h, $drop_start_m) = top(@time_control_settings) =~ /\B--timestart\s(\d+):(\d+)\b/) { + $drop_start = $drop_start_h*60 + $drop_start_m - 1; + } + if (my ($drop_stop_h, $drop_stop_m) = first(@time_control_settings) =~ /\B--timestop\s(\d+):(\d+)\b/) { + $drop_stop = $drop_stop_h*60 + $drop_stop_m + 1; + } + if (defined($drop_start) && defined($drop_stop)) { + my $day_time = 24*60; + $drop_start = ($drop_start + $day_time) % $day_time; + $drop_stop = ($drop_stop + $day_time) % $day_time; + + $time_start_h = int($drop_stop/60); + $time_start_m = $drop_stop%60; + $time_stop_h = int($drop_start/60); + $time_stop_m = $drop_start%60; + } + + $time_start_h //= 18; + $time_start_m //= 0; + $time_stop_h //= 21; + $time_stop_m //= 0; +} + +sub save() { + my $_wait = $in->wait_message(N("Please wait"), N("Please wait")); + + network::shorewall::set_in_file('start', $enable && $time_control, "INCLUDE $time_control_file"); + if ($enable && $time_control) { + my $day_time = 24*60; + #- start/stop dropping the minute after/before traffic is allowed + #- and make sure times are positive and in the 00:00 <-> 23:59 interval + my $drop_start = ($time_stop_h*60 + $time_stop_m + 1 + $day_time) % $day_time; + my $drop_stop = ($time_start_h*60 + $time_start_m - 1 + $day_time) % $day_time; + output_p($::prefix . $time_control_file, + join('', map { + my $chain = $_; + map { + sprintf("iptables -I $chain -j DROP -m time --timestart %02d:%02d --timestop %02d:%02d\n", + int($_->[0]/60), $_->[0]%60, + int($_->[1]/60), $_->[1]%60, + ); + } ($drop_stop >= $drop_start ? [ $drop_start, $drop_stop] : ([ 0, $drop_stop ], [ $drop_start, $day_time-1 ])); + #- if allowing start time is before allowing stop time, + #- we have to use two intervals to cover the completary parts of the day + } qw(net2fw fw2net)), + ); + #- allowing from 00:00 to 23:59 is a special case that does not need rules + $time_control = 0 if $drop_stop == $day_time - 1 && $drop_start == 0; + } + network::shorewall::set_in_file('start', $enable && $time_control, "INCLUDE $time_control_file"); + + if ($enable) { + $in->do_pkgs->ensure_are_installed([ qw(shorewall squid dansguardian) ]) + or quit_gui(1); + + $_->{apply}(list_get_entries($_->{list})) foreach @url_lists; + write_dansguardian(); + enable_transparent_proxy($proxy_port); + #- reload shorewall config if it has just been installed + $shorewall ||= network::shorewall::read(); + } + else { + $program_control = 0; + @url_lists[2]->{apply}(list_get_entries(@url_lists[2]->{list})); + } + services::set_status($_, $enable) foreach qw(squid dansguardian); + + if ($shorewall) { + $shorewall->{disabled} = 0 if $enable; + @{$shorewall->{accept_local_users}{http}} = if_($enable, uniq($proxy_user, list_get_entries($users_list))); + @{$shorewall->{accept_local_users}{$proxy_port}} = if_($enable, $guardian_user); + network::shorewall::set_redirected_ports($shorewall, 'tcp', $guardian_port, if_($enable, 'http', $proxy_port)); + network::shorewall::write($shorewall, $in); + } + + quit_gui(); +} + +sub resolve_symlinks { + + # Check if a given file (either the pure filename or in a SANE device + # string as ":") is a symlink, if so expand the link. + # If the new file name is a link, expand again, until finding the + # physical file. + my ($file) = @_; + my $prefix = ""; + if ($file =~ m!^([^/]*)(/.*)$!) { + $prefix = $1; + $file = $2; + } else { + return $file; + } + while (1) { + #my $ls = `ls -l $file 2> /dev/null`; + my $ls = readlink $file; + if ($ls =~ m!\s($file)\s*\->\s*(\S+)\s*$!) { + my $target = $2; + if ($target !~ m!^/! && $file =~ m!^(.*)/[^/]+$!) { + $target = "$1/$target"; + } + $file = $target; + } else { + last; + } + } + return $prefix . $file; +} + +sub remove_acl { + my ($file, $binary) = @_; + `setfacl -b $binary`; + clean_config_line($file, "$binary"); +} + +sub set_permissions { + my ($line, $line_info) = @_; + #`protect $line --add`; + chmod 0700, $line; + chown "root","root", $line; + #remove msec lines + #clean_config_line($msec_conf,"$line"); + subst_config_line($dansguardian_protected_program_list,"$line_info \n"); #adds the file to dansguardian_protected_program_list + subst_config_line($msec_conf,"$line\troot.root\t700\tforce\t\n"); #adds the file to msec + #`protect $line $_` foreach list_get_entries($users_program_list); + #add msec line or lines... + foreach my $user_msec (list_get_entries($users_program_list)) { + my @msec_line = grep { $_ && m/$line/g} chomp_(cat_($msec_conf)); + my @program_list_line = grep { $_ && m/^$line/g} chomp_(cat_($dansguardian_protected_program_list)); + `setfacl -m u:$user_msec:r-x $line`; + subst_config_line($dansguardian_protected_program_list,"$_$user_msec,\n") foreach @program_list_line; #adds the users to the programs blocked in msec + subst_config_line($msec_conf,"$_$user_msec:r-x,\n") foreach @msec_line; #adds the users to the programs blocked in msec + } +} + +sub restore_permissions { + my ($line) = @_; + foreach ($line){ + my ($fich, $usrname, $grpname, $mode) = /^(.*)\t(\w+)\.(\w+)\t(\d+)\s*/ or next; + $mode = sprintf "%04d", $mode;#make number with 4 digits + my $guid = getgrnam($grpname); + my $uid = getpwnam($usrname); + chown $uid, $guid, $fich; + chmod oct($mode), $fich; + } +} + +sub subst_config_line { + my ($file, $line) = @_; + my $key = first(split(' ', $line)); + my $done; + substInFile { + $done = 1 if s|^\s*$key\b.*\n|$line|; + $_ .= $line if eof && !$done; + } $file; +} + +sub clean_config_line { + my ($file, $line) = @_; + my $key = first(split(' ', $line)); + my $done; + substInFile { + $done = 1 if s|^\s*$key.*\n||; + } $file; +} + +sub block_internet_dansguardian { + my ($file, $line) = @_; + my $key = "#"; + substInFile { + s|^$key\*\*\s|**\n|; + } $file; +} + +sub unblock_internet_dansguardian { + my ($file) = @_; + my $key = "#"; + substInFile { + s|^\*\*\s|$key**\n|; + } $file; +} + +sub enable_transparent_proxy { + my ($port) = @_; + #- FIXME: use network::squid once it is rewritten to be more gentle with the config file + subst_config_line($network::squid::squid_conf_file, "http_port $port transparent\n"); +} + +#- mostly duplicated for MDK::Common::System::getVarsFromSh +sub read_dansguardian() { + my $guardian = {}; + foreach (cat_($dansguardian_filter_file)) { + s/#.*//; + s/^\s*//; + my ($v, $val) = /^(\w+)\s*=\s*(.*)/ or next; + $val = $1 if $val =~ /^"(.*)"$/ || $val =~ /^'(.*)'$/; + $guardian->{$v} = $val; + } + $guardian; +} + +sub write_dansguardian() { + require lang; + my $locale = lang::read(); + my $locale_lang = lang::getlocale_for_lang($locale->{lang}, $locale->{country}); + my %lang_to_dansguardian = reverse %dansguardian_langs; + my $dansguardian_lang = $lang_to_dansguardian{$locale_lang} || $lang_to_dansguardian{$locale->{lang}}; + + subst_config_line($dansguardian_main_file, "language = '$dansguardian_lang'\n") if $dansguardian_lang; + subst_config_line($dansguardian_filter_file, "naughtynesslimit = '$level'\n"); + subst_config_line($dansguardian_filter_file, "netblock = '$net_control'\n"); + subst_config_line($dansguardian_filter_file, "programblock = '$program_control'\n"); + if ($net_control) { + + block_internet_dansguardian($dansguardian_bannedsitelist); + + } + else { + + unblock_internet_dansguardian($dansguardian_bannedsitelist); + } +} + +sub include_guardian_file { + my ($guardian_file, $external_file) = @_; + my $to_add = ".Include<$external_file>\n"; + clean_config_line($guardian_file, "$to_add" ); + my @all = cat_($guardian_file); + if ((($dansguardian_bannedsitelist eq $guardian_file) && !$net_control) || (($dansguardian_exceptionsitelist eq $guardian_file) && $net_control)) { + if (!member($to_add, @all)) { + output_p($guardian_file, @all, $to_add); + } + } +} + +sub read_url_list { + my ($file) = @_; + grep { $_ && !/^\s*#/ } chomp_(cat_($file)); +} + +sub read_program_list { + my ($file) = @_; + grep { $_ && s/(\s*(\w+),)*//g } chomp_(cat_($file)); +} + +sub read_program_user_list { + my ($file) = @_; + my @user_list = grep { $_ && s/(.*?)\s//g } chomp_(cat_($file)); + uniq(map{ my $user = $_; + $user =~ m/(\w+),/g;} @user_list); +} + +sub apply_blacklist { + my @addr = @_; + my $blacklist_top = "/etc/dansguardian/lists/bannedsitelist"; + my $blacklist_category = "blocked by Mageia parental control tool"; + output_p($blacklist_url_file, map { $_ . "\n" } + qq(#listcategory: "$blacklist_category"), @addr); + include_guardian_file($blacklist_top, $blacklist_url_file); +} + +sub apply_whitelist { + my @addr = @_; + my $whitelist_top = "/etc/dansguardian/lists/exceptionsitelist"; + output_p($whitelist_url_file, map { $_ . "\n" } @addr); + include_guardian_file($whitelist_top, $whitelist_url_file); +} + +sub apply_block_program { + #my @addr = @_; + #output_p($acl_file, map { $_ . "\n" } @addr); + if ($program_control) { + my @original_list = read_program_list(@url_lists[2]->{file}); + my @orig_list = read_program_list(@url_lists[2]->{file}); + for (@original_list){ + s/\s(.*)//; + } + my @actual_list = list_get_entries(@url_lists[2]->{list}); + my @act_list = list_get_entries(@url_lists[2]->{list}); + for (@actual_list){ + s/\s(.*)//; + } + #code to make diff bettween vectors + my (@union, @intersection, @difference); + my $element; + @union = @intersection = @difference = (); + my %count = (); + foreach $element (@original_list, @actual_list) { $count{$element}++ }; + foreach $element (keys %count) { + # push @union, $element; + push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element; + } + if (scalar(@difference)) { + #keep the permissons save, make the way to do that + my $diff; + foreach $diff (@difference) { + my @orig_file = cat_($perms_orig); + my @progs_orig_file = grep { $_ && m/$diff/g } chomp_(cat_($perms_orig)); + #test if program is in msec + my @msec_program = grep { $_ && m/$diff/g } chomp_(cat_($msec_conf)); + if (scalar(@progs_orig_file)) {#test if is to remove or to add acl + #clean config file of the removed programs + foreach $element (@progs_orig_file){ + my $val = $element; + substInFile { + s|$element.*\n||; + } $perms_orig; + $val =~ s/\t(.*)\s*//; + $element =~ s/^(\d+)\t//; + if ($val) { + #write back in the msec file and set original file permissions + #`unprotect $diff --remove`; + remove_acl($dansguardian_protected_program_list, $diff); + subst_config_line($msec_conf,"$element\n"); + restore_permissions($element); + } + else { + #only make the permissions wright + #`unprotect $diff --remove`; + remove_acl($dansguardian_protected_program_list, $diff); + clean_config_line($msec_conf,"$diff"); + restore_permissions($element); + } + } + } + else { + if (scalar(@msec_program)){ + output_p($perms_orig, @orig_file, "1\t".$_."\n") foreach @msec_program; + #add file to msec and set acls + } + else { + my $mode = (stat($diff))[2] & 07777; + #"%04o" important to make 0755 to chmod ou chown + $mode = sprintf "%lo", $mode; + my $uid = (stat($diff))[4]; + my $gid = (stat($diff))[5]; + my $usrname = getpwuid($uid); + my $gname = getgrgid($gid); + my $to_add = "0\t$diff\t$usrname.$gname\t$mode\n"; + #keep the permissons safe make the way to do that + output_p($perms_orig, @orig_file, $to_add); + } + set_permissions($diff, grep {$_ && m/$diff/g} @act_list); + } + } + } + #this is just the case to reactivate the parental control + #`unprotect $_ --remove` foreach @intersection; + remove_acl($dansguardian_protected_program_list, $_) foreach @intersection; + foreach my $intersec (@intersection){ + set_permissions($intersec, grep {$_ && m/$intersec/g} @orig_list); + } + } + else { + my @original_list = list_get_entries(@url_lists[2]->{list}); + for (@original_list){ + s/\s(.*)//; + } + #restore the original file permissions + `setfacl -b $_` foreach @original_list; + foreach my $list (@original_list) { + my @progs_orig_file = grep { $_ && m/$list/g } chomp_(cat_($perms_orig)); + #test if program is in msec + if (scalar(@progs_orig_file)) { + #clean config file of the removed programs + foreach my $element (@progs_orig_file){ + my $val = $element; + $val =~ s/\t(.*)\s*//; + $element =~ s/^(\d+)\t//; + if ($val) { + #write back in the msec file and set original file permissions + subst_config_line($msec_conf,"$element\n"); + restore_permissions($element); + } + else { + #only make the permissions wright + clean_config_line($msec_conf,"$list"); + restore_permissions($element); + } + } + } + } + } +} -- cgit v1.2.1