#!/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 mygtk3; use ugtk3 qw(:create :helpers :wrappers); use Gtk3::SimpleList; use interactive; use network::shorewall; use network::squid; use services; use Encode; my $e2guardian_main_file = "/etc/e2guardian/e2guardian.conf"; my $e2guardian_filter_file = "/etc/e2guardian/e2guardianf1.conf"; my $time_control_file = "/etc/shorewall/time_control"; my $e2guardian_bannedsitelist = "/etc/e2guardian/lists/bannedsitelist"; my $e2guardian_exceptionsitelist = "/etc/e2guardian/lists/exceptionsitelist"; my $e2guardian_protected_program_list = "/etc/e2guardian/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 %e2guardian_levels = ( 160 => N_("Low"), 100 => N_("Normal"), 50 => N_("High"), ); my %e2guardian_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/e2guardian/lists/blacklists/drakguard/urls"; my $whitelist_url_file = "/etc/e2guardian/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 = 'e2guardian'; my $root_user = 'root'; load(); my $toolname = 'drakguard'; my $title = N("Parental Control"); my $icon = 'drakguard'; $ugtk3::wm_icon = $icon; my $w = ugtk3->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 = Gtk3::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 = Gtk3::SimpleList->new(N("Allowed users") => 'text'); $users_list->get_selection->set_mode('multiple'); @{$users_list->{data}} = difference2($shorewall->{accept_local_users}{http}, [ $root_user, $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 => $e2guardian_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, Gtk3::Banner->new($icon, $title)), 1, gtknew('Notebook', children => [ gtknew('Label', text => N("Configuration")), gtknew('VBox', spacing => 5, border_width => 5, children => [ 0, gtknew('WrappedLabel', 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 %e2guardian_levels ], text_ref => \$level, sensitive_ref => \$enable, format => sub { translate($e2guardian_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} = Gtk3::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 = Gtk3::SimpleList->new(N("Blocked users") => 'text'); $allusers_program_list->get_selection->set_mode('multiple'); @{$allusers_program_list->{data}} = sort(list_users()); $users_program_list = Gtk3::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; $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) { ($text) = /^Exec=(\w+)\s*/; if ($text eq "") { ($text) = /^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; # FIXME: bogus check: if ACLs are disabled everywhere but in /unused/path, it's OK... if (cat_('/boot/config') =~ /_FS_POSIX_ACL=y/ && grep { $_ && !/acl/ && !/^#/ && m/ext[23]|reiserfs/ } 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[23]|reiserfs/ && !/^#/ } chomp_(cat_($fstab_file)); foreach my $line (@ext_lines) { my ($flag) = $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" . N("It is necessary to restart your computer to activate it.")); } } else { my @mount = `mount`; if (grep { !/,acl/ && m/ext[23]|reiserfs/ } @mount) { $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" . N("It is necessary to restart your computer to activate it."), $acl_active = 0); } else { $acl_active = 1 } } update_time_change(); Gtk3->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) { my $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 Gtk3::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_e2guardian(); my $levelname = { %e2guardian_levels }->{$guardian->{naughtynesslimit}}; $net_control = $guardian->{netblock}; $program_control = $guardian->{programblock}; gtkval_modify(\$not_net_control, $enable && !$net_control); $level = { reverse %e2guardian_levels }->{$levelname} if $levelname; $level ||= { reverse %e2guardian_levels }->{High}; $enable = services::starts_on_boot('e2guardian'); $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 --kerneltz\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 e2guardian) ]) or quit_gui(1); $_->{apply}(list_get_entries($_->{list})) foreach @url_lists; write_e2guardian(); 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 e2guardian); if ($shorewall) { $shorewall->{disabled} = 0 if $enable; @{$shorewall->{accept_local_users}{http}} = if_($enable, uniq($proxy_user, $root_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($e2guardian_protected_program_list, "$line_info \n"); #adds the file to e2guardian_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_($e2guardian_protected_program_list)); `setfacl -m u:$user_msec:r-x $line`; subst_config_line($e2guardian_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) = @_; my ($fich, $usrname, $grpname, $mode) = $line =~ /^(.*)\t(\w+)\.(\w+)\t(\d+)\s*/ or return; $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)); substInFile { s|^\s*$key.*\n||; } $file; } sub block_internet_e2guardian { my ($file) = @_; my $key = "#"; substInFile { s|^$key\*\*\s|**\n|; } $file; } sub unblock_internet_e2guardian { 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 # Only use transparent proxy if squid version < 3.2. Handle upgrades nicely substr(`rpm -q squid`, 6, 3) < 3.2 ? subst_config_line($network::squid::squid_conf_file, "http_port $port transparent\n") : subst_config_line($network::squid::squid_conf_file, "http_port $port\n"); } #- mostly duplicated for MDK::Common::System::getVarsFromSh sub read_e2guardian() { my $guardian = {}; foreach (cat_($e2guardian_filter_file)) { s/#.*//; s/^\s*//; my ($v, $val) = /^(\w+)\s*=\s*(.*)/ or next; $val = $1 if $val =~ /^"(.*)"$/ || $val =~ /^'(.*)'$/; $guardian->{$v} = $val; } $guardian; } sub write_e2guardian() { require lang; my $locale = lang::read(); my $locale_lang = lang::getlocale_for_lang($locale->{lang}, $locale->{country}); my %lang_to_e2guardian = reverse %e2guardian_langs; my $e2guardian_lang = $lang_to_e2guardian{$locale_lang} || $lang_to_e2guardian{$locale->{lang}}; subst_config_line($e2guardian_main_file, "language = '$e2guardian_lang'\n") if $e2guardian_lang; subst_config_line($e2guardian_filter_file, "naughtynesslimit = '$level'\n"); subst_config_line($e2guardian_filter_file, "netblock = '$net_control'\n"); subst_config_line($e2guardian_filter_file, "programblock = '$program_control'\n"); if ($net_control) { block_internet_e2guardian($e2guardian_bannedsitelist); } else { unblock_internet_e2guardian($e2guardian_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 ($e2guardian_bannedsitelist eq $guardian_file && !$net_control || $e2guardian_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/e2guardian/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/e2guardian/lists/exceptionsitelist"; output_p($whitelist_url_file, map { $_ . "\n" } @addr); include_guardian_file($whitelist_top, $whitelist_url_file); } sub apply_block_program() { if ($program_control) { my @original_list = read_program_list($url_lists[2]{file}); my @orig_list = read_program_list($url_lists[2]{file}); foreach (@original_list) { s/\s(.*)//; } my @actual_list = list_get_entries($url_lists[2]{list}); my @act_list = list_get_entries($url_lists[2]{list}); foreach (@actual_list) { s/\s(.*)//; } #code to make diff bettween vectors my (@intersection, @difference); @intersection = @difference = (); my %count; foreach my $element (@original_list, @actual_list) { $count{$element}++ } foreach my $element (keys %count) { push @{ $count{$element} > 1 ? \@intersection : \@difference }, $element; } if (scalar(@difference)) { #keep the permissons save, make the way to do that foreach my $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 my $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($e2guardian_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($e2guardian_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($e2guardian_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}); foreach (@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); } } } } } }