ACC SHELL
/**
* Copyright 2004, Novell, Inc. All rights reserved.
*
* File: modules/SuSEFirewall.ycp
* Package: SuSEFirewall configuration
* Summary: Interface manipulation of /etc/sysconfig/SuSEFirewall
* Authors: Lukas Ocilka <locilka@suse.cz>
*
* $Id: SuSEFirewall.ycp 60742 2010-02-08 15:18:49Z locilka $
*
* Module for handling SuSEfirewall2.
*/
{
module "SuSEFirewall";
textdomain "base";
import "Mode";
import "Service";
import "NetworkInterfaces";
import "SuSEFirewallServices";
import "PortAliases";
import "Report";
import "Message";
import "Progress";
import "PortRanges";
import "PackageSystem";
import "FileUtils";
import "Directory";
import "Stage";
// <!-- SuSEFirewall VARIABLES //-->
string susefirewall_package = "SuSEfirewall2";
/**
* configuration hasn't been read for the default
* this should reduce the readings to only ONE
*/
boolean configuration_has_been_read = false;
/**
* String which includes all interfaces not-defined in any zone
*/
global string special_all_interface_string = "any";
/**
* Maximal number of port number, they are in the interval 1-65535 included
*/
global integer max_port_number = PortRanges::max_port_number;
/**
* Zone which works with the special_all_interface_string string
*/
global string special_all_interface_zone = "EXT";
/* firewall settings map */
map<string, any> SETTINGS = $[];
/* configuration was modified when true */
boolean modified = false;
/* defines if SuSEFirewall is running */
boolean is_running = false;
/* default settings for SuSEFirewall */
map<string, string> DEFAULT_SETTINGS = $[
"FW_LOG_ACCEPT_ALL" : "no",
"FW_LOG_ACCEPT_CRIT" : "yes",
"FW_LOG_DROP_ALL" : "no",
"FW_LOG_DROP_CRIT" : "yes",
"FW_PROTECT_FROM_INT" : "no",
"FW_ROUTE" : "no",
"FW_MASQUERADE" : "no",
"FW_ALLOW_FW_TRACEROUTE" : "yes",
"FW_ALLOW_PING_FW" : "yes",
"FW_ALLOW_FW_BROADCAST_EXT" : "no",
"FW_ALLOW_FW_BROADCAST_INT" : "no",
"FW_ALLOW_FW_BROADCAST_DMZ" : "no",
"FW_IGNORE_FW_BROADCAST_EXT" : "yes",
"FW_IGNORE_FW_BROADCAST_INT" : "no",
"FW_IGNORE_FW_BROADCAST_DMZ" : "no",
"FW_IPSEC_TRUST" : "no",
];
/* verbose_level -> if verbosity is more than 0, be verbose, starting in verbose mode */
integer verbose_level = 1;
/* list of known firewall zones */
list <string> known_firewall_zones = [ "INT", "DMZ", "EXT" ];
/* map defines zone name for all known firewall zones */
map <string, string> zone_names = $[
// TRANSLATORS: Firewall zone name - used in combo box or dialog title
"EXT" : _("External Zone"),
// TRANSLATORS: Firewall zone name - used in combo box or dialog title
"INT" : _("Internal Zone"),
// TRANSLATORS: Firewall zone name - used in combo box or dialog title
"DMZ" : _("Demilitarized Zone"),
];
/* internal zone identification - useful for protect-from-internal */
string int_zone_shortname = "INT";
/* list of protocols supported in firewall, use only upper-cases */
list <string> supported_protocols = [ "TCP", "UDP", "RPC", "IP" ];
/* list of keys in map of definition well-known services */
list <string> service_defined_by = ["tcp_ports", "udp_ports", "rpc_ports", "ip_protocols", "broadcast_ports"];
/* list of services currently allowed, which share ports (for instance RPC services) */
map <string, list <string> > allowed_conflict_services = $[];
/* services needed for well-running firewall */
list <string> firewall_services = [ "SuSEfirewall2_init", "SuSEfirewall2_setup" ];
list <string> firewall_services_reverse = [ "SuSEfirewall2_setup", "SuSEfirewall2_init" ];
list <string> SuSEFirewall_variables = [
// zones and interfaces
"FW_DEV_INT", "FW_DEV_DMZ", "FW_DEV_EXT",
// services in zones
"FW_SERVICES_INT_TCP", "FW_SERVICES_INT_UDP", "FW_SERVICES_INT_RPC", "FW_SERVICES_INT_IP",
"FW_SERVICES_DMZ_TCP", "FW_SERVICES_DMZ_UDP", "FW_SERVICES_DMZ_RPC", "FW_SERVICES_DMZ_IP",
"FW_SERVICES_EXT_TCP", "FW_SERVICES_EXT_UDP", "FW_SERVICES_EXT_RPC", "FW_SERVICES_EXT_IP",
"FW_PROTECT_FROM_INT",
// global routing, masquerading
"FW_ROUTE", "FW_MASQUERADE", "FW_FORWARD_MASQ", "FW_FORWARD_ALWAYS_INOUT_DEV",
// broadcast packets
"FW_ALLOW_FW_BROADCAST_EXT", "FW_ALLOW_FW_BROADCAST_INT", "FW_ALLOW_FW_BROADCAST_DMZ",
"FW_IGNORE_FW_BROADCAST_EXT", "FW_IGNORE_FW_BROADCAST_INT", "FW_IGNORE_FW_BROADCAST_DMZ",
// FATE #300970: Support for 'Samba & friends' browsing
"FW_SERVICES_ACCEPT_RELATED_EXT", "FW_SERVICES_ACCEPT_RELATED_INT", "FW_SERVICES_ACCEPT_RELATED_DMZ",
// logging
"FW_LOG_DROP_CRIT", "FW_LOG_DROP_ALL", "FW_LOG_ACCEPT_CRIT", "FW_LOG_ACCEPT_ALL",
// IPsec support
"FW_IPSEC_TRUST",
// Custom rulezz
// net,protocol[,dport][,sport]
"FW_SERVICES_ACCEPT_EXT", "FW_SERVICES_ACCEPT_INT", "FW_SERVICES_ACCEPT_DMZ",
// Custom kernel modules, e.g., for FTP
"FW_LOAD_MODULES",
// Services defined in /usr/share/SuSEfirewall2/services/ directory
// FATE #300687: Ports for SuSEfirewall added via packages
"FW_CONFIGURATIONS_EXT", "FW_CONFIGURATIONS_INT", "FW_CONFIGURATIONS_DMZ",
];
list <string> one_line_per_record = ["FW_FORWARD_MASQ", "FW_SERVICES_ACCEPT_EXT", "FW_SERVICES_ACCEPT_INT", "FW_SERVICES_ACCEPT_DMZ"];
// FATE #300970: Firewall support for SMB browsing
string broadcast_related_module = "nf_conntrack_netbios_ns";
// <!-- SuSEFirewall VARIABLES //-->
// <!-- SuSEFirewall GLOBAL FUNCTIONS USED BY LOCAL ONES //-->
/**
* Returns whether records in variable should be written one record on one line.
* @return boolean if wolpr
*/
boolean WriteOneRecordPerLine (string key_name) {
if (key_name == nil && key_name == "")
return true;
return (contains (one_line_per_record, key_name));
}
/**
* Function sets internal variable, which indicates, that any
* "firewall settings were modified", to "true".
*/
global define void SetModified () {
modified = true;
}
/**
* Do not use this function.
* Only for firewall installation proposal.
*/
global define void ResetModified () {
y2milestone("Reseting firewall-modified to 'false'");
modified = false;
}
/**
* Function returns list of known firewall zones (shortnames)
*
* @return list <string> of firewall zones
*
* @example GetKnownFirewallZones() -> ["DMZ", "EXT", "INT"]
*/
global define list <string> GetKnownFirewallZones () {
return known_firewall_zones;
}
global define boolean IsServiceSupportedInZone (string service, string zone);
global define list <string> GetSpecialInterfacesInZone (string zone);
global define void AddSpecialInterfaceIntoZone (string interface, string zone);
/**
* Variable for ReportOnlyOnce() function
*/
list <string> report_only_once = [];
/**
* Report the error, warning, message only once.
* Stores the error, warning, message in memory.
* This is just a helper function that could avoid from filling y2log up with
* a lot of the very same messages - 'foreach()' is a very powerful builtin.
*
* @param string error, warning or message
* @return boolean whether the message should be reported or not
*
* @example
* string error = sformat("Port number %1 is invalid.", port_nr);
* if (ReportOnlyOnce(error)) y2error(error);
*/
boolean ReportOnlyOnce (string what_to_report) {
if (contains(report_only_once, what_to_report)) {
return false;
} else {
report_only_once = add (report_only_once, what_to_report);
return true;
}
}
// <!-- SuSEFirewall GLOBAL FUNCTIONS USED BY LOCAL ONES //-->
// <!-- SuSEFirewall LOCAL FUNCTIONS //-->
/**
* Function returns whether the feature 'any' network interface is supported in the
* firewall configuration. The string 'any' must be in the 'EXT' zone.
*
* @return boolean is_supported whether the feature is supported or not
*/
global boolean IsAnyNetworkInterfaceSupported () {
return contains(GetSpecialInterfacesInZone(special_all_interface_zone), special_all_interface_string);
}
/**
* Function return list of variables needed for SuSEFirewall's settings.
*
* @return list <string> of names of variables
*/
list <string> GetListOfSuSEFirewallVariables () {
return SuSEFirewall_variables;
}
/**
* Local function for increasing the verbosity level.
*/
void IncreaseVerbosity () {
verbose_level = verbose_level + 1;
}
/**
* Local function for decreasing the verbosity level.
*/
void DecreaseVerbosity () {
verbose_level = verbose_level - 1;
}
/**
* Local function returns if other functions should produce verbose output.
* like popups, reporting errors, etc.
*
* @return boolean is_verbose
*/
boolean IsVerbose () {
// verbose level must be above zero to be verbose
return (verbose_level > 0);
}
/**
* Local function for returning default values (if defined) for sysconfig variables.
*
* @param string sysconfig variable
* @return string default value
*/
string GetDefaultValue (string variable) {
return (string) DEFAULT_SETTINGS[variable]:"";
}
/**
* Local function for reading list of sysconfig variables into internal variables.
*
* @param list <string> of sysconfig variables
*/
void ReadSysconfigSuSEFirewall (list<string> variables) {
foreach (string variable, variables, {
string value = (string) SCR::Read(add(.sysconfig.SuSEfirewall2,variable));
// if variable is undefined, get default value
if (value == nil || value == "")
value = GetDefaultValue(variable);
// BNC #426000
// backslash at the end
if (regexpmatch (value, "[ \t]*\\\\[ \t]*\n")) {
list <string> rules = splitstring (value, "\\ \t\n");
rules = filter (string one_rule, rules, {
return (one_rule != nil && one_rule != "");
});
value = mergestring (rules, " ");
}
// BNC #194419
// replace all "\n" with " " in variables
if (regexpmatch(value, "\n"))
value = mergestring(splitstring(value, "\n"), " ");
// replace all "\t" with " " in variables
if (regexpmatch(value, "\t"))
value = mergestring(splitstring(value, "\t"), " ");
SETTINGS[variable] = value;
});
}
/**
* Local function for reseting list of sysconfig variables in internal variables.
*
* @param list <string> of sysconfig variables
*/
void ResetSysconfigSuSEFirewall (list<string> variables) {
foreach (string variable, variables, {
// reseting means getting default variables
SETTINGS[variable] = GetDefaultValue(variable);
});
}
/**
* Local function for writing the list of internal variables into sysconfig.
* List of variables is list of keys in SETTINGS map, to sync configuration
* into the disk, use `nil` as the last list item.
*
* @param list <string> of sysconfig variables
* @return boolean if successful
*/
boolean WriteSysconfigSuSEFirewall (list<string> variables) {
boolean write_status = true;
string value = "";
foreach (string variable, variables, {
// if variable is undefined, get default value
value = SETTINGS[variable]:GetDefaultValue(variable);
if (WriteOneRecordPerLine (variable) == true) {
value = mergestring (splitstring (value, " "), "\n");
}
write_status = (boolean) SCR::Write(
add(.sysconfig.SuSEfirewall2,variable),
value
);
if (! write_status) {
Report::Error(Message::CannotWriteSettingsTo("/etc/sysconfig/SuSEFirewall"));
break;
}
});
write_status = SCR::Write(.sysconfig.SuSEfirewall2, nil);
if (! write_status) {
Report::Error(Message::CannotWriteSettingsTo("/etc/sysconfig/SuSEFirewall"));
}
return write_status;
}
/**
* Local function returns if protocol is supported by firewall.
* Protocol name must be in upper-cases.
*
* @param string protocol
* @return boolean if protocol is supported
*/
boolean IsSupportedProtocol (string protocol) {
return contains(supported_protocols, protocol);
}
/**
* Local function returns if zone (shortname like "EXT") is supported by firewall.
* Undefined zones are, for sure, unsupported.
*
* @param string zone shortname
* @return boolean if zone is known and supported.
*/
boolean IsKnownZone (string zone) {
boolean is_zone = false;
foreach (string known_zone, GetKnownFirewallZones(), {
if (known_zone == zone) {
is_zone = true;
break;
}
});
return is_zone;
}
/**
* Local function returns configuration string used in configuration for zone.
* For instance "ext" for "EXT" zone.
*
* @param string zone shortname
* @return string zone configuration string
*/
string GetZoneConfigurationString (string zone) {
if (IsKnownZone(zone)) {
// zones in SuSEFirewall configuration are identified by lowercased zone shorters
return tolower(zone);
}
return nil;
}
/**
* Local function returns zone name (shortname) for configuration string.
* For instance "EXT" for "ext" zone.
*
* @param string zone configuration string
* @return string zone shortname
*/
string GetConfigurationStringZone (string zone_string) {
if (IsKnownZone(toupper(zone_string))) {
// zones in SuSEFirewall configuration are identified by lowercased zone shorters
return toupper(zone_string);
}
return nil;
}
/**
* Function returns list of allowed services for zone and protocol
*
* @param string zone
* @param string protocol
* @return list <string> of allowed services/ports
*/
list <string> GetAllowedServicesForZoneProto (string zone, string protocol) {
return splitstring(SETTINGS["FW_SERVICES_" + zone + "_" + protocol]:"", " ");
}
/**
* Function sets list of services as allowed ports for zone and protocol
*
* @param list <string> of allowed ports/services
* @param string zone
* @param string protocol
*/
void SetAllowedServicesForZoneProto (list <string> allowed_services, string zone, string protocol) {
SetModified();
SETTINGS["FW_SERVICES_" + zone + "_" + protocol] = mergestring (toset(allowed_services), " ");
}
/**
* Local function returns configuration string for broadcast packets.
*
* @return string with broadcast configuration
*/
string GetBroadcastConfiguration (string zone) {
return SETTINGS["FW_ALLOW_FW_BROADCAST_" + zone]:"no";
}
/**
* Local function saves configuration string for broadcast packets.
*
* @param string with broadcast configuration
*/
void SetBroadcastConfiguration (string zone, string broadcast_configuration) {
SetModified();
SETTINGS["FW_ALLOW_FW_BROADCAST_" + zone] = broadcast_configuration;
}
/**
* Local function return map of allowed ports (without aliases).
* If any list for zone is defined but empty, all allowed
* UDP ports for this zone also accept broadcast packets.
* This function returns only ports that are mentioned in configuration,
* it doesn't return ports that are listed in some service (defined by package)
* which is enabled.
*
* @return map <string, list <string> > strings are allowed ports or port ranges
*
* @struct $[
* "ZONE1" : [ "port1", "port2" ],
* "ZONE2" : [ "port3", "port4" ],
* "ZONE3" : [ ]
* ]
*/
global define map <string, list <string> > GetBroadcastAllowedPorts () {
map <string, list <string> > allowed_ports = $[];
foreach (string zone, GetKnownFirewallZones(), {
string broadcast = GetBroadcastConfiguration(zone);
// no broadcast allowed for this zone
if (broadcast == "no") {
allowed_ports[zone] = [];
// all UDP port allowed in zone also allow broadcast
} else if (broadcast == "yes") {
allowed_ports[zone] = GetAllowedServicesForZoneProto (zone, "UDP");
// only listed ports allows broadcast
} else {
allowed_ports[zone] = splitstring(broadcast, " ");
allowed_ports[zone] = filter (string not_space, splitstring(broadcast, " "), {
return not_space != "";
});
}
});
y2debug("Allowed Broadcast Ports: %1", allowed_ports);
return allowed_ports;
}
/**
* Function creates allowed-broadcast-ports string from broadcast map and saves it.
*
* @param map <zone_string, list <string> > strings are allowed ports or port ranges
* @see GetBroadcastAllowedPorts() for an example of data
*/
global define void SetBroadcastAllowedPorts (map <string, list <string> > broadcast) {
SetModified();
foreach (string zone, GetKnownFirewallZones(), {
SetBroadcastConfiguration(zone, mergestring(broadcast[zone]:[], " "));
});
}
/**
* Function returns if broadcast is allowed for needed ports in zone.
*
* @param list <string> ports
* @param string zone
* @return boolean if is allowed
*
* @example IsBroadcastAllowed (["port-xyz", "53"], "EXT") -> true
*/
boolean IsBroadcastAllowed (list <string> needed_ports, string zone) {
if (size(needed_ports)==0) {
y2warning("Unknown service with no needed ports!");
return nil;
}
// getting broadcast allowed ports
map <string, list <string> > allowed_ports_map = GetBroadcastAllowedPorts();
// Divide allowed port ranges and aliases (also with their port aliases)
map <string, list <string> > allowed_ports_divided = PortRanges::DividePortsAndPortRanges (
allowed_ports_map[zone]:[], true
);
// If there are no allowed ports at all
if (allowed_ports_divided["ports"]:[] == [] && allowed_ports_divided["port_ranges"]:[] == []) {
return false;
}
// clean up the memory a bit
allowed_ports_map = nil;
boolean is_allowed = true;
// checking all needed ports;
foreach (string needed_port, needed_ports, {
// allowed ports don't contain the needed one and also portranges don't
if (
!contains (allowed_ports_divided["ports"]:[], needed_port) &&
!PortRanges::PortIsInPortranges (needed_port, allowed_ports_divided["port_ranges"]:[])
) {
is_allowed = false;
break;
}
});
return is_allowed;
}
/**
* Local function removes list of ports from port allowing broadcast packets in zone.
*
* @param list <of ports> to be removed
* @param string zone
*/
void RemoveAllowedBroadcast (list <string> needed_ports, string zone) {
SetModified();
map <string, list <string> > allowed_ports = GetBroadcastAllowedPorts();
list <string> list_ports_allowed = allowed_ports[zone]:[];
// ports to be allowed one by one
foreach (string allow_this_port, needed_ports, {
// remove all aliases of ports yet mentioned in zone
list <string> aliases_of_port = PortAliases::GetListOfServiceAliases(allow_this_port);
list_ports_allowed = filter (string just_allowed, list_ports_allowed, {
return (! contains(aliases_of_port, just_allowed));
});
});
allowed_ports[zone] = list_ports_allowed;
// save it using function
SetBroadcastAllowedPorts(allowed_ports);
}
/**
* Local function adds list of ports to ports accepting broadcast
*
* @param list <string> of ports
*/
void AddAllowedBroadcast (list <string> needed_ports, string zone) {
// changing only if ports are not allowed
if (! IsBroadcastAllowed (needed_ports, zone)) {
SetModified();
map <string, list <string> > allowed_ports = GetBroadcastAllowedPorts();
list <string> list_ports_allowed = allowed_ports[zone]:[];
// ports to be allowed one by one
foreach (string allow_this_port, needed_ports, {
// at first: remove all aliases of ports yet mentioned in zone
list <string> aliases_of_port = PortAliases::GetListOfServiceAliases(allow_this_port);
list_ports_allowed = filter (string just_allowed, list_ports_allowed, {
return (! contains(aliases_of_port, just_allowed));
});
// at second: add only one
list_ports_allowed = add(list_ports_allowed, allow_this_port);
});
allowed_ports[zone] = list_ports_allowed;
// save it using function
SetBroadcastAllowedPorts(allowed_ports);
}
}
/**
* Local function for removing (disallowing) single service/port
* for defined protocol and zone. Functions doesn't take care of
* port-aliases.
*
* @param string service/port
* @param string protocol
* @param string zone
* @return boolean success
*/
boolean RemoveServiceFromProtocolZone(string remove_service, string protocol, string zone) {
SetModified();
string key = "FW_SERVICES_" + zone + "_" + protocol;
list <string> allowed = splitstring(SETTINGS[key]:"", " ");
allowed = filter (string single_service, allowed, {
return single_service != "" && single_service != remove_service;
});
SETTINGS[key] = mergestring(toset(allowed), " ");
return true;
}
/**
* Local function removes ports and their aliases (if check_for_aliases is true), for
* requested protocol and zone.
*
* @param list <string> ports to be removed
* @param string protocol
* @param string zone
* @param boolean check for port-aliases
*/
void RemoveAllowedPortsOrServices (list <string> remove_ports, string protocol, string zone, boolean check_for_aliases) {
if (size(remove_ports)<1) {
y2warning("Undefined list of %1 services/ports for service", protocol);
return;
}
SetModified();
// all allowed ports
map <string, list <string> > allowed_services = PortRanges::DividePortsAndPortRanges (
GetAllowedServicesForZoneProto (zone, protocol), false
);
// removing all aliases of ports too, adding aliases into
if (check_for_aliases) {
list <string> remove_ports_with_aliases = [];
foreach (string remove_port, remove_ports, {
// skip port ranges, they cannot have any port-alias
if (PortRanges::IsPortRange (remove_port)) {
remove_ports_with_aliases = add (remove_ports_with_aliases, remove_port);
return;
}
list <string> remove_these_ports = PortAliases::GetListOfServiceAliases(remove_port);
if (remove_these_ports == nil) { remove_these_ports = [ remove_port ]; }
remove_ports_with_aliases = (list<string>) union (remove_ports_with_aliases,
remove_these_ports
);
});
remove_ports = remove_ports_with_aliases;
}
remove_ports = toset(remove_ports);
// Remove ports only once (because of port aliases), any => integers and strings
list <any> already_removed = [];
foreach (string remove_port, remove_ports, {
// Removing from normal ports
allowed_services["ports"] = filter (string allowed_port, allowed_services["ports"]:[], {
return allowed_port != "" && allowed_port != remove_port;
});
// Removing also from port ranges
if (allowed_services["port_ranges"]:[] != []) {
// Removing a real port from port ranges
if (! PortRanges::IsPortRange (remove_port)) {
integer remove_port_nr = PortAliases::GetPortNumber(remove_port);
// Because of all port aliases
if (!contains(already_removed, remove_port_nr)) {
already_removed = add (already_removed, remove_port_nr);
allowed_services["port_ranges"] = PortRanges::RemovePortFromPortRanges (
remove_port_nr, allowed_services["port_ranges"]:[]
);
}
// Removing a port range from port ranges
} else {
if (!contains(already_removed, remove_port)) {
// Just filtering the exact port range
allowed_services["port_ranges"] = filter (string one_port_range, allowed_services["port_ranges"]:[], {
return one_port_range != remove_port;
});
already_removed = add (already_removed, remove_port);
}
}
}
});
list <string> allowed_services_all = (list <string>) union (
allowed_services["ports"]:[],
allowed_services["port_ranges"]:[]
);
allowed_services_all = PortRanges::FlattenServices (allowed_services_all, protocol);
SetAllowedServicesForZoneProto (allowed_services_all, zone, protocol);
}
/**
* Local function allows ports for requested protocol and zone.
*
* @param list <string> ports to be added
* @param string protocol
* @param string zone
*/
void AddAllowedPortsOrServices (list <string> add_ports, string protocol, string zone) {
if (size(add_ports)<1) {
y2warning("Undefined list of %1 services/ports for service", protocol);
return;
}
SetModified();
// all allowed ports
list <string> allowed_services = GetAllowedServicesForZoneProto (zone, protocol);
allowed_services = (list<string>) union (allowed_services, add_ports);
allowed_services = PortRanges::FlattenServices (allowed_services, protocol);
SetAllowedServicesForZoneProto (allowed_services, zone, protocol);
}
/**
* Removes service defined by package (FATE #300687) from enabled services.
*
* @param string service_id
* @param string zone
*
* @example
* RemoveServiceDefinedByPackageFromZone ("service:irc-server", "EXT");
*/
void RemoveServiceDefinedByPackageFromZone (string service, string zone) {
if (! IsKnownZone(zone)) {
return nil;
}
if (service == nil) {
y2error ("Service Id can't be nil!");
return nil;
} else if (regexpmatch (service, "^service:.*")) {
service = regexpsub (service, "^service:(.*)", "\\1");
}
// services defined by package are listed without "service:" which is here
// just to distinguish between dynamic and static definitions
list <string> supported_services = splitstring (SETTINGS["FW_CONFIGURATIONS_" + zone]:"", " ");
// Removing the service
supported_services = filter (string one_service, supported_services, {
return one_service != service;
});
SETTINGS["FW_CONFIGURATIONS_" + zone] = mergestring (supported_services, " ");
SetModified();
}
/**
* Adds service defined by package (FATE #300687) into list of enabled services.
*
* @param string service_id
* @param string zone
*
* @example
* AddServiceDefinedByPackageIntoZone ("service:irc-server", "EXT");
*/
void AddServiceDefinedByPackageIntoZone (string service, string zone) {
if (! IsKnownZone(zone)) {
return nil;
}
if (service == nil) {
y2error ("Service Id can't be nil!");
return nil;
} else if (regexpmatch (service, "^service:.*")) {
service = regexpsub (service, "^service:(.*)", "\\1");
}
// services defined by package are listed without "service:" which is here
// just to distinguish between dynamic and static definitions
list <string> supported_services = splitstring (SETTINGS["FW_CONFIGURATIONS_" + zone]:"", " ");
// Adding the service
supported_services = toset (add (supported_services, service));
SETTINGS["FW_CONFIGURATIONS_" + zone] = mergestring (supported_services, " ");
SetModified();
}
/**
* Local function removes well-known service's support from zone.
* Allowed ports are removed with all of their port-aliases.
*
* @param string service id
* @param string zone
*/
void RemoveServiceSupportFromZone (string service, string zone) {
map <string, list <string> > needed = SuSEFirewallServices::GetNeededPortsAndProtocols(service);
// unknown service
if (needed == nil) {
y2error("Undefined service '%1'", service);
return nil;
}
// FATE #300687: Ports for SuSEfirewall added via packages
if (SuSEFirewallServices::ServiceDefinedByPackage (service)) {
if (IsServiceSupportedInZone (service,zone) == true)
RemoveServiceDefinedByPackageFromZone (service, zone);
return nil;
}
SetModified();
// Removing service ports (and also port aliases for TCP and UDP)
foreach (string key, service_defined_by, {
list <string> needed_ports = needed[key]:[];
if (needed_ports == []) return;
if (key == "tcp_ports") {
RemoveAllowedPortsOrServices(needed_ports, "TCP", zone, true);
} else if (key == "udp_ports") {
RemoveAllowedPortsOrServices(needed_ports, "UDP", zone, true);
} else if (key == "rpc_ports") {
RemoveAllowedPortsOrServices(needed_ports, "RPC", zone, false);
} else if (key == "ip_protocols") {
RemoveAllowedPortsOrServices(needed_ports, "IP", zone, false);
} else if ("broadcast_ports" == key) {
RemoveAllowedBroadcast(needed_ports, zone);
} else {
y2error("Unknown key '%1'", key);
}
});
}
/**
* Local function adds well-known service's support into zone. It first of all
* removes the current support for service with port-aliases.
*
* @param string service id
* @param string zone
*/
void AddServiceSupportIntoZone (string service, string zone) {
map <string, list <string> > needed = SuSEFirewallServices::GetNeededPortsAndProtocols (service);
// unknown service
if (needed == nil) {
y2error("Undefined service '%1'", service);
return nil;
}
SetModified();
// FATE #300687: Ports for SuSEfirewall added via packages
if (SuSEFirewallServices::ServiceDefinedByPackage (service)) {
AddServiceDefinedByPackageIntoZone (service, zone);
return nil;
}
// Removing service ports first (and also port aliases for TCP and UDP)
if (IsServiceSupportedInZone(service,zone) == true) {
RemoveServiceSupportFromZone(service,zone);
}
foreach (string key, service_defined_by, {
list <string> needed_ports = needed[key]:[];
if (needed_ports == []) return;
if (key == "tcp_ports") {
AddAllowedPortsOrServices(needed_ports, "TCP", zone);
} else if (key == "udp_ports") {
AddAllowedPortsOrServices(needed_ports, "UDP", zone);
} else if (key == "rpc_ports") {
AddAllowedPortsOrServices(needed_ports, "RPC", zone);
} else if (key == "ip_protocols") {
AddAllowedPortsOrServices(needed_ports, "IP", zone);
} else if ("broadcast_ports" == key) {
AddAllowedBroadcast(needed_ports, zone);
} else {
y2error("Unknown key '%1'", key);
}
});
}
// <!-- SuSEFirewall LOCAL FUNCTIONS //-->
// <!-- SuSEFirewall GLOBAL FUNCTIONS //-->
// bnc #388773
// By default needed packages are just checked, not installed
boolean check_and_install_package = false;
/**
* By default SuSEfirewall2 packages are just checked whether they are installed.
* With this function, you can change the behavior to also offer installing
* the packages.
*
* @param boolean new_status, 'true' if packages should be offered for installation
*/
global void SetInstallPackagesIfMissing (boolean new_status) {
if (new_status == nil) {
y2error ("Wrong value: %1", new_status);
return;
}
check_and_install_package = new_status;
if (check_and_install_package) {
y2milestone ("SuSEfirewall2 packages will installed if missing");
} else {
y2milestone ("SuSEfirewall2 packages will not be installed even if missing");
}
}
/* Are needed packages (SuSEfirewall2) installed? */
boolean needed_packages_installed = nil;
/**
* Returns whether all needed packages are installed.
*
* @return boolean whether SuSEfirewall2 is installed
*/
global boolean SuSEFirewallIsInstalled () {
if (needed_packages_installed == nil) {
// In mode normal, package can be installed on request
// if required by the module
if (check_and_install_package && Mode::normal()) {
needed_packages_installed = PackageSystem::CheckAndInstallPackages ([susefirewall_package]);
y2milestone ("CheckAndInstallPackages -> %1", needed_packages_installed);
// In mode install/update network might be down
} else {
needed_packages_installed = PackageSystem::Installed (susefirewall_package);
y2milestone ("Installed -> %1", needed_packages_installed);
}
} else if (needed_packages_installed == false) {
y2milestone ("SuSEfirewall2 is not installed, skipping...");
}
return needed_packages_installed;
}
// Configuration has been read and it's useful
boolean fw_service_can_be_configured = false;
/**
* Functions returns whether any firewall's configuration was modified.
*
* @return boolean if the configuration was modified
*/
global define boolean GetModified () {
// Changed SuSEFirewall or
// Changed SuSEFirewallServices (needs resatrting as well)
return (modified || SuSEFirewallServices::GetModified());
}
/**
* Function resets flag which doesn't allow to read configuration from disk again.
* So you actually can reread the configuration from disk. Currently, only the first
* Read() call reads the configuration from disk.
*/
global define void ResetReadFlag () {
configuration_has_been_read = false;
}
/**
* Function returns localized name of the zone identified by zone shortname.
*
* @param string short name
* @return string zone name
*
* @example
* LANG=en_US GetZoneFullName ("EXT") -> "External Zone"
* LANG=cs_CZ GetZoneFullName ("EXT") -> "Externí Zóna"
*/
global define string GetZoneFullName (string zone) {
// TRANSLATORS: Firewall zone full-name, used as combo box item or dialog title
return zone_names[zone]:_("Unknown Zone");
}
/**
* Function sets if firewall should be protected from internal zone.
*
* @param boolean set to be protected from internal zone
*/
global define void SetProtectFromInternalZone (boolean set_protect) {
SetModified();
if (set_protect) {
SETTINGS["FW_PROTECT_FROM_INT"] = "yes";
} else {
SETTINGS["FW_PROTECT_FROM_INT"] = "no";
}
}
/**
* Function returns if firewall is protected from internal zone.
*
* @return boolean if protected from internal
*/
global define boolean GetProtectFromInternalZone () {
return (SETTINGS["FW_PROTECT_FROM_INT"]:"no" == "yes");
}
/**
* Function sets if firewall should support routing.
*
* @param boolean set to support route or not
*/
global define void SetSupportRoute (boolean set_route) {
SetModified();
if (set_route) {
SETTINGS["FW_ROUTE"] = "yes";
} else {
SETTINGS["FW_ROUTE"] = "no";
}
}
/**
* Function returns if firewall supports routing.
*
* @return boolean if route is supported
*/
global define boolean GetSupportRoute () {
return (SETTINGS["FW_ROUTE"]:"no" == "yes");
}
/**
* Function sets how firewall should trust successfully decrypted IPsec packets.
* It should be the zone name (shortname) or 'no' to trust packets the same as
* firewall trusts the zone from which IPsec packet came.
*
* @param string zone or "no"
*/
global define void SetTrustIPsecAs (string zone) {
SetModified();
// do not trust
if (zone == "no") {
SETTINGS["FW_IPSEC_TRUST"] = "no";
} else {
// trust IPsec is a known zone
if (IsKnownZone(zone)) {
zone = GetZoneConfigurationString(zone);
SETTINGS["FW_IPSEC_TRUST"] = zone;
// unknown zone, changing to default value
} else {
string defaultv = GetDefaultValue("FW_IPSEC_TRUST");
y2warning("Trust IPsec as '%1' (unknown zone) changed to '%2'", zone, defaultv);
SETTINGS["FW_IPSEC_TRUST"] = defaultv;
}
}
}
/**
* Function returns the trust level of IPsec packets.
* See SetTrustIPsecAs() for more information.
*
* @return string zone or "no"
*/
global define string GetTrustIPsecAs () {
// do not trust
if (SETTINGS["FW_IPSEC_TRUST"]:nil == "no") {
return "no";
// default value for 'yes" ~= "INT"
} else if (SETTINGS["FW_IPSEC_TRUST"]:nil == "yes") {
return "INT";
} else {
string zone = GetConfigurationStringZone(SETTINGS["FW_IPSEC_TRUST"]:"");
// trust as named zone (if known)
if (IsKnownZone(zone)) {
return zone;
// unknown zone, change to default value
} else {
SetModified();
string defaultv = GetDefaultValue("FW_IPSEC_TRUST");
y2warning("Trust IPsec as '%1' (unknown zone) changed to '%2'", SETTINGS["FW_IPSEC_TRUST"]:"", defaultv);
SetTrustIPsecAs(defaultv);
return "no";
}
}
}
/**
* Function which returns if SuSEfirewall2 should start in Write process.
* In fact it means that SuSEfirewall2 will at the end.
*
* @return boolean if the firewall should start
*/
global define boolean GetStartService () {
return (boolean) SETTINGS["start_firewall"]:false;
}
/**
* Function which sets if SuSEfirewall should start in Write process.
*
* @param boolean start_service at Write() process
* @see GetStartService()
*/
global define void SetStartService (boolean start_service) {
if (! SuSEFirewall::SuSEFirewallIsInstalled()) {
y2warning ("Cannot set SetStartService");
return nil;
}
if (GetStartService() != start_service) {
SetModified();
y2milestone("Setting start-firewall to %1", start_service);
SETTINGS["start_firewall"] = start_service;
} else {
// without set modified!
y2milestone("start-firewall has been already set to %1", start_service);
SETTINGS["start_firewall"] = start_service;
}
}
/**
* Function which returns whether SuSEfirewall should be enabled in
* /etc/init.d/ starting scripts during the Write() process
*
* @see Write()
* @see EnableServices()
*
* @return boolean if the firewall should start
*/
global define boolean GetEnableService () {
return (boolean) SETTINGS["enable_firewall"]:false;
}
/**
* Function which sets if SuSEfirewall should start in Write process
*
* @param boolean start_service at Write() process
*/
global define void SetEnableService (boolean enable_service) {
if (! SuSEFirewall::SuSEFirewallIsInstalled()) {
y2warning ("Cannot set SetEnableService");
return nil;
}
if (GetEnableService() != enable_service) {
SetModified();
y2milestone("Setting enable-firewall to %1", enable_service);
SETTINGS["enable_firewall"] = enable_service;
} else {
// without set modified
y2milestone("enable-firewall has been already set to %1", enable_service);
SETTINGS["enable_firewall"] = enable_service;
}
}
/**
* Functions starts services needed for SuSEFirewall
*
* @return boolean result
*/
global define boolean StartServices () {
boolean all_ok = true;
if (! SuSEFirewallIsInstalled()) return false;
// bug #215416
// SuSEfirewall2_init doesn't need to be called, only enabled
if (Mode::testsuite()) return true;
string tmpdir_file = (string) SCR::Read(.target.tmpdir);
if (tmpdir_file == nil || tmpdir_file == "") tmpdir_file = "/var/lib/YaST2";
tmpdir_file = tmpdir_file + "/SuSEfirewall2_YaST_output";
string command = sformat(
"/sbin/SuSEfirewall2 start 2>'%1'; cat '%1'; rm -rf '%1'",
tmpdir_file
);
y2milestone ("Starting firewall...");
map cmd = (map) SCR::Execute (.target.bash_output, command);
if (cmd["exit"]:nil != 0) {
y2error ("Starting firewall: >%1< returned %2", command, cmd);
all_ok = false;
} else {
y2milestone ("Started");
}
return all_ok;
}
/**
* Functions stops services needed for SuSEFirewall
*
* @return boolean result
*/
global define boolean StopServices () {
boolean all_ok = true;
if (! SuSEFirewallIsInstalled()) return false;
// bug #215416
// SuSEfirewall2_init doesn't need to be called, only disabled
if (Mode::testsuite()) return true;
string tmpdir_file = (string) SCR::Read(.target.tmpdir);
if (tmpdir_file == nil || tmpdir_file == "") tmpdir_file = "/var/lib/YaST2";
tmpdir_file = tmpdir_file + "/SuSEfirewall2_YaST_output";
string command = sformat(
"/sbin/SuSEfirewall2 stop 2>'%1'; cat '%1'; rm -rf '%1'",
tmpdir_file
);
y2milestone ("Stopping firewall...");
map cmd = (map) SCR::Execute (.target.bash_output, command);
if (cmd["exit"]:nil != 0) {
y2error ("Stopping firewall: >%1< returned %2", command, cmd);
all_ok = false;
} else {
y2milestone ("Stopped");
}
return all_ok;
}
/**
* Functions enables services needed for SuSEFirewall in /etc/inet.d/
*
* @return boolean result
*/
global define boolean EnableServices () {
boolean all_ok = true;
if (! SuSEFirewallIsInstalled()) return false;
foreach (string service, firewall_services, {
y2debug("Enabling service: %1", service);
if (! Service::Enable(service)) {
all_ok = true;
// TRANSLATORS: a popup error message
Report::Error (sformat (_("Cannot enable service '%1'."), service));
}
});
return all_ok;
}
/**
* Functions disables services needed for SuSEFirewall in /etc/inet.d/
*
* @return boolean result
*/
global define boolean DisableServices () {
boolean all_ok = true;
if (! SuSEFirewallIsInstalled()) return false;
foreach (string service, firewall_services_reverse, {
y2debug("Disabling service: %1", service);
if (! Service::Disable(service)) {
all_ok = false;
// TRANSLATORS: a popup error message
Report::Error (sformat (_("Cannot disable service '%1'."), service));
}
});
return all_ok;
}
/**
* Function determines if all SuSEFirewall scripts are enabled in
* init scripts /etc/init.d/ now.
* For configuration "enabled" status use GetEnableService().
*
* @return boolean if enabled
*/
global define boolean IsEnabled () {
boolean enabled = false;
if (! SuSEFirewallIsInstalled()) return false;
//if (Mode::normal() || Mode::commandline()) {
foreach (string service, firewall_services, {
enabled = Service::Enabled(service);
// All services have to be enabled
if (!enabled) {
y2milestone("Firewall service %1 is not enabled", service);
break;
}
});
//}
if (enabled) {
y2milestone("Firewall init scripts are enabled");
}
return enabled;
}
/**
* Function determines if at least one SuSEFirewall script is started now.
* For configuration "started" status use GetStartService().
*
* @return boolean if started
*/
global define boolean IsStarted () {
boolean started = false;
if (! SuSEFirewallIsInstalled()) return false;
//if (Mode::normal() || Mode::commandline()) {
foreach (string service, firewall_services, {
if (Service::Status(service) == 0) {
started = true;
break;
}
});
//}
if (started == true) {
y2milestone("Firewall services are started");
} else {
y2milestone("Firewall services are stopped");
}
return started;
}
/**
* Function for getting exported SuSEFirewall configuration
*
* @return map <string, any> with configuration
*/
global define map <string, any> Export () {
return SETTINGS;
}
/**
* Function for setting SuSEFirewall configuration from input
*
* @param map <string, any> with configuration
*/
global define void Import (map <string, any> import_settings) {
SetModified();
SETTINGS = import_settings;
}
/**
* Function returns if the interface is in zone.
*
* @param string interface
* @param string firewall zone
* @return boolean is in zone
*
* @example IsInterfaceInZone ("eth-id-01:11:DA:9C:8A:2F", "INT") -> false
*/
global define boolean IsInterfaceInZone(string interface, string zone) {
list <string> interfaces = splitstring(SETTINGS[ "FW_DEV_" + zone ]:"", " ");
return contains(interfaces, interface);
}
/**
* Function returns the firewall zone of interface, nil if no zone includes
* the interface. Error is reported when interface is found in multiple
* firewall zones, then the first appearance is returned.
*
* @param string interface
* @return string zone
*
* @example GetZoneOfInterface ("eth-id-01:11:DA:9C:8A:2F") -> "DMZ"
*/
global define string GetZoneOfInterface (string interface) {
list interface_zone = [];
foreach (string zone, GetKnownFirewallZones(), {
if (IsInterfaceInZone(interface, zone)) interface_zone = add (interface_zone, zone);
});
if (IsVerbose() && size(interface_zone) > 1) {
// TRANSLATORS: Error message, %1 = interface name (like eth0)
Report::Error(sformat(_("Interface '%1' is included in multiple firewall zones.
Continuing with configuration can produce errors.
It is recommended to leave the configuration and repair it manually in
the file '/etc/sysconfig/SuSEFirewall'."), interface));
}
// return the first existence of interface in zones
// if it is not presented anywhere, nil is returned
return (string) interface_zone[0]:nil;
}
/**
* Function returns list of zones of requested interfaces
*
* @param list<string> interfaces
* @return list<string> firewall zones
*
* @example
* GetZonesOfInterfaces (["eth1","eth4"]) -> ["DMZ", "EXT"]
*/
global define list<string> GetZonesOfInterfaces (list<string> interfaces) {
list<string> zones = [];
string zone = "";
foreach (string interface, interfaces, {
zone = GetZoneOfInterface(interface);
if (zone != nil) zones = add(zones, zone);
});
return toset(zones);
}
global define list<string> GetInterfacesInZoneSupportingAnyFeature (string zone);
/**
* Function returns list of zones of requested interfaces.
* Special string 'any' in 'EXT' zone is supported.
*
* @param list<string> interfaces
* @return list<string> firewall zones
*
* @example
* GetZonesOfInterfaces (["eth1","eth4"]) -> ["EXT"]
*/
global define list<string> GetZonesOfInterfacesWithAnyFeatureSupported (list<string> interfaces) {
list<string> zones = [];
string zone = "";
// 'any' in 'EXT'
list <string> interfaces_covered_by_any =
SuSEFirewall::GetInterfacesInZoneSupportingAnyFeature(special_all_interface_zone);
foreach (string interface, interfaces, {
// interface is covered by 'any' in 'EXT'
if (contains(interfaces_covered_by_any, interface))
zone = special_all_interface_zone;
// interface is explicitely mentioned in some zone
else
zone = GetZoneOfInterface(interface);
if (zone != nil) zones = add(zones, zone);
});
return toset(zones);
}
/**
* Function returns list of maps of known interfaces.
* @struct [ $[ "id":"modem0", "name":"Askey 815C", "type":"dialup", "zone":"EXT" ], ... ]
*
* @return list <map <string, string> >
* @return list <map <string, string> > of all interfaces
*/
global define list <map <string, string> > GetAllKnownInterfaces () {
list <map <string, string> > known_interfaces = [];
// All dial-up interfaces
list <string> dialup_interfaces = NetworkInterfaces::List("dialup");
if (dialup_interfaces == nil) dialup_interfaces = [];
// bugzilla #303858 - wrong values from NetworkInterfaces
dialup_interfaces = filter (string one_iface, dialup_interfaces, {
if (one_iface == nil || one_iface == "") {
y2error ("Wrong interface definition '%1'", one_iface);
return false;
}
return true;
});
dialup_interfaces = filter (string interface, dialup_interfaces, ``{
return interface != "" && !issubstring (interface, "lo") && !issubstring (interface, "sit");
});
// All non-dial-up interfaces
list <string> non_dialup_interfaces = NetworkInterfaces::List("");
if (non_dialup_interfaces == nil) non_dialup_interfaces = [];
// bugzilla #303858 - wrong values from NetworkInterfaces
non_dialup_interfaces = filter (string one_iface, non_dialup_interfaces, {
if (one_iface == nil || one_iface == "") {
y2error ("Wrong interface definition '%1'", one_iface);
return false;
}
return true;
});
non_dialup_interfaces = filter (string interface, non_dialup_interfaces, ``{
return interface != "" && !issubstring (interface, "lo") && !issubstring (interface, "sit")
&& !contains (dialup_interfaces, interface);
});
foreach (string interface, dialup_interfaces, {
known_interfaces = add(known_interfaces, $[
"id" : interface,
"type" : "dialup",
// using function to get name
"name" : NetworkInterfaces::GetValue(interface, "NAME"),
"zone" : GetZoneOfInterface(interface),
]);
});
foreach (string interface, non_dialup_interfaces, {
known_interfaces = add(known_interfaces, $[
"id" : interface,
// using function to get name
"name" : NetworkInterfaces::GetValue(interface, "NAME"),
"zone" : GetZoneOfInterface(interface),
]);
});
return known_interfaces;
}
/**
* Function returns list of non-dial-up interfaces.
*
* @return list <string> of non-dial-up interface names
* @example GetAllNonDialUpInterfaces() -> ["eth1", "eth2"]
*/
global define list <string> GetAllNonDialUpInterfaces () {
list <string> non_dial_up_interfaces = [];
foreach (map<string, string> interface, SuSEFirewall::GetAllKnownInterfaces(), {
if (interface["type"]:nil != "dial_up")
non_dial_up_interfaces = add (non_dial_up_interfaces, interface["id"]:"");
});
return non_dial_up_interfaces;
}
/**
* Function returns list of dial-up interfaces.
*
* @return list <string> of dial-up interface names
* @example GetAllDialUpInterfaces() -> ["modem0", "dsl5"]
*/
global define list <string> GetAllDialUpInterfaces () {
list <string> dial_up_interfaces = [];
foreach (map <string, string> interface, SuSEFirewall::GetAllKnownInterfaces(), {
if (interface["type"]:nil == "dial_up")
dial_up_interfaces = add (dial_up_interfaces, interface["id"]:"");
});
return dial_up_interfaces;
}
/**
* Function returns list of all known interfaces.
*
* @return list <string> of interfaces
* @example GetListOfKnownInterfaces() -> ["eth1", "eth2", "modem0", "dsl5"]
*/
global define list <string> GetListOfKnownInterfaces () {
list <string> interfaces = [];
foreach (map interface_map, GetAllKnownInterfaces(), {
interfaces = add (interfaces, interface_map["id"]:"");
});
return interfaces;
}
/**
* Function removes interface from defined zone.
*
* @param string interface
* @param string zone
* @example RemoveInterfaceFromZone ("modem0", "EXT")
*/
global define void RemoveInterfaceFromZone (string interface, string zone) {
SetModified();
y2milestone("Removing interface '%1' from '%2' zone.", interface, zone);
list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
interfaces_in_zone = filter (string single_interface, interfaces_in_zone, {
return single_interface != "" && single_interface != interface;
});
SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
}
/**
* Functions adds interface into defined zone.
* All appearances of interface in other zones are removed.
*
* @param string interface
* @param string zone
* @example AddInterfaceIntoZone ("eth5", "DMZ")
*/
global define void AddInterfaceIntoZone (string interface, string zone) {
SetModified();
string current_zone = GetZoneOfInterface(interface);
DecreaseVerbosity();
// removing all appearances of interface in zones, excepting current_zone==new_zone
while (current_zone != nil && current_zone != zone) {
// interface is in any zone already, removing it at first
if (current_zone != zone) {
RemoveInterfaceFromZone(interface, current_zone);
}
current_zone = GetZoneOfInterface(interface);
}
IncreaseVerbosity();
y2milestone("Adding interface '%1' into '%2' zone.", interface, zone);
list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
interfaces_in_zone = toset(add (interfaces_in_zone, interface));
SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
}
/**
* Function returns list of known interfaces in requested zone.
* Special strings like 'any' or 'auto' and unknown interfaces are removed from list.
*
* @param string zone
* @return list <string> of interfaces
* @example GetInterfacesInZone ("DMZ") -> ["eth4", "eth5"]
*/
global define list<string> GetInterfacesInZone (string zone) {
list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
list <string> known_interfaces_now = GetListOfKnownInterfaces();
// filtering special strings
interfaces_in_zone = filter(string interface, interfaces_in_zone, ``{
return interface != "" && contains(known_interfaces_now, interface);
});
return interfaces_in_zone;
}
/**
* Function returns all interfaces already configured in firewall.
*
* @return list <string> of configured interfaces
*/
global define list<string> GetFirewallInterfaces () {
list<string> firewall_configured_devices = [];
foreach (string zone, GetKnownFirewallZones(), {
firewall_configured_devices = (list<string>) union (firewall_configured_devices, GetInterfacesInZone(zone));
});
return toset(firewall_configured_devices);
}
/**
* Returns list of interfaces not mentioned in any zone and covered by the
* special string 'any' in zone 'EXT' if such string exists there and the zone
* is EXT. If the feature 'any' is not set, function returns empty list.
*
* @param string zone
* @return list <string> of interfaces covered by special string 'any'
* @see IsAnyNetworkInterfaceSupported()
*/
global define list<string> InterfacesSupportedByAnyFeature (string zone) {
list <string> result = [];
if (zone == special_all_interface_zone && IsAnyNetworkInterfaceSupported()) {
list <string> known_interfaces_now = GetListOfKnownInterfaces();
list <string> configured_interfaces = GetFirewallInterfaces();
foreach (string one_interface, known_interfaces_now, {
if (! contains(configured_interfaces, one_interface)) {
y2milestone("Interface '%1' supported by special string '%2' in zone '%3'",
one_interface, special_all_interface_string, special_all_interface_zone);
result = add (result, one_interface);
}
});
}
return result;
}
/**
* Function returns list of known interfaces in requested zone.
* Special string 'any' in EXT zone covers all interfaces without
* any zone assignment.
*
* @param string zone
* @return list <string> of interfaces
*/
global define list<string> GetInterfacesInZoneSupportingAnyFeature (string zone) {
list <string> interfaces_in_zone = GetInterfacesInZone(zone);
// 'any' in EXT zone, add all interfaces without zone to this one
list <string> interfaces_covered_by_any = InterfacesSupportedByAnyFeature(zone);
if (size(interfaces_covered_by_any)>0) {
interfaces_in_zone = (list <string>) union (interfaces_in_zone, interfaces_covered_by_any);
}
return interfaces_in_zone;
}
boolean ArePortsOrServicesAllowed (list <string> needed_ports, string protocol, string zone, boolean check_for_aliases);
/**
* Function returns if requested service is allowed in respective zone.
* Function takes care for service's aliases (only for TCP and UDP).
* Service is defined by set of parameters such as port and protocol.
*
* @param string service (service name, port name, port alias or port number)
* @param protocol TCP, UDP, RCP or IP
* @param interface name (like modem0), firewall zone (like "EXT") or "any" for all zones.
* @return boolean if service is allowed
*
* @example
* HaveService ("ssh", "TCP", "EXT") -> true
* HaveService ("ssh", "TCP", "modem0") -> false
* HaveService ("53", "UDP", "dsl") -> false
*/
global define boolean HaveService(string service, string protocol, string interface) {
if (! IsSupportedProtocol(protocol)) {
y2error("Unknown protocol: %1", protocol);
return nil;
}
// definition of searched zones
list<string> zones = [];
// "any" for all zones, this is ugly
if (interface == "any") {
zones = GetKnownFirewallZones();
// string interface is the zone name
} else if (IsKnownZone(interface)) {
zones = add (zones, interface);
// interface is the interface name
} else {
interface = GetZoneOfInterface(interface);
if (interface != nil) {
zones = add (zones, interface);
}
}
// SuSEFirewall feature FW_PROTECT_FROM_INT
// should not be protected and searched zones include also internal (or the zone IS internal, sure)
if (! GetProtectFromInternalZone() && contains(zones, int_zone_shortname)) {
y2milestone("Checking for service '%1', in '%2', PROTECT_FROM_INTERNAL='no' => allowed", service, interface);
return true;
}
// Check and return whether the service (port) is supported anywhere
boolean ret = false;
foreach (string zone, zones, {
// This function can also handle port ranges
if (ArePortsOrServicesAllowed([service], protocol, zone, true)) {
ret = true;
break;
}
});
return ret;
}
/**
* Function adds service into selected zone (or zone of interface) for selected protocol.
* Function take care about port-aliases, first of all, removes all of them.
*
* @param string service/port
* @param string protocol TCP, UDP, RPC, IP
* @param string zone name or interface name
* @return boolean success
*
* @example
* AddService ("ssh", "TCP", "EXT")
* AddService ("ssh", "TCP", "dsl0")
*/
global define boolean AddService (string service, string protocol, string interface) {
boolean success = false;
y2milestone("Adding service %1, protocol %2 to %3", service, protocol, interface);
if (! IsSupportedProtocol(protocol)) {
y2error("Unknown protocol: %1", protocol);
return false;
}
list <string> zones_affected = [];
// "all" means for all known zones
if (interface == "all") {
zones_affected = GetKnownFirewallZones();
// zone or interface name
} else {
// is probably an interface name
if (! IsKnownZone(interface)) {
// interface is probably interface-name, checking for respective zone
interface = GetZoneOfInterface(interface);
// interface is not assigned to any zone
if (interface == nil) {
// TRANSLATORS: Error message, %1 = interface name (like eth0)
Report::Error(sformat(_("Interface '%1' is not assigned to any firewall zone.
Run YaST2 Firewall and assign it.
"), interface)
);
y2warning("Interface '%1' is not assigned to any firewall zone", interface);
return false;
}
}
zones_affected = [interface];
}
SetModified();
// Adding service support into each mentioned zone
foreach (string zone, zones_affected, {
// If there isn't already
if (!ArePortsOrServicesAllowed([service], protocol, zone, true)) {
AddAllowedPortsOrServices([service], protocol, zone);
} else {
y2milestone("Port %1 has been already allowed in %2", service, zone);
}
});
return true;
}
/**
* Function removes service from selected zone (or for interface) for selected protocol.
* Function takes care about port-aliases, removes all of them.
*
* @param string service/port
* @param string protocol TCP, UDP, RPC, IP
* @param string zone name or interface name
* @return boolean success
*
* @example
* RemoveService ("22", "TCP", "DMZ") -> true
* is the same as
* RemoveService ("ssh", "TCP", "DMZ") -> true
*/
global define boolean RemoveService (string service, string protocol, string interface) {
boolean success = false;
y2milestone("Removing service %1, protocol %2 from %3", service, protocol, interface);
if (! IsSupportedProtocol(protocol)) {
y2error("Unknown protocol: %1", protocol);
return false;
}
list <string> zones_affected = [];
// "all" means for all known zones
if (interface == "all") {
zones_affected = GetKnownFirewallZones();
// zone or interface name
} else {
if (! IsKnownZone(interface)) {
// interface is probably interface-name, checking for respective zone
interface = GetZoneOfInterface(interface);
// interface is not assigned to any zone
if (interface == nil) {
// TRANSLATORS: Error message, %1 = interface name (like eth0)
Report::Error(sformat(_("Interface '%1' is not assigned to any firewall zone.
Run YaST2 Firewall and assign it.
"), interface)
);
y2warning("Interface '%1' is not assigned to any firewall zone", interface);
return false;
}
}
zones_affected = [interface];
}
SetModified();
// Adding service support into each mentioned zone
foreach (string zone, zones_affected, {
// if the service is allowed
if (ArePortsOrServicesAllowed([service], protocol, zone, true)) {
RemoveAllowedPortsOrServices([service], protocol, zone, true);
} else {
y2milestone("Port %1 has been already removed from %2", service, zone);
}
});
return true;
}
/**
* Function returns if needed services are all allowed (or not) in the firewall.
* Last parameter sets if it also should check for port-aliases, what makes sense
* for TCP and UDP ports.
* Protocols and Zones aren't checked for existency. It's on you to do it.
*
* @param list <string> needed (checked) ports for service
* @param string protocol TCP, UDP, RPC or IP
* @param zone name like EXT
* @param boolean check for port-aliases (true is a reasonable default)
* @return boolean if all ports are allowed
* @example
* ArePortsOrServicesAllowed (["53", "54"], "UDP", "INT", true) -> true
*/
boolean ArePortsOrServicesAllowed (list <string> needed_ports, string protocol, string zone, boolean check_for_aliases) {
boolean are_allowed = true;
if (size(needed_ports)<1) {
y2warning("Undefined list of %1 services/ports for service", protocol);
return true;
}
map <string, list <string> > allowed_ports = $[];
// BTW: only TCP and UDP ports can have aliases and only TCP and UDP ports can have port ranges
if (check_for_aliases) {
allowed_ports = PortRanges::DividePortsAndPortRanges (
GetAllowedServicesForZoneProto (zone, protocol), true
);
} else {
allowed_ports["ports"] = GetAllowedServicesForZoneProto (zone, protocol);
}
foreach (string needed_port, needed_ports, {
if (
! contains(allowed_ports["ports"]:[], needed_port) &&
! PortRanges::PortIsInPortranges (needed_port, allowed_ports["port_ranges"]:[])
) {
are_allowed = false;
break;
}
});
return are_allowed;
}
/**
* Returns whether a service is mentioned in FW_CONFIGURATIONS_[EXT|INT|DMZ].
* These services are defined by random packages.
*
* @return boolean if service is supported in zone
* @param string service, e.g., "service:sshd"
* @param string zone, e.g., "EXT"
*
* @example
* IsServiceDefinedByPackageSupportedInZone ("service:sshd", "EXT") -> true
*/
boolean IsServiceDefinedByPackageSupportedInZone (string service, string zone) {
if (! IsKnownZone(zone)) {
return nil;
}
if (service == nil) {
y2error ("Service Id can't be nil!");
return nil;
} else if (regexpmatch (service, "^service:.*")) {
service = regexpsub (service, "^service:(.*)", "\\1");
}
// services defined by package are listed without "service:" which is here
// just to distinguish between dynamic and static definitions
list <string> supported_services = splitstring (SETTINGS["FW_CONFIGURATIONS_" + zone]:"", " ");
return contains (supported_services, service);
}
/**
* Function returns if service is supported (allowed) in zone. Service must be defined
* in the SuSEFirewallServices. Works transparently also with services defined by packages.
* Such service starts with "service:" prefix.
*
* @see YCP Module SuSEFirewallServices
* @param string service id
* @param string zone
* @return boolean if supported
*
* @example
* // All ports defined by dns-server service in SuSEFirewallServices module
* // are enabled in the respective zone
* IsServiceSupportedInZone ("dns-server", "EXT") -> true
* // irc-server definition exists on the system and the irc-server
* // is mentioned in FW_CONFIGURATIONS_EXT variable of SuSEfirewall2
* IsServiceSupportedInZone ("service:irc-server", "EXT") -> true
*/
global define boolean IsServiceSupportedInZone (string service, string zone) {
if (! IsKnownZone(zone)) {
return nil;
}
map <string, list <string> > needed = SuSEFirewallServices::GetNeededPortsAndProtocols(service);
// unknown service
if (needed == nil) {
y2error("Undefined service '%1'", service);
return nil;
}
// SuSEFirewall feature FW_PROTECT_FROM_INT
// should not be protected and searched zones include also internal (or the zone IS internal, sure)
if (zone == int_zone_shortname && ! GetProtectFromInternalZone()) {
y2milestone("Checking for service '%1', in '%2', PROTECT_FROM_INTERNAL='no' => allowed", service, zone);
return true;
}
// FATE #300687: Ports for SuSEfirewall added via packages
if (SuSEFirewallServices::ServiceDefinedByPackage(service)) {
boolean supported = IsServiceDefinedByPackageSupportedInZone (service, zone);
return supported;
}
// starting with nil value, any false means that the service is not supported
boolean service_is_supported = nil;
foreach (string key, service_defined_by, {
list <string> needed_ports = needed[key]:[];
if (needed_ports == []) return;
if (key == "tcp_ports") {
service_is_supported = ArePortsOrServicesAllowed(needed_ports, "TCP", zone, true);
} else if (key == "udp_ports") {
service_is_supported = ArePortsOrServicesAllowed(needed_ports, "UDP", zone, true);
} else if (key == "rpc_ports") {
service_is_supported = ArePortsOrServicesAllowed(needed_ports, "RPC", zone, false);
} else if (key == "ip_protocols") {
service_is_supported = ArePortsOrServicesAllowed(needed_ports, "IP", zone, false);
} else if ("broadcast_ports" == key) {
// testing for allowed broadcast ports
service_is_supported = IsBroadcastAllowed(needed_ports, zone);
} else {
y2error("Unknown key '%1'", key);
}
// service is not supported, we don't have to do more tests
if (service_is_supported == false) break;
});
return service_is_supported;
}
/**
* Function returns map of supported services all network interfaces.
*
* @param list <string> of services
* @return map <string, map < string, boolean > >
*
* @struct Returns $[service : $[ interface : supported_status ]]
*
* @example
* GetServicesInZones (["service:irc-server"]) -> $["service:irc-server":$["eth1":true]]
* // No such service "something"
* GetServicesInZones (["something"])) -> $["something":$["eth1":nil]]
* GetServicesInZones (["samba-server"]) -> $["samba-server":$["eth1":false]]
*/
global define map <string, map <string, boolean> > GetServicesInZones (list<string> services) {
// list of interfaces for each zone
map <string, list <string> > interface_in_zone = $[];
foreach (string interface, GetListOfKnownInterfaces(), {
// zone of interface
string zone_used = GetZoneOfInterface(interface);
// interface can be unassigned
if (zone_used == nil || zone_used == "") {
return;
}
interface_in_zone[zone_used] = add (interface_in_zone[zone_used]:[], interface);
});
// $[ service : $[ network_interface : status ]]
map <string, map <string, boolean> > services_status = $[];
// for all services requested
foreach (string service, services, {
services_status[service] = $[];
// for all zones in configuration
foreach (string zone, list <string> interfaces, interface_in_zone, {
boolean status = IsServiceSupportedInZone(service, zone);
// for all interfaces in zone
foreach (string interface, interfaces, {
services_status[service, interface] = status;
});
});
});
return services_status;
}
/**
* Function returns map of supported services in all firewall zones.
*
* @param list <string> of services
* @return map <string, map < string, boolean> >
*
* @struct Returns $[service : $[ zone_name : supported_status]]
*
* @example
* // Firewall in not protected from internal zone, that's why
* // all services report that they are enabled in INT zone
* GetServices (["samba-server", "service:irc-server"]) -> $[
* "samba-server" : $["DMZ":false, "EXT":false, "INT":true],
* "service:irc-server" : $["DMZ":false, "EXT":true, "INT":true]
* ]
*/
global define map <string, map <string, boolean> > GetServices (list<string> services) {
// $[ service : $[ firewall_zone : status ]]
map <string, map <string, boolean> > services_status = $[];
// for all services requested
foreach (string service, services, {
services_status[service] = $[];
// for all zones in configuration
foreach (string zone, GetKnownFirewallZones(), {
services_status[service,zone] = IsServiceSupportedInZone(service, zone);
});
});
return services_status;
}
/**
* Function sets status for several services in several firewall zones.
*
* @param list <string> service ids
* @param list <string> firewall zones (EXT|INT|DMZ...)
* @param boolean new status of services
* @return boolean if successfull
*
* @example
* SetServicesForZones (["samba-server", "service:irc-server"], ["DMZ", "EXT"], false);
* SetServicesForZones (["samba-server", "service:irc-server"], ["EXT", "DMZ"], true);
*
* @see GetServicesInZones()
* @see GetServices()
*/
global define boolean SetServicesForZones (list<string> services_ids, list<string> firewall_zones, boolean new_status) {
// no groups == all groups
if (size(firewall_zones)==0) firewall_zones = GetKnownFirewallZones();
// setting for each service
foreach (string service_id, services_ids, {
foreach (string firewall_zone, firewall_zones, {
// zone must be known one
if (! IsKnownZone(firewall_zone)) {
y2error("Zone '%1' is unknown firewall zone, skipping...", firewall_zone);
return;
}
SetModified();
// setting new status
if (new_status == true) {
y2milestone("Adding '%1' into '%2' zone", service_id, firewall_zone);
AddServiceSupportIntoZone(service_id, firewall_zone);
} else {
y2milestone("Removing '%1' from '%2' zone", service_id, firewall_zone);
RemoveServiceSupportFromZone(service_id, firewall_zone);
}
});
});
}
/**
* Function sets status for several services on several network interfaces.
*
* @param list <string> service ids
* @param list <string> network interfaces
* @param boolean new status of services
* @return boolean if successfull
*
* @example
* // Disabling services
* SetServices (["samba-server", "service:irc-server"], ["eth1", "modem0"], false)
* // Enabling services
* SetServices (["samba-server", "service:irc-server"], ["eth1", "modem0"], true)
* @see SetServicesForZones()
*/
global define boolean SetServices (list<string> services_ids, list<string> interfaces, boolean new_status) {
list<string> firewall_zones = GetZonesOfInterfacesWithAnyFeatureSupported(interfaces);
if (size(firewall_zones)==0) {
y2error("Interfaces '%1' are not in any group if interfaces", interfaces);
return false;
}
SetModified();
return SetServicesForZones(services_ids, firewall_zones, new_status);
}
/**
* Local function sets the default configuration and fills internal values.
*/
void ReadDefaultConfiguration () {
SETTINGS = $[];
ResetSysconfigSuSEFirewall ( GetListOfSuSEFirewallVariables() );
}
/**
* Local function reads current configuration and fills internal values.
*/
void ReadCurrentConfiguration () {
SETTINGS = $[];
// is firewall enabled in /etc/init.d/ ?
SETTINGS["enable_firewall"] = IsEnabled();
// is firewall started now?
SETTINGS["start_firewall"] = IsStarted();
ReadSysconfigSuSEFirewall ( GetListOfSuSEFirewallVariables() );
}
// old internal services definitions are converted to new services defined by packages
// but only once
string converted_to_services_dbp_file = Directory::vardir + "/yast2-firewall-already-converted-to-sdbp";
// services have been already converted
boolean already_converted = false;
global void ConvertToServicesDefinedByPackages();
/**
* Fills the configuration with default settings,
* adjusts internal variables that firewall cannot be configured.
*/
void FillUpEmptyConfig () {
// do not call it again
configuration_has_been_read = true;
// Default settings, services are disabled
SETTINGS = DEFAULT_SETTINGS;
SETTINGS["enable_firewall"] = false;
SETTINGS["start_firewall"] = false;
// Cannot be configured, packages weren't installed
fw_service_can_be_configured = false;
}
/**
* Function for reading SuSEFirewall configuration.
* Fills internal variables only.
*
* @return boolean if successful
*/
global define boolean Read () {
// Don't fill up the logs with tones of Check-logs
// Turn on for debugging
NetworkInterfaces::report_every_check = false;
// Do not read it again and again
// to avoid rewriting changes already made
if (configuration_has_been_read) {
y2milestone ("SuSEfirewall2 configuration has been read already.");
return fw_service_can_be_configured;
}
// bnc #429861
if (Stage::initial()) {
y2warning ("Stage::initial -> firewall can't be configured.");
FillUpEmptyConfig();
return false;
}
if (! SuSEFirewallIsInstalled()) {
y2warning ("Package not installed, disabling SuSEfirewall2-related functions.");
FillUpEmptyConfig();
return false;
}
// Can be configured, packages were installed
fw_service_can_be_configured = true;
// Progress only for normal configuration
boolean have_progress = (Mode::normal());
if (have_progress) {
// TRANSLATORS: Dialog caption
string read_caption = _("Initializing Firewall Configuration");
Progress::New( read_caption, " ", 4,
[
// TRANSLATORS: Progress step
_("Check for network devices"),
// TRANSLATORS: Progress step
_("Read current configuration"),
// TRANSLATORS: Progress step
_("Check possibly conflicting services"),
// TRANSLATORS: Progress step
_("Read dynamic definitions of installed services"),
],
[
// TRANSLATORS: Progress step
_("Checking for network devices..."),
// TRANSLATORS: Progress step
_("Reading current configuration..."),
// TRANSLATORS: Progress step
_("Checking possibly conflicting services..."),
// TRANSLATORS: Progress step
_("Reading dynamic definitions of installed services..."),
Message::Finished(),
],
""
);
Progress::NextStage();
}
// Always call NI::Read, bnc #396646
NetworkInterfaces::Read();
if (Mode::installation() || Mode::autoinst()) {
// Allways modified for installation, allways save the final state
// fixing bug #67355
// SetModified();
boolean make_parser_happy = true;
}
if (have_progress) Progress::NextStage();
// get default configuration for autoinstallation
// if (Mode::installation() || Mode::autoinst()) {
if (Mode::autoinst()) {
ReadDefaultConfiguration();
// read current configuration for another cases
} else {
ReadCurrentConfiguration();
}
if (have_progress) Progress::NextStage();
// checking if any possibly conficting services were turned on in configuration
// filling internal values for later checkings
// CheckAllPossiblyConflictingServices();
// -- Function has been turned off as we don't support services defined by YaST itself anymore --
y2milestone("Firewall configuration has been read: %1.", SETTINGS);
// to read configuration only once
configuration_has_been_read = true;
if (have_progress) Progress::NextStage();
SuSEFirewallServices::ReadServicesDefinedByRPMPackages();
if (have_progress) Progress::NextStage();
// bnc #399217
// Converting built-in service definitions to services defined by packages
ConvertToServicesDefinedByPackages();
if (have_progress) Progress::Finish();
return true;
}
/**
* Function returns whether some RPC service is allowed in the configuration.
* These services reallocate their ports when restarted. See details in
* bugzilla bug #186186.
*
* @return boolean some_RPC_service_used
*/
boolean AnyRPCServiceInConfiguration () {
boolean ret = false;
foreach (string fw_zone, GetKnownFirewallZones(), {
string fw_rule = sformat("FW_SERVICES_%1_RPC", fw_zone);
string listed_services = SETTINGS[fw_rule]:GetDefaultValue(fw_rule);
// easy case
if (listed_services == nil || listed_services == "") return;
// something listed but it still might be empty definition
list <string> services_list = splitstring (listed_services, " \n\t");
services_list = filter (string service, services_list, {
return (service != "");
});
if (size (listed_services) > 0) {
ret = true;
break;
}
});
y2milestone ("Some RPC service found: %1", ret);
return ret;
}
/**
* Function which stops firewall. Then firewall is started immediately when firewall
* is wanted to be started: SetStartService(boolean).
*
* @return boolean if successful
*/
global define boolean ActivateConfiguration () {
// just disabled
if (! SuSEFirewallIsInstalled()) return true;
// Firewall should start after Write()
if (GetStartService()) {
// Not started - start it
if (!IsStarted()) {
y2milestone("Starting firewall services");
return StartServices();
// Started - restart it
} else {
// modified - restart it, or ...
// bugzilla #186186
// If any RPC service is configured to be allowed, always restart the firewall
// Some of these service's ports might have been reallocated (when SuSEFirewall
// is used from outside, e.g., yast2-nfs-server)
if (GetModified() || AnyRPCServiceInConfiguration()) {
y2milestone("Stopping firewall services");
StopServices();
y2milestone("Starting firewall services");
return StartServices();
// not modified - skip restart
} else {
y2milestone("Configuration hasn't modified, skipping restarting services");
return true;
}
}
// Firewall should stop after Write()
} else {
// started - stop
if (IsStarted()) {
y2milestone("Stopping firewall services");
return StopServices();
// stopped - skip stopping
} else {
y2milestone("Firewall has been stopped already");
return true;
}
}
}
/**
* Function writes configuration into /etc/sysconfig/ and enables or disables
* firewall in /etc/init.d/ by the setting SetEnableService(boolean).
* This is a write-only configuration, firewall is never started only enabled
* or disabled.
*
* @return boolean if successful
*/
global define boolean WriteConfiguration () {
// just disabled
if (! SuSEFirewallIsInstalled()) return true;
// Progress only for normal configuration and command line
boolean have_progress = (Mode::normal());
if (have_progress) {
// TRANSLATORS: Dialog caption
string write_caption = _("Writing Firewall Configuration");
Progress::New( write_caption, " ", 2,
[
// TRANSLATORS: Progress step
_("Write firewall settings"),
// TRANSLATORS: Progress step
_("Adjust firewall service"),
],
[
// TRANSLATORS: Progress step
_("Writing firewall settings..."),
// TRANSLATORS: Progress step
_("Adjusting firewall service..."),
// TRANSLATORS: Progress step
Message::Finished(),
],
""
);
Progress::NextStage();
}
// only modified configuration is written
if (GetModified()) {
y2milestone("Firewall configuration has been changed. Writing: %1.", SETTINGS);
if (! WriteSysconfigSuSEFirewall ( GetListOfSuSEFirewallVariables() )) {
// TRANSLATORS: a popup error message
Report::Error(_("Writing settings failed"));
return false;
}
} else {
y2milestone("Firewall settings weren't modified, skipping...");
}
if (have_progress) Progress::NextStage();
// Adjusting services
if (GetModified()) {
// enabling firewall in /etc/init.d/
if (SETTINGS["enable_firewall"]:false) {
y2milestone("Enabling firewall services");
if (! EnableServices()) {
return false;
}
// disabling firewall in /etc/init.d/
} else {
y2milestone("Disabling firewall services");
if (! DisableServices()) {
return false;
}
}
} else {
y2milestone("Firewall enable/disable wasn't modified, skipping...");
}
if (have_progress) Progress::NextStage();
if (already_converted && ! FileUtils::Exists (converted_to_services_dbp_file)) {
y2milestone ("Writing %1: %2",
converted_to_services_dbp_file,
SCR::Write (.target.string, converted_to_services_dbp_file, "")
);
}
if (have_progress) Progress::Finish();
return true;
}
void CheckKernelModules ();
/**
* Helper function for the backward compatibility.
* See WriteConfiguration(). Remove from code ASAP.
*
* @return boolean if succesful
*/
global define boolean WriteOnly() {
return WriteConfiguration();
}
/**
* Function for writing and enabling configuration it is an union of
* WriteConfiguration() and ActivateConfiguration().
*
* @return boolean if succesfull
*/
global define boolean Write () {
CheckKernelModules();
// just disabled
if (! SuSEFirewallIsInstalled()) return true;
if (! WriteConfiguration()) return false;
if (! ActivateConfiguration()) return false;
return true;
}
/**
* Function for saving configuration and restarting firewall.
* Is is the same as Write() but write is allways forced.
*
* @return boolean if successful
*/
global define boolean SaveAndRestartService () {
y2milestone("Forced save and restart");
SetModified();
SetStartService(true);
if (! Write()) {
return false;
}
return true;
}
/**
* This powerful function returns list of services/ports which are
* not assigned to any fully-supported known-services.
* This function doesn't check for services defined by packages.
* They are listed by a different way.
*
* @return list <string> of additional (unassigned) services
*
* @example
* GetAdditionalServices("TCP", "EXT") -> ["53", "128"]
*/
global define list <string> GetAdditionalServices (string protocol, string zone) {
list <string> additional_services = [];
if (! IsSupportedProtocol(protocol)) {
y2error("Unknown protocol '%1'", protocol);
return nil;
}
if (! IsKnownZone(zone)) {
y2error("Unknown zone '%1'", zone);
return nil;
}
// all ports or services allowed in zone for protocol
list <string> all_allowed_services = GetAllowedServicesForZoneProto(zone, protocol);
// all ports or services used by known service
list <string> all_used_services = [];
// trying all possible (known) services
foreach (string service_id, string service_name, SuSEFirewallServices::GetSupportedServices(), {
// only when the service is allowed in zone - remove all its needed ports
if (IsServiceSupportedInZone(service_id, zone) == true) {
// all needed ports etc for service/protocol
list <string> needed_all = [];
if (protocol == "TCP") {
needed_all = SuSEFirewallServices::GetNeededTCPPorts(service_id);
} else if (protocol == "UDP") {
needed_all = SuSEFirewallServices::GetNeededUDPPorts(service_id);
} else if (protocol == "RPC") {
needed_all = SuSEFirewallServices::GetNeededRPCPorts(service_id);
} else if (protocol == "IP") {
needed_all = SuSEFirewallServices::GetNeededIPProtocols(service_id);
}
foreach (string remove_port, needed_all, {
// all used services and their aliases
all_used_services = (list <string>) union (
all_used_services, PortAliases::GetListOfServiceAliases(remove_port)
);
});
}
});
// some services are used by known defined-services
if (size(all_used_services)>0) {
all_used_services = toset (all_used_services);
// removing all used services from all allowed
all_allowed_services = filter (string port, all_allowed_services, {
return (! contains(all_used_services, port));
});
}
// well, actually it returns list of services not-assigned to any well-known service
return all_allowed_services;
}
/**
* Function sets additional ports/services from taken list. Firstly, all additional services
* are removed also with their aliases. Secondly new ports/protocols are added.
* It uses GetAdditionalServices() function to get the current state and
* then it removes what has been removed and adds what has been added.
*
* @param string protocol
* @param string zone
* @param list <string> list of ports/protocols
* @see GetAdditionalServices()
*
* @example
* SetAdditionalServices ("TCP", "EXT", ["53", "128"])
*/
global define void SetAdditionalServices (string protocol, string zone, list <string> new_list_services) {
list <string> old_list_services = toset(GetAdditionalServices(protocol, zone));
new_list_services = toset(new_list_services);
if (new_list_services != old_list_services) {
SetModified();
list <string> add_services = [];
list <string> remove_services = [];
// Add these services
foreach (string service, new_list_services, {
if (!contains(old_list_services, service))
add_services = add (add_services, service);
});
// Remove these services
foreach (string service, old_list_services, {
if (!contains(new_list_services, service))
remove_services = add (remove_services, service);
});
if (size(remove_services)>0) {
y2milestone("Removing additional services %1/%2 from zone %3", remove_services, protocol, zone);
RemoveAllowedPortsOrServices (remove_services, protocol, zone, true);
}
if (size(add_services)>0) {
y2milestone("Adding additional services %1/%2 into zone %3", add_services, protocol, zone);
AddAllowedPortsOrServices (add_services, protocol, zone);
}
}
}
/**
* Function returns if any other firewall then SuSEfirewall2 is currently running on the
* system. It uses command `iptables` to get information about just active iptables
* rules and compares the output with current status of SuSEfirewall2.
*
* @return boolean if other firewall is running
*/
global define boolean IsOtherFirewallRunning () {
boolean any_firewall_running = true;
// grep must return at least blank lines, else it returns 'exit 1' instead of 'exit 0'
string command = "iptables -L -n | grep -v \"^\\(Chain\\|target\\)\"";
map iptables = (map) SCR::Execute(.target.bash_output, command);
if (iptables["exit"]:0 == 0) {
list <string> iptables_list = splitstring(iptables["stdout"]:"", "\n");
iptables_list = filter (string iptable_rule, iptables_list, {
return iptable_rule != "";
});
y2milestone("Count of active iptables now: %1", size(iptables_list));
// none iptables rules
if (size(iptables_list)>0) {
any_firewall_running = true;
// any iptables rules exist
} else {
any_firewall_running = false;
}
// error running command
} else {
y2error("Services Command: %1 (Exit %2) -> %3", command, iptables["exit"]:nil, iptables["stderr"]:nil);
return nil;
}
// any firewall is running but it is not a SuSEfirewall2
if (any_firewall_running && !IsStarted()) {
y2warning("Any other firewall is running...");
return true;
}
// no firewall is running or the running firewall is SuSEfirewall2
return false;
}
/**
* Function returns map of `interfaces in zones`.
*
* @return map <string, list <string> > interface in zones
*
* @struct map $[zone : [list of interfaces]]
*
* @example
* GetFirewallInterfacesMap() -> $["DMZ":[], "EXT":["dsl0"], "INT":["eth1", "eth2"]]
*/
global define map <string, list <string> > GetFirewallInterfacesMap () {
map <string, list <string> > firewall_interfaces_now = $[];
// list of all known interfaces
list <string> known_interfaces = GetListOfKnownInterfaces();
// searching each zone
foreach (string zone, GetKnownFirewallZones(), {
// filtering non-existing interfaces
firewall_interfaces_now[zone] = filter (string interface, GetInterfacesInZone(zone), {
return contains(known_interfaces, interface);
});
});
return firewall_interfaces_now;
}
/**
* Function returns list of special strings like 'any' or 'auto' and uknown interfaces.
*
* @param string zone
* @return list <string> special strings or unknown interfaces
*
* @example
* GetSpecialInterfacesInZone("EXT") -> ["any", "unknown-1", "wrong-3"]
*/
global define list <string> GetSpecialInterfacesInZone (string zone) {
list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
list <string> known_interfaces_now = GetInterfacesInZone (zone);
// filtering known interfaces and spaces
interfaces_in_zone = filter(string interface, interfaces_in_zone, {
return interface != "" && !contains(known_interfaces_now, interface);
});
return interfaces_in_zone;
}
/**
* Function removes special string from defined zone.
*
* @param string interface
* @param string zone
*/
global define void RemoveSpecialInterfaceFromZone (string interface, string zone) {
SetModified();
y2milestone("Removing special string '%1' from '%2' zone.", interface, zone);
list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
interfaces_in_zone = filter (string single_interface, interfaces_in_zone, {
return single_interface != "" && single_interface != interface;
});
SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
}
/**
* Functions adds special string into defined zone.
*
* @param string interface
* @param string zone
*/
global define void AddSpecialInterfaceIntoZone (string interface, string zone) {
SetModified();
y2milestone("Adding special string '%1' into '%2' zone.", interface, zone);
list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
interfaces_in_zone = toset(add (interfaces_in_zone, interface));
SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
}
/**
* Function returns actual state of Masquerading support.
*
* @return boolean if supported
*/
global define boolean GetMasquerade () {
return (SETTINGS["FW_MASQUERADE"]:"no" == "yes" && SETTINGS["FW_ROUTE"]:"no" == "yes");
}
/**
* Function sets Masquerade support.
*
* @param boolean to support or not to support it
*/
global define void SetMasquerade (boolean enable) {
SetModified();
SETTINGS["FW_MASQUERADE"] = (enable ? "yes" : "no");
// routing is needed for masquerading, but we can't swithc it off when disabling masquerading
if (enable) SETTINGS["FW_ROUTE"] = "yes";
}
/**
* Function returns list of rules of forwarding ports
* to masqueraded IPs.
*
* @return list <map <string, string> > list of rules
*
* @struct list [$[ key: value ]]
*
* @example
* GetListOfForwardsIntoMasquerade() -> [
* $[
* "forward_to":"172.24.233.1",
* "protocol":"tcp",
* "req_ip":"192.168.0.3",
* "req_port":"355",
* "source_net":"192.168.0.0/20",
* "to_port":"533"],
* ...
* ]
*/
global define list <map <string, string> > GetListOfForwardsIntoMasquerade () {
list <map <string, string> > list_of_rules = [];
foreach (string forward_rule, splitstring(SETTINGS["FW_FORWARD_MASQ"]:"", " "), {
if (forward_rule == "") return;
// Format: <source network>,<ip to forward to>,<protocol>,<port>[,redirect port,[destination ip]]
list <string> fw_rul = splitstring(forward_rule,",");
// first four parameters has to be defined
if (fw_rul[0]:"" == "" || fw_rul[1]:"" == "" || fw_rul[2]:"" == "" || fw_rul[3]:"" == "")
y2warning("Wrong definition of redirect rule: '%1', part of '%2'",
forward_rule, SETTINGS["FW_FORWARD_MASQ"]:""
);
list_of_rules = add (list_of_rules, $[
"source_net" : fw_rul[0]:"",
"forward_to" : fw_rul[1]:"",
"protocol" : tolower(fw_rul[2]:""),
"req_port" : tolower(fw_rul[3]:""),
// to_port is req_port when undefined
"to_port" : tolower(fw_rul[4]:fw_rul[3]:""),
"req_ip" : tolower(fw_rul[5]:""),
]);
});
return list_of_rules;
}
/**
* Function removes rule for forwarding into masquerade
* from the list of current rules returned by GetListOfForwardsIntoMasquerade().
*
* @params integer item number
*
* @see GetListOfForwardsIntoMasquerade()
*/
global define void RemoveForwardIntoMasqueradeRule (integer remove_item) {
SetModified();
list <string> forward_rules = [];
integer row_counter = 0;
foreach (string forward_rule, splitstring(SETTINGS["FW_FORWARD_MASQ"]:"", " "), {
if (forward_rule == "") return;
if (row_counter != remove_item) {
forward_rules = add (forward_rules, forward_rule);
}
row_counter = row_counter + 1;
});
SETTINGS["FW_FORWARD_MASQ"] = mergestring(forward_rules, " ");
}
/**
* Adds forward into masquerade rule.
*
* @param string source_net
* @param string forward_to_ip
* @param string protocol
* @param string req_port
* @param string redirect_to_port
* @param string requested_ip
*
* @example
* AddForwardIntoMasqueradeRule ("0/0", "192.168.32.1", "TCP", "80", "8080", "10.0.0.1")
*/
global define void AddForwardIntoMasqueradeRule (
string source_net, string forward_to_ip, string protocol, string req_port,
string redirect_to_port, string requested_ip
) {
SetModified();
string masquerade_rules = SETTINGS["FW_FORWARD_MASQ"]:"";
masquerade_rules = masquerade_rules + (masquerade_rules != "" ? " ":"") +
source_net + "," +
forward_to_ip + "," +
protocol + "," +
req_port;
if (redirect_to_port != "" || requested_ip != "") {
if (requested_ip != "") {
masquerade_rules = masquerade_rules + "," + redirect_to_port + "," + requested_ip;
// port1 -> port2 are same
} else if (redirect_to_port != req_port) {
masquerade_rules = masquerade_rules + "," + redirect_to_port;
}
}
SETTINGS["FW_FORWARD_MASQ"] = masquerade_rules;
}
/**
* Function returns actual state of logging for rule taken as parameter.
*
* @param string rule definition 'ACCEPT' or 'DROP'
* @return string 'ALL', 'CRIT', or 'NONE'
*
* @example
* GetLoggingSettings("ACCEPT") -> "CRIT"
* GetLoggingSettings("DROP") -> "CRIT"
*/
global define string GetLoggingSettings(string rule) {
string ret_val = nil;
if (rule == "ACCEPT") {
if (SETTINGS["FW_LOG_ACCEPT_ALL"]:"no" == "yes") {
ret_val = "ALL";
} else if (SETTINGS["FW_LOG_ACCEPT_CRIT"]:"yes" == "yes") {
ret_val = "CRIT";
} else {
ret_val = "NONE";
}
} else if (rule == "DROP") {
if (SETTINGS["FW_LOG_DROP_ALL"]:"no" == "yes") {
ret_val = "ALL";
} else if (SETTINGS["FW_LOG_DROP_CRIT"]:"yes" == "yes") {
ret_val = "CRIT";
} else {
ret_val = "NONE";
}
} else {
y2error("Possible rules are only 'ACCEPT' or 'DROP'");
}
return ret_val;
}
/**
* Function sets state of logging for rule taken as parameter.
*
* @param string rule definition 'ACCEPT' or 'DROP'
* @param string new logging state 'ALL', 'CRIT', or 'NONE'
*
* @example
* SetLoggingSettings ("ACCEPT", "ALL")
* SetLoggingSettings ("DROP", "NONE")
*/
global define void SetLoggingSettings(string rule, string state) {
SetModified();
if (rule == "ACCEPT") {
if (state == "ALL") {
SETTINGS["FW_LOG_ACCEPT_CRIT"] = "yes";
SETTINGS["FW_LOG_ACCEPT_ALL"] = "yes";
} else if (state == "CRIT") {
SETTINGS["FW_LOG_ACCEPT_CRIT"] = "yes";
SETTINGS["FW_LOG_ACCEPT_ALL"] = "no";
} else {
SETTINGS["FW_LOG_ACCEPT_CRIT"] = "no";
SETTINGS["FW_LOG_ACCEPT_ALL"] = "no";
}
} else if (rule == "DROP") {
if (state == "ALL") {
SETTINGS["FW_LOG_DROP_CRIT"] = "yes";
SETTINGS["FW_LOG_DROP_ALL"] = "yes";
} else if (state == "CRIT") {
SETTINGS["FW_LOG_DROP_CRIT"] = "yes";
SETTINGS["FW_LOG_DROP_ALL"] = "no";
} else {
SETTINGS["FW_LOG_DROP_CRIT"] = "no";
SETTINGS["FW_LOG_DROP_ALL"] = "no";
}
} else {
y2error("Possible rules are only 'ACCEPT' or 'DROP'");
}
}
/**
* Function returns yes/no - ingoring broadcast for zone
*
* @param string zone
* @return string "yes" or "no"
*
* @example
* // Does not logg ignored broadcast packets
* GetIgnoreLoggingBroadcast ("EXT") -> "yes"
*/
global define string GetIgnoreLoggingBroadcast (string zone) {
if (! IsKnownZone(zone)) {
y2error("Unknown zone '%1'", zone);
return nil;
}
return SETTINGS["FW_IGNORE_FW_BROADCAST_" + zone]:"no";
}
/**
* Function sets yes/no - ingoring broadcast for zone
*
* @param string zone
* @param string ignore 'yes' or 'no'
*
* @example
* // Do not log broadcast packetes from DMZ
* SetIgnoreLoggingBroadcast ("DMZ", "yes")
*/
global define void SetIgnoreLoggingBroadcast (string zone, string bcast) {
if (! IsKnownZone(zone)) {
y2error("Unknown zone '%1'", zone);
return nil;
}
SetModified();
SETTINGS["FW_IGNORE_FW_BROADCAST_" + zone] = bcast;
}
/**
* Function adds a special interface 'xenbr+' into the FW_FORWARD_ALWAYS_INOUT_DEV variable.
*
* @see: https://bugzilla.novell.com/show_bug.cgi?id=154133
* @see: https://bugzilla.novell.com/show_bug.cgi?id=233934
* @see: https://bugzilla.novell.com/show_bug.cgi?id=375482
*/
global define void AddXenSupport () {
/*
// xenbr+ works for all bridges
// bridge number is newly dependant on network card number
// eth1 -> xenbr1, eth8 -> xenbr8
string special_xen_interface = "xenbr+";
SetModified();
list <string> allways_inout_dev = splitstring (SETTINGS["FW_FORWARD_ALWAYS_INOUT_DEV"]:"", " ");
allways_inout_dev = toset(add (allways_inout_dev, special_xen_interface));
SETTINGS["FW_FORWARD_ALWAYS_INOUT_DEV"] = mergestring(allways_inout_dev, " ");
y2milestone("FW_FORWARD_ALWAYS_INOUT_DEV -> %1", SETTINGS["FW_FORWARD_ALWAYS_INOUT_DEV"]:"");
*/
y2milestone ("The whole functionality is currently handled by SuSEfirewall2 itself");
}
// Firewall Expert Rulezz
/**
* Returns list of rules describing protocols and ports that are allowed
* to be accessed from listed hosts. All is returned as a single string.
* Zone needs to be defined.
*
* @param string zone
* @return string with rules
*/
global define string GetAcceptExpertRules (string zone) {
zone = toupper(zone);
// Check for zone
if (! contains(GetKnownFirewallZones(), zone)) {
y2error("Unknown firewall zone: %1", zone);
return nil;
}
return SETTINGS["FW_SERVICES_ACCEPT_" + zone]:"";
}
/**
* Sets expert allow rules for zone.
*
* @param string zone
* @param string whitespace-separated expert_rules
* @return boolean if successful
*/
global define boolean SetAcceptExpertRules (string zone, string expert_rules) {
zone = toupper(zone);
// Check for zone
if (! contains(GetKnownFirewallZones(), zone)) {
y2error("Unknown firewall zone: %1", zone);
return false;
}
SETTINGS["FW_SERVICES_ACCEPT_" + zone] = expert_rules;
SetModified();
return true;
}
/**
* Returns list of additional kernel modules, that are loaded by firewall on startup.
* For instance "ip_conntrack_ftp" and "ip_nat_ftp" for FTP service.
*
* @return list <string> of kernel modules
*
* @see /etc/sysconfig/SuSEfirewall2 option nr. 32 (FW_LOAD_MODULES)
*/
global define list <string> GetFirewallKernelModules () {
list <string> k_modules = splitstring (SETTINGS["FW_LOAD_MODULES"]:"", " \t\n");
k_modules = filter (string one_module, k_modules, {
return (one_module != "");
});
return toset (k_modules);
}
/**
* Sets list of additional kernel modules to be loaded by firewall on startup.
*
* @param list <string> of kernel modules
*
* @see /etc/sysconfig/SuSEfirewall2 option nr. 32
*
* @example SuSEFirewall::SetFirewallKernelModules (["ip_conntrack_ftp","ip_nat_ftp"]);
*/
global define void SetFirewallKernelModules (list <string> k_modules) {
k_modules = filter (string one_module, k_modules, {
if (one_module == nil) {
y2error ("List of modules %1 contains 'nil'! It will be ignored.", k_modules);
return false;
} else if (one_module == "") {
y2warning ("List of modules %1 contains an empty string, it will be ignored.", k_modules);
return false;
}
if (regexpmatch (one_module, " ") || regexpmatch (one_module, "\t")) {
y2warning (
"Additional module '%1' contains spaces. They will be evaluated as two or more modules later.",
one_module
);
}
return true;
});
SETTINGS["FW_LOAD_MODULES"] = mergestring (k_modules, " ");
SetModified();
}
map <string, string> protocol_translations = $[
// protocol name
"tcp" : _("TCP"),
// protocol name
"udp" : _("UDP"),
// protocol name
"_rpc_" : _("RPC"),
// protocol name
"ip" : _("IP"),
];
/**
* Returns translated protocol name. Translation is provided from
* SuSEfirewall2 sysconfig format to l10n format.
*
* @param string string from sysconfig (e.g., _rpc_)
* @return string translated string (e.g., RPC)
*/
global string GetProtocolTranslatedName (string protocol) {
protocol = tolower (protocol);
if (protocol == "") {
return "";
} else if (protocol_translations[protocol]:nil == nil) {
y2error ("Unknown protocol: %1", protocol);
// table item, %1 stands for the buggy protocol name
return sformat (_("Unknown protocol (%1)"), protocol);
} else {
return protocol_translations[protocol]:"";
}
}
/**
* Returns list of FW_SERVICES_ACCEPT_RELATED_*: Services to allow that are
* considered RELATED by the connection tracking engine, e.g., SLP browsing
* reply or Samba browsing reply.
*
* @param string zone
* @return list <string> list of definitions
*
* @example
* GetServicesAcceptRelated ("EXT") -> ["0/0,udp,427", "0/0,udp,137"]
*
* @see SetServicesAcceptRelated()
*/
global list <string> GetServicesAcceptRelated (string zone) {
if (! IsKnownZone (zone)) {
y2error ("Uknown zone '%1'", zone);
return [];
}
return splitstring (SETTINGS["FW_SERVICES_ACCEPT_RELATED_" + zone]:"", " \t\n");
}
/**
* Functions sets FW_SERVICES_ACCEPT_RELATED_*: Services to allow that are
* considered RELATED by the connection tracking engine, e.g., SLP browsing
* reply or Samba browsing reply.
*
* @param string zone
* @param list <string> list of rules
*
* @example
* SetServicesAcceptRelated ("EXT", ["0/0,udp,427", "0/0,udp,137"])
*
* @see GetServicesAcceptRelated()
*/
global void SetServicesAcceptRelated (string zone, list <string> ruleset) {
if (! IsKnownZone (zone)) {
y2error ("Uknown zone '%1'", zone);
return;
}
ruleset = filter (string one_rule, ruleset, {
return (one_rule != nil);
});
SetModified();
SETTINGS["FW_SERVICES_ACCEPT_RELATED_" + zone] = mergestring (ruleset, "\n");
}
/**
* Checks whether any Accept-Related rules have been defined.
* If true, required kernel modules are added.
*/
void CheckKernelModules () {
boolean needs_additional_module = false;
foreach (string one_zone, GetKnownFirewallZones(), {
if (size (GetServicesAcceptRelated (one_zone)) >= 0) {
y2milestone ("Some ServicesAcceptRelated are defined");
needs_additional_module = true;
break;
}
});
if (needs_additional_module) {
list <string> k_modules = splitstring (SETTINGS["FW_LOAD_MODULES"]:"", " ");
if (! contains (k_modules, broadcast_related_module)) {
y2warning ("FW_LOAD_MODULES doesn't contain %1, adding", broadcast_related_module);
k_modules = add (k_modules, broadcast_related_module);
SETTINGS["FW_LOAD_MODULES"] = mergestring (k_modules, " ");
SetModified();
}
}
}
/**
* Removes old-service definitions before they are added as services defined
* by packages.
*/
void RemoveOldAllowedServiceFromZone (map <string, any> old_service_def, string zone) {
y2milestone ("Removing: %1 from zone %2", old_service_def, zone);
if (old_service_def["tcp_ports"]:[] != []) {
foreach (string one_service, old_service_def["tcp_ports"]:[], {
RemoveService (one_service, "TCP", zone);
});
}
if (old_service_def["udp_ports"]:[] != []) {
foreach (string one_service, old_service_def["udp_ports"]:[], {
RemoveService (one_service, "UDP", zone);
});
}
if (old_service_def["rpc_ports"]:[] != []) {
foreach (string one_service, old_service_def["rpc_ports"]:[], {
RemoveService (one_service, "RPC", zone);
});
}
if (old_service_def["ip_protocols"]:[] != []) {
foreach (string one_service, old_service_def["ip_protocols"]:[], {
RemoveService (one_service, "IP", zone);
});
}
if (old_service_def["broadcast_ports"]:[] != []) {
map <string, list <string> > broadcast = GetBroadcastAllowedPorts();
broadcast[zone] = filter (string one_port, broadcast[zone]:[], {
return (! contains (old_service_def["broadcast_ports"]:[], one_port));
});
SetBroadcastAllowedPorts (broadcast);
}
}
/**
* Converts old built-in service definitions to services defined by packages.
*
* @see #bnc 399217
*/
global void ConvertToServicesDefinedByPackages () {
if (already_converted) {
return;
}
if (FileUtils::Exists (converted_to_services_dbp_file)) {
y2milestone ("Configuration has been already converted");
already_converted = true;
return;
}
// $[ zone : $[ protocol : [ list of ports ] ] ]
map <string, map <string, list <string> > > current_conf = $[];
foreach (string zone, GetKnownFirewallZones (), {
current_conf[zone] = $[];
foreach (string protocol, supported_protocols, {
current_conf[zone, protocol] = GetAllowedServicesForZoneProto (zone, protocol);
current_conf[zone, "broadcast"] = splitstring (GetBroadcastConfiguration (zone), " \n");
});
});
y2milestone ("Current conf: %1", current_conf);
foreach (string zone, GetKnownFirewallZones (), {
foreach (string old_service_id, map <string, any> old_service_def, SuSEFirewallServices::OLD_SERVICES, {
y2milestone ("Checking %1 in %2 zone", old_service_id, zone);
if (old_service_def["tcp_ports"]:[] != [] && ArePortsOrServicesAllowed (old_service_def["tcp_ports"]:[], "TCP", zone, true) != true)
return;
if (old_service_def["udp_ports"]:[] != [] && ArePortsOrServicesAllowed (old_service_def["udp_ports"]:[], "UDP", zone, true) != true)
return;
if (old_service_def["rpc_ports"]:[] != [] && ArePortsOrServicesAllowed (old_service_def["rpc_ports"]:[], "RPC", zone, false) != true)
return;
if (old_service_def["ip_protocols"]:[] != [] && ArePortsOrServicesAllowed (old_service_def["ip_protocols"]:[], "IP", zone, false) != true)
return;
if (old_service_def["broadcast_ports"]:[] != [] && IsBroadcastAllowed (old_service_def["broadcast_ports"]:[], zone) != true)
return;
if (old_service_def["convert_to"]:[] == []) {
y2milestone ("Service %1 supported, but it doesn't have any replacement", old_service_id);
return;
}
boolean replaced = false;
foreach (string replacement, old_service_def["convert_to"]:[], {
if (SuSEFirewallServices::IsKnownService (replacement)) {
y2milestone ("Old service %1 matches %2", old_service_id, replacement);
RemoveOldAllowedServiceFromZone (old_service_def, zone);
SetServicesForZones ([replacement], [zone], true);
replaced = true;
break;
}
});
if (! replaced) {
y2warning ("Old service %1 matches %2 but none are installed", old_service_id, old_service_def["convert_to"]:[]);
}
});
});
y2milestone ("Converting done");
already_converted = true;
}
// <!-- SuSEFirewall GLOBAL FUNCTIONS //-->
/* EOF */
}
ACC SHELL 2018