aboutsummaryrefslogtreecommitdiffstats
path: root/lib/AdminPanel/Shared
diff options
context:
space:
mode:
authorMatteo Pasotti <matteo.pasotti@gmail.com>2015-01-08 17:29:54 +0100
committerMatteo Pasotti <matteo.pasotti@gmail.com>2015-01-08 17:29:54 +0100
commitab9bc693f8e8b31792eff493d860e9bb4d072cbf (patch)
tree1417543ee00cb1da6996982439af3b719e81f3ca /lib/AdminPanel/Shared
parentc3bfd51e5d52af523d039f8612be0058b01f9335 (diff)
parent6525f2ec4019ffad75c25164075f33f1aaa05e0d (diff)
downloadcolin-keep-ab9bc693f8e8b31792eff493d860e9bb4d072cbf.tar
colin-keep-ab9bc693f8e8b31792eff493d860e9bb4d072cbf.tar.gz
colin-keep-ab9bc693f8e8b31792eff493d860e9bb4d072cbf.tar.bz2
colin-keep-ab9bc693f8e8b31792eff493d860e9bb4d072cbf.tar.xz
colin-keep-ab9bc693f8e8b31792eff493d860e9bb4d072cbf.zip
Merge branch 'manawall'
Diffstat (limited to 'lib/AdminPanel/Shared')
-rw-r--r--lib/AdminPanel/Shared/Firewall.pm35
-rw-r--r--lib/AdminPanel/Shared/GUI.pm180
-rw-r--r--lib/AdminPanel/Shared/Shorewall.pm265
3 files changed, 480 insertions, 0 deletions
diff --git a/lib/AdminPanel/Shared/Firewall.pm b/lib/AdminPanel/Shared/Firewall.pm
new file mode 100644
index 0000000..ac44777
--- /dev/null
+++ b/lib/AdminPanel/Shared/Firewall.pm
@@ -0,0 +1,35 @@
+# vim: set et ts=4 sw=4:
+#*****************************************************************************
+#
+# Copyright (c) 2013-2014 Matteo Pasotti <matteo.pasotti@gmail.com>
+#
+# 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.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+#*****************************************************************************
+package AdminPanel::Shared::Firewall;
+
+use Moose;
+use diagnostics;
+use utf8;
+
+use lib qw(/usr/lib/libDrakX);
+use network::nfs;
+use network::network;
+use network::tools;
+
+sub _initialize {
+ my $self = shift();
+}
+
+1;
diff --git a/lib/AdminPanel/Shared/GUI.pm b/lib/AdminPanel/Shared/GUI.pm
index ced99c9..e305276 100644
--- a/lib/AdminPanel/Shared/GUI.pm
+++ b/lib/AdminPanel/Shared/GUI.pm
@@ -325,6 +325,66 @@ sub ask_YesOrNo {
#=============================================================
+=head2 ask_TwoConfigurableButtons
+
+=head3 INPUT
+
+$info: HASH, information to be passed to the dialog.
+ title => dialog title
+ text => string to be swhon into the dialog
+ richtext => 1 if using rich text
+ button_one => caption for the first button
+ button_two => caption for the second button
+ default_button => (optional) 1: "First button"
+
+=head3 OUTPUT
+
+ 0: "Button One Caption" button has been pressed
+ 1: "Button Two Caption" button has been pressed
+
+=head3 DESCRIPTION
+
+This function create a two-buttons dialog with a 'title', a
+question 'text' and a label for each button passed as parameters.
+
+=cut
+
+#=============================================================
+
+sub ask_TwoConfigurableButtons {
+ my ($self, $info) = @_;
+
+ return 0 if ( ! $info );
+
+ my $retVal = 0;
+ yui::YUI::widgetFactory;
+ my $factory = yui::YExternalWidgets::externalWidgetFactory("mga");
+ $factory = yui::YMGAWidgetFactory::getYMGAWidgetFactory($factory);
+ my $dlg = $factory->createDialogBox($yui::YMGAMessageBox::B_TWO);
+
+ $dlg->setTitle($info->{title}) if (exists $info->{title});
+ my $rt = (exists $info->{richtext}) ? $info->{richtext} : 0;
+ $dlg->setText($info->{text}, $rt) if (exists $info->{text});
+
+ $dlg->setButtonLabel($info->{button_one}, $yui::YMGAMessageBox::B_ONE );
+ $dlg->setButtonLabel($info->{button_two}, $yui::YMGAMessageBox::B_TWO);
+ if (exists $info->{default_button} && $info->{default_button} == 1) {
+ $dlg->setDefaultButton($yui::YMGAMessageBox::B_ONE);
+ }
+ else {
+ $dlg->setDefaultButton($yui::YMGAMessageBox::B_TWO);
+ }
+ $dlg->setMinSize(50, 5);
+
+ $retVal = $dlg->show() == $yui::YMGAMessageBox::B_ONE ? 1 : 0;
+
+ $dlg = undef;
+
+ return $retVal;
+}
+
+#=============================================================
+
=head2 arrayListToYItemCollection
=head3 INPUT
@@ -467,6 +527,126 @@ sub ask_fromList {
#=============================================================
+=head2 ask_multiple_fromList
+
+=head3 INPUT
+
+$info: HASH, information to be passed to the dialog.
+ title => dialog title
+ header => combobox header
+ default_item => selected item if any
+ list => item list
+ default_button => (optional) 1: Select (any other values Cancel)
+
+=head3 OUTPUT
+
+ undef: if Cancel button has been pressed
+ selected item: if Select button has been pressed
+
+=head3 DESCRIPTION
+
+This function create a dialog with variable checkboxes in which to
+choose the items from a given list.
+
+Warning: to use only for a reduced set of items because of no scroll available
+
+=cut
+
+#=============================================================
+
+sub ask_multiple_fromList {
+ my ($self, $info) = @_;
+
+ die "Missing dialog information" if (!$info);
+ die "Title is mandatory" if (! exists $info->{title});
+ die "Header is mandatory" if (! exists $info->{header});
+ die "List is mandatory" if (! exists $info->{list} );
+ die "At least one element is mandatory into list" if (scalar(@{$info->{list}}) < 1);
+
+ my @selections = ();
+ my $factory = yui::YUI::widgetFactory;
+
+ ## push application title
+ my $appTitle = yui::YUI::app()->applicationTitle();
+ ## set new title to get it in dialog
+ yui::YUI::app()->setApplicationTitle($info->{title});
+
+ my $dlg = $factory->createPopupDialog($yui::YDialogNormalColor);
+ my $layout = $factory->createVBox($dlg);
+
+ my @ckbox_array = ();
+
+ for my $item(@{$info->{list}})
+ {
+ my $ckbox = $factory->createCheckBox(
+ $factory->createLeft($factory->createHBox($layout)),
+ $item->{text},
+ ${$item->{val}}
+ );
+ $ckbox->setNotify(1);
+ push @ckbox_array, {
+ widget => \$ckbox,
+ text => $item,
+ value => $ckbox->value(),
+ };
+ $ckbox->DISOWN();
+ }
+
+ my $align = $factory->createRight($layout);
+ my $hbox = $factory->createHBox($align);
+ my $selectButton = $factory->createPushButton($hbox, $self->loc->N("Select"));
+ my $cancelButton = $factory->createPushButton($hbox, $self->loc->N("Cancel"));
+
+ if (exists $info->{default_button} ) {
+ my $dflBtn = ($info->{default_button} == 1) ? $selectButton : $cancelButton;
+ $dlg->setDefaultButton($selectButton);
+ }
+
+ while (1) {
+ my $event = $dlg->waitForEvent();
+
+ my $eventType = $event->eventType();
+ #event type checking
+ if ($eventType == $yui::YEvent::CancelEvent) {
+ last;
+ }
+ elsif ($eventType == $yui::YEvent::WidgetEvent) {
+ # widget selected
+ my $widget = $event->widget();
+
+ for my $ckbox (@ckbox_array)
+ {
+ if($widget == ${$ckbox->{widget}})
+ {
+ ${$ckbox->{value}} = !${$ckbox->{value}};
+ }
+ }
+ if ($widget == $cancelButton) {
+ last;
+ }
+ elsif ($widget == $selectButton) {
+ foreach my $ckbox (@ckbox_array)
+ {
+ if($ckbox->{value} == 1)
+ {
+ push @selections, $ckbox->{text};
+ }
+ }
+ last;
+ }
+ }
+ }
+
+ destroy $dlg;
+
+ #restore old application title
+ yui::YUI::app()->setApplicationTitle($appTitle);
+
+ return @selections;
+}
+
+#=============================================================
+
=head2 AboutDialog
=head3 INPUT
diff --git a/lib/AdminPanel/Shared/Shorewall.pm b/lib/AdminPanel/Shared/Shorewall.pm
new file mode 100644
index 0000000..03b29aa
--- /dev/null
+++ b/lib/AdminPanel/Shared/Shorewall.pm
@@ -0,0 +1,265 @@
+package AdminPanel::Shared::Shorewall; # $Id: shorewall.pm 254244 2009-03-18 22:54:32Z eugeni $
+
+use lib qw(/usr/lib/libDrakX); # helps perl_checker
+use detect_devices;
+use network::network;
+use AdminPanel::Shared::RunProgram;
+use MDK::Common::Func qw(if_ partition map_each);
+use MDK::Common::File qw(cat_ substInFile output_with_perm);
+use MDK::Common::Various qw(to_bool);
+use MDK::Common::DataStructure qw(is_empty_array_ref);
+use List::Util qw(any);
+use List::MoreUtils qw(uniq);
+use log;
+
+my $shorewall_root = "/etc/shorewall";
+our $firewall_icon = $::isInstall ? 'banner-security' : '/usr/share/mcc/themes/default/firewall-mdk.png';
+
+sub check_iptables() {
+ -f "$::prefix/etc/sysconfig/iptables" ||
+ $::isStandalone && do {
+ system('modprobe iptable_nat');
+ -x '/sbin/iptables' && listlength(`/sbin/iptables -t nat -nL`) > 8;
+ };
+}
+
+sub set_config_file {
+ my ($file, $ver, @l) = @_;
+
+ my $done;
+ substInFile {
+ my $last_line = /^#LAST LINE/ && $_;
+ if (!$done && ($last_line || eof)) {
+ $_ = join('', map { join("\t", @$_) . "\n" } @l);
+ $_ .= $last_line if $last_line;
+ $done = 1;
+ } else {
+ $_ = '' unless
+ /^#/ || $file eq 'rules' && /^SECTION/;
+ }
+ } "$::prefix${shorewall_root}${ver}/$file";
+}
+
+sub get_config_file {
+ my ($file, $o_ver) = @_;
+ map { [ split ' ' ] } grep { !/^#/ } cat_("$::prefix${shorewall_root}${o_ver}/$file");
+}
+
+# Note: Called from drakguard and drakfirewall.pm...
+# Deliberately not adding shorewall6 support here for now
+sub set_in_file {
+ my ($file, $enabled, @list) = @_;
+ my $done;
+ substInFile {
+ my $last_line = /^#LAST LINE/ && $_;
+ foreach my $l (@list) { s|^$l\n|| }
+ if (!$done && $enabled && ($last_line || eof)) {
+ $_ = join('', map { "$_\n" } @list);
+ $_ .= $last_line if $last_line;
+ $done = 1;
+ }
+ } "$::prefix${shorewall_root}/$file";
+}
+
+sub dev_to_shorewall {
+ my ($dev) = @_;
+ $dev =~ /^ippp/ && "ippp+" ||
+ $dev =~ /^ppp/ && "ppp+" ||
+ $dev;
+}
+
+sub get_net_zone_interfaces {
+ my ($interfacesfile, $_net, $all_intf) = @_;
+ #- read shorewall configuration first
+ my @interfaces = map { $_->[1] } grep { $_->[0] eq 'net' } $interfacesfile;
+ #- else try to find the best interface available
+ @interfaces ? @interfaces : @{$all_intf || []};
+}
+
+sub add_interface_to_net_zone {
+ my ($conf, $interface) = @_;
+ if (!member($interface, @{$conf->{net_zone}})) {
+ push @{$conf->{net_zone}}, $interface;
+ @{$conf->{loc_zone}} = grep { $_ ne $interface } @{$conf->{loc_zone}};
+ }
+}
+
+sub read_ {
+ my ($o_ver) = @_;
+ my $ver = '';
+ $ver = $o_ver if $o_ver;
+ #- read old rules file if config is not moved to rules.drakx yet
+ my @rules = get_config_file(-f "$::prefix${shorewall_root}${ver}/rules.drakx" ? 'rules.drakx' : 'rules', $ver);
+ require services;
+ my %conf = (disabled => !services::starts_on_boot("shorewall${ver}"),
+ version => $ver,
+ ports => join(' ', map {
+ my $e = $_;
+ map { "$_/$e->[3]" } split(',', $e->[4]);
+ } grep { $_->[0] eq 'ACCEPT' && $_->[1] eq 'net' } @rules),
+ );
+ push @{$conf{accept_local_users}{$_->[4]}}, $_->[8] foreach grep { $_->[0] eq 'ACCEPT+' } @rules;
+ $conf{redirects}{$_->[3]}{$_->[4]} = $_->[2] foreach grep { $_->[0] eq 'REDIRECT' } @rules;
+
+ if (my ($e) = get_config_file('masq', $ver)) {
+ ($conf{masq}{net_interface}, $conf{masq}{subnet}) = @$e;
+ }
+
+ my @policy = get_config_file('policy', $ver);
+ $conf{log_net_drop} = @policy ? (any { $_->[0] eq 'net' && $_->[1] eq 'all' && $_->[2] eq 'DROP' && $_->[3] } @policy) : 1;
+
+ return \%conf;
+
+ # get_zones has been moved to AdminPanel::Module::Firewall cause it requires
+ # user interaction thus it should be logically separated by shorewall
+ # get_zones(\%conf);
+ # get_config_file('zones', $ver) && \%conf;
+ # consequently, to read shorewall conf
+ # you have to do something like this now (within Module::Firewall)
+ # my $conf = AdminPanel::Shared::Shorewall::read_();
+ # OPTIONAL: my $self->get_zones(\$conf)
+ # my $shorewall = AdminPanel::Shared::Shorewall::get_config_file('zones', '') && $conf;
+}
+
+sub ports_by_proto {
+ my ($ports) = @_;
+ my %ports_by_proto;
+ foreach (split ' ', $ports) {
+ m!^(\d+(?::\d+)?)/(udp|tcp|icmp)$! or die "bad port $_\n";
+ push @{$ports_by_proto{$2}}, $1;
+ }
+ \%ports_by_proto;
+}
+
+#=============================================================
+
+=head2 write_
+
+=head3 INPUT
+
+ $conf: HASH, contains the configuration to write
+
+ $action: Str, possible values are "keep" or "drop"
+
+=head3 OUTPUT
+
+ 0: requires user interaction
+ 1: everything has been done
+
+=head3 DESCRIPTION
+
+This function stores the configuration for shorewall inside
+the proper files.
+
+=head3 NOTES
+
+if write_ is called without the $action parameter it can return 0
+(i.e. user interaction requested) when the firewall configuration
+has been manually changed.
+
+In that case the developer will have to handle this request by providing
+two choices within the domain (keep | drop) and then recall write_ with
+the choosen behaviour.
+
+=cut
+
+#=============================================================
+
+sub write_ {
+ my ($conf, $action) = @_;
+ my $ver = $conf->{version} || '';
+ my $use_pptp = any { /^ppp/ && cat_("$::prefix/etc/ppp/peers/$_") =~ /pptp/ } @{$conf->{net_zone}};
+ my $ports_by_proto = ports_by_proto($conf->{ports});
+ my $has_loc_zone = to_bool(@{$conf->{loc_zone} || []});
+
+ my ($include_drakx, $other_rules) = partition { $_ eq "INCLUDE\trules.drakx\n" } grep { !/^(#|SECTION)/ } cat_("$::prefix${shorewall_root}${ver}/rules");
+ #- warn if the config is already in rules.drakx and additionnal rules are configured
+ if (!is_empty_array_ref($include_drakx) && !is_empty_array_ref($other_rules)) {
+ if(!defined($action) || AdminPanel::Shared::trim($action) eq "")
+ {
+ return 0; # user interaction requested
+ }
+ my %actions = (
+ keep => N("Keep custom rules"),
+ drop => N("Drop custom rules"),
+ );
+ #- reset the rules files if the user has chosen to drop modifications
+ undef $include_drakx if $action eq 'drop';
+ }
+
+ my $interface_settings = sub {
+ my ($zone, $interface) = @_;
+ [ $zone, $interface, 'detect', if_(detect_devices::is_bridge_interface($interface), 'bridge') ];
+ };
+
+ set_config_file('zones', $ver,
+ if_($has_loc_zone, [ 'loc', 'ipv' . ($ver || '4') ]),
+ [ 'net', 'ipv' . ($ver || '4') ],
+ [ 'fw', 'firewall' ],
+ );
+ set_config_file('interfaces', $ver,
+ (map { $interface_settings->('net', $_) } @{$conf->{net_zone}}),
+ (map { $interface_settings->('loc', $_) } @{$conf->{loc_zone} || []}),
+ );
+ set_config_file('policy', $ver,
+ if_($has_loc_zone, [ 'loc', 'net', 'ACCEPT' ], [ 'loc', 'fw', 'ACCEPT' ], [ 'fw', 'loc', 'ACCEPT' ]),
+ [ 'fw', 'net', 'ACCEPT' ],
+ [ 'net', 'all', 'DROP', if_($conf->{log_net_drop}, 'info') ],
+ [ 'all', 'all', 'REJECT', 'info' ],
+ );
+ if (is_empty_array_ref($include_drakx)) {
+ #- make sure the rules.drakx config is read, erasing user modifications
+ set_config_file('rules', $ver, [ 'INCLUDE', 'rules.drakx' ]);
+ }
+ output_with_perm("$::prefix${shorewall_root}${ver}/" . 'rules.drakx', 0600, map { join("\t", @$_) . "\n" } (
+ if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'tcp', '1723' ]),
+ if_($use_pptp, [ 'ACCEPT', 'fw', 'loc:10.0.0.138', 'gre' ]),
+ (map_each { [ 'ACCEPT', 'net', 'fw', $::a, join(',', @$::b), '-' ] } %$ports_by_proto),
+ (map_each {
+ if_($::b, map { [ 'ACCEPT+', 'fw', 'net', 'tcp', $::a, '-', '-', '-', $_ ] } @$::b);
+ } %{$conf->{accept_local_users}}),
+ (map {
+ my $proto = $_;
+ #- WARNING: won't redirect ports from the firewall system if a local zone exists
+ #- set redirect_fw_only to workaround
+ map_each {
+ map { [ 'REDIRECT', $_, $::b, $proto, $::a, '-' ] } 'fw', if_($has_loc_zone, 'loc');
+ } %{$conf->{redirects}{$proto}};
+ } keys %{$conf->{redirects}}),
+ ));
+ set_config_file('masq', $ver, if_(exists $conf->{masq}, [ $conf->{masq}{net_interface}, $conf->{masq}{subnet} ]));
+
+ require services;
+ if ($conf->{disabled}) {
+ services::disable('shorewall', $::isInstall);
+ run_program::rooted($::prefix, '/sbin/shorewall', 'clear') unless $::isInstall;
+ } else {
+ services::enable('shorewall', $::isInstall);
+ }
+ return 1;
+}
+
+sub set_redirected_ports {
+ my ($conf, $proto, $dest, @ports) = @_;
+ if (@ports) {
+ $conf->{redirects}{$proto}{$_} = $dest foreach @ports;
+ } else {
+ my $r = $conf->{redirects}{$proto};
+ @ports = grep { $r->{$_} eq $dest } keys %$r;
+ delete $r->{$_} foreach @ports;
+ }
+}
+
+sub update_interfaces_list {
+ my ($o_intf) = @_;
+ if (!$o_intf || !member($o_intf, map { $_->[1] } get_config_file('interfaces'))) {
+ my $shorewall = network::shorewall::read();
+ $shorewall && !$shorewall->{disabled} and network::shorewall::write($shorewall);
+ }
+ if (!$o_intf || !member($o_intf, map { $_->[1] } get_config_file('interfaces', 6))) {
+ my $shorewall6 = network::shorewall::read(undef, 6);
+ $shorewall6 && !$shorewall6->{disabled} and network::shorewall::write($shorewall6);
+ }
+}
+
+1;