Blob Blame History Raw
Adapted version of

commit 133e8e7cc77dfe10269ac146f3c03810f50062dd
Author: Thomas Woerner <twoerner@redhat.com>
Date:   Thu Jan 15 17:36:09 2015 +0100

    Fix readdition of removed permanent direct settings (RHBZ#1182641)
    
    Permanent direct settings are not recognized as such while reloading firewalld
    after adding the rules to the permanent environment if firewalld has been
    reloaded after adding the settings in the first place and after they have been
    removed again from the permanent environment again.
    
    A new test has been added to firewall-cmd_test.sh for verification.

diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
index 7787103..2ac7484 100644
--- a/src/firewall/core/fw.py
+++ b/src/firewall/core/fw.py
@@ -211,9 +211,7 @@ class Firewall:
             log.debug1("Failed to load direct rules file '%s': %s",
                       FIREWALLD_DIRECT, msg)
         else:
-            self.direct.set_config((obj.get_all_chains(),
-                                    obj.get_all_rules(),
-                                    obj.get_all_passthroughs()))
+            self.direct.set_permanent_config(obj)
         self.config.set_direct(copy.deepcopy(obj))
 
         # check if default_zone is a valid zone
@@ -652,7 +650,7 @@ class Firewall:
         for zone in self.zone.get_zones():
             _zone_interfaces[zone] = self.zone.get_settings(zone)["interfaces"]
         # save direct config
-        _direct_config = self.direct.get_config()
+        _direct_config = self.direct.get_runtime_config()
         _old_dz = self.get_default_zone()
 
         # stop
diff --git a/src/firewall/core/fw_direct.py b/src/firewall/core/fw_direct.py
index 358d182..a4cbf51 100644
--- a/src/firewall/core/fw_direct.py
+++ b/src/firewall/core/fw_direct.py
@@ -56,10 +56,51 @@ class FirewallDirect:
         self._rules = LastUpdatedOrderedDict()
         self._rule_priority_positions = { }
         self._passthroughs = LastUpdatedOrderedDict()
+        self._obj = None
 
     def cleanup(self):
         self.__init_vars()
 
+    def set_permanent_config(self, obj):
+        # Apply permanent configuration and save the obj to be able to
+        # remove permanent configuration settings within get_runtime_config
+        # for use in firewalld reload.
+        self._obj = obj
+        self.set_config((obj.get_all_chains(),
+                         obj.get_all_rules(),
+                         obj.get_all_passthroughs()))
+
+    def get_runtime_config(self):
+        # Return only runtime changes
+        # Remove all chains, rules and passthroughs that are in self._obj
+        # (permanent config applied in firewalld _start.
+        chains = LastUpdatedOrderedDict()
+        rules = LastUpdatedOrderedDict()
+        passthroughs = LastUpdatedOrderedDict()
+
+        for table_id in self._chains:
+            (ipv, table) = table_id
+            for chain in self._chains[table_id]:
+                if not self._obj.query_chain(ipv, table, chain):
+                    chains.setdefault(table_id, [ ]).append(chain)
+
+        for chain_id in self._rules:
+            (ipv, table, chain) = chain_id
+            for (priority, args) in self._rules[chain_id]:
+                if not self._obj.query_rule(ipv, table, chain, priority, args):
+                    if not chain_id in rules:
+                        rules[chain_id] = LastUpdatedOrderedDict()
+                    rules[chain_id][rule_id] = priority
+
+        for ipv in self._passthroughs:
+            for args in self._passthroughs[ipv]:
+                if not self._obj.query_passthrough(ipv, args):
+                    if not ipv in passthroughs:
+                        passthroughs[ipv] = [ ]
+                    passthroughs[ipv].append(args)
+
+        return (chains, rules, passthroughs)
+
     def get_config(self):
         return (self._chains, self._rules, self._passthroughs)
 
#diff --git a/src/tests/firewall-cmd_test.sh b/src/tests/firewall-cmd_test.sh
#index 75f6e2f..2b03e6a 100755
#--- a/src/tests/firewall-cmd_test.sh
#+++ b/src/tests/firewall-cmd_test.sh
#@@ -85,6 +85,20 @@ assert_bad() {
#   fi
# }
# 
#+assert_bad_contains() {
#+  local args="${1}"
#+  local value="${2}"
#+  local ret
#+
#+  ret=$(${path}firewall-cmd ${args}) > /dev/null
#+  if [[ ( "$?" -ne 0 ) || ( "${ret}" = *${value}* ) ]]; then
#+    ((failures++))
#+    echo -e "${args} ... ${RED}${failures}. FAILED (non-zero exit status or '${ret}' does contain '${value}')${RESTORE}"
#+  else
#+    echo "${args} ... OK"
#+  fi
#+}
#+
# # rich rules need separate assert methods because of quotation hell
# assert_rich_good() {
#   local operation="${1}"
#@@ -563,6 +577,22 @@ assert_good          "--permanent --direct --remove-chain ipv4 filter ${mychain_
# assert_bad           "--permanent --direct --query-chain ipv4 filter ${mychain_p}"
# assert_good          "--permanent --direct --remove-chain ipv4 filter dummy" # removing nonexisting chain is just warning
# 
#+rule1="ipv4 nat OUTPUT 0 -s 1.2.3.4 -d 1.2.3.4 -p tcp --dport 80 -j REDIRECT --to-ports 81"
#+rule2="ipv4 nat OUTPUT 0 -s 1.2.3.4 -d 1.2.3.4 -p tcp --dport 80 -j REDIRECT --to-ports 82"
#+assert_good          "--permanent --direct --add-rule ${rule1}"
#+assert_good_contains "--permanent --direct --get-all-rules" "${rule1}"
#+assert_good          "--reload"
#+assert_good_contains "--direct --get-all-rules" "${rule1}"
#+assert_good          "--permanent --direct --remove-rule ${rule1}"
#+assert_good          "--permanent --direct --add-rule ${rule2}"
#+assert_good_contains "--permanent --direct --get-all-rules" "${rule2}"
#+assert_good          "--reload"
#+assert_bad_contains  "--direct --get-all-rules" "${rule1}"
#+assert_good_contains "--direct --get-all-rules" "${rule2}"
#+assert_good          "--permanent --direct --remove-rule ${rule2}"
#+assert_good          "--reload"
#+assert_bad_contains  "--direct --get-all-rules" "${rule2}"
#+
# # lockdown
# 
# cmd="/usr/bin/command"
commit e74cf839be5c51f4d5dec739b92c0c0f11d54f46
Merge: b5cc946 e32c402
Author: Thomas Woerner <twoerner@redhat.com>
Date:   Mon May 18 13:43:07 2015 +0200

    Merge pull request #17 from jpopelka/landscape-io
    
    Fix flaws found by landscape.io


commit e85770bf37e785fed2f14839e64929215ffdd40f
Author: Mathieu Le Marec - Pasquet <kiorky@cryptelium.net>
Date:   Tue May 12 18:46:16 2015 +0200

    Another attempt to fix reload with direct rules.
    
    This refs #12 #13
    This fixes #14
    
    Signed-off-by: Mathieu Le Marec - Pasquet <kiorky@cryptelium.net>

diff --git a/src/firewall/core/fw_direct.py b/src/firewall/core/fw_direct.py
index 48dd18f..1e0e009 100644
--- a/src/firewall/core/fw_direct.py
+++ b/src/firewall/core/fw_direct.py
@@ -88,9 +88,9 @@ class FirewallDirect:
             (ipv, table, chain) = chain_id
             for (priority, args) in self._rules[chain_id]:
                 if not self._obj.query_rule(ipv, table, chain, priority, args):
-                    if not chain_id in rules:
+                    if chain_id not in rules:
                         rules[chain_id] = LastUpdatedOrderedDict()
-                    rules[chain_id][rule_id] = priority
+                    rules[chain_id][(priority, args)] = priority
 
         for ipv in self._passthroughs:
             for args in self._passthroughs[ipv]: