Blob Blame History Raw
From 21dae834490f1d004b2468c1532bf78fbf455d9e Mon Sep 17 00:00:00 2001
From: Eric Garver <e@erig.me>
Date: Wed, 19 Dec 2018 13:40:22 -0500
Subject: [PATCH 2/8] Add "RFC3964_IPv4" config option

As per RFC 3964, filter IPv6 traffic with 6to4 destination addresses
that correspond to IPv4 addresses that should not be routed over the
public internet.

Defaults to "yes".

(cherry picked from commit fce80236bf38dcdfa4a66cd86e6dc03dd08d7f03)
---
 config/firewalld.conf                  |  7 +++++++
 doc/xml/firewalld.conf.xml             | 12 ++++++++++++
 doc/xml/firewalld.dbus.xml             | 10 ++++++++++
 src/firewall/config/__init__.py.in     |  1 +
 src/firewall/core/fw.py                |  9 +++++++++
 src/firewall/core/io/firewalld_conf.py | 12 +++++++++++-
 src/firewall/server/config.py          | 20 +++++++++++++++++---
 src/tests/dbus/firewalld.conf.at       |  2 ++
 8 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/config/firewalld.conf b/config/firewalld.conf
index 7cb02561fd4d..1dbce81469e0 100644
--- a/config/firewalld.conf
+++ b/config/firewalld.conf
@@ -70,3 +70,10 @@ FirewallBackend=nftables
 # behavior set this to "no".
 # Default: yes
 FlushAllOnReload=yes
+
+# RFC3964_IPv4
+# As per RFC 3964, filter IPv6 traffic with 6to4 destination addresses that
+# correspond to IPv4 addresses that should not be routed over the public
+# internet.
+# Defaults to "yes".
+RFC3964_IPv4=yes
diff --git a/doc/xml/firewalld.conf.xml b/doc/xml/firewalld.conf.xml
index 600919ae822d..457cadfaa38e 100644
--- a/doc/xml/firewalld.conf.xml
+++ b/doc/xml/firewalld.conf.xml
@@ -171,6 +171,18 @@
             </listitem>
         </varlistentry>
 
+        <varlistentry>
+            <term><option>RFC3964_IPv4</option></term>
+            <listitem>
+                <para>
+                As per RFC 3964, filter IPv6 traffic with 6to4 destination
+                addresses that correspond to IPv4 addresses that should not
+                be routed over the public internet.
+                Defaults to "yes".
+                </para>
+            </listitem>
+        </varlistentry>
+
     </variablelist>
 
   </refsect1>
diff --git a/doc/xml/firewalld.dbus.xml b/doc/xml/firewalld.dbus.xml
index 132200f3cb42..028d3778e4b6 100644
--- a/doc/xml/firewalld.dbus.xml
+++ b/doc/xml/firewalld.dbus.xml
@@ -2635,6 +2635,16 @@
               </para>
             </listitem>
           </varlistentry>
+          <varlistentry id="FirewallD1.config.Properties.RFC3964_IPv4">
+            <term>FirewallBackend - s - (rw)</term>
+            <listitem>
+              <para>
+                As per RFC 3964, filter IPv6 traffic with 6to4 destination
+                addresses that correspond to IPv4 addresses that should not be
+                routed over the public internet. Valid options are; yes, no.
+              </para>
+            </listitem>
+          </varlistentry>
         </variablelist>
       </refsect3>
     </refsect2>
diff --git a/src/firewall/config/__init__.py.in b/src/firewall/config/__init__.py.in
index 2cfbef804778..5bb318c5b269 100644
--- a/src/firewall/config/__init__.py.in
+++ b/src/firewall/config/__init__.py.in
@@ -131,3 +131,4 @@ FALLBACK_LOG_DENIED = "off"
 FALLBACK_AUTOMATIC_HELPERS = "system"
 FALLBACK_FIREWALL_BACKEND = "nftables"
 FALLBACK_FLUSH_ALL_ON_RELOAD = True
