Blame src/firewall/core/io/zone.py

Packit a8ec6b
# -*- coding: utf-8 -*-
Packit a8ec6b
#
Packit a8ec6b
# Copyright (C) 2011-2016 Red Hat, Inc.
Packit a8ec6b
#
Packit a8ec6b
# Authors:
Packit a8ec6b
# Thomas Woerner <twoerner@redhat.com>
Packit a8ec6b
#
Packit a8ec6b
# This program is free software; you can redistribute it and/or modify
Packit a8ec6b
# it under the terms of the GNU General Public License as published by
Packit a8ec6b
# the Free Software Foundation; either version 2 of the License, or
Packit a8ec6b
# (at your option) any later version.
Packit a8ec6b
#
Packit a8ec6b
# This program is distributed in the hope that it will be useful,
Packit a8ec6b
# but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit a8ec6b
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit a8ec6b
# GNU General Public License for more details.
Packit a8ec6b
#
Packit a8ec6b
# You should have received a copy of the GNU General Public License
Packit a8ec6b
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit a8ec6b
#
Packit a8ec6b
Packit a8ec6b
__all__ = [ "Zone", "zone_reader", "zone_writer" ]
Packit a8ec6b
Packit a8ec6b
import xml.sax as sax
Packit a8ec6b
import os
Packit a8ec6b
import io
Packit a8ec6b
import shutil
Packit a8ec6b
Packit a8ec6b
from firewall import config
Packit a8ec6b
from firewall.functions import checkIP, checkIP6, checkIPnMask, checkIP6nMask, checkInterface, uniqify, max_zone_name_len, u2b_if_py2, check_mac, portStr
Packit a8ec6b
from firewall.core.base import DEFAULT_ZONE_TARGET, ZONE_TARGETS
Packit a8ec6b
from firewall.core.io.io_object import PY2, IO_Object, \
Packit a8ec6b
    IO_Object_ContentHandler, IO_Object_XMLGenerator, check_port, \
Packit a8ec6b
    check_tcpudp, check_protocol
Packit a8ec6b
from firewall.core import rich
Packit a8ec6b
from firewall.core.logger import log
Packit a8ec6b
from firewall import errors
Packit a8ec6b
from firewall.errors import FirewallError
Packit a8ec6b
Packit a8ec6b
class Zone(IO_Object):
Packit a8ec6b
    """ Zone class """
Packit a8ec6b
Packit a8ec6b
    IMPORT_EXPORT_STRUCTURE = (
Packit a8ec6b
        ( "version",  "" ),                            # s
Packit a8ec6b
        ( "short", "" ),                               # s
Packit a8ec6b
        ( "description", "" ),                         # s
Packit a8ec6b
        ( "UNUSED", False ),                           # b
Packit a8ec6b
        ( "target", "" ),                              # s
Packit a8ec6b
        ( "services", [ "", ], ),                      # as
Packit a8ec6b
        ( "ports", [ ( "", "" ), ], ),                 # a(ss)
Packit a8ec6b
        ( "icmp_blocks", [ "", ], ),                   # as
Packit a8ec6b
        ( "masquerade", False ),                       # b
Packit a8ec6b
        ( "forward_ports", [ ( "", "", "", "" ), ], ), # a(ssss)
Packit a8ec6b
        ( "interfaces", [ "" ] ),                      # as
Packit a8ec6b
        ( "sources", [ "" ] ),                         # as
Packit a8ec6b
        ( "rules_str", [ "" ] ),                       # as
Packit a8ec6b
        ( "protocols", [ "", ], ),                     # as
Packit a8ec6b
        ( "source_ports", [ ( "", "" ), ], ),          # a(ss)
Packit a8ec6b
        ( "icmp_block_inversion", False ),             # b
Packit a8ec6b
        )
Packit a8ec6b
    DBUS_SIGNATURE = '(sssbsasa(ss)asba(ssss)asasasasa(ss)b)'
Packit a8ec6b
    ADDITIONAL_ALNUM_CHARS = [ "_", "-", "/" ]
Packit a8ec6b
    PARSER_REQUIRED_ELEMENT_ATTRS = {
Packit a8ec6b
        "short": None,
Packit a8ec6b
        "description": None,
Packit a8ec6b
        "zone": None,
Packit a8ec6b
        "service": [ "name" ],
Packit a8ec6b
        "port": [ "port", "protocol" ],
Packit a8ec6b
        "icmp-block": [ "name" ],
Packit a8ec6b
        "icmp-type": [ "name" ],
Packit a8ec6b
        "forward-port": [ "port", "protocol" ],
Packit a8ec6b
        "interface": [ "name" ],
Packit a8ec6b
        "rule": None,
Packit a8ec6b
        "source": None,
Packit a8ec6b
        "destination": [ "address" ],
Packit a8ec6b
        "protocol": [ "value" ],
Packit a8ec6b
        "source-port": [ "port", "protocol" ],
Packit a8ec6b
        "log":  None,
Packit a8ec6b
        "audit": None,
Packit a8ec6b
        "accept": None,
Packit a8ec6b
        "reject": None,
Packit a8ec6b
        "drop": None,
Packit a8ec6b
        "mark": [ "set" ],
Packit a8ec6b
        "limit": [ "value" ],
Packit a8ec6b
        "icmp-block-inversion": None,
Packit a8ec6b
        }
Packit a8ec6b
    PARSER_OPTIONAL_ELEMENT_ATTRS = {
Packit a8ec6b
        "zone": [ "name", "immutable", "target", "version" ],
Packit a8ec6b
        "masquerade": [ "enabled" ],
Packit a8ec6b
        "forward-port": [ "to-port", "to-addr" ],
Packit a8ec6b
        "rule": [ "family", "priority" ],
Packit a8ec6b
        "source": [ "address", "mac", "invert", "family", "ipset" ],
Packit a8ec6b
        "destination": [ "invert" ],
Packit a8ec6b
        "log": [ "prefix", "level" ],
Packit a8ec6b
        "reject": [ "type" ],
Packit a8ec6b
        }
Packit a8ec6b
Packit a8ec6b
    @staticmethod
Packit a8ec6b
    def index_of(element):
Packit a8ec6b
        for i, (el, dummy) in enumerate(Zone.IMPORT_EXPORT_STRUCTURE):
