summaryrefslogtreecommitdiffstats
path: root/bin/drakids
diff options
context:
space:
mode:
Diffstat (limited to 'bin/drakids')
-rw-r--r--bin/drakids337
1 files changed, 337 insertions, 0 deletions
diff --git a/bin/drakids b/bin/drakids
new file mode 100644
index 0000000..50cc786
--- /dev/null
+++ b/bin/drakids
@@ -0,0 +1,337 @@
+#!/usr/bin/perl
+
+use strict;
+use lib qw(/usr/lib/libDrakX);
+# i18n: IMPORTANT: to get correct namespace (drakx-net instead of libDrakX)
+BEGIN { unshift @::textdomains, 'drakx-net' }
+use common;
+use standalone;
+
+use Socket;
+use mygtk2 qw(gtknew);
+use ugtk2 qw(:dialogs);
+use POSIX qw(strftime);
+use dbus_object;
+use network::ifw;
+
+use Gtk2::SimpleList;
+
+use ugtk2 qw(:create :helpers :wrappers);
+
+my $loglist = create_attack_list();
+$loglist->get_selection->set_mode('single');
+
+my $blacklist = create_attack_list();
+$blacklist->get_selection->set_mode('multiple');
+
+my $whitelist = Gtk2::SimpleList->new(addr => 'hidden',
+ N("Allowed addresses") => 'text',
+ );
+$whitelist->get_selection->set_mode('multiple');
+$whitelist->set_headers_clickable(1);
+$whitelist->get_column(0)->signal_connect('clicked', \&sort_by_column, $whitelist->get_model);
+$whitelist->get_column(0)->set_sort_column_id(0);
+
+my $i_m_ifw2 = member("--ifw2", @ARGV);
+my $services_log = create_service_list('status');
+my $allowed_services = create_service_list();
+my $blocked_services = create_service_list();
+
+my $title = N("Interactive Firewall");
+my $icon = "drakfirewall";
+
+$ugtk2::wm_icon = $icon;
+my $w = ugtk2->new($title);
+
+my $ifw;
+eval {
+ my $bus = dbus_object::system_bus();
+ dbus_object::set_gtk2_watch_helper($bus);
+ network::ifw::init($bus, sub {
+ my ($_con, $msg) = @_;
+ my $member = $msg->get_member;
+ if ($member eq 'Attack') {
+ handle_log($msg->get_args_list);
+ } elsif ($member eq 'Blacklist') {
+ handle_blacklist($msg->get_args_list);
+ } elsif ($member eq 'Whitelist') {
+ handle_whitelist($msg->get_args_list);
+ } elsif ($member eq 'Clear') {
+ clear_lists();
+ } elsif ($member eq 'Init') {
+ handle_init();
+ } elsif ($member eq 'ManageRequest') {
+ $w->{window}->present;
+ }
+ });
+ $ifw = network::ifw->new($bus);
+};
+
+if ($@) {
+ err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+ $w->exit(1);
+}
+
+init_lists();
+
+gtkadd($w->{window},
+ gtknew('VBox', spacing => 5, children => [
+ $::isEmbedded ? () : (0, Gtk2::Banner->new($icon, $title)),
+ 1, gtknew('Notebook', children => [
+ if_($i_m_ifw2,
+ gtknew('Label', text => N("Log")),
+ gtknew('VBox', spacing => 5, children => [
+ 1, gtknew('ScrolledWindow', width => 600, height => 260, child => $services_log),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Allow"), clicked => sub {}),
+ gtknew('Button', text => N("Block"), clicked => sub {}),
+ gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit })
+ ]),
+ ]),
+ gtknew('Label', text => N("Allowed services")),
+ gtknew('VBox', spacing => 5, children => [
+ 1, gtknew('ScrolledWindow', width => 600, height => 260, child => $allowed_services),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Remove"), clicked => sub {}),
+ gtknew('Button', text => N("Block"), clicked => sub {}),
+ gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit })
+ ]),
+ ]),
+ gtknew('Label', text => N("Blocked services")),
+ gtknew('VBox', spacing => 5, children => [
+ 1, gtknew('ScrolledWindow', width => 600, height => 260, child => $blocked_services),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Remove"), clicked => sub {}),
+ gtknew('Button', text => N("Allow"), clicked => sub {}),
+ gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit })
+ ]),
+ ]),
+ ),
+ gtknew('Label', text => N("Log")),
+ gtknew('VBox', spacing => 5, children => [
+ 1, gtknew('ScrolledWindow', width => 600, height => 260, child => $loglist),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Clear logs"), clicked => \&clear_log),
+ gtknew('Button', text => N("Blacklist"), clicked => sub { blacklist(get_selected_log_seq()) }),
+ gtknew('Button', text => N("Whitelist"), clicked => sub { whitelist(get_selected_log()) }),
+ gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit })
+ ]),
+ ]),
+ gtknew('Label', text => N("Blacklist")),
+ gtknew('VBox', spacing => 5, children => [
+ 1, gtknew('ScrolledWindow', width => 600, height => 260, child => $blacklist),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Remove from blacklist"), clicked => sub { unblacklist(get_selected_blacklist()) }),
+ gtknew('Button', text => N("Move to whitelist"), clicked => sub {
+ my @addr = get_selected_blacklist();
+ unblacklist(@addr);
+ whitelist(@addr);
+ }),
+ gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit })
+ ]),
+ ]),
+ gtknew('Label', text => N("Whitelist")),
+ gtknew('VBox', spacing => 5, children => [
+ 1, gtknew('ScrolledWindow', width => 600, height => 260, child => $whitelist),
+ 0, gtknew('HButtonBox', layout => 'edge', children_loose => [
+ gtknew('Button', text => N("Remove from whitelist"), clicked => sub { unwhitelist(get_selected_whitelist()) }),
+ gtknew('Button', text => N("Close"), clicked => sub { Gtk2->main_quit })
+ ]),
+ ]),
+ ]),
+ ]),
+);
+$w->show;
+Gtk2->main;
+
+$w->exit(0);
+
+sub sort_by_column {
+ my ($column, $model) = @_;
+ my $col_id = $column->get_sort_column_id;
+ my ($old_id, $old_order) = $model->get_sort_column_id;
+ $model->set_sort_column_id($col_id, $old_id == $col_id && $old_order ne 'descending' ? 'ascending' : 'descending');
+}
+
+sub handle_init() {
+ $ifw->attach_object;
+ init_lists();
+}
+
+sub list_remove_addr {
+ my ($list, @addr) = @_;
+ #- workaround buggy Gtk2::SimpleList array abstraction, it destroys references
+ @$list = map { member($_->[0], @addr) ? () : [ @$_ ] } @$list;
+}
+
+#- may throw an exception
+sub init_blacklist() {
+ my @packets = $ifw->get_blacklist;
+ while (my @blacklist = splice(@packets, 0, 8)) {
+ handle_blacklist(@blacklist);
+ }
+}
+
+sub clear_blacklist() {
+ @{$blacklist->{data}} = ();
+}
+
+sub handle_blacklist {
+ attack_list_add($blacklist, network::ifw::attack_to_hash(\@_));
+}
+
+sub get_selected_blacklist() {
+ uniq(map { $blacklist->{data}[$_][0] } $blacklist->get_selected_indices);
+}
+
+sub blacklist {
+ my @seq = @_;
+ eval { $ifw->set_blacklist_verdict($_, 1) foreach @seq };
+ $@ and err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+}
+
+sub unblacklist {
+ my @addr = @_;
+ eval { $ifw->unblacklist($_) foreach @addr };
+ if (!$@) {
+ list_remove_addr($blacklist->{data}, @addr);
+ } else {
+ err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+ }
+}
+
+#- may throw an exception
+sub init_whitelist() {
+ handle_whitelist($_) foreach $ifw->get_whitelist;
+}
+
+sub clear_whitelist() {
+ @{$whitelist->{data}} = ();
+}
+
+sub handle_whitelist {
+ my ($addr) = @_;
+ push @{$whitelist->{data}}, [ $addr, network::ifw::resolve_address(network::ifw::get_ip_address($addr)) ];
+}
+
+sub get_selected_whitelist() {
+ uniq(map { $whitelist->{data}[$_][0] } $whitelist->get_selected_indices);
+}
+
+sub whitelist {
+ my @addr = @_;
+ eval { $ifw->whitelist($_) foreach @addr };
+ $@ and err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+}
+
+sub unwhitelist {
+ my @addr = @_;
+ eval { $ifw->unwhitelist($_) foreach @addr };
+ if (!$@) {
+ list_remove_addr($whitelist->{data}, @addr);
+ } else {
+ err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+ }
+}
+
+sub init_lists() {
+ eval {
+ init_loglist();
+ init_blacklist();
+ init_whitelist();
+ };
+ $@ and print "$@\n", err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+}
+
+sub clear_lists() {
+ clear_loglist();
+ clear_blacklist();
+ clear_whitelist();
+}
+
+sub create_attack_list() {
+ my $attacklist = Gtk2::SimpleList->new(addr => 'hidden',
+ seq => 'hidden',
+ timestamp => 'hidden',
+ N("Date") => 'text',
+ N("Remote host") => 'text',
+ N("Type") => 'text',
+ N("Service") => 'text',
+ N("Network interface") => 'text',
+ N("Protocol") => 'text',
+ );
+ $attacklist->set_headers_clickable(1);
+ foreach (0, 1, 2) {
+ $attacklist->get_column($_)->signal_connect('clicked', \&sort_by_column, $attacklist->get_model);
+ #- sort on timestamp if Date column is clicked
+ #- sort columns include hidden columns while list columns don't
+ $attacklist->get_column($_)->set_sort_column_id($_ == 0 ? 1 : $_ + 2);
+ }
+ $attacklist;
+}
+
+sub attack_list_add {
+ my ($attacklist, $attack) = @_;
+ push @{$attacklist->{data}}, [
+ $attack->{addr},
+ $attack->{seq},
+ $attack->{timestamp},
+ $attack->{date},
+ $attack->{hostname},
+ $attack->{type},
+ $attack->{service},
+ $attack->{indev},
+ $attack->{protocol},
+ ];
+}
+
+sub create_service_list {
+ my ($o_status) = @_;
+ my $service_list = Gtk2::SimpleList->new(
+ N("Application") => 'text',
+ N("Service") => 'text',
+ if_($o_status, N("Status") => 'text'),
+ );
+ N_("Allowed");
+ N_("Blocked");
+ $service_list->set_headers_clickable(1);
+ foreach (0, 1, if_($o_status, 2)) {
+ $service_list->get_column($_)->signal_connect('clicked', \&sort_by_column, $service_list->get_model);
+ }
+ $service_list;
+}
+
+#- may throw an exception
+sub init_loglist() {
+ my @packets = $ifw->get_reports(1);
+ while (my @attack = splice(@packets, 0, 10)) {
+ handle_log(@attack);
+ }
+}
+
+sub clear_loglist() {
+ @{$loglist->{data}} = ();
+}
+
+sub handle_log {
+ attack_list_add($loglist, network::ifw::attack_to_hash(\@_));
+}
+
+sub get_selected_log_seq() {
+ uniq(map { $loglist->{data}[$_][1] } $loglist->get_selected_indices);
+}
+sub get_selected_log() {
+ uniq(map { $loglist->{data}[$_][0] } $loglist->get_selected_indices);
+}
+
+sub clear_log() {
+ eval {
+ $ifw->clear_processed_reports;
+ $ifw->send_alert_ack;
+ };
+ if (!$@) {
+ clear_loglist();
+ } else {
+ err_dialog(N("Interactive Firewall"), N("Unable to contact daemon"));
+ }
+}