+FALLBACK_RFC3964_IPV4 = True
diff --git a/src/firewall/core/fw.py b/src/firewall/core/fw.py
index e614a4609edc..e8d77f11b2ae 100644
--- a/src/firewall/core/fw.py
+++ b/src/firewall/core/fw.py
@@ -309,6 +309,15 @@ class Firewall(object):
                 log.debug1("FlushAllOnReload is set to '%s'",
                            self._flush_all_on_reload)
 
+            if self._firewalld_conf.get("RFC3964_IPv4"):
+                value = self._firewalld_conf.get("RFC3964_IPv4")
+                if value.lower() in [ "no", "false" ]:
+                    self._rfc3964_ipv4 = False
+                else:
+                    self._rfc3964_ipv4 = True
+                log.debug1("RFC3964_IPv4 is set to '%s'",
+                           self._rfc3964_ipv4)
+
         self.config.set_firewalld_conf(copy.deepcopy(self._firewalld_conf))
 
         self._select_firewall_backend(self._firewall_backend)
diff --git a/src/firewall/core/io/firewalld_conf.py b/src/firewall/core/io/firewalld_conf.py
index 953a6d2618ec..4ba5bf5f218d 100644
--- a/src/firewall/core/io/firewalld_conf.py
+++ b/src/firewall/core/io/firewalld_conf.py
@@ -30,7 +30,8 @@ from firewall.functions import b2u, u2b, PY2
 
 valid_keys = [ "DefaultZone", "MinimalMark", "CleanupOnExit", "Lockdown", 
                "IPv6_rpfilter", "IndividualCalls", "LogDenied",
-               "AutomaticHelpers", "FirewallBackend", "FlushAllOnReload" ]
+               "AutomaticHelpers", "FirewallBackend", "FlushAllOnReload",
+               "RFC3964_IPv4" ]
 
 class firewalld_conf(object):
     def __init__(self, filename):
@@ -81,6 +82,7 @@ class firewalld_conf(object):
             self.set("AutomaticHelpers", config.FALLBACK_AUTOMATIC_HELPERS)
             self.set("FirewallBackend", config.FALLBACK_FIREWALL_BACKEND)
             self.set("FlushAllOnReload", "yes" if config.FALLBACK_FLUSH_ALL_ON_RELOAD else "no")
+            self.set("RFC3964_IPv4", "yes" if config.FALLBACK_RFC3964_IPV4 else "no")
             raise
 
         for line in f:
@@ -192,6 +194,14 @@ class firewalld_conf(object):
                             config.FALLBACK_FLUSH_ALL_ON_RELOAD)
             self.set("FlushAllOnReload", str(config.FALLBACK_FLUSH_ALL_ON_RELOAD))
 
+        value = self.get("RFC3964_IPv4")
+        if not value or value.lower() not in [ "yes", "true", "no", "false" ]:
+            if value is not None:
+                log.warning("RFC3964_IPv4 '%s' is not valid, using default "
+                            "value %s", value if value else '',
+                            config.FALLBACK_RFC3964_IPV4)
+            self.set("RFC3964_IPv4", str(config.FALLBACK_RFC3964_IPV4))
+
     # save to self.filename if there are key/value changes
     def write(self):
         if len(self._config) < 1:
diff --git a/src/firewall/server/config.py b/src/firewall/server/config.py
index ba04107fe4a1..971dc7d4a14a 100644
--- a/src/firewall/server/config.py
+++ b/src/firewall/server/config.py
@@ -107,6 +107,7 @@ class FirewallDConfig(slip.dbus.service.Object):
                                                 "AutomaticHelpers": "readwrite",
                                                 "FirewallBackend": "readwrite",
                                                 "FlushAllOnReload": "readwrite",
+                                                "RFC3964_IPv4": "readwrite",
                                               })
 
     @handle_exceptions
@@ -487,7 +488,7 @@ class FirewallDConfig(slip.dbus.service.Object):
         if prop not in [ "DefaultZone", "MinimalMark", "CleanupOnExit",
                          "Lockdown", "IPv6_rpfilter", "IndividualCalls",
                          "LogDenied", "AutomaticHelpers", "FirewallBackend",
-                         "FlushAllOnReload" ]:
+                         "FlushAllOnReload", "RFC3964_IPv4" ]:
             raise dbus.exceptions.DBusException(
                 "org.freedesktop.DBus.Error.InvalidArgs: "
                 "Property '%s' does not exist" % prop)