Packit a8ec6b
            if el == element:
Packit a8ec6b
                return i
Packit a8ec6b
        raise FirewallError(errors.UNKNOWN_ERROR, "index_of()")
Packit a8ec6b
Packit a8ec6b
    def __init__(self):
Packit a8ec6b
        super(Zone, self).__init__()
Packit a8ec6b
        self.version = ""
Packit a8ec6b
        self.short = ""
Packit a8ec6b
        self.description = ""
Packit a8ec6b
        self.UNUSED = False
Packit a8ec6b
        self.target = DEFAULT_ZONE_TARGET
Packit a8ec6b
        self.services = [ ]
Packit a8ec6b
        self.ports = [ ]
Packit a8ec6b
        self.protocols = [ ]
Packit a8ec6b
        self.icmp_blocks = [ ]
Packit a8ec6b
        self.masquerade = False
Packit a8ec6b
        self.forward_ports = [ ]
Packit a8ec6b
        self.source_ports = [ ]
Packit a8ec6b
        self.interfaces = [ ]
Packit a8ec6b
        self.sources = [ ]
Packit a8ec6b
        self.fw_config = None # to be able to check services and a icmp_blocks
Packit a8ec6b
        self.rules = [ ]
Packit a8ec6b
        self.icmp_block_inversion = False
Packit a8ec6b
        self.combined = False
Packit a8ec6b
        self.applied = False
Packit a8ec6b
Packit a8ec6b
    def cleanup(self):
Packit a8ec6b
        self.version = ""
Packit a8ec6b
        self.short = ""
Packit a8ec6b
        self.description = ""
Packit a8ec6b
        self.UNUSED = False
Packit a8ec6b
        self.target = DEFAULT_ZONE_TARGET
Packit a8ec6b
        del self.services[:]
Packit a8ec6b
        del self.ports[:]
Packit a8ec6b
        del self.protocols[:]
Packit a8ec6b
        del self.icmp_blocks[:]
Packit a8ec6b
        self.masquerade = False
Packit a8ec6b
        del self.forward_ports[:]
Packit a8ec6b
        del self.source_ports[:]
Packit a8ec6b
        del self.interfaces[:]
Packit a8ec6b
        del self.sources[:]
Packit a8ec6b
        self.fw_config = None # to be able to check services and a icmp_blocks
Packit a8ec6b
        del self.rules[:]
Packit a8ec6b
        self.icmp_block_inversion = False
Packit a8ec6b
        self.combined = False
Packit a8ec6b
        self.applied = False
Packit a8ec6b
Packit a8ec6b
    def encode_strings(self):
Packit a8ec6b
        """ HACK. I haven't been able to make sax parser return
Packit a8ec6b
            strings encoded (because of python 2) instead of in unicode.
Packit a8ec6b
            Get rid of it once we throw out python 2 support."""
Packit a8ec6b
        self.version = u2b_if_py2(self.version)
Packit a8ec6b
        self.short = u2b_if_py2(self.short)
Packit a8ec6b
        self.description = u2b_if_py2(self.description)
Packit a8ec6b
        self.target = u2b_if_py2(self.target)
Packit a8ec6b
        self.services = [u2b_if_py2(s) for s in self.services]
Packit a8ec6b
        self.ports = [(u2b_if_py2(po),u2b_if_py2(pr)) for (po,pr) in self.ports]
Packit a8ec6b
        self.protocols = [u2b_if_py2(pr) for pr in self.protocols]
Packit a8ec6b
        self.icmp_blocks = [u2b_if_py2(i) for i in self.icmp_blocks]
Packit a8ec6b
        self.forward_ports = [(u2b_if_py2(p1),u2b_if_py2(p2),u2b_if_py2(p3),u2b_if_py2(p4)) for (p1,p2,p3,p4) in self.forward_ports]
Packit a8ec6b
        self.source_ports = [(u2b_if_py2(po),u2b_if_py2(pr)) for (po,pr)
Packit a8ec6b
                             in self.source_ports]
Packit a8ec6b
        self.interfaces = [u2b_if_py2(i) for i in self.interfaces]
Packit a8ec6b
        self.sources = [u2b_if_py2(s) for s in self.sources]
Packit a8ec6b
        self.rules = [u2b_if_py2(s) for s in self.rules]
Packit Service 9bd718
Packit Service 9bd718
    def __getattr__(self, name):
Packit Service 9bd718
        if name == "rules_str":
Packit Service 9bd718
            rules_str = [str(rule) for rule in self.rules]
Packit Service 9bd718
            return rules_str
Packit Service 9bd718
        else:
Packit Service 9bd718
            return getattr(super(Zone, self), name)
Packit a8ec6b
Packit a8ec6b
    def __setattr__(self, name, value):
Packit a8ec6b
        if name == "rules_str":
Packit a8ec6b
            self.rules = [rich.Rich_Rule(rule_str=s) for s in value]
Packit a8ec6b
        else:
Packit a8ec6b
            super(Zone, self).__setattr__(name, value)
Packit a8ec6b
Packit a8ec6b
    def _check_config(self, config, item):
Packit a8ec6b
        if item == "services" and self.fw_config:
Packit a8ec6b
            existing_services = self.fw_config.get_services()
Packit a8ec6b
            for service in config:
Packit a8ec6b
                if service not in existing_services:
Packit a8ec6b
                    raise FirewallError(errors.INVALID_SERVICE,
Packit a8ec6b
                                        "'%s' not among existing services" % \
Packit a8ec6b
                                        service)
Packit a8ec6b
        elif item == "ports":
Packit a8ec6b
            for port in config:
Packit a8ec6b
                check_port(port[0])
Packit a8ec6b
                check_tcpudp(port[1])
Packit a8ec6b
        elif item == "protocols":
Packit a8ec6b
            for proto in config:
Packit a8ec6b
                check_protocol(proto)
Packit a8ec6b
        elif item == "icmp_blocks" and self.fw_config:
Packit a8ec6b
            existing_icmptypes = self.fw_config.get_icmptypes()
Packit a8ec6b
            for icmptype in config:
Packit a8ec6b
                if icmptype not in existing_icmptypes:
Packit a8ec6b
                    raise FirewallError(errors.INVALID_ICMPTYPE,
Packit a8ec6b
                                        "'%s' not among existing icmp types" % \
Packit a8ec6b
                                        icmptype)
