home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / modules / SuSEFirewall.ycp < prev    next >
Text File  |  2006-11-29  |  86KB  |  2,752 lines

  1. /**
  2.  * Copyright 2004, Novell, Inc.  All rights reserved.
  3.  *
  4.  * File:    modules/SuSEFirewall.ycp
  5.  * Package:    SuSEFirewall configuration
  6.  * Summary:    Interface manipulation of /etc/sysconfig/SuSEFirewall
  7.  * Authors:    Lukas Ocilka <locilka@suse.cz>
  8.  *
  9.  * $id$
  10.  *
  11.  * Module for handling SuSEfirewall2.
  12.  */
  13.  
  14. {
  15.     module "SuSEFirewall";
  16.     textdomain "base";
  17.  
  18.     import "Mode";
  19.     import "Service";
  20.     import "NetworkDevices";
  21.     import "SuSEFirewallServices";
  22.     import "PortAliases";
  23.     import "Report";
  24.     import "Message";
  25.     import "Progress";
  26.     import "PortRanges";
  27.  
  28.     # <!-- SuSEFirewall VARIABLES //-->
  29.  
  30.     /**
  31.      * configuration hasn't been read for the default
  32.      * this should reduce the readings to only ONE
  33.      */
  34.     boolean configuration_has_been_read = false;
  35.  
  36.     /**
  37.      * String which includes all interfaces not-defined in any zone
  38.      */
  39.     global string special_all_interface_string = "any";
  40.  
  41.     /**
  42.      * Maximal number of port number, they are in the interval 1-65535 included
  43.      */
  44.     global integer max_port_number = PortRanges::max_port_number;
  45.  
  46.     /**
  47.      * Zone which works with the special_all_interface_string string
  48.      */
  49.     global string special_all_interface_zone   = "EXT";
  50.  
  51.     /* firewall settings map */
  52.     map<string, any> SETTINGS = $[];
  53.  
  54.     /* configuration was modified when true */
  55.     boolean modified = false;
  56.  
  57.     /* defines if SuSEFirewall is running */
  58.     boolean is_running = false;
  59.  
  60.     /* default settings for SuSEFirewall */
  61.     map<string, string> DEFAULT_SETTINGS = $[
  62.     "FW_LOG_ACCEPT_ALL"        : "no",
  63.     "FW_LOG_ACCEPT_CRIT"        : "yes",
  64.     "FW_LOG_DROP_ALL"        : "no",
  65.     "FW_LOG_DROP_CRIT"        : "yes",
  66.     "FW_PROTECT_FROM_INT"        : "no",
  67.     "FW_ROUTE"            : "no",
  68.     "FW_MASQUERADE"            : "no",
  69.     "FW_ALLOW_FW_TRACEROUTE"    : "yes",
  70.     "FW_ALLOW_PING_FW"        : "yes",
  71.     "FW_ALLOW_FW_BROADCAST_EXT"    : "no",
  72.     "FW_ALLOW_FW_BROADCAST_INT"    : "no",
  73.     "FW_ALLOW_FW_BROADCAST_DMZ"    : "no",
  74.     "FW_IGNORE_FW_BROADCAST_EXT"    : "yes",
  75.     "FW_IGNORE_FW_BROADCAST_INT"    : "no",
  76.     "FW_IGNORE_FW_BROADCAST_DMZ"    : "no",
  77.     "FW_IPSEC_TRUST"        : "no",
  78.     ];
  79.  
  80.     /* verbose_level -> if verbosity is more than 0, be verbose, starting in verbose mode */
  81.     integer verbose_level = 1;
  82.  
  83.     /* list of known firewall zones */
  84.     list <string> known_firewall_zones = [ "INT", "DMZ", "EXT" ];
  85.  
  86.     /* map defines zone name for all known firewall zones */
  87.     map <string, string> zone_names = $[
  88.     // TRANSLATORS: Firewall zone name - used in combo box or dialog title
  89.     "EXT" : _("External Zone"),
  90.     // TRANSLATORS: Firewall zone name - used in combo box or dialog title
  91.     "INT" : _("Internal Zone"),
  92.     // TRANSLATORS: Firewall zone name - used in combo box or dialog title
  93.     "DMZ" : _("Demilitarized Zone"),
  94.     ];
  95.  
  96.     /* internal zone identification - useful for protect-from-internal */
  97.     string int_zone_shortname = "INT";
  98.  
  99.     /* list of protocols supported in firewall, use only upper-cases */
  100.     list <string> supported_protocols = [ "TCP", "UDP", "RPC", "IP" ];
  101.  
  102.     /* list of keys in map of definition well-known services */
  103.     list <string> service_defined_by = ["tcp_ports", "udp_ports", "rpc_ports", "ip_protocols", "broadcast_ports"];
  104.  
  105.     /* list of services currently allowed, which share ports (for instance RPC services) */
  106.     map <string, list <string> > allowed_conflict_services = $[];
  107.  
  108.     /* services needed for well-running firewall */
  109.     list <string> firewall_services = [ "SuSEfirewall2_init", "SuSEfirewall2_setup" ];
  110.     list <string> firewall_services_reverse = [ "SuSEfirewall2_setup", "SuSEfirewall2_init" ];
  111.  
  112.     list <string> SuSEFirewall_variables = [
  113.     // zones and interfaces
  114.     "FW_DEV_INT", "FW_DEV_DMZ", "FW_DEV_EXT",
  115.  
  116.     // services in zones
  117.     "FW_SERVICES_INT_TCP", "FW_SERVICES_INT_UDP", "FW_SERVICES_INT_RPC", "FW_SERVICES_INT_IP",
  118.     "FW_SERVICES_DMZ_TCP", "FW_SERVICES_DMZ_UDP", "FW_SERVICES_DMZ_RPC", "FW_SERVICES_DMZ_IP",
  119.     "FW_SERVICES_EXT_TCP", "FW_SERVICES_EXT_UDP", "FW_SERVICES_EXT_RPC", "FW_SERVICES_EXT_IP",
  120.     "FW_PROTECT_FROM_INT",
  121.  
  122.     // global routing, masquerading
  123.     "FW_ROUTE", "FW_MASQUERADE", "FW_FORWARD_MASQ", "FW_FORWARD_ALWAYS_INOUT_DEV",
  124.  
  125.     // broadcast packets
  126.     "FW_ALLOW_FW_BROADCAST_EXT", "FW_ALLOW_FW_BROADCAST_INT", "FW_ALLOW_FW_BROADCAST_DMZ",
  127.     "FW_IGNORE_FW_BROADCAST_EXT", "FW_IGNORE_FW_BROADCAST_INT", "FW_IGNORE_FW_BROADCAST_DMZ",
  128.  
  129.     // logging
  130.     "FW_LOG_DROP_CRIT", "FW_LOG_DROP_ALL", "FW_LOG_ACCEPT_CRIT", "FW_LOG_ACCEPT_ALL",
  131.  
  132.     // IPsec support
  133.     "FW_IPSEC_TRUST",
  134.     
  135.     // Custom rulezz
  136.     //     net,protocol[,dport][,sport]
  137.     "FW_SERVICES_ACCEPT_EXT", "FW_SERVICES_ACCEPT_INT", "FW_SERVICES_ACCEPT_DMZ",
  138.     ];
  139.  
  140.     # <!-- SuSEFirewall VARIABLES //-->
  141.  
  142.     # <!-- SuSEFirewall GLOBAL FUNCTIONS USED BY LOCAL ONES //-->
  143.  
  144.     /**
  145.      * Function sets internal variable, which indicates, that any
  146.      * "firewall settings were modified", to "true"
  147.      */
  148.     global define void SetModified () {
  149.     modified = true;
  150.     }
  151.  
  152.     // Please, do not us this function
  153.     // Only for firewall installation proposal
  154.     global define void ResetModified () {
  155.     y2milestone("Reseting firewall-modified to 'false'");
  156.     modified = false;
  157.     }
  158.  
  159.     /**
  160.      * Function returns list of known firewall zones (shortnames)
  161.      *
  162.      * @return    list <string> of firewall zones
  163.      */
  164.     global define list <string> GetKnownFirewallZones () {
  165.     return known_firewall_zones;
  166.     }
  167.  
  168.     global define boolean IsServiceSupportedInZone (string service, string zone);
  169.     global define list <string> GetSpecialInterfacesInZone (string zone);
  170.     global define void AddSpecialInterfaceIntoZone (string interface, string zone);
  171.     
  172.  
  173.     /**
  174.      * Variable for ReportOnlyOnce() function
  175.      */
  176.     list <string> report_only_once = [];
  177.  
  178.     /**
  179.      * Report the error, warning, message only once.
  180.      * Stores the error, warning, message in memory.
  181.      * This is just a helper function that could avoid from filling y2log up with
  182.      * a lot of the very same messages - 'foreach()' is a very powerful builtin.
  183.      *
  184.      * @param string error, warning or message
  185.      * @return boolean whether the message should be reported or not
  186.      *
  187.      * @example
  188.      *    string error = sformat("Port number %1 is invalid.", port_nr);
  189.      *    if (ReportOnlyOnce(error)) y2error(error);
  190.      */
  191.     boolean ReportOnlyOnce (string what_to_report) {
  192.     if (contains(report_only_once, what_to_report)) {
  193.         return false;
  194.     } else {
  195.         report_only_once = add (report_only_once, what_to_report);
  196.         return true;
  197.     }
  198.     }
  199.  
  200.     # <!-- SuSEFirewall GLOBAL FUNCTIONS USED BY LOCAL ONES //-->
  201.  
  202.     # <!-- SuSEFirewall LOCAL FUNCTIONS //-->
  203.  
  204.     /**
  205.      * Function returns whether the feature 'any' network interface is supported in the
  206.      * firewall configuration. The string 'any' must be in the 'EXT' zone.
  207.      *
  208.      * @return boolean is_supported whether the feature is supported or not
  209.      */
  210.     global boolean IsAnyNetworkInterfaceSupported () {
  211.     return contains(GetSpecialInterfacesInZone(special_all_interface_zone), special_all_interface_string);
  212.     }
  213.  
  214.     /**
  215.      * Function return list of variables needed for SuSEFirewall's settings.
  216.      *
  217.      * @return    list <string> of names of variables
  218.      */
  219.     list <string> GetListOfSuSEFirewallVariables () {
  220.     return SuSEFirewall_variables;
  221.     }
  222.  
  223.     /**
  224.      * Local function for increasing the verbosity level.
  225.      */
  226.     void IncreaseVerbosity () {
  227.     verbose_level = verbose_level + 1;
  228.     }
  229.     
  230.     /**
  231.      * Local function for decreasing the verbosity level.
  232.      */
  233.     void DecreaseVerbosity () {
  234.     verbose_level = verbose_level - 1;
  235.     }
  236.  
  237.     /**
  238.      * Local function returns if other functions should produce verbose output.
  239.      * like popups, reporting errors, etc.
  240.      */
  241.     boolean IsVerbose () {
  242.     // verbose level must be above zero to be verbose
  243.     return (verbose_level > 0);
  244.     }
  245.  
  246.     /**
  247.      * Local function for returning default values (if defined) for sysconfig variables.
  248.      *
  249.      * @param    string sysconfig variable
  250.      */
  251.     string GetDefaultValue (string variable) {
  252.     return (string) DEFAULT_SETTINGS[variable]:"";
  253.     }
  254.  
  255.     /**
  256.      * Local function for reading list of sysconfig variables into internal variables.
  257.      *
  258.      * @param    list <string> of sysconfig variables
  259.      */
  260.     void ReadSysconfigSuSEFirewall (list<string> variables) {
  261.     foreach (string variable, variables, {
  262.         string value = (string) SCR::Read(add(.sysconfig.SuSEfirewall2,variable));
  263.         // if variable is undefined, get default value
  264.         if (value == nil || value == "")
  265.         value = GetDefaultValue(variable);
  266.  
  267.         // see bugzilla #194419
  268.  
  269.         // replace all "\n" with " " in variables
  270.         if (regexpmatch(value, "\n"))
  271.         value = mergestring(splitstring(value, "\n"), " ");
  272.         // replace all "\t" with " " in variables
  273.         if (regexpmatch(value, "\t"))
  274.         value = mergestring(splitstring(value, "\t"), " ");
  275.  
  276.         SETTINGS[variable] = value;
  277.     });
  278.     }
  279.  
  280.     /**
  281.      * Local function for reseting list of sysconfig variables in internal variables.
  282.      *
  283.      * @param    list <string> of sysconfig variables
  284.      */
  285.     void ResetSysconfigSuSEFirewall (list<string> variables) {
  286.     foreach (string variable, variables, {
  287.         // reseting means getting default variables
  288.         SETTINGS[variable] = GetDefaultValue(variable);
  289.     });
  290.     }
  291.  
  292.     /**
  293.      * Local function for writing the list of internal variables into sysconfig.
  294.      * List of variables is list of keys in SETTINGS map, to sync configuration
  295.      * into the disk, use `nil` as the last list item.
  296.      *
  297.      * @param    list <string> of sysconfig variables
  298.      */
  299.     boolean WriteSysconfigSuSEFirewall (list<string> variables) {
  300.     boolean write_status = true;
  301.  
  302.     foreach (string variable, variables, {
  303.         write_status = (boolean) SCR::Write(
  304.         add(.sysconfig.SuSEfirewall2,variable),
  305.         // if variable is undefined, get default value
  306.         SETTINGS[variable]:GetDefaultValue(variable)
  307.         );
  308.  
  309.         if (! write_status) {
  310.         Report::Error(Message::CannotWriteSettingsTo("/etc/sysconfig/SuSEFirewall"));
  311.         break;
  312.         }
  313.     });
  314.  
  315.     write_status = SCR::Write(.sysconfig.SuSEfirewall2, nil);
  316.     if (! write_status) {
  317.         Report::Error(Message::CannotWriteSettingsTo("/etc/sysconfig/SuSEFirewall"));
  318.     }
  319.  
  320.     return write_status;
  321.     }
  322.  
  323.     /**
  324.      * Local function returns if protocol is supported by firewall.
  325.      * Protocol name must be in upper-cases.
  326.      *
  327.      * @param    string protocol
  328.      * @return    boolean if protocol is supported
  329.      */
  330.     boolean IsSupportedProtocol (string protocol) {
  331.     return contains(supported_protocols, protocol);
  332.     }
  333.  
  334.     /**
  335.      * Local function returns if zone (shortname like "EXT") is supported by firewall.
  336.      * Undefined zones are, for sure, unsupported.
  337.      *
  338.      * @param    string zone shortname
  339.      * @return    boolean if zone is known and supported.
  340.      */
  341.     boolean IsKnownZone (string zone) {
  342.     boolean is_zone = false;
  343.  
  344.     foreach (string known_zone, GetKnownFirewallZones(), {
  345.         if (known_zone == zone) {
  346.         is_zone = true;
  347.         break;
  348.         }
  349.     });
  350.  
  351.     return is_zone;
  352.     }
  353.  
  354.     /**
  355.      * Local function returns configuration string used in configuration for zone.
  356.      * For instance "ext" for "EXT" zone.
  357.      *
  358.      * @param    string zone shortname
  359.      * @return    string zone configuration string
  360.      */
  361.     string GetZoneConfigurationString (string zone) {
  362.     if (IsKnownZone(zone)) {
  363.         // zones in SuSEFirewall configuration are identified by lowercased zone shorters
  364.         return tolower(zone);
  365.     }
  366.     return nil;
  367.     }
  368.  
  369.     /**
  370.      * Local function returns zone name (shortname) for configuration string.
  371.      * For instance "EXT" for "ext" zone.
  372.      *
  373.      * @param    string zone configuration string
  374.      * @return    string zone shortname
  375.      */
  376.     string GetConfigurationStringZone (string zone_string) {
  377.     if (IsKnownZone(toupper(zone_string))) {
  378.         // zones in SuSEFirewall configuration are identified by lowercased zone shorters
  379.         return toupper(zone_string);
  380.     }
  381.     return nil;
  382.     }
  383.  
  384.     /**
  385.      * Function returns list of allowed services for zone and protocol
  386.      *
  387.      * @param    string zone
  388.      * @param    string protocol
  389.      * @return    list <string> of allowed services/ports
  390.      */
  391.     list <string> GetAllowedServicesForZoneProto (string zone, string protocol) {
  392.     return splitstring(SETTINGS["FW_SERVICES_" + zone + "_" + protocol]:"", " ");
  393.     }
  394.  
  395.     /**
  396.      * Function sets list of services as allowed ports for zone and protocol
  397.      *
  398.      * @param    list <string> of allowed ports/services
  399.      * @param    string zone
  400.      * @param    string protocol
  401.      */
  402.     void SetAllowedServicesForZoneProto (list <string> allowed_services, string zone, string protocol) {
  403.     SetModified();
  404.  
  405.     SETTINGS["FW_SERVICES_" + zone + "_" + protocol] = mergestring (toset(allowed_services), " ");
  406.     }
  407.  
  408.     /**
  409.      * Local function returns configuration string for broadcast packets.
  410.      *
  411.      * @return    string with broadcast configuration
  412.      */
  413.     string GetBroadcastConfiguration (string zone) {
  414.  
  415.     return SETTINGS["FW_ALLOW_FW_BROADCAST_" + zone]:"no";
  416.     }
  417.  
  418.     /**
  419.      * Local function saves configuration string for broadcast packets.
  420.      *
  421.      * @param    string with broadcast configuration
  422.      */
  423.     void SetBroadcastConfiguration (string zone, string broadcast_configuration) {
  424.     SetModified();
  425.  
  426.     SETTINGS["FW_ALLOW_FW_BROADCAST_" + zone] = broadcast_configuration;
  427.     }
  428.  
  429.     /**
  430.      * Local function return map of allowed ports (without aliases).
  431.      * If any list for zone is defined but empty, all allowed
  432.      * UDP ports for this zone also accept broadcast packets.
  433.      *
  434.      * @return    map <zone, list <string> > strings are allowed ports or port ranges
  435.      */
  436.     global define map <string, list <string> > GetBroadcastAllowedPorts () {
  437.  
  438.     map <string, list <string> > allowed_ports = $[];
  439.  
  440.     foreach (string zone, GetKnownFirewallZones(), {
  441.         string broadcast = GetBroadcastConfiguration(zone);
  442.         // no broadcast allowed for this zone
  443.         if (broadcast == "no") {
  444.         allowed_ports[zone] = [];
  445.         // all UDP port allowed in zone also allow broadcast
  446.         } else if (broadcast == "yes") {
  447.         allowed_ports[zone] = GetAllowedServicesForZoneProto (zone, "UDP");
  448.         // only listed ports allows broadcast
  449.         } else {
  450.         allowed_ports[zone] = splitstring(broadcast, " ");
  451.         allowed_ports[zone] = filter (string not_space, splitstring(broadcast, " "), {
  452.             return not_space != "";
  453.         });
  454.         }
  455.     });
  456.  
  457.     y2debug("Allowed Broadcast Ports: %1", allowed_ports);
  458.  
  459.     return allowed_ports;
  460.     }
  461.  
  462.     /**
  463.      * Function creates allowed-broadcast-ports string from broadcast map and saves it.
  464.      *
  465.      * @param    map <zone_string, list <string> > strings are allowed ports or port ranges
  466.      */
  467.     global define void SetBroadcastAllowedPorts (map <string, list <string> > broadcast) {
  468.     SetModified();
  469.  
  470.     foreach (string zone, GetKnownFirewallZones(), {
  471.         SetBroadcastConfiguration(zone, mergestring(broadcast[zone]:[], " "));
  472.     });
  473.     }
  474.  
  475.     /**
  476.      * Function returns if broadcast is allowed for needed ports in zone.
  477.      *
  478.      * @param    list <string> ports
  479.      * @param    string zone
  480.      * @return    boolean if is allowed
  481.      */
  482.     boolean IsBroadcastAllowed (list <string> needed_ports, string zone) {
  483.     if (size(needed_ports)==0) {
  484.         y2warning("Unknown service with no needed ports!");
  485.         return nil;
  486.     }
  487.  
  488.     // getting broadcast allowed ports
  489.     map <string, list <string> > allowed_ports_map = GetBroadcastAllowedPorts();
  490.  
  491.     // Divide allowed port ranges and aliases (also with their port aliases)
  492.     map <string, list <string> > allowed_ports_divided = PortRanges::DividePortsAndPortRanges (
  493.         allowed_ports_map[zone]:[], true
  494.     );
  495.  
  496.     // If there are no allowed ports at all
  497.     if (allowed_ports_divided["ports"]:[] == [] && allowed_ports_divided["port_ranges"]:[] == []) {
  498.         return false;
  499.     }
  500.     // clean up the memory a bit
  501.     allowed_ports_map = nil;
  502.  
  503.     boolean is_allowed = true;
  504.     // checking all needed ports;
  505.     foreach (string needed_port, needed_ports, {
  506.         // allowed ports don't contain the needed one and also portranges don't
  507.         if (
  508.         !contains (allowed_ports_divided["ports"]:[], needed_port) &&
  509.         !PortRanges::PortIsInPortranges (needed_port, allowed_ports_divided["port_ranges"]:[])
  510.         ) {
  511.         is_allowed = false;
  512.         break;
  513.         }
  514.     });
  515.  
  516.     return is_allowed;
  517.     }
  518.  
  519.     /**
  520.      * Local function removes list of ports from port allowing broadcast packets in zone.
  521.      *
  522.      * @param    list <of ports> to be removed
  523.      * @param    string zone
  524.      */
  525.     void RemoveAllowedBroadcast (list <string> needed_ports, string zone) {
  526.     SetModified();
  527.  
  528.     map <string, list <string> > allowed_ports = GetBroadcastAllowedPorts();
  529.     list <string> list_ports_allowed = allowed_ports[zone]:[];
  530.  
  531.     // ports to be allowed one by one
  532.     foreach (string allow_this_port, needed_ports, {
  533.         // remove all aliases of ports yet mentioned in zone
  534.         list <string> aliases_of_port = PortAliases::GetListOfServiceAliases(allow_this_port);
  535.         list_ports_allowed = filter (string just_allowed, list_ports_allowed, {
  536.             return (! contains(aliases_of_port, just_allowed));
  537.         });
  538.     });
  539.     allowed_ports[zone] = list_ports_allowed;
  540.  
  541.     // save it using function
  542.     SetBroadcastAllowedPorts(allowed_ports);
  543.     }
  544.  
  545.     /**
  546.      * Local function adds list of ports to ports accepting broadcast
  547.      *
  548.      * @param    list <string> of ports
  549.      */
  550.     void AddAllowedBroadcast (list <string> needed_ports, string zone) {
  551.     // changing only if ports are not allowed
  552.     if (! IsBroadcastAllowed (needed_ports, zone)) {
  553.         SetModified();
  554.  
  555.         map <string, list <string> > allowed_ports = GetBroadcastAllowedPorts();
  556.         list <string> list_ports_allowed = allowed_ports[zone]:[];
  557.  
  558.         // ports to be allowed one by one
  559.         foreach (string allow_this_port, needed_ports, {
  560.         // at first: remove all aliases of ports yet mentioned in zone
  561.         list <string> aliases_of_port = PortAliases::GetListOfServiceAliases(allow_this_port);
  562.         list_ports_allowed = filter (string just_allowed, list_ports_allowed, {
  563.             return (! contains(aliases_of_port, just_allowed));
  564.         });
  565.         // at second: add only one
  566.         list_ports_allowed = add(list_ports_allowed, allow_this_port);
  567.         });
  568.         allowed_ports[zone] = list_ports_allowed;
  569.  
  570.         // save it using function
  571.         SetBroadcastAllowedPorts(allowed_ports);
  572.     }
  573.     }
  574.  
  575.     /**
  576.      * Local function for removing (disallowing) single service/port
  577.      * for defined protocol and zone. Functions doesn't take care of
  578.      * port-aliases.
  579.      *
  580.      * @param    string service/port
  581.      * @param    string protocol
  582.      * @param    string zone
  583.      * @return    boolean success
  584.      */
  585.     boolean RemoveServiceFromProtocolZone(string remove_service, string protocol, string zone) {
  586.     SetModified();
  587.  
  588.     string key = "FW_SERVICES_" + zone + "_" + protocol;
  589.  
  590.     list <string> allowed = splitstring(SETTINGS[key]:"", " ");
  591.     allowed = filter (string single_service, allowed, {
  592.         return single_service != "" && single_service != remove_service;
  593.     });
  594.     SETTINGS[key] = mergestring(toset(allowed), " ");
  595.  
  596.     return true;
  597.     }
  598.  
  599.     /**
  600.      * Local function removes ports and their aliases (if check_for_aliases is true), for
  601.      * requested protocol and zone.
  602.      *
  603.      * @param    list <string> ports to be removed
  604.      * @param    string protocol
  605.      * @param    string zone
  606.      * @param    boolean check for port-aliases
  607.      */
  608.     void RemoveAllowedPortsOrServices (list <string> remove_ports, string protocol, string zone, boolean check_for_aliases) {
  609.     if (size(remove_ports)<1) {
  610.         y2warning("Undefined list of %1 services/ports for service", protocol);
  611.         return;
  612.     }
  613.  
  614.     SetModified();
  615.  
  616.     // all allowed ports
  617.     map <string, list <string> > allowed_services = PortRanges::DividePortsAndPortRanges (
  618.         GetAllowedServicesForZoneProto (zone, protocol), false
  619.     );
  620.  
  621.     // removing all aliases of ports too, adding aliases into
  622.     if (check_for_aliases) {
  623.         list <string> remove_ports_with_aliases = [];
  624.         foreach (string remove_port, remove_ports, {
  625.         // skip port ranges, they cannot have any port-alias
  626.         if (PortRanges::IsPortRange (remove_port)) {
  627.             remove_ports_with_aliases = add (remove_ports_with_aliases, remove_port);
  628.             return;
  629.         }
  630.         list <string> remove_these_ports = PortAliases::GetListOfServiceAliases(remove_port);
  631.         if (remove_these_ports == nil) { remove_these_ports = [ remove_port ]; }
  632.         remove_ports_with_aliases = (list<string>) union (remove_ports_with_aliases,
  633.             remove_these_ports
  634.         );
  635.         });
  636.         remove_ports = remove_ports_with_aliases;
  637.         
  638.     }
  639.     remove_ports = toset(remove_ports);
  640.  
  641.     // Remove ports only once (because of port aliases), any => integers and strings
  642.     list <any> already_removed = [];
  643.  
  644.     foreach (string remove_port, remove_ports, {
  645.         // Removing from normal ports
  646.         allowed_services["ports"] = filter (string allowed_port, allowed_services["ports"]:[], {
  647.         return allowed_port != "" && allowed_port != remove_port;
  648.         });
  649.  
  650.         // Removing also from port ranges
  651.         if (allowed_services["port_ranges"]:[] != []) {
  652.         // Removing a real port from port ranges
  653.         if (! PortRanges::IsPortRange (remove_port)) {
  654.             integer remove_port_nr = PortAliases::GetPortNumber(remove_port);
  655.             // Because of all port aliases
  656.             if (!contains(already_removed, remove_port_nr)) {
  657.             already_removed = add (already_removed, remove_port_nr);
  658.             allowed_services["port_ranges"] = PortRanges::RemovePortFromPortRanges (
  659.                 remove_port_nr, allowed_services["port_ranges"]:[]
  660.             );
  661.             }
  662.         // Removing a port range from port ranges
  663.         } else {
  664.             if (!contains(already_removed, remove_port)) {
  665.             // Just filtering the exact port range
  666.             allowed_services["port_ranges"] = filter (string one_port_range, allowed_services["port_ranges"]:[], {
  667.                 return one_port_range != remove_port;
  668.             });
  669.             already_removed = add (already_removed, remove_port);
  670.             }
  671.         }
  672.         }
  673.     });
  674.     
  675.     list <string> allowed_services_all = (list <string>) union (
  676.         allowed_services["ports"]:[],
  677.         allowed_services["port_ranges"]:[]
  678.     );
  679.     allowed_services_all = PortRanges::FlattenServices (allowed_services_all, protocol);
  680.     
  681.     SetAllowedServicesForZoneProto (allowed_services_all, zone, protocol);
  682.     }
  683.  
  684.     /**
  685.      * Local function allows ports for requested protocol and zone.
  686.      *
  687.      * @param    list <string> ports to be added
  688.      * @param    string protocol
  689.      * @param    string zone
  690.      */
  691.     void AddAllowedPortsOrServices (list <string> add_ports, string protocol, string zone) {
  692.     if (size(add_ports)<1) {
  693.         y2warning("Undefined list of %1 services/ports for service", protocol);
  694.         return;
  695.     }
  696.  
  697.     SetModified();
  698.  
  699.     // all allowed ports
  700.     list <string> allowed_services = GetAllowedServicesForZoneProto (zone, protocol);
  701.  
  702.     allowed_services = (list<string>) union (allowed_services, add_ports);
  703.     allowed_services = PortRanges::FlattenServices (allowed_services, protocol);
  704.  
  705.     SetAllowedServicesForZoneProto (allowed_services, zone, protocol);
  706.     }
  707.  
  708.     /**
  709.      * Local function removes well-known service's support from zone.
  710.      * Allowed ports are removed with all of their port-aliases.
  711.      *
  712.      * @param    string service id
  713.      * @param    string zone
  714.      */
  715.     void RemoveServiceSupportFromZone (string service, string zone) {
  716.     map <string, list <string> > needed = SuSEFirewallServices::GetNeededPortsAndProtocols(service);
  717.     // unknown service
  718.     if (needed == nil) {
  719.         y2error("Undefined service '%1'", service);
  720.         return nil;
  721.     }
  722.  
  723.     SetModified();
  724.  
  725.     // Removing service ports (and also port aliases for TCP and UDP)
  726.     foreach (string key, service_defined_by, {
  727.         list <string> needed_ports = needed[key]:[];
  728.         if (needed_ports == []) return;
  729.  
  730.         if (key == "tcp_ports") {
  731.         RemoveAllowedPortsOrServices(needed_ports, "TCP", zone, true);
  732.         } else if (key == "udp_ports") {
  733.         RemoveAllowedPortsOrServices(needed_ports, "UDP", zone, true);
  734.         } else if (key == "rpc_ports") {
  735.         RemoveAllowedPortsOrServices(needed_ports, "RPC", zone, false);
  736.         } else if (key == "ip_protocols") {
  737.         RemoveAllowedPortsOrServices(needed_ports, "IP", zone, false);
  738.         } else if ("broadcast_ports" == key) {
  739.         RemoveAllowedBroadcast(needed_ports, zone);
  740.         } else {
  741.         y2error("Unknown key '%1'", key);
  742.         }
  743.     });
  744.     }
  745.  
  746.     /**
  747.      * Local function adds well-known service's support into zone. It first of all
  748.      * removes the current support for service with port-aliases.
  749.      *
  750.      * @param    string service id
  751.      * @param    string zone
  752.      */
  753.     void AddServiceSupportIntoZone (string service, string zone) {
  754.     map <string, list <string> > needed = SuSEFirewallServices::GetNeededPortsAndProtocols(service);
  755.     // unknown service
  756.     if (needed == nil) {
  757.         y2error("Undefined service '%1'", service);
  758.         return nil;
  759.     }
  760.  
  761.     SetModified();
  762.  
  763.     // Removing service ports first (and also port aliases for TCP and UDP)
  764.     if (IsServiceSupportedInZone(service,zone)) {
  765.         RemoveServiceSupportFromZone(service,zone);
  766.     }
  767.  
  768.     foreach (string key, service_defined_by, {
  769.         list <string> needed_ports = needed[key]:[];
  770.         if (needed_ports == []) return;
  771.  
  772.         if (key == "tcp_ports") {
  773.         AddAllowedPortsOrServices(needed_ports, "TCP", zone);
  774.         } else if (key == "udp_ports") {
  775.         AddAllowedPortsOrServices(needed_ports, "UDP", zone);
  776.         } else if (key == "rpc_ports") {
  777.         AddAllowedPortsOrServices(needed_ports, "RPC", zone);
  778.         } else if (key == "ip_protocols") {
  779.         AddAllowedPortsOrServices(needed_ports, "IP", zone);
  780.         } else if ("broadcast_ports" == key) {
  781.         AddAllowedBroadcast(needed_ports, zone);
  782.         } else {
  783.         y2error("Unknown key '%1'", key);
  784.         }
  785.     });
  786.     }
  787.  
  788.     /**
  789.      * Local function returns conflicting services.
  790.      *
  791.      * @return    list <string> of services
  792.      */
  793.     list <string> GetPossiblyConflictServices () {
  794.     return SuSEFirewallServices::GetPossiblyConflictServices();
  795.     }
  796.  
  797.     /**
  798.      * Local function for handling conflicting services in memory.
  799.      * Makes sense for services which share ports like RPC services.
  800.      *
  801.      * @param    string service id
  802.      * @param    boolean enable or disable
  803.      */
  804.     void HandleConflictService(string service, string zone, boolean enable) {
  805.     // only possibly conflict services are handled
  806.     if (! contains(GetPossiblyConflictServices(), service)) return;
  807.  
  808.     SetModified();
  809.  
  810.     if (enable) {
  811.         // adding new conflict service into list of allowed services
  812.         allowed_conflict_services[zone] = toset(add(allowed_conflict_services[zone]:[], service));
  813.     } else {
  814.         // removing current conflict service from list
  815.         allowed_conflict_services[zone] = filter(string filter_service, allowed_conflict_services[zone]:[], {
  816.         return filter_service != service;
  817.         });
  818.         // adding all allowed conflict services again
  819.         foreach (string conflict_service, allowed_conflict_services[zone]:[], {
  820.         AddServiceSupportIntoZone (conflict_service, zone);
  821.         });
  822.     }
  823.     }
  824.  
  825.     # <!-- SuSEFirewall LOCAL FUNCTIONS //-->
  826.  
  827.     # <!-- SuSEFirewall GLOBAL FUNCTIONS //-->
  828.  
  829.     /**
  830.      * Functions returns if any firewall's configuration was modified
  831.      * or wasn't
  832.      *
  833.      * @return    boolean if the configuration was modified
  834.      */
  835.     global define boolean GetModified () {
  836.     return modified;
  837.     }
  838.  
  839.     /**
  840.      * Function resets flag which doesn't allow to read configuration from disk again
  841.      */
  842.     global define void ResetReadFlag () {
  843.     configuration_has_been_read = false;
  844.     }
  845.  
  846.     /**
  847.      * Function returns name of the zone identified by zone shortname.
  848.      *
  849.      * @param    string short name
  850.      * @return    string zone name
  851.      */
  852.     global define string GetZoneFullName (string zone) {
  853.     // TRANSLATORS: Firewall zone full-name, used as combo box item or dialog title
  854.     return zone_names[zone]:_("Unknown Zone");
  855.     }
  856.  
  857.     /**
  858.      * Function sets if firewall should be protected from internal zone.
  859.      *
  860.      * @param    boolean set to be protected from internal zone
  861.      */
  862.     global define void SetProtectFromInternalZone (boolean set_protect) {
  863.     SetModified();
  864.  
  865.     if (set_protect) {
  866.         SETTINGS["FW_PROTECT_FROM_INT"] = "yes";
  867.     } else {
  868.         SETTINGS["FW_PROTECT_FROM_INT"] = "no";
  869.     }
  870.     }
  871.  
  872.     /**
  873.      * Function returns if firewall is protected from internal zone
  874.      *
  875.      * @return    boolean if protected from internal
  876.      */
  877.     global define boolean GetProtectFromInternalZone () {
  878.     return (SETTINGS["FW_PROTECT_FROM_INT"]:"no" == "yes");
  879.     }
  880.  
  881.     /**
  882.      * Function sets if firewall should support routing.
  883.      *
  884.      * @param    boolean set to support route or not
  885.      */
  886.     global define void SetSupportRoute (boolean set_route) {
  887.     SetModified();
  888.  
  889.     if (set_route) {
  890.         SETTINGS["FW_ROUTE"] = "yes";
  891.     } else {
  892.         SETTINGS["FW_ROUTE"] = "no";
  893.     }
  894.     }
  895.  
  896.     /**
  897.      * Function returns if firewall supports routing.
  898.      *
  899.      * @return    boolean if route is supported
  900.      */
  901.     global define boolean GetSupportRoute () {
  902.     return (SETTINGS["FW_ROUTE"]:"no" == "yes");
  903.     }
  904.  
  905.     /**
  906.      * Function sets how firewall should trust successfully decrypted IPsec packets.
  907.      * It should be the zone name (shortname) or 'no' to trust packets the same as
  908.      * firewall trusts the zone from which IPsec packet came.
  909.      *
  910.      * @param    string zone or "no"
  911.      */
  912.     global define void SetTrustIPsecAs (string zone) {
  913.     SetModified();
  914.  
  915.     // do not trust
  916.     if (zone == "no") {
  917.         SETTINGS["FW_IPSEC_TRUST"] = "no";
  918.     } else {
  919.         // trust IPsec is a known zone
  920.         if (IsKnownZone(zone)) {
  921.         zone = GetZoneConfigurationString(zone);
  922.         SETTINGS["FW_IPSEC_TRUST"] = zone;
  923.         // unknown zone, changing to default value
  924.         } else {
  925.         string defaultv = GetDefaultValue("FW_IPSEC_TRUST");
  926.         y2warning("Trust IPsec as '%1' (unknown zone) changed to '%2'", zone, defaultv);
  927.         SETTINGS["FW_IPSEC_TRUST"] = defaultv;
  928.         }
  929.     }
  930.     }
  931.  
  932.     /**
  933.      * Function returns the trust level of IPsec packets.
  934.      * See SetTrustIPsecAs() for more information.
  935.      *
  936.      * @return    string zone or "no"
  937.      */
  938.     global define string GetTrustIPsecAs () {
  939.     // do not trust
  940.     if (SETTINGS["FW_IPSEC_TRUST"]:nil == "no") {
  941.         return "no";
  942.     // default value for 'yes" ~= "INT"
  943.     } else if (SETTINGS["FW_IPSEC_TRUST"]:nil == "yes") {
  944.         return "INT";
  945.     } else {
  946.         string zone = GetConfigurationStringZone(SETTINGS["FW_IPSEC_TRUST"]:"");
  947.         // trust as named zone (if known)
  948.         if (IsKnownZone(zone)) {
  949.         return zone;
  950.         // unknown zone, change to default value
  951.         } else {
  952.         SetModified();
  953.         string defaultv = GetDefaultValue("FW_IPSEC_TRUST");
  954.         y2warning("Trust IPsec as '%1' (unknown zone) changed to '%2'", SETTINGS["FW_IPSEC_TRUST"]:"", defaultv);
  955.         SetTrustIPsecAs(defaultv);
  956.         return "no";
  957.         }
  958.     }
  959.     }
  960.  
  961.     /**
  962.      * Function which returns if SuSEfirewall should start in Write process
  963.      *
  964.      * @return    boolean if the firewall should start
  965.      */
  966.     global define boolean GetStartService () {
  967.     return (boolean) SETTINGS["start_firewall"]:false;
  968.     }
  969.  
  970.     /**
  971.      * Function which sets if SuSEfirewall should start in Write process
  972.      *
  973.      * @param    boolean start_service at Write() process
  974.      */
  975.     global define void SetStartService (boolean start_service) {
  976.     if (GetStartService() != start_service) {
  977.         SetModified();
  978.  
  979.         y2milestone("Setting start-firewall to %1", start_service);
  980.         SETTINGS["start_firewall"] = start_service;
  981.     } else {
  982.         // without set modified!
  983.         y2milestone("start-firewall has been already set to %1", start_service);
  984.         SETTINGS["start_firewall"] = start_service;
  985.     }
  986.     }
  987.  
  988.     /**
  989.      * Function which returns whether SuSEfirewall should be enabled in
  990.      * /etc/init.d/ starting scripts during the Write() process
  991.      * @see Write()
  992.      * @see EnableServices()
  993.      *
  994.      * @return    boolean if the firewall should start
  995.      */
  996.     global define boolean GetEnableService () {
  997.     return (boolean) SETTINGS["enable_firewall"]:false;
  998.     }
  999.  
  1000.     /**
  1001.      * Function which sets if SuSEfirewall should start in Write process
  1002.      *
  1003.      * @param    boolean start_service at Write() process
  1004.      */
  1005.     global define void SetEnableService (boolean enable_service) {
  1006.     if (GetEnableService() != enable_service) {
  1007.         SetModified();
  1008.     
  1009.         y2milestone("Setting enable-firewall to %1", enable_service);
  1010.         SETTINGS["enable_firewall"] = enable_service;
  1011.     } else {
  1012.         // without set modified
  1013.         y2milestone("enable-firewall has been already set to %1", enable_service);
  1014.         SETTINGS["enable_firewall"] = enable_service;
  1015.     }
  1016.     }
  1017.  
  1018.     /**
  1019.      * Functions starts services needed for SuSEFirewall
  1020.      *
  1021.      * @return    boolean result
  1022.      */
  1023.     global define boolean StartServices () {
  1024.     boolean all_ok = true;
  1025.  
  1026.     // bug #215416
  1027.     // SuSEfirewall2_init doesn't need to be called, only enabled
  1028.     //foreach (string service, firewall_services, {
  1029.     //    y2debug("Starting service: %1", service);
  1030.     //
  1031.     //    if (! Service::Start(service)) {
  1032.     //    all_ok = false;
  1033.     //    y2error("Error starting service: %1", service);
  1034.     //    } 
  1035.     //});
  1036.  
  1037.     //string tmpdir_file = (string) SCR::Read(.target.tmpdir);
  1038.     //if (tmpdir_file == nil || tmpdir_file == "") tmpdir_file = "/tmp";
  1039.  
  1040.     string tmpdir_file = "/var/lib/YaST2";
  1041.     tmpdir_file = tmpdir_file + "/SuSEfirewall2_YaST_output";
  1042.     string command = sformat(
  1043.         "/sbin/SuSEfirewall2 start 2>'%1'; cat '%1'; rm -rf '%1'",
  1044.         tmpdir_file
  1045.     );
  1046.     y2milestone ("Starting firewall...");
  1047.     map cmd = (map) SCR::Execute (.target.bash_output, command);
  1048.     if (cmd["exit"]:nil != 0) {
  1049.         y2error ("Starting firewall: >%1< returned %2", command, cmd);
  1050.         all_ok = false;
  1051.     } else {
  1052.         y2milestone ("Started");
  1053.     }
  1054.     
  1055.     return all_ok;
  1056.     }
  1057.  
  1058.     /**
  1059.      * Functions stops services needed for SuSEFirewall
  1060.      *
  1061.      * @return    boolean result
  1062.      */
  1063.     global define boolean StopServices () {
  1064.     boolean all_ok = true;
  1065.  
  1066.     // bug #215416
  1067.     // SuSEfirewall2_init doesn't need to be called, only disabled
  1068.     //foreach (string service, firewall_services_reverse, {
  1069.     //    y2debug("Stopping service: %1", service);
  1070.     //
  1071.     //    if (! Service::Stop (service)) {
  1072.     //    y2error("Error stopping service: %1", service);
  1073.     //    all_ok = false;
  1074.     //    }
  1075.     //});
  1076.  
  1077.     // string tmpdir_file = (string) SCR::Read(.target.tmpdir);
  1078.     // if (tmpdir_file == nil || tmpdir_file == "") tmpdir_file = "/tmp";
  1079.  
  1080.     string tmpdir_file = "/var/lib/YaST2";
  1081.     tmpdir_file = tmpdir_file + "/SuSEfirewall2_YaST_output";
  1082.     string command = sformat(
  1083.         "/sbin/SuSEfirewall2 stop 2>'%1'; cat '%1'; rm -rf '%1'",
  1084.         tmpdir_file
  1085.     );
  1086.     y2milestone ("Stopping firewall...");
  1087.     map cmd = (map) SCR::Execute (.target.bash_output, command);
  1088.     if (cmd["exit"]:nil != 0) {
  1089.         y2error ("Stopping firewall: >%1< returned %2", command, cmd);
  1090.         all_ok = false;
  1091.     } else {
  1092.         y2milestone ("Stopped");
  1093.     }
  1094.  
  1095.     return all_ok;
  1096.     }
  1097.  
  1098.     /**
  1099.      * Functions enables services needed for SuSEFirewall in /etc/inet.d/
  1100.      *
  1101.      * @return    boolean result
  1102.      */
  1103.     global define boolean EnableServices () {
  1104.     boolean all_ok = true;
  1105.  
  1106.     foreach (string service, firewall_services, {
  1107.         y2debug("Enabling service: %1", service);
  1108.  
  1109.         if (! Service::Enable(service)) {
  1110.         all_ok = true;
  1111.         // TRANSLATORS: a popup error message
  1112.         Report::Error (sformat (_("Cannot enable service '%1'."), service));
  1113.         }
  1114.     });
  1115.  
  1116.     return all_ok;
  1117.     }
  1118.  
  1119.     /**
  1120.      * Functions disables services needed for SuSEFirewall in /etc/inet.d/
  1121.      *
  1122.      * @return    boolean result
  1123.      */
  1124.     global define boolean DisableServices () {
  1125.     boolean all_ok = true;
  1126.  
  1127.     foreach (string service, firewall_services_reverse, {
  1128.         y2debug("Disabling service: %1", service);
  1129.  
  1130.         if (! Service::Disable(service)) {
  1131.         all_ok = false;
  1132.         // TRANSLATORS: a popup error message
  1133.         Report::Error (sformat (_("Cannot disable service '%1'."), service));
  1134.         }
  1135.     });
  1136.  
  1137.     return all_ok;
  1138.     }
  1139.  
  1140.  
  1141.     /**
  1142.      * Function determines if all SuSEFirewall scripts are enabled in
  1143.      * init scripts /etc/init.d/ now.
  1144.      * For configuration "enabled" status use GetEnableService().
  1145.      *
  1146.      * @return    boolean if enabled
  1147.      */
  1148.     global define boolean IsEnabled () {
  1149.     boolean enabled = false;
  1150.  
  1151.     //if (Mode::normal() || Mode::commandline()) {
  1152.         foreach (string service, firewall_services, {
  1153.         enabled = Service::Enabled(service);
  1154.         // All services have to be enabled
  1155.         if (!enabled) {
  1156.             y2milestone("Firewall service %1 is not enabled", service);
  1157.             break;
  1158.         }
  1159.         });
  1160.     //}
  1161.  
  1162.     if (enabled) {
  1163.         y2milestone("Firewall init scripts are enabled");
  1164.     }
  1165.  
  1166.     return enabled;
  1167.     }
  1168.  
  1169.     /**
  1170.      * Function determines if at least one SuSEFirewall script is started now.
  1171.      * For configuration "started" status use GetStartService().
  1172.      *
  1173.      * @return    boolean if started
  1174.      */
  1175.     global define boolean IsStarted () {
  1176.     boolean started = false;
  1177.  
  1178.     //if (Mode::normal() || Mode::commandline()) {
  1179.         foreach (string service, firewall_services, {
  1180.         if (Service::Status(service) == 0) {
  1181.             started = true;
  1182.             break;
  1183.         }
  1184.         });
  1185.     //}
  1186.  
  1187.     if (started == true) {
  1188.         y2milestone("Firewall services are started");
  1189.     } else {
  1190.         y2milestone("Firewall services are stopped");
  1191.     }
  1192.  
  1193.     return started;
  1194.     }
  1195.  
  1196.     /**
  1197.      * Function for getting exported SuSEFirewall configuration
  1198.      *
  1199.      * @return    map <string, any> with configuration
  1200.      */
  1201.     global define map <string, any> Export () {
  1202.     return SETTINGS;
  1203.     }
  1204.  
  1205.     /**
  1206.      * Function for setting SuSEFirewall configuration from input
  1207.      *
  1208.      * @param    map <string, any> with configuration
  1209.      */
  1210.     global define void Import (map <string, any> import_settings) {
  1211.     SetModified();
  1212.  
  1213.     SETTINGS = import_settings;
  1214.     }
  1215.  
  1216.     /**
  1217.      * Function returns if the interface is in zone.
  1218.      *
  1219.      * @param    string interface
  1220.      * @param    string firewall zone
  1221.      * @return    boolean is in zone
  1222.      */
  1223.     global define boolean IsInterfaceInZone(string interface, string zone) {
  1224.     list <string> interfaces = splitstring(SETTINGS[ "FW_DEV_" + zone ]:"", " ");
  1225.     return contains(interfaces, interface);
  1226.     }
  1227.  
  1228.     /**
  1229.      * Function returns the firewall zone of interface, nil if no zone includes
  1230.      * the interface. Error is reported when interface is found in multiple
  1231.      * firewall zones, then the first appearance is returned.
  1232.      *
  1233.      * @param    string interface
  1234.      * @return    string zone
  1235.      */
  1236.     global define string GetZoneOfInterface (string interface) {
  1237.     list interface_zone = [];
  1238.  
  1239.     foreach (string zone, GetKnownFirewallZones(), {
  1240.         if (IsInterfaceInZone(interface, zone)) interface_zone = add (interface_zone, zone);
  1241.     });
  1242.  
  1243.     if (IsVerbose() && size(interface_zone) > 1) {
  1244.         // TRANSLATORS: Error message, %1 = interface name (like eth0)
  1245.         Report::Error(sformat(_("Interface '%1' is included in multiple firewall zones.
  1246. Continuing with configuration can produce errors.
  1247.  
  1248. It is recommended to leave the configuration and repair it manually in
  1249. the file '/etc/sysconfig/SuSEFirewall'."), interface));
  1250.     }
  1251.  
  1252.     // return the first existence of interface in zones
  1253.     // if it is not presented anywhere, nil is returned
  1254.     return (string) interface_zone[0]:nil;
  1255.     }
  1256.  
  1257.     /**
  1258.      * Function returns list of zones of requested interfaces
  1259.      *
  1260.      * @param    list<string> interfaces
  1261.      * @param    list<string> firewall zones
  1262.      */
  1263.     global define list<string> GetZonesOfInterfaces (list<string> interfaces) {
  1264.     list<string> zones = [];
  1265.     string zone = "";
  1266.  
  1267.     foreach (string interface, interfaces, {
  1268.         zone = GetZoneOfInterface(interface);
  1269.         if (zone != nil) zones = add(zones, zone);
  1270.     });
  1271.     
  1272.     return toset(zones);
  1273.     }
  1274.  
  1275.     global define list<string> GetInterfacesInZoneSupportingAnyFeature (string zone);
  1276.  
  1277.     /**
  1278.      * Function returns list of zones of requested interfaces.
  1279.      * Special string 'any' in 'EXT' zone is supported.
  1280.      *
  1281.      * @param    list<string> interfaces
  1282.      * @param    list<string> firewall zones
  1283.      */
  1284.     global define list<string> GetZonesOfInterfacesWithAnyFeatureSupported (list<string> interfaces) {
  1285.     list<string> zones = [];
  1286.     string zone = "";
  1287.     
  1288.     // 'any' in 'EXT'
  1289.     list <string> interfaces_covered_by_any =
  1290.         SuSEFirewall::GetInterfacesInZoneSupportingAnyFeature(special_all_interface_zone);
  1291.  
  1292.     foreach (string interface, interfaces, {
  1293.         // interface is covered by 'any' in 'EXT'
  1294.         if (contains(interfaces_covered_by_any, interface))
  1295.         zone = special_all_interface_zone;
  1296.         // interface is explicitely mentioned in some zone
  1297.         else
  1298.         zone = GetZoneOfInterface(interface);
  1299.  
  1300.         if (zone != nil) zones = add(zones, zone);
  1301.     });
  1302.     
  1303.     return toset(zones);
  1304.     }
  1305.  
  1306.     /**
  1307.      * Function returns list of maps of known interfaces.
  1308.      * @struct [ $[ "id":"modem0", "name":"Askey 815C", "type":"dialup", "zone":"EXT" ], ... ]
  1309.      *
  1310.      * @return    list <map <string, string> >
  1311.      */
  1312.     global define list <map <string, string> > GetAllKnownInterfaces () {
  1313.     list <map <string, string> > known_interfaces = [];
  1314.     
  1315.     // All dial-up interfaces
  1316.     list <string> dialup_interfaces = NetworkDevices::List("dialup");
  1317.     dialup_interfaces = filter(string interface, dialup_interfaces, ``{
  1318.         return interface != "" && !issubstring(interface, "lo") && !issubstring(interface, "sit");
  1319.     });
  1320.  
  1321.     // All non-dial-up interfaces
  1322.     list <string> non_dialup_interfaces = NetworkDevices::List("");
  1323.     non_dialup_interfaces = filter(string interface, non_dialup_interfaces, ``{
  1324.         return interface != "" && !issubstring(interface, "lo") && !issubstring(interface, "sit")
  1325.         && !contains(dialup_interfaces, interface);
  1326.     });
  1327.  
  1328.     foreach (string interface, dialup_interfaces, {
  1329.         known_interfaces = add(known_interfaces, $[
  1330.         "id" : interface,
  1331.         "type" : "dialup",
  1332.         // using function to get name
  1333.         "name" : NetworkDevices::GetValue(interface, "NAME"),
  1334.         "zone" : GetZoneOfInterface(interface),
  1335.         ]);
  1336.     });
  1337.  
  1338.     foreach (string interface, non_dialup_interfaces, {
  1339.         known_interfaces = add(known_interfaces, $[
  1340.         "id" : interface,
  1341.         // using function to get name
  1342.         "name" : NetworkDevices::GetValue(interface, "NAME"),
  1343.         "zone" : GetZoneOfInterface(interface),
  1344.         ]);
  1345.     });
  1346.  
  1347.     return known_interfaces;
  1348.     }
  1349.  
  1350.     /**
  1351.      * Function returns list of non-dial-up interfaces.
  1352.      *
  1353.      * @return list <string> of non-dial-up interface names
  1354.      */
  1355.     global define list <string> GetAllNonDialUpInterfaces () {
  1356.     list <string> non_dial_up_interfaces = [];
  1357.     foreach (map<string, string> interface, SuSEFirewall::GetAllKnownInterfaces(), {
  1358.         if (interface["type"]:nil != "dial_up")
  1359.         non_dial_up_interfaces = add (non_dial_up_interfaces, interface["id"]:"");
  1360.     });
  1361.     
  1362.     return non_dial_up_interfaces;
  1363.     }
  1364.  
  1365.     /**
  1366.      * Function returns list of dial-up interfaces.
  1367.      *
  1368.      * @return list <string> of dial-up interface names
  1369.      */
  1370.     global define list <string> GetAllDialUpInterfaces () {
  1371.     list <string> dial_up_interfaces = [];
  1372.     foreach (map <string, string> interface, SuSEFirewall::GetAllKnownInterfaces(), {
  1373.         if (interface["type"]:nil == "dial_up")
  1374.         dial_up_interfaces = add (dial_up_interfaces, interface["id"]:"");
  1375.     });
  1376.     
  1377.     return dial_up_interfaces;
  1378.     }
  1379.  
  1380.     /**
  1381.      * Function returns list of all known interfaces.
  1382.      *
  1383.      * @return    list <string> of interfaces
  1384.      */
  1385.     global define list <string> GetListOfKnownInterfaces () {
  1386.     list <string> interfaces = [];
  1387.  
  1388.     foreach (map interface_map, GetAllKnownInterfaces(), {
  1389.         interfaces = add (interfaces, interface_map["id"]:"");
  1390.     });
  1391.  
  1392.     return interfaces;
  1393.     }
  1394.  
  1395.     /**
  1396.      * Function removes interface from defined zone.
  1397.      *
  1398.      * @param    string interface
  1399.      * @param    string zone
  1400.      */
  1401.     global define void RemoveInterfaceFromZone (string interface, string zone) {
  1402.     SetModified();
  1403.  
  1404.     y2milestone("Removing interface '%1' from '%2' zone.", interface, zone);
  1405.  
  1406.     list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
  1407.     interfaces_in_zone = filter (string single_interface, interfaces_in_zone, {
  1408.         return single_interface != "" && single_interface != interface;
  1409.     });
  1410.     SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
  1411.     }
  1412.  
  1413.     /**
  1414.      * Functions adds interface into defined zone.
  1415.      * All appearances of interface in other zones are removed.
  1416.      *
  1417.      * @param    string interface
  1418.      * @param    string zone
  1419.      */
  1420.     global define void AddInterfaceIntoZone (string interface, string zone) {
  1421.     SetModified();
  1422.     
  1423.     string current_zone = GetZoneOfInterface(interface);
  1424.  
  1425.     DecreaseVerbosity();
  1426.     // removing all appearances of interface in zones, excepting current_zone==new_zone
  1427.     while (current_zone != nil && current_zone != zone) {
  1428.         // interface is in any zone already, removing it at first
  1429.         if (current_zone != zone) {
  1430.         RemoveInterfaceFromZone(interface, current_zone);
  1431.         }
  1432.         current_zone = GetZoneOfInterface(interface);
  1433.     }
  1434.     IncreaseVerbosity();
  1435.  
  1436.     y2milestone("Adding interface '%1' into '%2' zone.", interface, zone);
  1437.     list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
  1438.     interfaces_in_zone = toset(add (interfaces_in_zone, interface));
  1439.     SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
  1440.     }
  1441.     
  1442.     /**
  1443.      * Function returns list of known interfaces in requested zone.
  1444.      * Special strings like 'any' or 'auto' and unknown interfaces are removed from list.
  1445.      *
  1446.      * @param    string zone
  1447.      * @return    list <string> of interfaces
  1448.      */
  1449.     global define list<string> GetInterfacesInZone (string zone) {
  1450.     list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
  1451.  
  1452.     list <string> known_interfaces_now = GetListOfKnownInterfaces();
  1453.  
  1454.     // filtering special strings
  1455.     interfaces_in_zone = filter(string interface, interfaces_in_zone, ``{
  1456.         return interface != "" && contains(known_interfaces_now, interface);
  1457.     });
  1458.     
  1459.     return interfaces_in_zone;
  1460.     }
  1461.  
  1462.     /**
  1463.      * Function returns all interfaces configured in firewall, already
  1464.      *
  1465.      * @return    list <string> of configured interfaces
  1466.      */
  1467.     global define list<string> GetFirewallInterfaces () {
  1468.     list<string> firewall_configured_devices = [];
  1469.  
  1470.     foreach (string zone, GetKnownFirewallZones(), {
  1471.         firewall_configured_devices = (list<string>) union (firewall_configured_devices, GetInterfacesInZone(zone));
  1472.     });
  1473.  
  1474.     return toset(firewall_configured_devices);
  1475.     }
  1476.  
  1477.     /**
  1478.      * Returns list of interfaces not mentioned in any zone and covered by the
  1479.      * special string 'any' in zone 'EXT' if such string exists there and the zone
  1480.      * is EXT.
  1481.      *
  1482.      * @param string zone
  1483.      * @return list <string> of interfaces covered by special string 'any'
  1484.      */
  1485.     global define list<string> InterfacesSupportedByAnyFeature (string zone) {
  1486.     list <string> result = [];
  1487.     
  1488.     if (zone == special_all_interface_zone && IsAnyNetworkInterfaceSupported()) {
  1489.         list <string> known_interfaces_now  = GetListOfKnownInterfaces();
  1490.         list <string> configured_interfaces = GetFirewallInterfaces();
  1491.         foreach (string one_interface, known_interfaces_now, {
  1492.         if (! contains(configured_interfaces, one_interface)) {
  1493.             y2milestone("Interface '%1' supported by special string '%2' in zone '%3'",
  1494.             one_interface, special_all_interface_string, special_all_interface_zone);
  1495.             result = add (result, one_interface);
  1496.         }
  1497.         });
  1498.     }
  1499.     
  1500.     return result;
  1501.     }
  1502.  
  1503.     /**
  1504.      * Function returns list of known interfaces in requested zone.
  1505.      * Special string 'any' in EXT zone covers all interfaces without
  1506.      * any zone assignment.
  1507.      *
  1508.      * @param    string zone
  1509.      * @return    list <string> of interfaces
  1510.      */
  1511.     global define list<string> GetInterfacesInZoneSupportingAnyFeature (string zone) {
  1512.     list <string> interfaces_in_zone = GetInterfacesInZone(zone);
  1513.  
  1514.     // 'any' in EXT zone, add all interfaces without zone to this one
  1515.     list <string> interfaces_covered_by_any = InterfacesSupportedByAnyFeature(zone);
  1516.     if (size(interfaces_covered_by_any)>0) {
  1517.         interfaces_in_zone = (list <string>) union (interfaces_in_zone, interfaces_covered_by_any);
  1518.     }
  1519.     
  1520.     return interfaces_in_zone;
  1521.     }
  1522.  
  1523.     boolean ArePortsOrServicesAllowed (list <string> needed_ports, string protocol, string zone, boolean check_for_aliases);
  1524.  
  1525.     /**
  1526.      * Function returns if requested service is allowed in respective zone.
  1527.      * Function takes care for service's aliases (only for TCP and UDP).
  1528.      *
  1529.      * @param    string service (service name, port name, port alias or port number)
  1530.      * @param    protocol TCP, UDP, RCP or IP
  1531.      * @param    interface name (like modem0), firewall zone (like "EXT") or "any" for all zones.
  1532.      * @return    boolean if service is allowed
  1533.      */
  1534.     global define boolean HaveService(string service, string protocol, string interface) {
  1535.     if (! IsSupportedProtocol(protocol)) {
  1536.         y2error("Unknown protocol: %1", protocol);
  1537.         return nil;
  1538.     }
  1539.  
  1540.     // definition of searched zones
  1541.     list<string> zones = [];
  1542.  
  1543.     // "any" for all zones, this is ugly
  1544.     if (interface == "any") {
  1545.         zones = GetKnownFirewallZones();
  1546.     // string interface is the zone name
  1547.     } else if (IsKnownZone(interface)) {
  1548.         zones = add (zones, interface);
  1549.     // interface is the interface name
  1550.     } else {
  1551.         interface = GetZoneOfInterface(interface);
  1552.         if (interface != nil) {
  1553.         zones = add (zones, interface);
  1554.         }
  1555.     }
  1556.     
  1557.     // SuSEFirewall feature FW_PROTECT_FROM_INT
  1558.     // should not be protected and searched zones include also internal (or the zone IS internal, sure)
  1559.     if (! GetProtectFromInternalZone() && contains(zones, int_zone_shortname)) {
  1560.         y2milestone("Checking for service '%1', in '%2', PROTECT_FROM_INTERNAL='no' => allowed", service, interface);
  1561.         return true;
  1562.     }
  1563.     
  1564.     // Check and return whether the service (port) is supported anywhere
  1565.     boolean ret = false;
  1566.     foreach (string zone, zones, {
  1567.         // This function can also handle port ranges
  1568.         if (ArePortsOrServicesAllowed([service], protocol, zone, true)) {
  1569.         ret = true;
  1570.         break;
  1571.         }
  1572.     });
  1573.     
  1574.     return ret;
  1575.     }
  1576.  
  1577.     /**
  1578.      * Function adds service into selected zone (or zone of interface) for selected protocol.
  1579.      * Function take care about port-aliases, first of all, removes all of them.
  1580.      *
  1581.      * @param    string service/port
  1582.      * @param    string protocol TCP, UDP, RPC, IP
  1583.      * @param    string zone name or interface name
  1584.      * @return    boolean success
  1585.      */
  1586.     global define boolean AddService (string service, string protocol, string interface) {
  1587.     boolean success = false;
  1588.     y2milestone("Adding service %1, protocol %2 to %3", service, protocol, interface);
  1589.  
  1590.     if (! IsSupportedProtocol(protocol)) {
  1591.         y2error("Unknown protocol: %1", protocol);
  1592.         return false;
  1593.     }
  1594.  
  1595.     list <string> zones_affected = [];
  1596.  
  1597.     // "all" means for all known zones
  1598.     if (interface == "all") {
  1599.         zones_affected = GetKnownFirewallZones();
  1600.  
  1601.     // zone or interface name
  1602.     } else {
  1603.         // is probably an interface name
  1604.         if (! IsKnownZone(interface)) {
  1605.         // interface is probably interface-name, checking for respective zone
  1606.         interface = GetZoneOfInterface(interface);
  1607.         // interface is not assigned to any zone
  1608.         if (interface == nil) {
  1609.             // TRANSLATORS: Error message, %1 = interface name (like eth0)
  1610.             Report::Error(sformat(_("Interface '%1' is not assigned to any firewall zone.
  1611. Run YaST2 Firewall and assign it.
  1612. "), interface)
  1613.             );
  1614.             y2warning("Interface '%1' is not assigned to any firewall zone", interface);
  1615.             return false;
  1616.         }
  1617.         }
  1618.         zones_affected = [interface];
  1619.     }
  1620.  
  1621.     SetModified();
  1622.  
  1623.     // Adding service support into each mentioned zone
  1624.     foreach (string zone, zones_affected, {
  1625.         // If there isn't already
  1626.         if (!ArePortsOrServicesAllowed([service], protocol, zone, true)) {
  1627.         AddAllowedPortsOrServices([service], protocol, zone);
  1628.         } else {
  1629.         y2milestone("Port %1 has been already allowed in %2", service, zone);
  1630.         }
  1631.     });
  1632.  
  1633.     return true;
  1634.     }
  1635.  
  1636.     /**
  1637.      * Function removes service from selected zone (or for interface) for selected protocol.
  1638.      * Function take care about port-aliases, removes all of them.
  1639.      *
  1640.      * @param    string service/port
  1641.      * @param    string protocol TCP, UDP, RPC, IP
  1642.      * @param    string zone name or interface name
  1643.      * @return    boolean success
  1644.      */
  1645.     global define boolean RemoveService (string service, string protocol, string interface) {
  1646.     boolean success = false;
  1647.     y2milestone("Removing service %1, protocol %2 from %3", service, protocol, interface);
  1648.  
  1649.     if (! IsSupportedProtocol(protocol)) {
  1650.         y2error("Unknown protocol: %1", protocol);
  1651.         return false;
  1652.     }
  1653.  
  1654.     list <string> zones_affected = [];
  1655.  
  1656.     // "all" means for all known zones
  1657.     if (interface == "all") {
  1658.         zones_affected = GetKnownFirewallZones();
  1659.  
  1660.     // zone or interface name
  1661.     } else {
  1662.         if (! IsKnownZone(interface)) {
  1663.         // interface is probably interface-name, checking for respective zone
  1664.         interface = GetZoneOfInterface(interface);
  1665.         // interface is not assigned to any zone
  1666.         if (interface == nil) {
  1667.             // TRANSLATORS: Error message, %1 = interface name (like eth0)
  1668.             Report::Error(sformat(_("Interface '%1' is not assigned to any firewall zone.
  1669. Run YaST2 Firewall and assign it.
  1670. "), interface)
  1671.             );
  1672.             y2warning("Interface '%1' is not assigned to any firewall zone", interface);
  1673.             return false;
  1674.         }
  1675.         }
  1676.         zones_affected = [interface];
  1677.     }
  1678.  
  1679.     SetModified();
  1680.  
  1681.  
  1682.     // Adding service support into each mentioned zone
  1683.     foreach (string zone, zones_affected, {
  1684.         // if the service is allowed
  1685.         if (ArePortsOrServicesAllowed([service], protocol, zone, true)) {
  1686.         RemoveAllowedPortsOrServices([service], protocol, zone, true);
  1687.         } else {
  1688.         y2milestone("Port %1 has been already removed from %2", service, zone);
  1689.         }
  1690.     });
  1691.  
  1692.     return true;
  1693.     }
  1694.  
  1695.     /**
  1696.      * Function returns if needed services are all allowed (or not) in the firewall.
  1697.      * Last parameter sets if it also should check for port-aliases, what makes sense
  1698.      * for TCP and UDP ports.
  1699.      * Protocols and Zones aren't checked for existency. It's on you to do it.
  1700.      *
  1701.      * @param    list <string> needed (checked) ports for service
  1702.      * @param    string protocol TCP, UDP, RPC or IP
  1703.      * @param    zone name like EXT
  1704.      * @param    boolean check for port-aliases
  1705.      * @return    boolean if all ports are allowed
  1706.      */
  1707.     boolean ArePortsOrServicesAllowed (list <string> needed_ports, string protocol, string zone, boolean check_for_aliases) {
  1708.     boolean are_allowed = true;
  1709.  
  1710.     if (size(needed_ports)<1) {
  1711.         y2warning("Undefined list of %1 services/ports for service", protocol);
  1712.         return true;
  1713.     }
  1714.  
  1715.     map <string, list <string> > allowed_ports = $[];
  1716.     // BTW: only TCP and UDP ports can have aliases and only TCP and UDP ports can have port ranges
  1717.     if (check_for_aliases) {
  1718.         allowed_ports = PortRanges::DividePortsAndPortRanges (
  1719.         GetAllowedServicesForZoneProto (zone, protocol), true
  1720.         );
  1721.     } else {
  1722.         allowed_ports["ports"] = GetAllowedServicesForZoneProto (zone, protocol);
  1723.     }
  1724.  
  1725.     foreach (string needed_port, needed_ports, {
  1726.         if (
  1727.         ! contains(allowed_ports["ports"]:[], needed_port) &&
  1728.         ! PortRanges::PortIsInPortranges (needed_port, allowed_ports["port_ranges"]:[])
  1729.         ) {
  1730.         are_allowed = false;
  1731.         break;
  1732.         }
  1733.     });
  1734.  
  1735.     return are_allowed;
  1736.     }
  1737.  
  1738.     /**
  1739.      * Function returns if service is supported (allowed) in zone. Service must be defined
  1740.      * in the SuSEFirewallServices.
  1741.      *
  1742.      * @see Module SuSEFirewallServices
  1743.      * @param    string service id
  1744.      * @param    string zone
  1745.      * @return    boolean if supported
  1746.      */
  1747.     global define boolean IsServiceSupportedInZone (string service, string zone) {
  1748.     if (! IsKnownZone(zone)) {
  1749.         return nil;
  1750.     }
  1751.  
  1752.     map <string, list <string> > needed = SuSEFirewallServices::GetNeededPortsAndProtocols(service);
  1753.     // unknown service
  1754.     if (needed == nil) {
  1755.         y2error("Undefined service '%1'", service);
  1756.         return nil;
  1757.     }
  1758.  
  1759.     // SuSEFirewall feature FW_PROTECT_FROM_INT
  1760.     // should not be protected and searched zones include also internal (or the zone IS internal, sure)
  1761.     if (zone == int_zone_shortname && ! GetProtectFromInternalZone()) {
  1762.         y2milestone("Checking for service '%1', in '%2', PROTECT_FROM_INTERNAL='no' => allowed", service, zone);
  1763.         return true;
  1764.     }
  1765.  
  1766.     // starting with nil value, any false means that the service is not supported
  1767.     boolean service_is_supported = nil;
  1768.     foreach (string key, service_defined_by, {
  1769.         list <string> needed_ports = needed[key]:[];
  1770.         if (needed_ports == []) return;
  1771.  
  1772.         if (key == "tcp_ports") {
  1773.         service_is_supported = ArePortsOrServicesAllowed(needed_ports, "TCP", zone, true);
  1774.         } else if (key == "udp_ports") {
  1775.         service_is_supported = ArePortsOrServicesAllowed(needed_ports, "UDP", zone, true);
  1776.         } else if (key == "rpc_ports") {
  1777.         service_is_supported = ArePortsOrServicesAllowed(needed_ports, "RPC", zone, false);
  1778.         } else if (key == "ip_protocols") {
  1779.         service_is_supported = ArePortsOrServicesAllowed(needed_ports, "IP", zone, false);
  1780.         } else if ("broadcast_ports" == key) {
  1781.         // testing for allowed broadcast ports
  1782.         service_is_supported = IsBroadcastAllowed(needed_ports, zone);
  1783.         } else {
  1784.         y2error("Unknown key '%1'", key);
  1785.         }
  1786.  
  1787.         // service is not supported, we don't have to do more tests
  1788.         if (service_is_supported == false) break;
  1789.     });
  1790.  
  1791.     return service_is_supported;
  1792.     }
  1793.  
  1794.     /**
  1795.      * Function returns map of supported services all network interfaces.
  1796.      *
  1797.      * @param    list <string> of services
  1798.      * @return    map <string, map < string : boolean > >
  1799.      * @struct    Returns $[service : $[ interface : supported_status ]]
  1800.      */
  1801.     global define map <string, map <string, boolean> > GetServicesInZones (list<string> services) {
  1802.     // list of interfaces for each zone
  1803.     map <string, list <string> > interface_in_zone = $[];
  1804.  
  1805.     foreach (string interface, GetListOfKnownInterfaces(), {
  1806.         // zone of interface
  1807.         string zone_used = GetZoneOfInterface(interface);
  1808.         // interface can be unassigned
  1809.         if (zone_used == nil || zone_used == "") {
  1810.         return;
  1811.         }
  1812.         interface_in_zone[zone_used] = add (interface_in_zone[zone_used]:[], interface);
  1813.     });
  1814.  
  1815.     // $[ service : $[ network_interface : status ]]
  1816.     map <string, map <string, boolean> > services_status = $[];
  1817.  
  1818.     // for all services requested
  1819.     foreach (string service, services, {
  1820.         services_status[service] = $[];
  1821.         // for all zones in configuration
  1822.         foreach (string zone, list <string> interfaces, interface_in_zone, {
  1823.         boolean status = IsServiceSupportedInZone(service, zone);
  1824.         // for all interfaces in zone
  1825.         foreach (string interface, interfaces, {
  1826.             services_status[service, interface] = status;
  1827.         });
  1828.         });
  1829.     });
  1830.  
  1831.     return services_status;
  1832.     }
  1833.  
  1834.     /**
  1835.      * Function returns map of supported services in all firewall zones.
  1836.      *
  1837.      * @param    list <string> of services
  1838.      * @return    map <string, map < string : boolean> >
  1839.      * @struct    Returns $[service : $[ zone_name : supported_status]]
  1840.      */
  1841.     global define map <string, map <string, boolean> > GetServices (list<string> services) {
  1842.     // $[ service : $[ firewall_zone : status ]]
  1843.     map <string, map <string, boolean> > services_status = $[];
  1844.  
  1845.     // for all services requested
  1846.     foreach (string service, services, {
  1847.         services_status[service] = $[];
  1848.         // for all zones in configuration
  1849.         foreach (string zone, GetKnownFirewallZones(), {
  1850.         services_status[service,zone] = IsServiceSupportedInZone(service, zone);
  1851.         });
  1852.     });
  1853.  
  1854.     return services_status;
  1855.     }
  1856.  
  1857.     /**
  1858.      * Function sets status for several services in several firewall zones.
  1859.      *
  1860.      * @param    list <string> service ids
  1861.      * @param    list <string> firewall zones (EXT|INT|DMZ...)
  1862.      * @param    boolean new status of services
  1863.      * @return    boolean if successfull
  1864.      */
  1865.     global define boolean SetServicesForZones (list<string> services_ids, list<string> firewall_zones, boolean new_status) {
  1866.     // no groups == all groups
  1867.     if (size(firewall_zones)==0) firewall_zones = GetKnownFirewallZones();
  1868.  
  1869.     // setting for each service
  1870.     foreach (string service_id, services_ids, {
  1871.         foreach (string firewall_zone, firewall_zones, {
  1872.         // zone must be known one
  1873.         if (! IsKnownZone(firewall_zone)) {
  1874.             y2error("Zone '%1' is unknown firewall zone, skipping...", firewall_zone);
  1875.             return;
  1876.         }
  1877.  
  1878.         SetModified();
  1879.  
  1880.         // setting new status
  1881.         if (new_status == true) {
  1882.             y2milestone("Adding '%1' into '%2' zone", service_id, firewall_zone);
  1883.             AddServiceSupportIntoZone(service_id, firewall_zone);
  1884.             HandleConflictService(service_id, firewall_zone, true);
  1885.         } else {
  1886.             y2milestone("Removing '%1' from '%2' zone", service_id, firewall_zone);
  1887.             RemoveServiceSupportFromZone(service_id, firewall_zone);
  1888.             HandleConflictService(service_id, firewall_zone, false);
  1889.         }
  1890.         });
  1891.     });
  1892.     }
  1893.  
  1894.     /**
  1895.      * Function sets status for several services in several network interfaces.
  1896.      *
  1897.      * @param    list <string> service ids
  1898.      * @param    list <string> network interfaces
  1899.      * @param    boolean new status of services
  1900.      * @return    boolean if successfull
  1901.      */
  1902.     global define boolean SetServices (list<string> services_ids, list<string> interfaces, boolean new_status) {
  1903.     list<string> firewall_zones = GetZonesOfInterfacesWithAnyFeatureSupported(interfaces);
  1904.     if (size(firewall_zones)==0) {
  1905.         y2error("Interfaces '%1' are not in any group if interfaces", interfaces);
  1906.         return false;
  1907.     }
  1908.  
  1909.     SetModified();
  1910.  
  1911.     return SetServicesForZones(services_ids, firewall_zones, new_status);
  1912.     }
  1913.  
  1914.     /**
  1915.      * Local function check is any of possibly conflicting services was turned on in
  1916.      * the firewall configuration.
  1917.      */
  1918.     void CheckAllPossiblyConflictingServices () {
  1919.     // For all known zones
  1920.     foreach (string zone, GetKnownFirewallZones(), {
  1921.         // Exception:
  1922.         // There are no possible conflicts if zone isn't protected
  1923.         if (zone == "INT" && ! GetProtectFromInternalZone()) return;
  1924.  
  1925.         // For all possible conflicting services
  1926.         foreach (string service, GetPossiblyConflictServices(), {
  1927.         // Possibly conflicting service is supported (on)
  1928.         if (IsServiceSupportedInZone (service, zone)) {
  1929.             allowed_conflict_services[zone] = add (allowed_conflict_services[zone]:[], service);
  1930.         }
  1931.         });
  1932.  
  1933.         // Exception:
  1934.         // NIS-client's ports are the subset of NIS-server's ports
  1935.         if (
  1936.         contains(allowed_conflict_services[zone]:[], "nis-server")
  1937.         &&
  1938.         contains(allowed_conflict_services[zone]:[], "nis-client")
  1939.         ) {
  1940.         // Removing nis-client from allowed services, when both of them found
  1941.         y2warning("Ignoring found nis-client as the subset of nis-server, for zone %1", zone);
  1942.         allowed_conflict_services[zone] = filter (
  1943.             string service, allowed_conflict_services[zone]:[], {
  1944.             return service != "nis-client";
  1945.             }
  1946.         );
  1947.         }
  1948.         allowed_conflict_services[zone] = toset(allowed_conflict_services[zone]:[]);
  1949.     });
  1950.  
  1951.     y2milestone("Possibly conflicting services found allowed: %1", allowed_conflict_services);
  1952.     }
  1953.  
  1954.     /**
  1955.      * Local function sets the default configuration and fills internal values.
  1956.      */
  1957.     void ReadDefaultConfiguration () {
  1958.     SETTINGS = $[];
  1959.  
  1960.     ResetSysconfigSuSEFirewall ( GetListOfSuSEFirewallVariables() );
  1961.     }
  1962.  
  1963.     /**
  1964.      * Local function reads current configuration and fills internal values.
  1965.      */
  1966.     void ReadCurrentConfiguration () {
  1967.     SETTINGS = $[];
  1968.  
  1969.     // is firewall enabled in /etc/init.d/ ?
  1970.         SETTINGS["enable_firewall"] = IsEnabled();
  1971.     // is firewall started now?
  1972.     SETTINGS["start_firewall"]  = IsStarted();
  1973.  
  1974.     ReadSysconfigSuSEFirewall ( GetListOfSuSEFirewallVariables() );
  1975.     }
  1976.  
  1977.     /**
  1978.      * Function for reading SuSEFirewall configuration.
  1979.      * Fills internal variables only.
  1980.      */
  1981.     global define boolean Read () {
  1982.     // Don't fill up the logs with tones of Check-logs
  1983.     // Turn on for debugging
  1984.     // NetworkDevices::report_every_check = false;
  1985.  
  1986.     if (configuration_has_been_read) {
  1987.         y2milestone("SuSEfirewall2 configuration has been read already.");
  1988.         return true;
  1989.     }
  1990.  
  1991.     // Progress only for normal configuration
  1992.     boolean have_progress = (Mode::normal());
  1993.  
  1994.     if (have_progress) {
  1995.         // TRANSLATORS: Dialog caption
  1996.         string read_caption = _("Initializing Firewall Configuration");
  1997.  
  1998.         Progress::New( read_caption, " ", 3,
  1999.         [
  2000.             // TRANSLATORS: Progress step
  2001.             _("Check for network devices"),
  2002.             // TRANSLATORS: Progress step
  2003.             _("Read current configuration"),
  2004.             // TRANSLATORS: Progress step
  2005.             _("Check possibly conflicting services"),
  2006.         ],
  2007.         [
  2008.             // TRANSLATORS: Progress step
  2009.             _("Checking for network devices..."),
  2010.             // TRANSLATORS: Progress step
  2011.             _("Reading current configuration..."),
  2012.             // TRANSLATORS: Progress step
  2013.             _("Checking possibly conflicting services..."),
  2014.             Message::Finished(),
  2015.         ],
  2016.         ""
  2017.         );
  2018.  
  2019.         Progress::NextStage();
  2020.     }
  2021.  
  2022.     if (Mode::normal() || Mode::commandline()) {
  2023.         NetworkDevices::Read();
  2024.     } else if (Mode::installation() || Mode::autoinst()) {
  2025.         // Allways modified for installation, allways save the final state
  2026.         // fixing bug #67355
  2027.         // SetModified();
  2028.         boolean make_parser_happy = true;
  2029.     }
  2030.  
  2031.     if (have_progress) Progress::NextStage();
  2032.  
  2033.     // get default configuration for autoinstallation
  2034.     // if (Mode::installation() || Mode::autoinst()) {
  2035.     if (Mode::autoinst()) {
  2036.         ReadDefaultConfiguration();
  2037.     // read current configuration for another cases
  2038.     } else {
  2039.         ReadCurrentConfiguration();
  2040.     }
  2041.  
  2042.     if (have_progress) Progress::NextStage();
  2043.  
  2044.     // checking if any possibly conficting services were turned on in configuration
  2045.     // filling internal values for later checkings
  2046.     CheckAllPossiblyConflictingServices();
  2047.  
  2048.     y2milestone("Firewall configuration has been read: %1.", SETTINGS);
  2049.     // to read configuration only once
  2050.     configuration_has_been_read = true;
  2051.  
  2052.     if (have_progress) Progress::NextStage();
  2053.  
  2054.     if (have_progress) Progress::Finish();
  2055.  
  2056.     return true;
  2057.     }
  2058.     
  2059.     /**
  2060.      * Function returns whether some RPC service is allowed in the configuration.
  2061.      * These services reallocate their ports when restarted. See details in
  2062.      * bugzilla bug #186186.
  2063.      *
  2064.      * @return boolean some_RPC_service_used
  2065.      */
  2066.     boolean AnyRPCServiceInConfiguration () {
  2067.     boolean ret = false;
  2068.  
  2069.     foreach (string fw_zone, GetKnownFirewallZones(), {
  2070.         string fw_rule = sformat("FW_SERVICES_%1_RPC", fw_zone);
  2071.         string listed_services = SETTINGS[fw_rule]:GetDefaultValue(fw_rule);
  2072.         // easy case
  2073.         if (listed_services == nil || listed_services == "") return;
  2074.  
  2075.         // something listed but it still might be empty definition
  2076.         list <string> services_list = splitstring (listed_services, " \n\t");
  2077.         services_list = filter (string service, services_list, {
  2078.         return (service != "");
  2079.         });
  2080.         if (size (listed_services) > 0) {
  2081.         ret = true;
  2082.         break;
  2083.         }
  2084.     });
  2085.     
  2086.     y2milestone ("Some RPC service found: %1", ret);
  2087.     return ret;
  2088.     }
  2089.  
  2090.     /**
  2091.      * Function which stops firewall. Then firewall is started immediately when firewall
  2092.      * is wanted to be started: SetStartService(boolean).
  2093.      *
  2094.      * @return    boolean if successful
  2095.      */
  2096.     global define boolean ActivateConfiguration () {
  2097.     // Firewall should start after Write()
  2098.     if (GetStartService()) {
  2099.         // Not started - start it
  2100.         if (!IsStarted()) {
  2101.         y2milestone("Starting firewall services");
  2102.         return StartServices();
  2103.         // Started - restart it
  2104.         } else {
  2105.         // modified - restart it, or ...
  2106.         // bugzilla #186186
  2107.         // If any RPC service is configured to be allowed, always restart the firewall
  2108.         // Some of these service's ports might have been reallocated (when SuSEFirewall
  2109.         // is used from outside, e.g., yast2-nfs-server)
  2110.         if (GetModified() || AnyRPCServiceInConfiguration()) {
  2111.             y2milestone("Stopping firewall services");
  2112.             StopServices();
  2113.             y2milestone("Starting firewall services");
  2114.             return StartServices();
  2115.         // not modified - skip restart
  2116.         } else {
  2117.             y2milestone("Configuration hasn't modified, skipping restarting services");
  2118.         }
  2119.         }
  2120.     // Firewall should stop after Write()
  2121.     } else {
  2122.         // started - stop
  2123.         if (IsStarted()) {
  2124.         y2milestone("Stopping firewall services");
  2125.         return StopServices();
  2126.         // stopped - skip stopping
  2127.         } else {
  2128.         y2milestone("Firewall has been stopped already");
  2129.         return true;
  2130.         }
  2131.     }
  2132.     }
  2133.  
  2134.     /**
  2135.      * Function writes configuration into /etc/sysconfig/ and enables or disables
  2136.      * firewall in /etc/init.d/ by the setting SetEnableService(boolean).
  2137.      * This is a write-only configuration, firewall is never started only enabled
  2138.      * or disabled.
  2139.      *
  2140.      * @return    boolean if successful
  2141.      */
  2142.     global define boolean WriteConfiguration () {
  2143.     // Progress only for normal configuration and command line
  2144.     boolean have_progress = (Mode::normal());
  2145.  
  2146.     if (have_progress) {
  2147.         // TRANSLATORS: Dialog caption
  2148.         string write_caption = _("Writing Firewall Configuration");
  2149.  
  2150.         Progress::New( write_caption, " ", 2,
  2151.         [
  2152.             // TRANSLATORS: Progress step
  2153.             _("Write firewall settings"),
  2154.             // TRANSLATORS: Progress step
  2155.             _("Adjust firewall service"),
  2156.         ],
  2157.         [
  2158.             // TRANSLATORS: Progress step
  2159.             _("Writing firewall settings..."),
  2160.             // TRANSLATORS: Progress step
  2161.             _("Adjusting firewall service..."),
  2162.             // TRANSLATORS: Progress step
  2163.             Message::Finished(),
  2164.         ],
  2165.         ""
  2166.         );
  2167.  
  2168.         Progress::NextStage();
  2169.     }
  2170.  
  2171.     // only modified configuration is written
  2172.     if (GetModified()) {
  2173.         y2milestone("Firewall configuration has been changed. Writing: %1.", SETTINGS);
  2174.  
  2175.         if (! WriteSysconfigSuSEFirewall ( GetListOfSuSEFirewallVariables() )) {
  2176.         // TRANSLATORS: a popup error message
  2177.         Report::Error(_("Writing settings failed"));
  2178.         return false;
  2179.         }
  2180.     } else {
  2181.         y2milestone("Firewall settings weren't modified, skipping...");
  2182.     }
  2183.  
  2184.     if (have_progress) Progress::NextStage();
  2185.  
  2186.     // Adjusting services
  2187.     if (GetModified()) {
  2188.         // enabling firewall in /etc/init.d/
  2189.         if (SETTINGS["enable_firewall"]:false) {
  2190.         y2milestone("Enabling firewall services");
  2191.         if (! EnableServices()) {
  2192.             return false;
  2193.         }
  2194.         // disabling firewall in /etc/init.d/    
  2195.         } else {
  2196.         y2milestone("Disabling firewall services");
  2197.         if (! DisableServices()) {
  2198.             return false;
  2199.         }
  2200.         }
  2201.     } else {
  2202.         y2milestone("Firewall enable/disable wasn't modified, skipping...");
  2203.     }
  2204.  
  2205.     if (have_progress) Progress::NextStage();
  2206.  
  2207.     if (have_progress) Progress::Finish();
  2208.  
  2209.     return true;
  2210.     }
  2211.  
  2212.     /**
  2213.      * Helper function for the backward compatibility.
  2214.      * See WriteConfiguration(). Remove from code ASAP.
  2215.      */
  2216.     global define boolean WriteOnly() {
  2217.     return WriteConfiguration();
  2218.     }
  2219.  
  2220.     /**
  2221.      * Function for writing and enabling configuration it is an union of
  2222.      * WriteConfiguration() and ActivateConfiguration().
  2223.      *
  2224.      * @return    boolean if succesfull
  2225.      */
  2226.     global define boolean Write () {
  2227.  
  2228.     if (! WriteConfiguration())    return false;
  2229.  
  2230.     if (! ActivateConfiguration())    return false;
  2231.  
  2232.     return true;
  2233.     }
  2234.  
  2235.     /**
  2236.      * Function for saving configuration and restarting firewall.
  2237.      * Is is the same as Write() but write is allways forced.
  2238.      *
  2239.      * @return    boolean if successful
  2240.      */
  2241.     global define boolean SaveAndRestartService () {
  2242.     y2milestone("Forced save and restart");
  2243.     SetModified();
  2244.  
  2245.     SetStartService(true);
  2246.  
  2247.     if (! Write()) {
  2248.         return false;
  2249.     }
  2250.     
  2251.     return true;
  2252.     }
  2253.  
  2254.     /**
  2255.      * This powerful function returns list of services/ports which are
  2256.      * not assigned to any fully-supported known-services.
  2257.      *
  2258.      * @return    list <string> of additional (unassigned) services
  2259.      */
  2260.     global define list <string> GetAdditionalServices (string protocol, string zone) {
  2261.     list <string> additional_services = [];
  2262.  
  2263.     if (! IsSupportedProtocol(protocol)) {
  2264.         y2error("Unknown protocol '%1'", protocol);
  2265.         return nil;
  2266.     }
  2267.     if (! IsKnownZone(zone)) {
  2268.         y2error("Unknown zone '%1'", zone);
  2269.         return nil;
  2270.     }
  2271.  
  2272.     // all ports or services allowed in zone for protocol
  2273.     list <string> all_allowed_services = GetAllowedServicesForZoneProto(zone, protocol);
  2274.  
  2275.     // all ports or services used by known service
  2276.     list <string> all_used_services = [];
  2277.  
  2278.     // trying all possible (known) services
  2279.     foreach (string service_id, string service_name, SuSEFirewallServices::GetSupportedServices(), {
  2280.         // only when the service is allowed in zone - remove all its needed ports
  2281.         if (IsServiceSupportedInZone(service_id, zone)) {
  2282.  
  2283.         // all needed ports etc for service/protocol, well, I'm not good at function pointers :-<
  2284.         list <string> needed_all = [];
  2285.         if (protocol == "TCP") {
  2286.             needed_all = SuSEFirewallServices::GetNeededTCPPorts(service_id);
  2287.         } else if (protocol == "UDP") {
  2288.             needed_all = SuSEFirewallServices::GetNeededUDPPorts(service_id);
  2289.         } else if (protocol == "RPC") {
  2290.             needed_all = SuSEFirewallServices::GetNeededRPCPorts(service_id);
  2291.         } else if (protocol == "IP") {
  2292.             needed_all = SuSEFirewallServices::GetNeededIPProtocols(service_id);
  2293.         }
  2294.         foreach (string remove_port, needed_all, {
  2295.             // all used services and their aliases
  2296.             all_used_services = (list <string>) union (
  2297.             all_used_services, PortAliases::GetListOfServiceAliases(remove_port)
  2298.             );
  2299.         });
  2300.  
  2301.         }
  2302.     });
  2303.  
  2304.     // some services are used by known defined-services
  2305.     if (size(all_used_services)>0) {
  2306.         all_used_services = toset (all_used_services);
  2307.         // removing all used services from all allowed
  2308.         all_allowed_services = filter (string port, all_allowed_services, {
  2309.         return (! contains(all_used_services, port));
  2310.         });
  2311.     }
  2312.  
  2313.     // well, actually it returns list of services not-assigned to any well-known service
  2314.     return all_allowed_services;
  2315.     }
  2316.  
  2317.     /**
  2318.      * Function sets additional ports/services from taken list. Firstly, all additional services
  2319.      * are removed also with their aliases. Secondly new ports/protocols are added.
  2320.      *
  2321.      * @param    string protocol
  2322.      * @param    string zone
  2323.      * @param    list <string> list of ports/protocols
  2324.      */
  2325.     global define void SetAdditionalServices (string protocol, string zone, list <string> new_list_services) {
  2326.     list <string> old_list_services = toset(GetAdditionalServices(protocol, zone));
  2327.     new_list_services = toset(new_list_services);
  2328.  
  2329.     if (new_list_services != old_list_services) {
  2330.         SetModified();
  2331.  
  2332.         list <string> add_services = [];
  2333.         list <string> remove_services = [];
  2334.  
  2335.         // Add these services
  2336.         foreach (string service, new_list_services, {
  2337.         if (!contains(old_list_services, service))
  2338.             add_services = add (add_services, service);
  2339.         });
  2340.         // Remove these services
  2341.         foreach (string service, old_list_services, {
  2342.         if (!contains(new_list_services, service))
  2343.             remove_services = add (remove_services, service);
  2344.         });
  2345.  
  2346.         if (size(remove_services)>0) {
  2347.         y2milestone("Removing additional services %1/%2 from zone %3", remove_services, protocol, zone);
  2348.         RemoveAllowedPortsOrServices (remove_services, protocol, zone, true);
  2349.         }
  2350.         if (size(add_services)>0) {
  2351.         y2milestone("Adding additional services %1/%2 into zone %3", add_services, protocol, zone);
  2352.         AddAllowedPortsOrServices (add_services, protocol, zone);
  2353.         }
  2354.     }
  2355.     }
  2356.  
  2357.     /**
  2358.      * Function returns if any other firewall then SuSEfirewall2 is currently running on the
  2359.      * system. It uses command `iptables` to get information about just active iptables
  2360.      * rules and compares the output with current status of SuSEfirewall2.
  2361.      *
  2362.      * @return    boolean if other firewall is running
  2363.      */
  2364.     global define boolean IsOtherFirewallRunning () {
  2365.     boolean any_firewall_running = true;
  2366.  
  2367.     // grep must return at least blank lines, else it returns 'exit 1' instead of 'exit 0'
  2368.     string command = "iptables -L -n | grep -v \"^\\(Chain\\|target\\)\"";
  2369.  
  2370.     map iptables = (map) SCR::Execute(.target.bash_output, command);
  2371.     if (iptables["exit"]:0 == 0) {
  2372.         list <string> iptables_list = splitstring(iptables["stdout"]:"", "\n");
  2373.         iptables_list = filter (string iptable_rule, iptables_list, {
  2374.         return iptable_rule != "";
  2375.         });
  2376.  
  2377.         y2milestone("Count of active iptables now: %1", size(iptables_list));
  2378.  
  2379.         // none iptables rules
  2380.         if (size(iptables_list)>0) {
  2381.         any_firewall_running = true;
  2382.         // any iptables rules exist
  2383.         } else {
  2384.         any_firewall_running = false;
  2385.         }
  2386.     // error running command
  2387.     } else {
  2388.         y2error("Services Command: %1 (Exit %2) -> %3", command, iptables["exit"]:nil, iptables["stderr"]:nil);
  2389.         return nil;
  2390.     }
  2391.  
  2392.     // any firewall is running but it is not a SuSEfirewall2
  2393.     if (any_firewall_running && !IsStarted()) {
  2394.         y2warning("Any other firewall is running...");
  2395.         return true;
  2396.     }
  2397.     // no firewall is running or the running firewall is SuSEfirewall2
  2398.     return false;
  2399.     }
  2400.  
  2401.     /**
  2402.      * Function returns map of `interfaces in zones`.
  2403.      *
  2404.      * @return    map <string, list <string> >
  2405.      * @struct    map $[zone : [list of interfaces]]
  2406.      */
  2407.     global define map <string, list <string> > GetFirewallInterfacesMap () {
  2408.     map <string, list <string> > firewall_interfaces_now = $[];
  2409.  
  2410.     // list of all known interfaces
  2411.     list <string> known_interfaces = GetListOfKnownInterfaces();
  2412.  
  2413.     // searching each zone
  2414.     foreach (string zone, GetKnownFirewallZones(), {
  2415.         // filtering non-existing interfaces
  2416.         firewall_interfaces_now[zone] = filter (string interface, GetInterfacesInZone(zone), {
  2417.         return contains(known_interfaces, interface);
  2418.         });
  2419.     });
  2420.  
  2421.     return firewall_interfaces_now;
  2422.     }
  2423.  
  2424.     /**
  2425.      * Function returns list of special strings like 'any' or 'auto' and uknown interfaces.
  2426.      *
  2427.      * @param    string zone
  2428.      * @return    list <string> special strings or unknown interfaces
  2429.      */
  2430.     global define list <string> GetSpecialInterfacesInZone (string zone) {
  2431.     list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
  2432.  
  2433.     list <string> known_interfaces_now = GetInterfacesInZone (zone);
  2434.  
  2435.     // filtering known interfaces and spaces
  2436.     interfaces_in_zone = filter(string interface, interfaces_in_zone, {
  2437.         return interface != "" && !contains(known_interfaces_now, interface);
  2438.     });
  2439.     
  2440.     return interfaces_in_zone;
  2441.     }
  2442.  
  2443.     /**
  2444.      * Function removes special string from defined zone.
  2445.      *
  2446.      * @param    string interface
  2447.      * @param    string zone
  2448.      */
  2449.     global define void RemoveSpecialInterfaceFromZone (string interface, string zone) {
  2450.     SetModified();
  2451.  
  2452.     y2milestone("Removing special string '%1' from '%2' zone.", interface, zone);
  2453.  
  2454.     list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
  2455.     interfaces_in_zone = filter (string single_interface, interfaces_in_zone, {
  2456.         return single_interface != "" && single_interface != interface;
  2457.     });
  2458.     SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
  2459.     }
  2460.  
  2461.     /**
  2462.      * Functions adds special string into defined zone.
  2463.      *
  2464.      * @param    string interface
  2465.      * @param    string zone
  2466.      */
  2467.     global define void AddSpecialInterfaceIntoZone (string interface, string zone) {
  2468.     SetModified();
  2469.     
  2470.     y2milestone("Adding special string '%1' into '%2' zone.", interface, zone);
  2471.     list <string> interfaces_in_zone = splitstring (SETTINGS["FW_DEV_" + zone]:"", " ");
  2472.     interfaces_in_zone = toset(add (interfaces_in_zone, interface));
  2473.     SETTINGS["FW_DEV_" + zone] = mergestring(interfaces_in_zone, " ");
  2474.     }
  2475.  
  2476.     /**
  2477.      * Function returns actual state of Masquerading support.
  2478.      *
  2479.      * @return    boolean if supported
  2480.      */
  2481.     global define boolean GetMasquerade () {
  2482.     return (SETTINGS["FW_MASQUERADE"]:"no" == "yes" && SETTINGS["FW_ROUTE"]:"no" == "yes");
  2483.     }
  2484.  
  2485.     /**
  2486.      * Function sets Masquerade support.
  2487.      *
  2488.      * @param    boolean to support or not to support it
  2489.      */
  2490.     global define void SetMasquerade (boolean enable) {
  2491.     SetModified();
  2492.  
  2493.     SETTINGS["FW_MASQUERADE"] = (enable ? "yes" : "no");
  2494.  
  2495.     // routing is needed for masquerading, but we can't swithc it off when disabling masquerading
  2496.     if (enable) SETTINGS["FW_ROUTE"] = "yes";
  2497.     }
  2498.  
  2499.     /**
  2500.      * Function returns list of rules of forwarding ports
  2501.      * to masqueraded IPs.
  2502.      *
  2503.      * @retyrn  list <map <string, string> >
  2504.      * @struct    list [$[ key: value ]]
  2505.      */
  2506.     global define list <map <string, string> > GetListOfForwardsIntoMasquerade () {
  2507.     list <map <string, string> > list_of_rules = [];
  2508.  
  2509.     foreach (string forward_rule, splitstring(SETTINGS["FW_FORWARD_MASQ"]:"", " "), {
  2510.         if (forward_rule == "") return;
  2511.  
  2512.         // Format: <source network>,<ip to forward to>,<protocol>,<port>[,redirect port,[destination ip]]
  2513.         list <string> fw_rul = splitstring(forward_rule,",");
  2514.  
  2515.         // first four parameters has to be defined
  2516.         if (fw_rul[0]:"" == "" || fw_rul[1]:"" == "" || fw_rul[2]:"" == "" || fw_rul[3]:"" == "")
  2517.         y2warning("Wrong definition of redirect rule: '%1', part of '%2'",
  2518.             forward_rule, SETTINGS["FW_FORWARD_MASQ"]:""
  2519.         );
  2520.  
  2521.         list_of_rules = add (list_of_rules, $[
  2522.         "source_net" : fw_rul[0]:"",
  2523.         "forward_to" : fw_rul[1]:"",
  2524.         "protocol"   : tolower(fw_rul[2]:""),
  2525.         "req_port"   : tolower(fw_rul[3]:""),
  2526.         // to_port is req_port when undefined
  2527.         "to_port"    : tolower(fw_rul[4]:fw_rul[3]:""),
  2528.         "req_ip"     : tolower(fw_rul[5]:""),
  2529.         ]);
  2530.     });
  2531.  
  2532.     return list_of_rules;
  2533.     }
  2534.  
  2535.     /**
  2536.      * Function removes rule for forwarding into masquerade
  2537.      * from the list of current rules.
  2538.      *
  2539.      * @params    integer item number
  2540.      */
  2541.     global define void RemoveForwardIntoMasqueradeRule (integer remove_item) {
  2542.     SetModified();
  2543.  
  2544.     list <string> forward_rules = [];
  2545.  
  2546.     integer row_counter = 0;
  2547.     foreach (string forward_rule, splitstring(SETTINGS["FW_FORWARD_MASQ"]:"", " "), {
  2548.         if (forward_rule == "") return;
  2549.  
  2550.         if (row_counter != remove_item) {
  2551.         forward_rules = add (forward_rules, forward_rule);
  2552.         }
  2553.         
  2554.         row_counter = row_counter + 1;
  2555.     });
  2556.  
  2557.     SETTINGS["FW_FORWARD_MASQ"] = mergestring(forward_rules, " ");
  2558.     }
  2559.  
  2560.     /**
  2561.      * Adds forward into masquerade rule.
  2562.      */
  2563.     global define void AddForwardIntoMasqueradeRule (
  2564.     string source_net, string forward_to_ip, string protocol, string req_port,
  2565.     string redirect_to_port, string requested_ip
  2566.     ) {
  2567.     SetModified();
  2568.  
  2569.     string masquerade_rules = SETTINGS["FW_FORWARD_MASQ"]:"";
  2570.  
  2571.     masquerade_rules = masquerade_rules + (masquerade_rules != "" ? " ":"") +
  2572.         source_net + "," +
  2573.         forward_to_ip + "," +
  2574.         protocol + "," +
  2575.         req_port;
  2576.  
  2577.     if (redirect_to_port != "" || requested_ip != "") {
  2578.         if (requested_ip != "") {
  2579.         masquerade_rules = masquerade_rules + "," + redirect_to_port + "," + requested_ip;
  2580.         // port1 -> port2 are same
  2581.         } else if (redirect_to_port != req_port) {
  2582.         masquerade_rules = masquerade_rules + "," + redirect_to_port;
  2583.         }
  2584.     }
  2585.  
  2586.     SETTINGS["FW_FORWARD_MASQ"] = masquerade_rules;
  2587.     }
  2588.  
  2589.     /**
  2590.      * Function returns actual state of logging for rule taken as parameter.
  2591.      *
  2592.      * @param    string rule definition 'ACCEPT' or 'DROP'
  2593.      * @return    string 'ALL', 'CRIT', or 'NONE'
  2594.      */
  2595.     global define string GetLoggingSettings(string rule) {
  2596.     string ret_val = nil;
  2597.  
  2598.     if (rule == "ACCEPT") {
  2599.         if (SETTINGS["FW_LOG_ACCEPT_ALL"]:"no" == "yes") {
  2600.         ret_val = "ALL";
  2601.         } else if (SETTINGS["FW_LOG_ACCEPT_CRIT"]:"yes" == "yes") {
  2602.         ret_val = "CRIT";
  2603.         } else {
  2604.         ret_val = "NONE";
  2605.         }
  2606.     } else if (rule == "DROP") {
  2607.         if (SETTINGS["FW_LOG_DROP_ALL"]:"no" == "yes") {
  2608.         ret_val = "ALL";
  2609.         } else if (SETTINGS["FW_LOG_DROP_CRIT"]:"yes" == "yes") {
  2610.         ret_val = "CRIT";
  2611.         } else {
  2612.         ret_val = "NONE";
  2613.         }
  2614.     } else {
  2615.         y2error("Possible rules are only 'ACCEPT' or 'DROP'");
  2616.     }
  2617.  
  2618.     return ret_val;
  2619.     }
  2620.  
  2621.     /**
  2622.      * Function sets state of logging for rule taken as parameter.
  2623.      *
  2624.      * @param    string rule definition 'ACCEPT' or 'DROP'
  2625.      * @param    string new logging state 'ALL', 'CRIT', or 'NONE'
  2626.      */
  2627.     global define void SetLoggingSettings(string rule, string state) {
  2628.     SetModified();
  2629.  
  2630.     if (rule == "ACCEPT") {
  2631.         if (state == "ALL") {
  2632.         SETTINGS["FW_LOG_ACCEPT_CRIT"] = "yes";
  2633.         SETTINGS["FW_LOG_ACCEPT_ALL"]  = "yes";
  2634.         } else if (state == "CRIT") {
  2635.         SETTINGS["FW_LOG_ACCEPT_CRIT"] = "yes";
  2636.         SETTINGS["FW_LOG_ACCEPT_ALL"]  = "no";
  2637.         } else {
  2638.         SETTINGS["FW_LOG_ACCEPT_CRIT"] = "no";
  2639.         SETTINGS["FW_LOG_ACCEPT_ALL"]  = "no";
  2640.         }
  2641.     } else if (rule == "DROP") {
  2642.         if (state == "ALL") {
  2643.         SETTINGS["FW_LOG_DROP_CRIT"] = "yes";
  2644.         SETTINGS["FW_LOG_DROP_ALL"]  = "yes";
  2645.         } else if (state == "CRIT") {
  2646.         SETTINGS["FW_LOG_DROP_CRIT"] = "yes";
  2647.         SETTINGS["FW_LOG_DROP_ALL"]  = "no";
  2648.         } else {
  2649.         SETTINGS["FW_LOG_DROP_CRIT"] = "no";
  2650.         SETTINGS["FW_LOG_DROP_ALL"]  = "no";
  2651.         }
  2652.     } else {
  2653.         y2error("Possible rules are only 'ACCEPT' or 'DROP'");
  2654.     }
  2655.     }
  2656.  
  2657.     /**
  2658.      * Function returns yes/no - ingoring broadcast for zone
  2659.      *
  2660.      * @param    string zone
  2661.      */
  2662.     global define string GetIgnoreLoggingBroadcast (string zone) {
  2663.     if (! IsKnownZone(zone)) {
  2664.         y2error("Unknown zone '%1'", zone);
  2665.         return nil;
  2666.     }
  2667.  
  2668.     return SETTINGS["FW_IGNORE_FW_BROADCAST_" + zone]:"no";
  2669.     }
  2670.  
  2671.     /**
  2672.      * Function sets yes/no - ingoring broadcast for zone
  2673.      *
  2674.      * @param    string zone
  2675.      * @param    string ignore 'yes' or 'no'
  2676.      */
  2677.     global define void SetIgnoreLoggingBroadcast (string zone, string bcast) {
  2678.     if (! IsKnownZone(zone)) {
  2679.         y2error("Unknown zone '%1'", zone);
  2680.         return nil;
  2681.     }
  2682.  
  2683.     SetModified();
  2684.  
  2685.     SETTINGS["FW_IGNORE_FW_BROADCAST_" + zone] = bcast;
  2686.     }
  2687.  
  2688.     /**
  2689.      * Function adds a special interface into the FW_FORWARD_ALWAYS_INOUT_DEV variable
  2690.      *
  2691.      * @see: https://bugzilla.novell.com/show_bug.cgi?id=154133
  2692.      */
  2693.     global define void AddXenSupport () {
  2694.     string special_xen_interface = "xenbr0";
  2695.  
  2696.     SetModified();
  2697.  
  2698.     list <string> allways_inout_dev = splitstring (SETTINGS["FW_FORWARD_ALWAYS_INOUT_DEV"]:"", " ");
  2699.     allways_inout_dev = toset(add (allways_inout_dev, special_xen_interface));
  2700.     SETTINGS["FW_FORWARD_ALWAYS_INOUT_DEV"] = mergestring(allways_inout_dev, " ");
  2701.     
  2702.     y2milestone("FW_FORWARD_ALWAYS_INOUT_DEV -> %1", SETTINGS["FW_FORWARD_ALWAYS_INOUT_DEV"]:"");
  2703.     }
  2704.  
  2705.     // Firewall Expert Rulezz
  2706.  
  2707.     /*\
  2708.      * Returns list of rules describing protocols and ports that are allowed
  2709.      * to be accessed from listed hosts. All is returned as a single string.
  2710.      * Zone needs to be defined.
  2711.      *
  2712.      * @param string zone
  2713.      * @return string with rules
  2714.      */
  2715.     global define string GetAcceptExpertRules (string zone) {
  2716.     zone = toupper(zone);
  2717.  
  2718.     // Check for zone
  2719.     if (! contains(GetKnownFirewallZones(), zone)) {
  2720.         y2error("Unknown firewall zone: %1", zone);
  2721.         return nil;
  2722.     }
  2723.  
  2724.     return SETTINGS["FW_SERVICES_ACCEPT_" + zone]:"";
  2725.     }
  2726.  
  2727.     /*\
  2728.      * Sets expert allow rules for zone.
  2729.      *
  2730.      * @param string zone
  2731.      * @param string whitespace-separated expert_rules
  2732.      * @return boolean if successful
  2733.      */
  2734.     global define boolean SetAcceptExpertRules (string zone, string expert_rules) {
  2735.     zone = toupper(zone);
  2736.  
  2737.     // Check for zone
  2738.     if (! contains(GetKnownFirewallZones(), zone)) {
  2739.         y2error("Unknown firewall zone: %1", zone);
  2740.         return false;
  2741.     }
  2742.     
  2743.     SETTINGS["FW_SERVICES_ACCEPT_" + zone] = expert_rules;
  2744.  
  2745.     return true;
  2746.     }
  2747.  
  2748.     # <!-- SuSEFirewall GLOBAL FUNCTIONS //-->
  2749.  
  2750. /* EOF */
  2751. }
  2752.