ACC SHELL
/**
* File: firewall/uifunctions.ycp
* Package: Configuration YaST2 Firewall
* Summary: Configuration dialogs handling functions
* Authors: Lukas Ocilka <locilka@suse.cz>
*
* $Id: uifunctions.ycp 59814 2009-11-26 18:24:30Z kmachalkova $
*
* Configuration dialogs handling.
* Both Expert and Simple.
*/
{
textdomain "firewall";
import "Confirm";
import "SuSEFirewall";
import "SuSEFirewallServices";
import "SuSEFirewallExpertRules";
import "PortAliases";
import "Popup";
import "Address";
import "Wizard";
import "Report";
import "Label";
import "Mode";
import "IP";
import "Netmask";
import "PortRanges";
include "firewall/generalfunctions.ycp";
include "firewall/helps.ycp";
include "firewall/subdialogs.ycp";
// GLOBAL UI CONFIGURATION
term all_popup_definition = `opt(`decorated,`centered);
// EXAMPLE FUNCTIONS
/*
* void ExampleInit(string key) {
* y2milestone("Example Init");
* }
*
* symbol ExampleHandle(string key, map event) {
* any ret = event["ID"]:nil;
* y2milestone("Example Handle");
* return nil;
* }
*
* void ExampleStore(string key, map event) {
* any ret = event["ID"]:nil;
* y2milestone("Example Store");
* }
*
*/
/**
* Checks the network entry which can be defined in several formats.
*
* @example
* CheckNetwork ("192.168.0.1") -> true
* CheckNetwork ("192.168.0.0/20") -> true
* CheckNetwork ("192.168.0.0/255.255.255.0") -> true
* CheckNetwork ("0/0") -> true
*/
boolean CheckNetwork (string network) {
boolean ret = nil;
if (network == nil || network == "") {
ret = false;
} else if (network == "0/0") {
ret = true;
// 192.168.0.1, 0.8.55.999
} else if (regexpmatch(network, "^[0123456789\.]+$")) {
ret = IP::Check4 (network);
// 192.168.0.0/20, 0.8.55/158
} else if (regexpmatch(network, "^[0123456789\.]+/[0123456789]+$")) {
string network_ip = regexpsub (network, "^([0123456789\.]+)/[0123456789]+$", "\\1");
string network_mask = regexpsub (network, "^[0123456789\.]+/([0123456789]+)$", "\\1");
ret = (IP::Check4 (network_ip) && Netmask::CheckPrefix4 (network_mask));
// 192.168.0.0/255.255.255.0, 0.8.55/10.258.12
} else if (regexpmatch(network, "^[0123456789\.]+/[0123456789\.]+$")) {
string network_ip = regexpsub (network, "^([0123456789\.]+)/[0123456789\.]+$", "\\1");
string network_mask = regexpsub (network, "^[0123456789\.]+/([0123456789\.]+)$", "\\1");
ret = (IP::Check4 (network_ip) && Netmask::Check4 (network_mask));
}
if (ret != true && ! Mode::testsuite()) {
// TRANSLATORS: error message, %1 represents the erroneous network definition
Report::Error (sformat (_("Invalid network definition '%1'.
Network can be defined as an IP or IP with slash and netmask.
For instance: 192.168.0.1
or 192.168.0.0/20
or 192.168.0.0/255.255.255.0
or 0/0"), network));
}
return ret;
}
// UI Functions
/**
* Sets the dialog icon.
*/
void SetFirewallIcon () {
Wizard::SetTitleIcon("yast-firewall");
}
/**
* Function disables the back button.
* Fake function for CWM Tree Widget.
*/
void DisableBackButton (string key) {
SetFirewallIcon();
UI::ChangeWidget(`id(`back), `Enabled, false);
}
/**
* Function saves configuration and restarts firewall
*/
boolean SaveAndRestart () {
Wizard::CreateDialog ();
Wizard::RestoreHelp (HelpForDialog("saving_configuration"));
boolean success = SuSEFirewall::SaveAndRestartService ();
if (success) SuSEFirewall::SetStartService(true);
sleep(500);
UI::CloseDialog ();
return success;
}
/**
* Function starts Firewall services and sets firewall
* to be started after exiting YaST
*/
boolean StartNow() {
UI::OpenDialog(`Label(_("Starting firewall...")));
SuSEFirewall::SetStartService(true);
boolean ret = SuSEFirewall::StartServices();
UI::CloseDialog ();
return ret;
}
/**
* Function stops Firewall services and sets firewall
* to be stopped after exiting YaST
*/
boolean StopNow() {
UI::OpenDialog(`Label(_("Stopping firewall...")));
SuSEFirewall::SetStartService(false);
boolean ret = SuSEFirewall::StopServices();
UI::CloseDialog ();
return ret;
}
/**
* Function sets appropriate states for [Change] and [Custom] buttons
*/
void SetFirewallInterfacesCustomAndChangeButtons(string current_item) {
// if called from Init() function
if (current_item == nil)
current_item = (string) UI::QueryWidget(
`id ("table_firewall_interfaces"), `CurrentItem);
// string is one of known network interfaces
if (regexpmatch(current_item, "^known-.*")) {
UI::ChangeWidget(`id("change_firewall_interface"), `Enabled, true);
UI::ChangeWidget(`id("user_defined_firewall_interface"), `Enabled, true);
// string is a custom string
} else {
UI::ChangeWidget(`id("change_firewall_interface"), `Enabled, false);
UI::ChangeWidget(`id("user_defined_firewall_interface"), `Enabled, true);
}
}
// maximum length of the string "Interface Name" (min. 3)
integer max_length_intname = 35;
/**
* Function redraws Interfaces Table
*/
void RedrawFirewallInterfaces() {
list <term> table_items = [];
// firstly listing all known interfaces
foreach (map <string, string> interface, SuSEFirewall::GetAllKnownInterfaces(), {
// TRANSLATORS: table item, connected with firewall zone of interface
string zone_name = _("No zone assigned");
if (interface["zone"]:nil != nil)
zone_name = SuSEFirewall::GetZoneFullName(interface["zone"]:nil);
// shortening the network card name
if (interface["name"]:nil != nil && size(interface["name"]:"")>max_length_intname) {
interface["name"] = substring(interface["name"]:"", 0, (max_length_intname - 3)) + "...";
}
table_items = add (table_items, `item( `id("known-" + interface["id"]:nil),
interface["name"]:nil,
interface["id"]:nil,
zone_name
));
});
foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
list <string> specials = SuSEFirewall::GetSpecialInterfacesInZone(zone);
string zone_name = SuSEFirewall::GetZoneFullName(zone);
string custom_string_text = "";
foreach (string special, specials, {
// TRANSLATORS: table item, "User defined string" instead of Device_name
custom_string_text = _("Custom string");
table_items = add (table_items, `item( `id("special-" + special),
custom_string_text,
special,
zone_name
));
});
});
UI::ChangeWidget ( `id("table_firewall_interfaces"), `Items, table_items);
SetFirewallInterfacesCustomAndChangeButtons(nil);
}
// map of device names
map <string, string> known_device_names = $[];
/**
* Function initializes Interfaces table and known_device_names
*/
void InitFirewallInterfaces (string key) {
SetFirewallIcon();
// initializing names of interfaces
known_device_names = $[];
foreach (map <string, string> known_interface, SuSEFirewall::GetAllKnownInterfaces(), {
// shortening the network card name
if (size(known_interface["name"]:"")>max_length_intname) {
known_interface["name"] = substring(known_interface["name"]:"", 0, (max_length_intname - 3)) + "...";
}
known_device_names[known_interface["id"]:""] = known_interface["name"]:"";
});
// known interfaces/string have ID: "known-" + interface
// uknown strings have ID: "special-" + string
RedrawFirewallInterfaces();
}
/**
* Function handles popup dialog witch setting Interface into Zone
*/
void HandlePopupSetFirewallInterfaceIntoZone (string interface) {
// interface could be unassigned
// TRANSLATORAS: selection box item, connected with firewall zone of interface
list <term> zones = [ `item(`id(""), _("No Zone Assigned")) ];
// current zone of interface
string current_zone = SuSEFirewall::GetZoneOfInterface (interface);
foreach (string zone_shortname, SuSEFirewall::GetKnownFirewallZones(), {
zones = add (zones, `item(
`id(zone_shortname), SuSEFirewall::GetZoneFullName(zone_shortname),
(zone_shortname == current_zone ? true:false)
));
});
// opening popup
UI::OpenDialog(all_popup_definition, SetFirewallInterfaceIntoZone(
known_device_names[interface]:"",
interface,
zones
));
string ret = (string) UI::UserInput();
boolean changed = false;
if (ret == "ok") {
string new_zone = (string) UI::QueryWidget(`id("zone_for_interface"), `Value);
if (new_zone != current_zone) {
changed = true;
SuSEFirewall::AddInterfaceIntoZone(interface, new_zone);
}
}
UI::CloseDialog();
if (changed) RedrawFirewallInterfaces();
}
/**
* Function handles popup with additional settings in zones
*/
void HandlePopupAdditionalSettingsForZones () {
map <string, list <string> > starting_additionals = $[];
map <string, map <string, string> > zones_additons = $[];
foreach (string zone_shortname, SuSEFirewall::GetKnownFirewallZones(), {
list <string> specials = SuSEFirewall::GetSpecialInterfacesInZone(zone_shortname);
starting_additionals[zone_shortname] = specials;
zones_additons[zone_shortname] = $[
"name" : SuSEFirewall::GetZoneFullName(zone_shortname),
"items" : mergestring(specials, " "),
];
});
UI::OpenDialog(all_popup_definition, AdditionalSettingsForZones(zones_additons));
string ret = (string) UI::UserInput();
boolean changed = false;
if (ret == "ok") {
list <list <string> > events_remove = [];
list <list <string> > events_add = [];
foreach (string zone_shortname, SuSEFirewall::GetKnownFirewallZones(), {
list <string> new_additions = splitstring((string) UI::QueryWidget(`id("zone_additions_" + zone_shortname), `Value), " ");
// checking for new additions
foreach (string new_addition_item, new_additions, {
if (new_addition_item != "" && !contains(starting_additionals[zone_shortname]:[], new_addition_item)) {
changed = true;
events_add = add (events_add, [ new_addition_item, zone_shortname ]);
}
});
// checking for removed additions
foreach (string old_addition_item, starting_additionals[zone_shortname]:[], {
if (old_addition_item != "" && !contains(new_additions, old_addition_item)) {
changed = true;
events_remove = add (events_remove, [ old_addition_item, zone_shortname ]);
}
});
});
foreach (list <string> adding, events_add, {
SuSEFirewall::AddSpecialInterfaceIntoZone(adding[0]:"", adding[1]:"");
});
foreach (list <string> removing, events_remove, {
SuSEFirewall::RemoveSpecialInterfaceFromZone(removing[0]:"", removing[1]:"");
});
}
UI::CloseDialog();
if (changed) RedrawFirewallInterfaces();
}
/**
* Function handles whole firewall-interfaces dialg
*/
symbol HandleFirewallInterfaces (string key, map event) {
any ret = event["ID"]:nil;
// "Activated" (double-click) or "SelectionChanged" (any other)
string event_reason = event["EventReason"]:"SelectionChanged";
string current_item = (string) UI::QueryWidget(
`id ("table_firewall_interfaces"), `CurrentItem);
// double click on the table item
if (ret == "table_firewall_interfaces" && event_reason == "Activated") {
// known iterface means -> as it was pressed [Change] button
if (regexpmatch(current_item, "^known-")) {
ret = "change_firewall_interface";
// known iterface means -> as it was pressed [Custom] button
} else if (regexpmatch(current_item, "^special-")) {
ret = "user_defined_firewall_interface";
}
}
// Double click on the item or some modification button has been pressed
if (ret == "change_firewall_interface" || ret == "user_defined_firewall_interface") {
// "change" can handle both interfaces and special strings
if (ret == "change_firewall_interface") {
// handling interfaces
if (regexpmatch(current_item, "^known-")) {
HandlePopupSetFirewallInterfaceIntoZone(
regexpsub(current_item, "^known-(.*)", "\\1")
);
// handling special strings
} else if (regexpmatch(current_item, "^special-")) {
HandlePopupAdditionalSettingsForZones();
} else {
y2error("Uknown interfaces_item '%1'", current_item);
}
// "user-defined" can only handle special strings
} else if (ret == "user_defined_firewall_interface") {
HandlePopupAdditionalSettingsForZones();
}
// single click (changed current item)
} else if (ret == "table_firewall_interfaces" && event_reason == "SelectionChanged") {
SetFirewallInterfacesCustomAndChangeButtons(current_item);
}
return nil;
}
/**
* Reports that the port definition is wrong. Either a single port
* or a port range. Returns whether user accepts the wrong port definition
* despite this warning.
*
* @param integer port_nr
* @param string port_definition might be a single port or a port-range definition
* @return boolean whether user accepts the port definition despite the warning.
*
* @example
* // maximum port number is 65535, port range
* boolean accepted = ReportWrongPortDefinition(99999, "5:99999");
* // dtto., single port
* boolean whattodo = ReportWrongPortDefinition(78910, "78910");
*/
boolean ReportWrongPortDefinition (string port_nr, string port_definition) {
string port_err = "";
if (port_nr == port_definition) {
// TRANSLATORS: error message, %1 stands for the port number
port_err = sformat(_("Port number %1 is invalid."), port_nr);
} else {
// TRANSLATORS: error message, %1 stands for the port number,
// %2 stands for, e.g., port range, where the wrong port definition %1 was found
port_err = sformat(
_("Port number %1 in definition %2 is invalid."),
port_nr, port_definition
);
}
return Popup::ContinueCancelHeadline (
// TRANSLATORS: popup headline
_("Invalid Port Definition"),
port_err + "\n\n" +
// TRANSLATORS: popup message, %1 stands for the maximal port number
// that is possible to use in port-range
sformat(_("The port number must be in the interval from 1 to %1 (inclusive)."), SuSEFirewall::max_port_number)
);
}
boolean CheckPortNumberDefinition (integer port_nr, string port) {
if (port_nr < 1 || port_nr > SuSEFirewall::max_port_number) {
return ReportWrongPortDefinition(tostring(port_nr), port);
} else {
return true;
}
}
boolean CheckPortNameDefinition (string port_name) {
if (PortAliases::IsAllowedPortName(port_name)) {
return true;
} else {
Report::Error (PortAliases::AllowedPortNameOrNumber());
return false;
}
}
/**
* Function checks list of ports if they exist (are known).
*
* @param string ui_id for the setfocus
* @param list <string> of ports to be checked
*/
boolean CheckIfTheyAreAllKnownPorts(string ui_id, list <string> ports) {
boolean checked = true;
// begin of for~each
foreach (string port, ports, {
// previos port was wrong, break the loop
if (!checked) break;
// just a waste-space
if (port == "") return;
// common numeric port
if (regexpmatch(port, "^[0123456789]+$")) {
integer port_nr = tointeger(port);
if (CheckPortNumberDefinition(port_nr, port) && checked) checked = true;
else checked = false;
return;
}
// common port range
if (regexpmatch(port, "^[0123456789]+:[0123456789]+$")) {
string port1 = regexpsub(port, "^([0123456789]+):[0123456789]+$", "\\1");
string port2 = regexpsub(port, "^[0123456789]+:([0123456789]+)$", "\\1");
integer port1i = tointeger(port1);
integer port2i = tointeger(port2);
if (! CheckPortNumberDefinition(port1i, port)) checked = false;
if (! CheckPortNumberDefinition(port2i, port)) checked = false;
// port range is defined as 'A:B' where A<B
else if (port1i != nil && port2i != nil && port1i < port2i) return;
else if (!Popup::ContinueCancelHeadline (
// TRANSLATORS: popup headline
_("Invalid Port Range Definition"),
// TRANSLATORS: popup message, %1 is a port-range defined by user
sformat(_("Port range %1 is invalid.
It must be defined as the min_port_number:max_port_number and
max_port_number must be bigger than min_port_number."), port)
) && checked) {
checked = false;
}
return;
}
// port number
if (! PortAliases::IsKnownPortName(port)) {
if (! Popup::ContinueCancelHeadline(
// TRANSLATORS: popup headline
_("Unknown Port Name"),
sformat(
// TRANSLATORS: popup message, %1 is a port-name
_("Port name %1 is unknown in your current system.
It probably would not work.
Really use this port?
"),
port
)
)) checked = false;
return;
}
// end of for~each
});
if (!checked) {
UI::SetFocus(`id(ui_id));
}
return checked;
}
/**
* Checks the string (services definition) for syntax errors
*
* @param string services_definition
* @return boolean whether everything was ok or whether user wants is despite the error
*/
boolean CheckAdditionalServicesDefinition (string services_definition) {
if (regexpmatch(services_definition, ",")) {
list <string> ports = splitstring(services_definition, ",");
return Popup::YesNoHeadline (
// TRANSLATORS: popup headline
_("Invalid Additional Service Definition"),
// TRANSLATORS: popup message, %1 stands for the wrong settings (might be quite long)
sformat(_("It appears that the additional service settings
%1
are wrong. Entries should be separated by spaces instead of commas,
which are not allowed.
Really use the current settings?"), services_definition)
);
}
return true;
}
boolean HandlePopupAdditionalServices (string zone) {
string zone_name = SuSEFirewall::GetZoneFullName(zone);
UI::OpenDialog(all_popup_definition, AdditionalServices(zone_name));
// getting additional services
list <string> additional_tcp = toset(SuSEFirewall::GetAdditionalServices("TCP", zone));
list <string> additional_udp = toset(SuSEFirewall::GetAdditionalServices("UDP", zone));
list <string> additional_rpc = toset(SuSEFirewall::GetAdditionalServices("RPC", zone));
list <string> additional_ip = toset(SuSEFirewall::GetAdditionalServices("IP", zone));
// filling up popup dialog
UI::ChangeWidget(`id("additional_tcp"), `Value, mergestring(additional_tcp, " "));
UI::ChangeWidget(`id("additional_udp"), `Value, mergestring(additional_udp, " "));
UI::ChangeWidget(`id("additional_rpc"), `Value, mergestring(additional_rpc, " "));
UI::ChangeWidget(`id("additional_ip"), `Value, mergestring(additional_ip, " "));
// Filling up help
UI::ChangeWidget(`help_text, `Value, HelpForDialog("additional-services"));
any ret = nil;
boolean ret_value = false;
while (true) {
ret = UI::UserInput();
if (ret == "ok") {
string s_additional_tcp = (string) UI::QueryWidget(`id("additional_tcp"), `Value);
list <string> new_additional_tcp = toset(splitstring(s_additional_tcp, " "));
string s_additional_udp = (string) UI::QueryWidget(`id("additional_udp"), `Value);
list <string> new_additional_udp = toset(splitstring(s_additional_udp, " "));
string s_additional_rpc = (string) UI::QueryWidget(`id("additional_rpc"), `Value);
list <string> new_additional_rpc = toset(splitstring(s_additional_rpc, " "));
string s_additional_ip = (string) UI::QueryWidget(`id("additional_ip"), `Value);
list <string> new_additional_ip = toset(splitstring(s_additional_ip, " "));
// Check the format
if (!CheckAdditionalServicesDefinition(s_additional_tcp)) continue;
if (!CheckAdditionalServicesDefinition(s_additional_udp)) continue;
if (!CheckAdditionalServicesDefinition(s_additional_rpc)) continue;
if (!CheckAdditionalServicesDefinition(s_additional_ip)) continue;
// checking for known TCP and UDP port names
if (!CheckIfTheyAreAllKnownPorts("additional_tcp", new_additional_tcp)) continue;
if (!CheckIfTheyAreAllKnownPorts("additional_udp", new_additional_udp)) continue;
SuSEFirewall::SetAdditionalServices("TCP", zone, new_additional_tcp);
SuSEFirewall::SetAdditionalServices("UDP", zone, new_additional_udp);
SuSEFirewall::SetAdditionalServices("RPC", zone, new_additional_rpc);
SuSEFirewall::SetAdditionalServices("IP", zone, new_additional_ip );
ret_value = true;
break;
} else if (ret == "cancel" || ret == `cancel) {
ret_value = false;
break;
}
}
UI::CloseDialog();
return ret_value;
}
void RedrawAllowedServicesDialog (string current_zone) {
if (SuSEFirewall::GetProtectFromInternalZone() == false && current_zone == "INT") {
UI::ChangeWidget(`id("allow_service_names"), `Enabled, false);
UI::ChangeWidget(`id("add_allowed_service"), `Enabled, false);
UI::ChangeWidget(`id("table_allowed_services"), `Enabled, false);
UI::ChangeWidget(`id("remove_allowed_service"), `Enabled, false);
UI::ChangeWidget(`id("advanced_allowed_service"), `Enabled, false);
} else {
UI::ChangeWidget(`id("allow_service_names"), `Enabled, true);
UI::ChangeWidget(`id("add_allowed_service"), `Enabled, true);
UI::ChangeWidget(`id("table_allowed_services"), `Enabled, true);
UI::ChangeWidget(`id("remove_allowed_service"), `Enabled, true);
UI::ChangeWidget(`id("advanced_allowed_service"), `Enabled, true);
}
}
void RedrawAllowedServices(string current_zone) {
if (! contains(SuSEFirewall::GetKnownFirewallZones(), current_zone)) {
y2error("Unknown zone '%1'", current_zone);
return nil;
}
// FIXME: protect from internal, disabling table, etc...
list <term> allowed_services = [];
// sorted by translated service_name
map <string, string> translations_to_service_ids = $[];
foreach (string service_id, string service_name, SuSEFirewallServices::GetSupportedServices(), {
// a service with the very same name (translation) already defined
if (translations_to_service_ids[service_name]:nil != nil) {
// service:apache2 -> apache2
if (SuSEFirewallServices::ServiceDefinedByPackage (service_id)) {
service_name = sformat (
"%1 (%2)",
service_name, SuSEFirewallServices::GetFilenameFromServiceDefinedByPackage (service_id)
);
} else {
service_name = sformat (
"%1 (%2)",
service_name, service_id
);
}
}
translations_to_service_ids[service_name] = service_id;
});
list <term> all_known_services = GetDefinedServicesListedItems();
list <term> not_allowed_services = [];
// not protected, all services are allowed
if (current_zone == "INT" && !SuSEFirewall::GetProtectFromInternalZone()) {
foreach (string service_name, string service_id, translations_to_service_ids, {
allowed_services = add (allowed_services, `item(`id(service_id), service_name));
});
// protected, only allowed services
} else {
foreach (string service_name, string service_id, translations_to_service_ids, {
if (SuSEFirewall::IsServiceSupportedInZone(service_id, current_zone)) {
allowed_services = add (allowed_services, `item(`id(service_id), service_name, SuSEFirewallServices::GetDescription(service_id)));
} else {
not_allowed_services = add (not_allowed_services, `item(`id(service_id), service_name));
}
});
}
// BNC #461790: A better sorting
allowed_services = sort (term x, term y, allowed_services,
``(tolower(x[1]:"a") <= tolower(y[1]:"b"))
);
not_allowed_services = sort (term x, term y, not_allowed_services,
``(tolower(x[1]:"a") <= tolower(y[1]:"b"))
);
UI::ChangeWidget(`id("table_allowed_services"), `Items, allowed_services);
UI::ReplaceWidget(`id("allow_service_names_replacepoint"),
// TRANSLATORS: select box
`ComboBox(`id("allow_service_names"), _("&Service to Allow"), not_allowed_services)
);
// disable or enable buttons, selectboxes, table
RedrawAllowedServicesDialog(current_zone);
if (size (allowed_services) == 0) {
UI::ChangeWidget(`id("remove_allowed_service"), `Enabled, false);
}
}
void InitAllowedServices (string key) {
SetFirewallIcon();
if (SuSEFirewall::GetProtectFromInternalZone()) {
UI::ChangeWidget(`id("protect_from_internal"), `Value, true);
} else {
UI::ChangeWidget(`id("protect_from_internal"), `Value, false);
}
// The default zone
string init_zone = "EXT";
// All zones
list <string> all_currently_known_zones = SuSEFirewall::GetKnownFirewallZones();
// The default zone must exist in configuration
if (! contains(all_currently_known_zones, init_zone)) {
init_zone = all_currently_known_zones[0]:nil;
}
// Checking
if (init_zone == nil) {
y2error("There are no zones defined!");
return;
}
RedrawAllowedServices(init_zone);
UI::ChangeWidget(`id("allowed_services_zone"), `Value, init_zone);
}
symbol HandleAllowedServices (string key, map event) {
any ret = event["ID"]:nil;
string current_zone = (string) UI::QueryWidget(`id("allowed_services_zone"), `Value);
// changing zone
if (ret == "allowed_services_zone") {
RedrawAllowedServices (current_zone);
} else if (ret == "protect_from_internal") {
boolean protect_from_internal = (boolean) UI::QueryWidget(`id("protect_from_internal"), `Value);
SuSEFirewall::SetProtectFromInternalZone(protect_from_internal);
RedrawAllowedServices (current_zone);
} else if (ret == "add_allowed_service") {
string add_service = (string) UI::QueryWidget(`id("allow_service_names"), `Value);
SuSEFirewall::SetServicesForZones([add_service], [current_zone], true);
RedrawAllowedServices (current_zone);
} else if (ret == "remove_allowed_service") {
if (Confirm::DeleteSelected()) {
string remove_service = (string) UI::QueryWidget(`id("table_allowed_services"), `CurrentItem);
SuSEFirewall::SetServicesForZones([remove_service], [current_zone], false);
RedrawAllowedServices (current_zone);
}
} else if (ret == "advanced_allowed_service") {
// redraw when "OK" button pressed
if (HandlePopupAdditionalServices(current_zone)) {
RedrawAllowedServices (current_zone);
}
}
return nil;
}
/**
* Function sets UI for Masquerade Table (and buttons) enabled or disabled
*
* @param boolean enable
*/
void SetMasqueradeTableUsable (boolean usable) {
UI::ChangeWidget(`id("table_redirect_masq"), `Enabled, usable);
UI::ChangeWidget(`id("add_redirect_to_masquerade"), `Enabled, usable);
UI::ChangeWidget(`id("remove_redirect_to_masquerade"), `Enabled, usable);
}
/**
* Function returns if masquerading is possible.
* Masquerading needs at least two interfaces in two different firewall zones.
* One of them has to be External.
*
* @return boolean if possible.
*/
boolean IsMasqueradingPossible () {
// FIXME: for Expert configuration, there is possible to set the masqueraded zone
// it is EXT for Simple configuration as default
boolean possible = false;
// if (!IsThisExpertConfiguration()) {
// needs to have any external and any other interface
boolean has_external = false;
boolean has_other = false;
foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
// no interfaces in zone
if ( size( union(
SuSEFirewall::GetInterfacesInZone(zone),
SuSEFirewall::GetSpecialInterfacesInZone(zone)
)) == 0) return;
if (zone == "EXT") has_external = true;
else has_other = true;
});
possible = (has_external && has_other);
// } else {
// y2error("FIXME: missing functionality for expert configuration");
//}
return possible;
}
void InitMasquerading (string key) {
SetFirewallIcon();
boolean masquerade = SuSEFirewall::GetMasquerade();
boolean masquerade_possible = IsMasqueradingPossible();
// setting checkbox
UI::ChangeWidget(`id("masquerade_networks"), `Value, masquerade);
// enabling or disabling masquerade redirect table when masquerading is enabled
// and also possible
//if (!IsThisExpertConfiguration()) {
SetMasqueradeTableUsable(masquerade && masquerade_possible);
//}
// impossible masquerading, user gets information why
if (!masquerade_possible) {
// disabling checkbox
UI::ChangeWidget(`id("masquerade_networks"), `Enabled, false);
UI::ReplaceWidget(`id("replacepoint_masquerade_information"),
//(!IsThisExpertConfiguration() ?
// TRANSLATORS: informative label
`Left(`Label(_("Masquerading needs at least one external interface and one other interface.")))
//:
//`Left(`Label("FIXME: missing functionality for expert configuration"))
//)
);
}
return nil;
}
boolean CheckExistency(string ui_id) {
if (UI::QueryWidget(`id(ui_id), `Value) == "") {
UI::SetFocus(`id(ui_id));
// TRANSLATORS: popup message
Popup::Error(_("This entry must be completed."));
return false;
}
return true;
}
boolean CheckPort(string ui_id) {
string port = (string) UI::QueryWidget(`id(ui_id), `Value);
// no port can be allowed
if (port == "") return true;
// checking for port-name rightness
if (!PortAliases::IsAllowedPortName(port)) {
UI::SetFocus(`id(ui_id));
Popup::Error(
// TRANSLATORS: popup message, right port definition is two lines below this message
_("Wrong port definition.")
+ "\n\n" +
PortAliases::AllowedPortNameOrNumber()
);
return false;
}
// checking for known TCP and UDP port names
if (!CheckIfTheyAreAllKnownPorts(ui_id, [port])) return false;
return true;
}
/**
* Function checks port number got as parameter.
* If check fails SetFocus is called and an empty string is returned.
*/
string CheckPortNumber (string port_to_be_checked, string widget_id) {
string port_number = GetPortNumber(port_to_be_checked);
// if port name wasn't found
if (port_number=="") {
Popup::Error(
// TRANSLATORS: popup error message
_("Wrong port definition.
No port number found for this port name.
Use the port number instead of the port name.
")
);
// setfocus for GUI
if (widget_id!="" && widget_id!=nil) UI::SetFocus(`id(widget_id));
}
return port_number;
}
boolean CheckIP(string ui_id) {
string ip = (string) UI::QueryWidget(`id(ui_id), `Value);
if (!Address::Check4(ip)) {
UI::SetFocus(`id(ui_id));
Popup::Error(
// TRANSLATORS: popup message, right definition is two lines belos this message
_("Invalid IP definition.")
+ "\n\n" +
Address::Valid4()
);
return false;
}
return true;
}
string UserReadablePortName (string port, string protocol) {
if (port == "") return "";
if (port == nil) return nil;
protocol = tolower (protocol);
// Do not seek port number for RPC services
if (protocol == "rpc" || protocol == "_rpc_") return port;
// number
if (regexpmatch (port, "^[0123456789]+$")) {
string port_name = GetPortName (port);
// port name must be known and not the same as defined yet
if (port_name != nil && port_name != port) {
port = sformat("%1 (%2)", port_name, port);
}
// not a port range
} else if (! regexpmatch (port, "^[0123456789]+:[0123456789]+$")) {
string port_number = GetPortNumber (port);
if (port_number != nil && port_number != port) {
port = sformat("%1 (%2)", port, port_number);
}
}
return port;
}
void RedrawRedirectToMasqueradedIPTable() {
list <term> items = [];
integer row_id = 0;
foreach (map <string, string> rule, SuSEFirewall::GetListOfForwardsIntoMasquerade(), {
// redirect_to_port is the same as requested_port if not defined
if (rule["to_port"]:""=="") {
rule["to_port"] = rule["req_port"]:"";
}
// printing port names rather then port numbers
foreach (string key, [ "req_port", "to_port" ], {
rule[key] = UserReadablePortName (rule[key]:"", rule["protocol"]:"");
});
items = add (items,
`item(`id(row_id),
rule["source_net"]:"",
rule["protocol"]:"",
rule["req_ip"]:"",
rule["req_port"]:"",
UI::Glyph(`BulletArrowRight),
rule["forward_to"]:"",
rule["to_port"]:""
)
);
row_id = row_id + 1;
});
UI::ChangeWidget (`id("table_redirect_masq"), `Items, items);
}
void HandlePopupAddRedirectToMasqueradedIPRule () {
UI::OpenDialog(all_popup_definition, AddRedirectToMasqueradedIPRule());
UI::SetFocus (`id("add_source_network"));
boolean ret_value = false;
while (true) {
any ret = UI::UserInput();
if (ret == "cancel" || ret == `cancel) {
break;
} else if (ret == "ok") {
if (!CheckExistency("add_requested_port")) continue;
if (!CheckExistency("add_source_network")) continue;
if (!CheckExistency("add_redirectto_ip")) continue;
if (!CheckPort("add_requested_port")) continue;
if (!CheckPort("add_redirectto_port")) continue;
if (!CheckIP("add_redirectto_ip")) continue;
// FIXME: checking for spaces in sttrings
// removing space from start or end of the string
string add_source_network = (string) UI::QueryWidget(`id("add_source_network"), `Value);
string add_requested_ip = (string) UI::QueryWidget(`id("add_requested_ip"), `Value);
string add_protocol = (string) UI::QueryWidget(`id("add_protocol"), `Value);
string add_requested_port = (string) UI::QueryWidget(`id("add_requested_port"), `Value);
string add_redirectto_ip = (string) UI::QueryWidget(`id("add_redirectto_ip"), `Value);
string add_redirectto_port = (string) UI::QueryWidget(`id("add_redirectto_port"), `Value);
// Ports must be port numbers, getting port numbers from port names
if (add_requested_port!="" && add_requested_port!=nil) {
add_requested_port = CheckPortNumber (add_requested_port, "add_requested_port");
if (add_requested_port==nil) continue;
}
if (add_redirectto_port!="" && add_redirectto_port!=nil) {
add_redirectto_port = CheckPortNumber (add_redirectto_port, "add_redirectto_port");
if (add_redirectto_port==nil) continue;
}
SuSEFirewall::AddForwardIntoMasqueradeRule (add_source_network, add_redirectto_ip, add_protocol,
add_requested_port, add_redirectto_port, add_requested_ip);
ret_value = true;
break;
}
}
UI::CloseDialog();
if (ret_value) RedrawRedirectToMasqueradedIPTable();
}
symbol HandleMasquerading (string key, map event) {
any ret = event["ID"]:nil;
if (ret == "masquerade_networks") {
boolean masquerade = (boolean) UI::QueryWidget(`id("masquerade_networks"), `Value);
SuSEFirewall::SetMasquerade(masquerade);
// enabling or disabling masquerade redirect table when masquerade enabled
//if (!IsThisExpertConfiguration()) {
SetMasqueradeTableUsable(masquerade);
//}
}
return nil;
}
symbol HandleRedirectToMasqueradedIP (string key, map event) {
any ret = event["ID"]:nil;
if (ret == "add_redirect_to_masquerade") {
HandlePopupAddRedirectToMasqueradedIPRule();
} else if (ret == "remove_redirect_to_masquerade") {
integer current_item = (integer) UI::QueryWidget(`id("table_redirect_masq"), `CurrentItem);
if (Confirm::DeleteSelected()) {
SuSEFirewall::RemoveForwardIntoMasqueradeRule(current_item);
RedrawRedirectToMasqueradedIPTable();
}
}
}
void InitRedirectToMasqueradedIP (string key) {
SetFirewallIcon();
RedrawRedirectToMasqueradedIPTable();
}
void HandlePopupIPsecTrustAsZone () {
UI::OpenDialog(all_popup_definition, IPsecTrustAsZone());
string default_value = SuSEFirewall::GetTrustIPsecAs();
UI::ChangeWidget(`id("trust_ipsec_as"), `Value, default_value);
any ret = UI::UserInput();
if (ret == "ok") {
string new_value = (string) UI::QueryWidget(`id("trust_ipsec_as"), `Value);
SuSEFirewall::SetTrustIPsecAs(new_value);
}
UI::CloseDialog();
}
// IPsec support opens IPsec traffic from external zone
void InitIPsecSupport (string key) {
SetFirewallIcon();
// FIXME: check whether such service exists
boolean supported = SuSEFirewall::IsServiceSupportedInZone("service:ipsec", "EXT");
if (supported == nil) {
y2error ("No such service 'service:ipsec'");
UI::ChangeWidget(`id("ispsec_support"), `Enabled, false);
} else {
UI::ChangeWidget(`id("ispsec_support"), `Enabled, true);
UI::ChangeWidget(`id("ispsec_support"), `Value, supported);
}
}
symbol HandleIPsecSupport (string key, map event) {
any ret = event["ID"]:nil;
if (ret == "ipsec_details") {
HandlePopupIPsecTrustAsZone();
}
return nil;
}
void StoreIPsecSupport (string key, map event) {
boolean to_support = (boolean) UI::QueryWidget(`id("ispsec_support"), `Value);
SuSEFirewall::SetServicesForZones(["ipsec"], ["EXT"], to_support);
}
void InitLoggingLevel (string key) {
SetFirewallIcon();
UI::ChangeWidget(`id("logging_ACCEPT"), `Value, SuSEFirewall::GetLoggingSettings("ACCEPT"));
UI::ChangeWidget(`id("logging_DROP"), `Value, SuSEFirewall::GetLoggingSettings("DROP"));
}
void StoreLoggingLevel (string key, map event) {
SuSEFirewall::SetLoggingSettings("ACCEPT",
(string) UI::QueryWidget(`id("logging_ACCEPT"), `Value));
SuSEFirewall::SetLoggingSettings("DROP",
(string) UI::QueryWidget(`id("logging_DROP"), `Value));
}
void InitBroadcastConfigurationSimple (string key) {
SetFirewallIcon();
term replace_dialog = `VBox();
map <string, list <string> > allowed_bcast_ports = SuSEFirewall::GetBroadcastAllowedPorts ();
foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
string zone_name = SuSEFirewall::GetZoneFullName(zone);
string ports_for_zone = mergestring(allowed_bcast_ports[zone]:[], " ");
boolean log_packets = (SuSEFirewall::GetIgnoreLoggingBroadcast(zone) == "no");
replace_dialog = add(replace_dialog,
`HBox(
`HWeight( 40,
`InputField (`id("bcast_ports_" + zone), `opt (`hstretch), zone_name, ports_for_zone)
),
`HWeight( 60,
`VBox (
`Label(""),
// TRANSLATORS: check box
`CheckBox(`id("bcast_log_" + zone), _("&Log Not Accepted Broadcast Packets"), log_packets)
)
)
)
);
});
UI::ReplaceWidget(`id("replace_point_bcast"), replace_dialog);
}
// FIXME: should check for PortAliases::IsKnownPortName() in future
void StoreBroadcastConfigurationSimple (string key, map event) {
map <string, list <string> > allowed_bcast_ports = $[];
foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
list <string> allowed_ports = splitstring((string) UI::QueryWidget(`id("bcast_ports_" + zone), `Value), " ");
boolean log_packets = (boolean) UI::QueryWidget(`id("bcast_log_" + zone), `Value);
allowed_bcast_ports[zone] = allowed_ports;
SuSEFirewall::SetIgnoreLoggingBroadcast(zone, (log_packets ? "no":"yes"));
});
SuSEFirewall::SetBroadcastAllowedPorts(allowed_bcast_ports);
}
boolean firewall_enabled_st = nil;
boolean firewall_started_st = nil;
void InitServiceStartVsStartedStopped (string key) {
firewall_enabled_st = SuSEFirewall::GetEnableService();
firewall_started_st = SuSEFirewall::IsStarted();
}
void SetEnableFirewall (boolean new_state) {
if (firewall_enabled_st == new_state) {
y2milestone ("Enable firewall status preserved (enable=%1)", firewall_enabled_st);
return;
}
boolean curr_running = SuSEFirewall::IsStarted();
boolean new_running = new_state;
// disabling firewall
if (new_state == false && curr_running == true) {
// TRANSLATORS: popup question
if (Popup::YesNo (_("Firewall automatic starting has been disabled
but firewall is currently running.
Stop the firewall after the new configuration is written?"))) {
y2milestone ("User decided to stop the firewall after it is disabled");
new_running = false;
} else {
y2milestone ("User decided not to stop the firewall after it is disabled");
new_running = true;
}
}
// Changes the default values - Enable and Start at once
SuSEFirewall::SetEnableService (new_state);
SuSEFirewall::SetStartService (new_running);
y2milestone("New Settings - Firewall Enabled: %1, Firewall Started: %2 (after Write())",
SuSEFirewall::GetEnableService(), SuSEFirewall::GetStartService()
);
}
string customrules_current_zone = nil;
void RedrawCustomRules (string current_zone) {
if (current_zone == nil || ! contains (SuSEFirewall::GetKnownFirewallZones(), current_zone)) {
y2error("Unknown zone '%1'", current_zone);
return nil;
}
list <map <string, string> > rules = SuSEFirewallExpertRules::GetListOfAcceptRules (current_zone);
// some rules are already defined
if (size(rules) > 0) {
integer counter = -1;
list <term> items = maplist (map <string, string> one_rule, rules, {
counter = counter + 1;
return `item (
`id (counter),
one_rule["network"]:"",
SuSEFirewall::GetProtocolTranslatedName (one_rule["protocol"]:""),
UserReadablePortName (one_rule["dport"]:"", one_rule["protocol"]:""),
UserReadablePortName (one_rule["sport"]:"", "")
);
});
items = sort (term aa, term bb, items, ``(aa[1]:"" < bb[1]:""));
UI::ChangeWidget (`id ("custom_rules_table"), `Items, items);
UI::ChangeWidget (`id ("remove_custom_rule"), `Enabled, true);
// no rules defined
} else {
UI::ChangeWidget (`id ("custom_rules_table"), `Items, []);
UI::ChangeWidget (`id ("remove_custom_rule"), `Enabled, false);
}
}
void InitCustomRules (string key) {
SetFirewallIcon();
// set the default once, EXT is the first one
if (customrules_current_zone == nil) {
foreach (string one_zone, (list <string>) union (SuSEFirewall::GetKnownFirewallZones(), ["EXT"]), {
// at least one interface in the zone
if (size (SuSEFirewall::GetInterfacesInZoneSupportingAnyFeature(one_zone)) > 0)
customrules_current_zone = one_zone;
});
// nothing found, set the default manually
if (customrules_current_zone == nil)
customrules_current_zone = "EXT";
}
UI::ChangeWidget (`id ("custom_rules_firewall_zone"), `Value, customrules_current_zone);
RedrawCustomRules (customrules_current_zone);
}
void DeleteSelectedCustomRule (string selected_zone, integer current_item) {
if (SuSEFirewallExpertRules::DeleteRuleID (selected_zone, current_item)) {
RedrawCustomRules (selected_zone);
UI::ChangeWidget (`id("custom_rules_table"), `SelectedItem, 0);
}
}
boolean CheckPortNameOrNumber (string port) {
// port number
if (regexpmatch(port, "^[0123456789]+$")) {
return CheckPortNumberDefinition (tointeger (port), port);
// not a port range
} else if (! regexpmatch(port, "^[0123456789]+:[0123456789]+$")) {
return CheckPortNameDefinition (port);
}
}
boolean HandlePopupAddCustomRule (string selected_zone) {
UI::OpenDialog (all_popup_definition,
`HBox (
`MinWidth (
30,
`RichText (HelpForDialog ("custom-rules-popup"))
),
AddCustomFirewallRule()
)
);
UI::SetFocus (`id("add_source_network"));
boolean ret_value = false;
while (true) {
any ret = UI::UserInput();
if (ret == "cancel" || ret == `cancel) {
break;
} else if (ret == "ok") {
if (!CheckExistency("add_source_network")) continue;
if (!CheckExistency("add_protocol")) continue;
string add_source_network = (string) UI::QueryWidget(`id("add_source_network"), `Value);
string add_protocol = (string) UI::QueryWidget(`id("add_protocol"), `Value);
string add_destination_port = (string) UI::QueryWidget(`id("add_destination_port"), `Value);
string add_source_port = (string) UI::QueryWidget(`id("add_source_port"), `Value);
// network is mandatory
if (add_source_network == "" || ! CheckNetwork (add_source_network)) {
UI::SetFocus (`id ("add_source_network"));
Report::Error (sformat (_("Invalid network definition '%1'"), add_source_network) + "\n" + SuSEFirewallExpertRules::ValidNetwork());
continue;
}
// destination port is optional
if (add_destination_port != "") {
if (PortRanges::IsPortRange (add_destination_port)) {
if (! PortRanges::IsValidPortRange (add_destination_port)) {
UI::SetFocus (`id ("add_destination_port"));
Report::Error (sformat (_("Invalid port range '%1'"), add_destination_port));
continue;
}
} else if (! CheckPortNameOrNumber (add_destination_port)) {
UI::SetFocus (`id ("add_destination_port"));
Report::Error (sformat (_("Invalid port name or number '%1'"), add_destination_port) + "\n" + PortAliases::AllowedPortNameOrNumber());
continue;
}
}
// source port is optional
if (add_source_port != "") {
if (PortRanges::IsPortRange (add_source_port)) {
if (! PortRanges::IsValidPortRange (add_source_port)) {
UI::SetFocus (`id ("add_source_port"));
Report::Error (sformat (_("Invalid port range '%1'"), add_source_port));
continue;
}
} else if (! CheckPortNameOrNumber (add_source_port)) {
UI::SetFocus (`id ("add_source_port"));
Report::Error (sformat (_("Invalid port name or number '%1'"), add_source_port) + "\n" + PortAliases::AllowedPortNameOrNumber());
continue;
}
}
SuSEFirewallExpertRules::AddNewAcceptRule (
selected_zone,
$[
"network" : add_source_network,
"protocol" : add_protocol,
"dport" : add_destination_port,
"sport" : add_source_port
]
);
ret_value = true;
break;
}
}
UI::CloseDialog();
return ret_value;
}
symbol HandleCustomRules (string key, map event) {
any ret = event["ID"]:nil;
string selected_zone = (string) UI::QueryWidget (`id ("custom_rules_firewall_zone"), `Value);
if (ret == "custom_rules_firewall_zone") {
customrules_current_zone = selected_zone;
RedrawCustomRules (selected_zone);
} else if (ret == "add_custom_rule") {
if (HandlePopupAddCustomRule (selected_zone)) {
RedrawCustomRules (selected_zone);
}
} else if (ret == "remove_custom_rule") {
integer current_item = (integer) UI::QueryWidget(`id("custom_rules_table"), `CurrentItem);
if (current_item != nil && Confirm::DeleteSelected()) {
DeleteSelectedCustomRule (selected_zone, current_item);
}
}
return nil;
}
string GetBcastServiceName (string protocol, string sport) {
if (protocol == "udp" && sport == "") {
return _("All services using UDP");
} else if (protocol == "tcp" && sport == "") {
return _("All services using TCP");
} else if (protocol == "udp" && PortAliases::GetPortNumber (sport) == 137) {
return _("Samba browsing");
} else if (protocol == "udp" && PortAliases::GetPortNumber (sport) == 427) {
return _("SLP browsing");
} else {
return sformat ("%1/%2", SuSEFirewall::GetProtocolTranslatedName (protocol), sport);
}
}
string GetBcastNetworkName (string network) {
if (network == "0/0") {
return _("All networks");
} else {
return sformat (_("Subnet: %1"), network);
}
}
void RedrawBroadcastReplyTable () {
list <term> items = [];
foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
list <string> ruleset = SuSEFirewall::GetServicesAcceptRelated (zone);
integer rule_in_ruleset = -1;
foreach (string one_rule, ruleset, {
rule_in_ruleset = rule_in_ruleset + 1;
list <string> rulelist = splitstring (one_rule, ",");
items = add (items, `item (
`id (sformat ("%1 %2", zone, rule_in_ruleset)),
SuSEFirewall::GetZoneFullName (zone),
sformat (GetBcastServiceName (rulelist[1]:"", rulelist[2]:"")),
GetBcastNetworkName (rulelist[0]:"0/0")
));
});
});
if (UI::WidgetExists (`id ("table_broadcastreply")))
UI::ChangeWidget (`id ("table_broadcastreply"), `Items, items);
if (UI::WidgetExists (`id (`delete_br)))
UI::ChangeWidget (`id (`delete_br), `Enabled, (size (items) != 0));
}
void InitBroadcastReply (string key) {
RedrawBroadcastReplyTable();
}
map <string, string> service_to_protocol = $[
"samba" : "udp",
"slp" : "udp",
"all-udp" : "udp",
"all-ycp" : "udp",
];
map <string, string> service_to_port = $[
"samba" : "137",
"slp" : "427",
"all-udp" : "",
"all-tcp" : "",
];
string GetBcastServiceProtocol (string service) {
return service_to_protocol[service]:"";
}
string GetBcastServicePort (string service) {
return service_to_port[service]:"";
}
boolean ValidateBroadcastReplyRule (string zone, string network, string service, string protocol, string port) {
if (service != "user-defined") {
return true;
}
if (! SuSEFirewallExpertRules::IsValidNetwork (network)) {
UI::SetFocus (`id (`network));
Report::Error (sformat (_("Invalid network definition '%1'"), network) + "\n" + SuSEFirewallExpertRules::ValidNetwork());
return false;
}
if (! PortAliases::IsAllowedPortName (port)) {
UI::SetFocus (`id (`port));
Report::Error (sformat (_("Invalid port name or number '%1'"), port) + "\n" + PortAliases::AllowedPortNameOrNumber());
return false;
}
return true;
}
boolean AddAcceptBroadcastReplyRule () {
list <term> zones = [];
foreach (string zone_shortname, SuSEFirewall::GetKnownFirewallZones(), {
zones = add (zones, `item(
`id(zone_shortname), SuSEFirewall::GetZoneFullName(zone_shortname),
// hard-coded default
(zone_shortname == "EXT")
));
});
UI::OpenDialog (
`VBox (
`Left (`ComboBox (`id (`zone), _("&Zone"), zones)),
`Left (`MinWidth (18, `ComboBox (`id (`network), `opt (`editable), _("&Network"), ["0/0"]))),
`Left (`ComboBox (`id (`service), `opt (`notify), _("&Service"), [
`item (`id ("samba"), GetBcastServiceName ("udp", "137")),
`item (`id ("slp"), GetBcastServiceName ("udp", "427")),
`item (`id ("all-udp"), GetBcastServiceName ("udp", "")),
`item (`id ("all-tcp"), GetBcastServiceName ("tcp", "")),
`item (`id ("user-defined"), _("User-defined service"))
])),
`HSquash (`HBox (
`HWeight (1, `ComboBox (`id (`protocol), `opt (`disabled), _("&Protocol"), [
`item (`id ("udp"), SuSEFirewall::GetProtocolTranslatedName ("udp"), true),
`item (`id ("tcp"), SuSEFirewall::GetProtocolTranslatedName ("tcp"))
])),
`HWeight (1, `InputField (`id (`port), `opt (`disabled), _("Po&rt"), ""))
)),
`VSpacing (1),
`ButtonBox (
`PushButton (`id (`ok), `opt (`okButton, `default, `key_F10), Label::AddButton()),
`PushButton (`id (`cancel), `opt (`cancelButton, `key_F9), Label::CancelButton())
)
)
);
boolean dialog_ret = false;
while (true) {
any ret = UI::UserInput();
if (ret == `service) {
boolean custom_service = (UI::QueryWidget (`id (`service), `Value) == "user-defined");
UI::ChangeWidget (`id (`protocol), `Enabled, custom_service);
UI::ChangeWidget (`id (`port), `Enabled, custom_service);
} else if (ret == `ok) {
// read the current settings
string zone = (string) UI::QueryWidget (`id (`zone), `Value);
string network = (string) UI::QueryWidget (`id (`network), `Value);
string service = (string) UI::QueryWidget (`id (`service), `Value);
// use either pre-defined or user-defined
string protocol = (service == "user-defined" ?
(string) UI::QueryWidget (`id (`protocol), `Value)
:
GetBcastServiceProtocol (service)
);
// use either pre-defined or user-defined
string port = (service == "user-defined" ?
(string) UI::QueryWidget (`id (`port), `Value)
:
GetBcastServicePort (service)
);
if (! ValidateBroadcastReplyRule (zone, network, service, protocol, port))
continue;
// Add the rule if validation went fine
list <string> items = SuSEFirewall::GetServicesAcceptRelated (zone);
string new_rule = sformat ("%1,%2", network, protocol);
if (port != "") new_rule = sformat ("%1,%2", new_rule, port);
items = add (items, new_rule);
SuSEFirewall::SetServicesAcceptRelated (zone, items);
// redraw table
dialog_ret = true;
break;
} else {
break;
}
}
UI::CloseDialog();
return dialog_ret;
}
symbol HandleBroadcastReply (string key, map event) {
any ret = event["ID"]:nil;
if (ret == `add_br) {
if (AddAcceptBroadcastReplyRule())
RedrawBroadcastReplyTable();
} else if (ret == `delete_br) {
string current_id = (string) UI::QueryWidget (`id ("table_broadcastreply"), `Value);
if (current_id != nil && current_id != "") {
if (Confirm::DeleteSelected()) {
list item_to_delete = splitstring (current_id, " ");
list <string> items = SuSEFirewall::GetServicesAcceptRelated (item_to_delete[0]:"");
integer item_in_list = tointeger (item_to_delete[1]:"-1");
items[item_in_list] = nil;
items = filter (string one_rule, items, { return one_rule != nil; });
SuSEFirewall::SetServicesAcceptRelated (item_to_delete[0]:"", items);
RedrawBroadcastReplyTable();
}
} else {
Report::Error (_("Select an item to delete."));
}
}
return nil;
}
}
ACC SHELL 2018