Packit a8ec6b
        elif item == "forward_ports":
Packit a8ec6b
            for fwd_port in config:
Packit a8ec6b
                check_port(fwd_port[0])
Packit a8ec6b
                check_tcpudp(fwd_port[1])
Packit a8ec6b
                if not fwd_port[2] and not fwd_port[3]:
Packit a8ec6b
                    raise FirewallError(
Packit a8ec6b
                        errors.INVALID_FORWARD,
Packit a8ec6b
                        "'%s' is missing to-port AND to-addr " % fwd_port)
Packit a8ec6b
                if fwd_port[2]:
Packit a8ec6b
                    check_port(fwd_port[2])
Packit a8ec6b
                if fwd_port[3]:
Packit a8ec6b
                    if not checkIP(fwd_port[3]) and not checkIP6(fwd_port[3]):
Packit a8ec6b
                        raise FirewallError(
Packit a8ec6b
                            errors.INVALID_ADDR,
Packit a8ec6b
                            "to-addr '%s' is not a valid address" % fwd_port[3])
Packit a8ec6b
        elif item == "source_ports":
Packit a8ec6b
            for port in config:
Packit a8ec6b
                check_port(port[0])
Packit a8ec6b
                check_tcpudp(port[1])
Packit a8ec6b
        elif item == "target":
Packit a8ec6b
            if config not in ZONE_TARGETS:
Packit a8ec6b
                raise FirewallError(errors.INVALID_TARGET, config)
Packit a8ec6b
        elif item == "interfaces":
Packit a8ec6b
            for interface in config:
Packit a8ec6b
                if not checkInterface(interface):
Packit a8ec6b
                    raise FirewallError(errors.INVALID_INTERFACE, interface)
Packit a8ec6b
        elif item == "sources":
Packit a8ec6b
            for source in config:
Packit a8ec6b
                if not checkIPnMask(source) and not checkIP6nMask(source) and \
Packit a8ec6b
                   not check_mac(source) and not source.startswith("ipset:"):
Packit a8ec6b
                    raise FirewallError(errors.INVALID_ADDR, source)
Packit a8ec6b
        elif item == "rules_str":
Packit a8ec6b
            for rule in config:
Packit Service 9bd718
                rich.Rich_Rule(rule_str=rule)
Packit a8ec6b
Packit a8ec6b
    def check_name(self, name):
Packit a8ec6b
        super(Zone, self).check_name(name)
Packit a8ec6b
        if name.startswith('/'):
Packit a8ec6b
            raise FirewallError(errors.INVALID_NAME,
Packit a8ec6b
                                "'%s' can't start with '/'" % name)
Packit a8ec6b
        elif name.endswith('/'):
Packit a8ec6b
            raise FirewallError(errors.INVALID_NAME,
Packit a8ec6b
                                "'%s' can't end with '/'" % name)
Packit a8ec6b
        elif name.count('/') > 1:
Packit a8ec6b
            raise FirewallError(errors.INVALID_NAME,
Packit a8ec6b
                                "more than one '/' in '%s'" % name)
Packit a8ec6b
        else:
Packit a8ec6b
            if "/" in name:
Packit a8ec6b
                checked_name = name[:name.find('/')]
Packit a8ec6b
            else:
Packit a8ec6b
                checked_name = name
Packit a8ec6b
            if len(checked_name) > max_zone_name_len():
Packit a8ec6b
                raise FirewallError(errors.INVALID_NAME,
Packit a8ec6b
                                    "Zone of '%s' has %d chars, max is %d %s" % (
Packit a8ec6b
                                    name, len(checked_name),
Packit a8ec6b
                                    max_zone_name_len(),
Packit a8ec6b
                                    self.combined))
Packit a8ec6b
Packit a8ec6b
    def combine(self, zone):
Packit a8ec6b
        self.combined = True
Packit a8ec6b
        self.filename = None
Packit a8ec6b
        self.version = ""
Packit a8ec6b
        self.short = ""
Packit a8ec6b
        self.description = ""
Packit a8ec6b
Packit a8ec6b
        for interface in zone.interfaces:
Packit a8ec6b
            if interface not in self.interfaces:
Packit a8ec6b
                self.interfaces.append(interface)
Packit a8ec6b
        for source in zone.sources:
Packit a8ec6b
            if source not in self.sources:
Packit a8ec6b
                self.sources.append(source)
Packit a8ec6b
        for service in zone.services:
Packit a8ec6b
            if service not in self.services:
Packit a8ec6b
                self.services.append(service)
Packit a8ec6b
        for port in zone.ports:
Packit a8ec6b
            if port not in self.ports:
Packit a8ec6b
                self.ports.append(port)
Packit a8ec6b
        for proto in zone.protocols:
Packit a8ec6b
            if proto not in self.protocols:
Packit a8ec6b
                self.protocols.append(proto)
Packit a8ec6b
        for icmp in zone.icmp_blocks:
Packit a8ec6b
            if icmp not in self.icmp_blocks:
Packit a8ec6b
                self.icmp_blocks.append(icmp)
Packit a8ec6b
        if zone.masquerade:
Packit a8ec6b
            self.masquerade = True
Packit a8ec6b
        for forward in zone.forward_ports:
Packit a8ec6b
            if forward not in self.forward_ports:
Packit a8ec6b
                self.forward_ports.append(forward)
Packit a8ec6b
        for port in zone.source_ports:
Packit a8ec6b
            if port not in self.source_ports:
Packit a8ec6b
                self.source_ports.append(port)
Packit a8ec6b
        for rule in zone.rules:
Packit a8ec6b
            self.rules.append(rule)
Packit a8ec6b
        if zone.icmp_block_inversion:
Packit a8ec6b
            self.icmp_block_inversion = True
Packit a8ec6b
Packit a8ec6b
# PARSER
Packit a8ec6b
Packit a8ec6b
class zone_ContentHandler(IO_Object_ContentHandler):
Packit a8ec6b
    def __init__(self, item):
Packit a8ec6b
        IO_Object_ContentHandler.__init__(self, item)
Packit a8ec6b
        self._rule = None
Packit a8ec6b
        self._rule_error = False
Packit a8ec6b
        self._limit_ok = None
Packit a8ec6b
Packit a8ec6b
    def startElement(self, name, attrs):
