summaryrefslogtreecommitdiffstats
path: root/bin
diff options
context:
space:
mode:
authorEugeni Dodonov <eugeni@mandriva.org>2010-04-07 19:55:56 +0000
committerEugeni Dodonov <eugeni@mandriva.org>2010-04-07 19:55:56 +0000
commit039f61cf2431986680c3ca1a75f19f188974882e (patch)
treec4b7405350a52a2753cc6fe53fbb743bf5859779 /bin
parentd16315b8efb8fa8fe2d021a435edccf8f0544605 (diff)
downloaddrakguard-039f61cf2431986680c3ca1a75f19f188974882e.tar
drakguard-039f61cf2431986680c3ca1a75f19f188974882e.tar.gz
drakguard-039f61cf2431986680c3ca1a75f19f188974882e.tar.bz2
drakguard-039f61cf2431986680c3ca1a75f19f188974882e.tar.xz
drakguard-039f61cf2431986680c3ca1a75f19f188974882e.zip
Added patch from Tiago Marques <tiago.marques@caixamagica.pt> to support application blocking, msec integration, white-black lists and UI improvements (#43335).
Diffstat (limited to 'bin')
-rwxr-xr-xbin/drakguard391
1 files changed, 372 insertions, 19 deletions
diff --git a/bin/drakguard b/bin/drakguard
index 2d02d37..f86dd37 100755
--- a/bin/drakguard
+++ b/bin/drakguard
@@ -14,10 +14,16 @@ 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 %dansguardian_levels = (
160 => N_("Low"),
100 => N_("Normal"),
@@ -55,7 +61,7 @@ my %dansguardian_langs = (
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);
+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);
my $shorewall = network::shorewall::read();
my $proxy_port = 3128;
my $proxy_user = 'squid';
@@ -78,6 +84,9 @@ 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 ]);
@@ -96,11 +105,30 @@ my @url_lists = (
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);
+}
+
+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;
@@ -112,13 +140,17 @@ gtkadd($w->{window},
1, gtknew('Notebook', children => [
gtknew('Label', text => N("Configuration")),
gtknew('VBox', spacing => 5, border_width => 5, children => [
- 1, gtknew('WrappedLabel', text => N("This tool allows to configure parental control. It can block access to web sites and restrict connection during a specified timeframe.")),
- 1, gtknew('Label'),
- 0, gtknew('Title2', label => N("Main options")),
+ 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('Label_Left', text_markup => N("Control level"),
+ 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 ],
@@ -165,27 +197,89 @@ gtkadd($w->{window},
my $url_list = $_;
$url_list->{list} = Gtk2::SimpleList->new($url_list->{list_title} => 'text');
$url_list->{list}->get_selection->set_mode('multiple');
- @{$url_list->{list}{data}} = read_url_list($url_list->{file});
+ 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', text => $url_list->{tab_title}),
- gtknew('VBox', spacing => 5, children => [
- 0, gtknew('HBox', border_width => 5, spacing => 5, children_loose => [
+ 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 => \$enable), 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 => \$enable, 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'),
- gtknew('Button', text => N("Add"), clicked => sub {
+ 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"), "/var/lib/caixamagica/programas"));
+ })),
+ 0, gtknew('Button', text => N("Add"), clicked => sub {
my $text = $entry->get_text;
- $text =~ s,^[^:]+://,,g; #- strip protocol
- list_add_entry($url_list->{list}, $text);
- $entry->set_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){
+ ($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', width => 500, height => 300, child => $url_list->{list}),
- 0, gtknew('HButtonBox', border_width => 5, layout => 'edge', children_loose => [
+ 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),
@@ -209,6 +303,17 @@ sub list_add_entry {
}
}
+sub list_add_entry_program {
+ my ($list, @addr) = @_;
+ foreach my $a (@addr) {
+ $b = $a;
+ $a =~ s/\s(.*)//g;
+ @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
@@ -238,6 +343,14 @@ 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);
@@ -246,6 +359,9 @@ sub quit_gui {
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');
@@ -314,6 +430,10 @@ sub save() {
#- 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) {
@@ -323,10 +443,78 @@ sub save() {
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 "<prefix>:<file>") 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){
+ ($fich, $usrname, $grpname, $mode) = /^(.*)\t(\w+)\.(\w+)\t(\d+)\s*/ or next;
+ }
+ $mode = sprintf "%04d", $mode;#make number with 4 digits
+ $guid = getgrnam($grpname);
+ $uid = getpwnam($usrname);
+ chown $uid, $guid, $fich;
+ chmod oct($mode), $fich;
+}
+
sub subst_config_line {
my ($file, $line) = @_;
my $key = first(split(' ', $line));
@@ -337,6 +525,31 @@ sub subst_config_line {
} $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
@@ -364,15 +577,29 @@ sub write_dansguardian() {
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, "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 (!member($to_add, @all)) {
- output_p($guardian_file, @all, $to_add);
+ 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);
+ }
}
}
@@ -381,6 +608,18 @@ sub read_url_list {
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";
@@ -396,3 +635,117 @@ sub apply_whitelist {
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
+ @union = @intersection = @difference = ();
+ %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
+ 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 $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 $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 $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);
+ }
+ }
+ }
+ }
+ }
+}