@@ -536,6 +537,10 @@ class FirewallDConfig(slip.dbus.service.Object):
             if value is None:
                 value = "yes" if config.FALLBACK_FLUSH_ALL_ON_RELOAD else "no"
             return dbus.String(value)
+        elif prop == "RFC3964_IPv4":
+            if value is None:
+                value = "yes" if config.FALLBACK_RFC3964_IPV4 else "no"
+            return dbus.String(value)
 
     @dbus_handle_exceptions
     def _get_dbus_property(self, prop):
@@ -559,6 +564,8 @@ class FirewallDConfig(slip.dbus.service.Object):
             return dbus.String(self._get_property(prop))
         elif prop == "FlushAllOnReload":
             return dbus.String(self._get_property(prop))
+        elif prop == "RFC3964_IPv4":
+            return dbus.String(self._get_property(prop))
         else:
             raise dbus.exceptions.DBusException(
                 "org.freedesktop.DBus.Error.InvalidArgs: "
@@ -599,7 +606,7 @@ class FirewallDConfig(slip.dbus.service.Object):
             for x in [ "DefaultZone", "MinimalMark", "CleanupOnExit",
                        "Lockdown", "IPv6_rpfilter", "IndividualCalls",
                        "LogDenied", "AutomaticHelpers", "FirewallBackend",
-                       "FlushAllOnReload" ]:
+                       "FlushAllOnReload", "RFC3964_IPv4" ]:
                 ret[x] = self._get_property(x)
         elif interface_name in [ config.dbus.DBUS_INTERFACE_CONFIG_DIRECT,
                                  config.dbus.DBUS_INTERFACE_CONFIG_POLICIES ]:
@@ -626,7 +633,8 @@ class FirewallDConfig(slip.dbus.service.Object):
             if property_name in [ "MinimalMark", "CleanupOnExit", "Lockdown",
                                   "IPv6_rpfilter", "IndividualCalls",
                                   "LogDenied", "AutomaticHelpers",
-                                  "FirewallBackend", "FlushAllOnReload" ]:
+                                  "FirewallBackend", "FlushAllOnReload",
+                                  "RFC3964_IPv4" ]:
                 if property_name == "MinimalMark":
                     try:
                         int(new_value)
@@ -665,6 +673,12 @@ class FirewallDConfig(slip.dbus.service.Object):
                         raise FirewallError(errors.INVALID_VALUE,
                                             "'%s' for %s" % \
                                             (new_value, property_name))
+                if property_name == "RFC3964_IPv4":
+                    if new_value.lower() not in ["yes", "true", "no", "false"]:
+                        raise FirewallError(errors.INVALID_VALUE,
+                                            "'%s' for %s" % \
+                                            (new_value, property_name))
+
                 self.config.get_firewalld_conf().set(property_name, new_value)
                 self.config.get_firewalld_conf().write()
                 self.PropertiesChanged(interface_name,
diff --git a/src/tests/dbus/firewalld.conf.at b/src/tests/dbus/firewalld.conf.at
index 72c61bdc4940..07f6d31de725 100644
--- a/src/tests/dbus/firewalld.conf.at
+++ b/src/tests/dbus/firewalld.conf.at
@@ -14,6 +14,7 @@ string "IndividualCalls" : variant string "no"
 string "Lockdown" : variant string "no"
 string "LogDenied" : variant string "off"
 string "MinimalMark" : variant int32 100
+string "RFC3964_IPv4" : variant string "yes"
 ])
 
 m4_define([_helper], [
@@ -33,6 +34,7 @@ _helper([IndividualCalls], [string:"yes"], [variant string "yes"])
 _helper([FirewallBackend], [string:"iptables"], [variant string "iptables"])
 _helper([FlushAllOnReload], [string:"no"], [variant string "no"])
 _helper([CleanupOnExit], [string:"yes"], [variant string "yes"])
+_helper([RFC3964_IPv4], [string:"no"], [variant string "no"])
 dnl Note: DefaultZone is RO
 m4_undefine([_helper])
 
-- 
2.18.0