Packit a8ec6b
        IO_Object_ContentHandler.startElement(self, name, attrs)
Packit a8ec6b
        if self._rule_error:
Packit a8ec6b
            return
Packit a8ec6b
Packit a8ec6b
        self.item.parser_check_element_attrs(name, attrs)
Packit a8ec6b
Packit a8ec6b
        if name == "zone":
Packit a8ec6b
            if "name" in attrs:
Packit a8ec6b
                log.warning("Ignoring deprecated attribute name='%s'",
Packit a8ec6b
                            attrs["name"])
Packit a8ec6b
            if "version" in attrs:
Packit a8ec6b
                self.item.version = attrs["version"]
Packit a8ec6b
            if "immutable" in attrs:
Packit a8ec6b
                log.warning("Ignoring deprecated attribute immutable='%s'",
Packit a8ec6b
                            attrs["immutable"])
Packit a8ec6b
            if "target" in attrs:
Packit a8ec6b
                target = attrs["target"]
Packit a8ec6b
                if target not in ZONE_TARGETS:
Packit a8ec6b
                    raise FirewallError(errors.INVALID_TARGET, target)
Packit a8ec6b
                if target != "" and target != DEFAULT_ZONE_TARGET:
Packit a8ec6b
                    self.item.target = target
Packit a8ec6b
Packit a8ec6b
        elif name == "short":
Packit a8ec6b
            pass
Packit a8ec6b
        elif name == "description":
Packit a8ec6b
            pass
Packit a8ec6b
        elif name == "service":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_Service(attrs["name"])
Packit a8ec6b
                return
Packit a8ec6b
            if attrs["name"] not in self.item.services:
Packit a8ec6b
                self.item.services.append(attrs["name"])
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Service '%s' already set, ignoring.",
Packit a8ec6b
                            attrs["name"])
Packit a8ec6b
Packit a8ec6b
        elif name == "port":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_Port(attrs["port"],
Packit a8ec6b
                                                    attrs["protocol"])
Packit a8ec6b
                return
Packit a8ec6b
            check_port(attrs["port"])
Packit a8ec6b
            check_tcpudp(attrs["protocol"])
Packit a8ec6b
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
Packit a8ec6b
            if entry not in self.item.ports:
Packit a8ec6b
                self.item.ports.append(entry)
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Port '%s/%s' already set, ignoring.",
Packit a8ec6b
                            attrs["port"], attrs["protocol"])
Packit a8ec6b
Packit a8ec6b
        elif name == "protocol":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_Protocol(attrs["value"])
Packit a8ec6b
            else:
Packit a8ec6b
                check_protocol(attrs["value"])
Packit a8ec6b
                if attrs["value"] not in self.item.protocols:
Packit a8ec6b
                    self.item.protocols.append(attrs["value"])
Packit a8ec6b
                else:
Packit a8ec6b
                    log.warning("Protocol '%s' already set, ignoring.",
Packit a8ec6b
                                attrs["value"])
Packit a8ec6b
        elif name == "icmp-block":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_IcmpBlock(attrs["name"])
Packit a8ec6b
                return
Packit a8ec6b
            if attrs["name"] not in self.item.icmp_blocks:
Packit a8ec6b
                self.item.icmp_blocks.append(attrs["name"])
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("icmp-block '%s' already set, ignoring.",
Packit a8ec6b
                            attrs["name"])
Packit a8ec6b
Packit a8ec6b
        elif name == "icmp-type":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_IcmpType(attrs["name"])
Packit a8ec6b
                return
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Invalid rule: icmp-block '%s' outside of rule",
Packit a8ec6b
                            attrs["name"])
Packit a8ec6b
Packit a8ec6b
        elif name == "masquerade":
Packit a8ec6b
            if "enabled" in attrs and \
Packit a8ec6b
               attrs["enabled"].lower() in [ "no", "false" ] :
Packit a8ec6b
                log.warning("Ignoring deprecated attribute enabled='%s'",
Packit a8ec6b
                            attrs["enabled"])
Packit a8ec6b
                return
Packit a8ec6b
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_Masquerade()
Packit a8ec6b
            else:
Packit a8ec6b
                if self.item.masquerade:
Packit a8ec6b
                    log.warning("Masquerade already set, ignoring.")
Packit a8ec6b
                else:
Packit a8ec6b
                    self.item.masquerade = True
Packit a8ec6b
Packit a8ec6b
        elif name == "forward-port":
Packit a8ec6b
            to_port = ""
Packit a8ec6b
            if "to-port" in attrs:
Packit a8ec6b
                to_port = attrs["to-port"]
Packit a8ec6b
            to_addr = ""
Packit a8ec6b
            if "to-addr" in attrs:
Packit a8ec6b
                to_addr = attrs["to-addr"]
Packit a8ec6b
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_ForwardPort(attrs["port"],
Packit a8ec6b
                                                           attrs["protocol"],
Packit a8ec6b
                                                           to_port, to_addr)
Packit a8ec6b
                return
Packit a8ec6b
Packit a8ec6b
            check_port(attrs["port"])
Packit a8ec6b
            check_tcpudp(attrs["protocol"])
Packit a8ec6b
            if to_port:
Packit a8ec6b
                check_port(to_port)
Packit a8ec6b
            if to_addr:
Packit a8ec6b
                if not checkIP(to_addr) and not checkIP6(to_addr):
Packit a8ec6b
                    raise FirewallError(errors.INVALID_ADDR,
Packit a8ec6b
                                        "to-addr '%s' is not a valid address" \
Packit a8ec6b
                                        % to_addr)
Packit a8ec6b
            entry = (portStr(attrs["port"], "-"), attrs["protocol"],
Packit a8ec6b
                     portStr(to_port, "-"), str(to_addr))
Packit a8ec6b
            if entry not in self.item.forward_ports:
Packit a8ec6b
                self.item.forward_ports.append(entry)
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Forward port %s/%s%s%s already set, ignoring.",
Packit a8ec6b
                            attrs["port"], attrs["protocol"],
Packit a8ec6b
                            " >%s" % to_port if to_port else "",
Packit a8ec6b
                            " @%s" % to_addr if to_addr else "")
Packit a8ec6b
Packit a8ec6b
        elif name == "source-port":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.element:
