diff options
author | Matteo Pasotti <matteo.pasotti@gmail.com> | 2015-01-08 17:29:54 +0100 |
---|---|---|
committer | Matteo Pasotti <matteo.pasotti@gmail.com> | 2015-01-08 17:29:54 +0100 |
commit | ab9bc693f8e8b31792eff493d860e9bb4d072cbf (patch) | |
tree | 1417543ee00cb1da6996982439af3b719e81f3ca /lib/AdminPanel/Shared | |
parent | c3bfd51e5d52af523d039f8612be0058b01f9335 (diff) | |
parent | 6525f2ec4019ffad75c25164075f33f1aaa05e0d (diff) | |
download | colin-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.pm | 35 | ||||
-rw-r--r-- | lib/AdminPanel/Shared/GUI.pm | 180 | ||||
-rw-r--r-- | lib/AdminPanel/Shared/Shorewall.pm | 265 |
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; |