Packit a8ec6b
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                self._rule.element = rich.Rich_SourcePort(attrs["port"],
Packit a8ec6b
                                                          attrs["protocol"])
Packit a8ec6b
                return
Packit a8ec6b
            check_port(attrs["port"])
Packit a8ec6b
            check_tcpudp(attrs["protocol"])
Packit a8ec6b
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
Packit a8ec6b
            if entry not in self.item.source_ports:
Packit a8ec6b
                self.item.source_ports.append(entry)
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Source port '%s/%s' already set, ignoring.",
Packit a8ec6b
                            attrs["port"], attrs["protocol"])
Packit a8ec6b
Packit a8ec6b
        elif name == "interface":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                log.warning('Invalid rule: interface use in rule.')
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            # zone bound to interface
Packit a8ec6b
            if "name" not in attrs:
Packit a8ec6b
                log.warning('Invalid interface: Name missing.')
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            if attrs["name"] not in self.item.interfaces:
Packit a8ec6b
                self.item.interfaces.append(attrs["name"])
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Interface '%s' already set, ignoring.",
Packit a8ec6b
                            attrs["name"])
Packit a8ec6b
Packit a8ec6b
        elif name == "source":
Packit a8ec6b
            if self._rule:
Packit a8ec6b
                if self._rule.source:
Packit a8ec6b
                    log.warning("Invalid rule: More than one source in rule '%s', ignoring.",
Packit a8ec6b
                                str(self._rule))
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
                invert = False
Packit a8ec6b
                if "invert" in attrs and \
Packit a8ec6b
                        attrs["invert"].lower() in [ "yes", "true" ]:
Packit a8ec6b
                    invert = True
Packit a8ec6b
                addr = mac = ipset = None
Packit a8ec6b
                if "address" in attrs:
Packit a8ec6b
                    addr = attrs["address"]
Packit a8ec6b
                if "mac" in attrs:
Packit a8ec6b
                    mac = attrs["mac"]
Packit a8ec6b
                if "ipset" in attrs:
Packit a8ec6b
                    ipset = attrs["ipset"]
Packit a8ec6b
                self._rule.source = rich.Rich_Source(addr, mac, ipset,
Packit a8ec6b
                                                     invert=invert)
Packit a8ec6b
                return
Packit a8ec6b
            # zone bound to source
Packit a8ec6b
            if "address" not in attrs and "ipset" not in attrs:
Packit a8ec6b
                log.warning('Invalid source: No address no ipset.')
Packit a8ec6b
                return
Packit a8ec6b
            if "address" in attrs and "ipset" in attrs:
Packit a8ec6b
                log.warning('Invalid source: Address and ipset.')
Packit a8ec6b
                return
Packit a8ec6b
            if "family" in attrs:
Packit a8ec6b
                log.warning("Ignoring deprecated attribute family='%s'",
Packit a8ec6b
                            attrs["family"])
Packit a8ec6b
            if "invert" in attrs:
Packit a8ec6b
                log.warning('Invalid source: Invertion not allowed here.')
Packit a8ec6b
                return
Packit a8ec6b
            if "address" in attrs:
Packit a8ec6b
                if not checkIPnMask(attrs["address"]) and \
Packit a8ec6b
                   not checkIP6nMask(attrs["address"]) and \
Packit a8ec6b
                   not check_mac(attrs["address"]):
Packit a8ec6b
                    raise FirewallError(errors.INVALID_ADDR, attrs["address"])
Packit a8ec6b
            if "ipset" in attrs:
Packit a8ec6b
                entry = "ipset:%s" % attrs["ipset"]
Packit a8ec6b
                if entry not in self.item.sources:
Packit a8ec6b
                    self.item.sources.append(entry)
Packit a8ec6b
                else:
Packit a8ec6b
                    log.warning("Source '%s' already set, ignoring.",
Packit a8ec6b
                                attrs["address"])
Packit a8ec6b
            if "address" in attrs:
Packit a8ec6b
                entry = attrs["address"]
Packit a8ec6b
                if entry not in self.item.sources:
Packit a8ec6b
                    self.item.sources.append(entry)
Packit a8ec6b
                else:
Packit a8ec6b
                    log.warning("Source '%s' already set, ignoring.",
Packit a8ec6b
                                attrs["address"])
Packit a8ec6b
Packit a8ec6b
        elif name == "destination":
Packit a8ec6b
            if not self._rule:
Packit a8ec6b
                log.warning('Invalid rule: Destination outside of rule')
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            if self._rule.destination:
Packit a8ec6b
                log.warning("Invalid rule: More than one destination in rule '%s', ignoring.",
Packit a8ec6b
                            str(self._rule))
Packit a8ec6b
                return
Packit a8ec6b
            invert = False
Packit a8ec6b
            if "invert" in attrs and \
Packit a8ec6b
                    attrs["invert"].lower() in [ "yes", "true" ]:
Packit a8ec6b
                invert = True
Packit a8ec6b
            self._rule.destination = rich.Rich_Destination(attrs["address"],
Packit a8ec6b
                                                           invert)
Packit a8ec6b
Packit a8ec6b
        elif name in [ "accept", "reject", "drop", "mark" ]:
Packit a8ec6b
            if not self._rule:
Packit a8ec6b
                log.warning('Invalid rule: Action outside of rule')
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            if self._rule.action:
Packit a8ec6b
                log.warning('Invalid rule: More than one action')
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            if name == "accept":
Packit a8ec6b
                self._rule.action = rich.Rich_Accept()
Packit a8ec6b
            elif name == "reject":
Packit a8ec6b
                _type = None
Packit a8ec6b
                if "type" in attrs:
Packit a8ec6b
                    _type = attrs["type"]
Packit a8ec6b
                self._rule.action = rich.Rich_Reject(_type)
Packit a8ec6b
            elif name == "drop":
Packit a8ec6b
                self._rule.action = rich.Rich_Drop()
Packit a8ec6b
            elif name == "mark":
Packit a8ec6b
                _set = attrs["set"]
Packit a8ec6b
                self._rule.action = rich.Rich_Mark(_set)
Packit a8ec6b
            self._limit_ok = self._rule.action
Packit a8ec6b
Packit a8ec6b
        elif name == "log":
Packit a8ec6b
            if not self._rule:
Packit a8ec6b
                log.warning('Invalid rule: Log outside of rule')
Packit a8ec6b
                return
Packit a8ec6b
            if self._rule.log:
Packit a8ec6b
                log.warning('Invalid rule: More than one log')
Packit a8ec6b
                return
Packit a8ec6b
            level = None
Packit a8ec6b
            if "level" in attrs:
Packit a8ec6b
                level = attrs["level"]
Packit a8ec6b
                if level not in [ "emerg", "alert", "crit", "error",
Packit a8ec6b
                                  "warning", "notice", "info", "debug" ]:
Packit a8ec6b
                    log.warning('Invalid rule: Invalid log level')
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
            prefix = attrs["prefix"] if "prefix" in attrs else None
Packit a8ec6b
            self._rule.log = rich.Rich_Log(prefix, level)
Packit a8ec6b
            self._limit_ok = self._rule.log
Packit a8ec6b
Packit a8ec6b
        elif name == "audit":
Packit a8ec6b
            if not self._rule:
Packit a8ec6b
                log.warning('Invalid rule: Audit outside of rule')
Packit a8ec6b
                return
Packit a8ec6b
            if self._rule.audit:
Packit a8ec6b
                log.warning("Invalid rule: More than one audit in rule '%s', ignoring.",
Packit a8ec6b
                            str(self._rule))
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            self._rule.audit = rich.Rich_Audit()
Packit a8ec6b
            self._limit_ok = self._rule.audit
Packit a8ec6b
Packit a8ec6b
        elif name == "rule":
Packit a8ec6b
            family = None
Packit a8ec6b
            priority = 0
Packit a8ec6b
            if "family" in attrs:
Packit a8ec6b
                family = attrs["family"]
Packit a8ec6b
                if family not in [ "ipv4", "ipv6" ]:
Packit a8ec6b
                    log.warning('Invalid rule: Rule family "%s" invalid',
Packit a8ec6b
                                attrs["family"])
Packit a8ec6b
                    self._rule_error = True
Packit a8ec6b
                    return
Packit a8ec6b
            if "priority" in attrs:
Packit a8ec6b
                priority = int(attrs["priority"])
Packit a8ec6b
            self._rule = rich.Rich_Rule(family=family, priority=priority)
Packit a8ec6b
Packit a8ec6b
        elif name == "limit":
Packit a8ec6b
            if not self._limit_ok:
Packit a8ec6b
                log.warning('Invalid rule: Limit outside of action, log and audit')
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            if self._limit_ok.limit:
Packit a8ec6b
                log.warning("Invalid rule: More than one limit in rule '%s', ignoring.",
Packit a8ec6b
                            str(self._rule))
Packit a8ec6b
                self._rule_error = True
Packit a8ec6b
                return
Packit a8ec6b
            value = attrs["value"]
Packit a8ec6b
            self._limit_ok.limit = rich.Rich_Limit(value)
Packit a8ec6b
Packit a8ec6b
        elif name == "icmp-block-inversion":
Packit a8ec6b
            if self.item.icmp_block_inversion:
Packit a8ec6b
                log.warning("Icmp-Block-Inversion already set, ignoring.")
Packit a8ec6b
            else:
Packit a8ec6b
                self.item.icmp_block_inversion = True
Packit a8ec6b
Packit a8ec6b
        else:
Packit a8ec6b
            log.warning("Unknown XML element '%s'", name)
Packit a8ec6b
            return
Packit a8ec6b
Packit a8ec6b
    def endElement(self, name):
Packit a8ec6b
        IO_Object_ContentHandler.endElement(self, name)
Packit a8ec6b
Packit a8ec6b
        if name == "rule":
Packit a8ec6b
            if not self._rule_error:
Packit a8ec6b
                try:
Packit a8ec6b
                    self._rule.check()
Packit a8ec6b
                except Exception as e:
Packit a8ec6b
                    log.warning("%s: %s", e, str(self._rule))
Packit a8ec6b
                else:
Packit Service 9bd718
                    if str(self._rule) not in \
Packit Service 9bd718
                       [ str(x) for x in self.item.rules ]:
Packit a8ec6b
                        self.item.rules.append(self._rule)
Packit a8ec6b
                    else:
Packit a8ec6b
                        log.warning("Rule '%s' already set, ignoring.",
Packit a8ec6b
                                    str(self._rule))
Packit a8ec6b
            self._rule = None
Packit a8ec6b
            self._rule_error = False
Packit a8ec6b
        elif name in [ "accept", "reject", "drop", "mark", "log", "audit" ]:
Packit a8ec6b
            self._limit_ok = None
Packit a8ec6b
Packit a8ec6b
def zone_reader(filename, path, no_check_name=False):
Packit a8ec6b
    zone = Zone()
Packit a8ec6b
    if not filename.endswith(".xml"):
Packit a8ec6b
        raise FirewallError(errors.INVALID_NAME,
Packit a8ec6b
                            "'%s' is missing .xml suffix" % filename)
Packit a8ec6b
    zone.name = filename[:-4]
Packit a8ec6b
    if not no_check_name:
Packit a8ec6b
        zone.check_name(zone.name)
Packit a8ec6b
    zone.filename = filename
Packit a8ec6b
    zone.path = path
Packit a8ec6b
    zone.builtin = False if path.startswith(config.ETC_FIREWALLD) else True
Packit a8ec6b
    zone.default = zone.builtin
Packit a8ec6b
    handler = zone_ContentHandler(zone)
Packit a8ec6b
    parser = sax.make_parser()
Packit a8ec6b
    parser.setContentHandler(handler)
Packit a8ec6b
    name = "%s/%s" % (path, filename)
Packit a8ec6b
    with open(name, "rb") as f:
Packit a8ec6b
        source = sax.InputSource(None)
Packit a8ec6b
        source.setByteStream(f)
Packit a8ec6b
        try:
Packit a8ec6b
            parser.parse(source)
Packit a8ec6b
        except sax.SAXParseException as msg:
Packit a8ec6b
            raise FirewallError(errors.INVALID_ZONE,
Packit a8ec6b
                                "not a valid zone file: %s" % \
Packit a8ec6b
                                msg.getException())
Packit a8ec6b
    del handler
Packit a8ec6b
    del parser
Packit a8ec6b
    if PY2:
Packit a8ec6b
        zone.encode_strings()
Packit a8ec6b
    return zone
Packit a8ec6b
Packit a8ec6b
def zone_writer(zone, path=None):
Packit a8ec6b
    _path = path if path else zone.path
Packit a8ec6b
Packit a8ec6b
    if zone.filename:
Packit a8ec6b
        name = "%s/%s" % (_path, zone.filename)
Packit a8ec6b
    else:
Packit a8ec6b
        name = "%s/%s.xml" % (_path, zone.name)
Packit a8ec6b
Packit a8ec6b
    if os.path.exists(name):
Packit a8ec6b
        try:
Packit a8ec6b
            shutil.copy2(name, "%s.old" % name)
Packit a8ec6b
        except Exception as msg:
Packit a8ec6b
            log.error("Backup of file '%s' failed: %s", name, msg)
Packit a8ec6b
Packit a8ec6b
    dirpath = os.path.dirname(name)
Packit a8ec6b
    if dirpath.startswith(config.ETC_FIREWALLD) and not os.path.exists(dirpath):
Packit a8ec6b
        if not os.path.exists(config.ETC_FIREWALLD):
Packit a8ec6b
            os.mkdir(config.ETC_FIREWALLD, 0o750)
Packit a8ec6b
        os.mkdir(dirpath, 0o750)
Packit a8ec6b
Packit a8ec6b
    f = io.open(name, mode='wt', encoding='UTF-8')
Packit a8ec6b
    handler = IO_Object_XMLGenerator(f)
Packit a8ec6b
    handler.startDocument()
Packit a8ec6b
Packit a8ec6b
    # start zone element
Packit a8ec6b
    attrs = {}
Packit a8ec6b
    if zone.version and zone.version != "":
Packit a8ec6b
        attrs["version"] = zone.version
Packit a8ec6b
    if zone.target != DEFAULT_ZONE_TARGET:
Packit a8ec6b
        attrs["target"] = zone.target
Packit a8ec6b
    handler.startElement("zone", attrs)
Packit a8ec6b
    handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # short
Packit a8ec6b
    if zone.short and zone.short != "":
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.startElement("short", { })
Packit a8ec6b
        handler.characters(zone.short)
Packit a8ec6b
        handler.endElement("short")
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # description
Packit a8ec6b
    if zone.description and zone.description != "":
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.startElement("description", { })
Packit a8ec6b
        handler.characters(zone.description)
Packit a8ec6b
        handler.endElement("description")
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # interfaces
Packit a8ec6b
    for interface in uniqify(zone.interfaces):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("interface", { "name": interface })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # source
Packit a8ec6b
    for source in uniqify(zone.sources):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        if "ipset:" in source:
Packit a8ec6b
            handler.simpleElement("source", { "ipset": source[6:] })
Packit a8ec6b
        else:
Packit a8ec6b
            handler.simpleElement("source", { "address": source })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # services
Packit a8ec6b
    for service in uniqify(zone.services):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("service", { "name": service })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # ports
Packit a8ec6b
    for port in uniqify(zone.ports):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("port", { "port": port[0], "protocol": port[1] })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # protocols
Packit a8ec6b
    for protocol in uniqify(zone.protocols):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("protocol", { "value": protocol })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # icmp-block-inversion
Packit a8ec6b
    if zone.icmp_block_inversion:
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("icmp-block-inversion", { })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # icmp-blocks
Packit a8ec6b
    for icmp in uniqify(zone.icmp_blocks):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("icmp-block", { "name": icmp })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # masquerade
Packit a8ec6b
    if zone.masquerade:
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("masquerade", { })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # forward-ports
Packit a8ec6b
    for forward in uniqify(zone.forward_ports):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        attrs = { "port": forward[0], "protocol": forward[1] }
Packit a8ec6b
        if forward[2] and forward[2] != "" :
Packit a8ec6b
            attrs["to-port"] = forward[2]
Packit a8ec6b
        if forward[3] and forward[3] != "" :
Packit a8ec6b
            attrs["to-addr"] = forward[3]
Packit a8ec6b
        handler.simpleElement("forward-port", attrs)
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # source-ports
Packit a8ec6b
    for port in uniqify(zone.source_ports):
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.simpleElement("source-port", { "port": port[0],
Packit a8ec6b
                                               "protocol": port[1] })
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # rules
Packit a8ec6b
    for rule in zone.rules:
Packit a8ec6b
        attrs = { }
Packit a8ec6b
        if rule.family:
Packit a8ec6b
            attrs["family"] = rule.family
Packit a8ec6b
        if rule.priority != 0:
Packit a8ec6b
            attrs["priority"] = str(rule.priority)
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.startElement("rule", attrs)
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        # source
Packit a8ec6b
        if rule.source:
Packit a8ec6b
            attrs = { }
Packit a8ec6b
            if rule.source.addr:
Packit a8ec6b
                attrs["address"] = rule.source.addr
Packit a8ec6b
            if rule.source.mac:
Packit a8ec6b
                attrs["mac"] = rule.source.mac
Packit a8ec6b
            if rule.source.ipset:
Packit a8ec6b
                attrs["ipset"] = rule.source.ipset
Packit a8ec6b
            if rule.source.invert:
Packit a8ec6b
                attrs["invert"] = "True"
Packit a8ec6b
            handler.ignorableWhitespace("    ")
Packit a8ec6b
            handler.simpleElement("source", attrs)
Packit a8ec6b
            handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        # destination
Packit a8ec6b
        if rule.destination:
Packit a8ec6b
            attrs = { "address": rule.destination.addr }
Packit a8ec6b
            if rule.destination.invert:
Packit a8ec6b
                attrs["invert"] = "True"
Packit a8ec6b
            handler.ignorableWhitespace("    ")
Packit a8ec6b
            handler.simpleElement("destination", attrs)
Packit a8ec6b
            handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        # element
Packit a8ec6b
        if rule.element:
Packit a8ec6b
            element = ""
Packit a8ec6b
            attrs = { }
Packit a8ec6b
Packit a8ec6b
            if type(rule.element) == rich.Rich_Service:
Packit a8ec6b
                element = "service"
Packit a8ec6b
                attrs["name"] = rule.element.name
Packit a8ec6b
            elif type(rule.element) == rich.Rich_Port:
Packit a8ec6b
                element = "port"
Packit a8ec6b
                attrs["port"] = rule.element.port
Packit a8ec6b
                attrs["protocol"] = rule.element.protocol
Packit a8ec6b
            elif type(rule.element) == rich.Rich_Protocol:
Packit a8ec6b
                element = "protocol"
Packit a8ec6b
                attrs["value"] = rule.element.value
Packit a8ec6b
            elif type(rule.element) == rich.Rich_Masquerade:
Packit a8ec6b
                element = "masquerade"
Packit a8ec6b
            elif type(rule.element) == rich.Rich_IcmpBlock:
Packit a8ec6b
                element = "icmp-block"
Packit a8ec6b
                attrs["name"] = rule.element.name
Packit a8ec6b
            elif type(rule.element) == rich.Rich_IcmpType:
Packit a8ec6b
                element = "icmp-type"
Packit a8ec6b
                attrs["name"] = rule.element.name
Packit a8ec6b
            elif type(rule.element) == rich.Rich_ForwardPort:
Packit a8ec6b
                element = "forward-port"
Packit a8ec6b
                attrs["port"] = rule.element.port
Packit a8ec6b
                attrs["protocol"] = rule.element.protocol
Packit a8ec6b
                if rule.element.to_port != "":
Packit a8ec6b
                    attrs["to-port"] = rule.element.to_port
Packit a8ec6b
                if rule.element.to_address != "":
Packit a8ec6b
                    attrs["to-addr"] = rule.element.to_address
Packit a8ec6b
            elif type(rule.element) == rich.Rich_SourcePort:
Packit a8ec6b
                element = "source-port"
Packit a8ec6b
                attrs["port"] = rule.element.port
Packit a8ec6b
                attrs["protocol"] = rule.element.protocol
Packit a8ec6b
            else:
Packit a8ec6b
                raise FirewallError(
Packit a8ec6b
                    errors.INVALID_OBJECT,
Packit a8ec6b
                    "Unknown element '%s' in zone_writer" % type(rule.element))
Packit a8ec6b
Packit a8ec6b
            handler.ignorableWhitespace("    ")
Packit a8ec6b
            handler.simpleElement(element, attrs)
Packit a8ec6b
            handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        # rule.element
Packit a8ec6b
Packit a8ec6b
        # log
Packit a8ec6b
        if rule.log:
Packit a8ec6b
            attrs = { }
Packit a8ec6b
            if rule.log.prefix:
Packit a8ec6b
                attrs["prefix"] = rule.log.prefix
Packit a8ec6b
            if rule.log.level:
Packit a8ec6b
                attrs["level"] = rule.log.level
Packit a8ec6b
            if rule.log.limit:
Packit a8ec6b
                handler.ignorableWhitespace("    ")
Packit a8ec6b
                handler.startElement("log", attrs)
Packit a8ec6b
                handler.ignorableWhitespace("\n      ")
Packit a8ec6b
                handler.simpleElement("limit",
Packit a8ec6b
                                      { "value": rule.log.limit.value })
Packit a8ec6b
                handler.ignorableWhitespace("\n    ")
Packit a8ec6b
                handler.endElement("log")
Packit a8ec6b
            else:
Packit a8ec6b
                handler.ignorableWhitespace("    ")
Packit a8ec6b
                handler.simpleElement("log", attrs)
Packit a8ec6b
            handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        # audit
Packit a8ec6b
        if rule.audit:
Packit a8ec6b
            attrs = {}
Packit a8ec6b
            if rule.audit.limit:
Packit a8ec6b
                handler.ignorableWhitespace("    ")
Packit a8ec6b
                handler.startElement("audit", { })
Packit a8ec6b
                handler.ignorableWhitespace("\n      ")
Packit a8ec6b
                handler.simpleElement("limit",
Packit a8ec6b
                                      { "value": rule.audit.limit.value })
Packit a8ec6b
                handler.ignorableWhitespace("\n    ")
Packit a8ec6b
                handler.endElement("audit")
Packit a8ec6b
            else:
Packit a8ec6b
                handler.ignorableWhitespace("    ")
Packit a8ec6b
                handler.simpleElement("audit", attrs)
Packit a8ec6b
            handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        # action
Packit a8ec6b
        if rule.action:
Packit a8ec6b
            action = ""
Packit a8ec6b
            attrs = { }
Packit a8ec6b
            if type(rule.action) == rich.Rich_Accept:
Packit a8ec6b
                action = "accept"
Packit a8ec6b
            elif type(rule.action) == rich.Rich_Reject:
Packit a8ec6b
                action = "reject"
Packit a8ec6b
                if rule.action.type:
Packit a8ec6b
                    attrs["type"] = rule.action.type
Packit a8ec6b
            elif type(rule.action) == rich.Rich_Drop:
Packit a8ec6b
                action = "drop"
Packit a8ec6b
            elif type(rule.action) == rich.Rich_Mark:
Packit a8ec6b
                action = "mark"
Packit a8ec6b
                attrs["set"] = rule.action.set
Packit a8ec6b
            else:
Packit a8ec6b
                log.warning("Unknown action '%s'", type(rule.action))
Packit a8ec6b
            if rule.action.limit:
Packit a8ec6b
                handler.ignorableWhitespace("    ")
Packit a8ec6b
                handler.startElement(action, attrs)
Packit a8ec6b
                handler.ignorableWhitespace("\n      ")
Packit a8ec6b
                handler.simpleElement("limit",
Packit a8ec6b
                                      { "value": rule.action.limit.value })
Packit a8ec6b
                handler.ignorableWhitespace("\n    ")
Packit a8ec6b
                handler.endElement(action)
Packit a8ec6b
            else:
Packit a8ec6b
                handler.ignorableWhitespace("    ")
Packit a8ec6b
                handler.simpleElement(action, attrs)
Packit a8ec6b
            handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
        handler.ignorableWhitespace("  ")
Packit a8ec6b
        handler.endElement("rule")
Packit a8ec6b
        handler.ignorableWhitespace("\n")
Packit a8ec6b
Packit a8ec6b
    # end zone element
Packit a8ec6b
    handler.endElement("zone")
Packit a8ec6b
    handler.ignorableWhitespace("\n")
Packit a8ec6b
    handler.endDocument()
Packit a8ec6b
    f.close()
Packit a8ec6b
    del handler