Exemplo n.º 1
0
 def startElement(self, name, attrs):
     IO_Object_ContentHandler.startElement(self, name, attrs)
     self.item.parser_check_element_attrs(name, attrs)
     if name == "helper":
         if "version" in attrs:
             self.item.version = attrs["version"]
         if "family" in attrs:
             self.item.check_ipv(attrs["family"])
             self.item.family = attrs["family"]
         if "module" in attrs:
             if not attrs["module"].startswith("nf_conntrack_"):
                 raise FirewallError(
                     errors.INVALID_MODULE,
                     "'%s' does not start with 'nf_conntrack_'" % \
                     attrs["module"])
             if len(attrs["module"].replace("nf_conntrack_", "")) < 1:
                 raise FirewallError(
                     errors.INVALID_MODULE,
                     "Module name '%s' too short" % attrs["module"])
             self.item.module = attrs["module"]
     elif name == "short":
         pass
     elif name == "description":
         pass
     elif name == "port":
         check_port(attrs["port"])
         check_tcpudp(attrs["protocol"])
         entry = (attrs["port"], attrs["protocol"])
         if entry not in self.item.ports:
             self.item.ports.append(entry)
         else:
             log.warning("Port '%s/%s' already set, ignoring.",
                         attrs["port"], attrs["protocol"])
Exemplo n.º 2
0
 def startElement(self, name, attrs):
     IO_Object_ContentHandler.startElement(self, name, attrs)
     self.item.parser_check_element_attrs(name, attrs)
     if name == "helper":
         if "version" in attrs:
             self.item.version = attrs["version"]
         if "family" in attrs:
             self.item.check_ipv(attrs["family"])
             self.item.family = attrs["family"]
         if "module" in attrs:
             if not attrs["module"].startswith("nf_conntrack_"):
                 raise FirewallError(
                     errors.INVALID_MODULE,
                     "'%s' does not start with 'nf_conntrack_'" % \
                     attrs["module"])
             if len(attrs["module"].replace("nf_conntrack_", "")) < 1:
                 raise FirewallError(
                     errors.INVALID_MODULE,
                     "Module name '%s' too short" % attrs["module"])
             self.item.module = attrs["module"]
     elif name == "short":
         pass
     elif name == "description":
         pass
     elif name == "port":
         check_port(attrs["port"])
         check_tcpudp(attrs["protocol"])
         entry = (attrs["port"], attrs["protocol"])
         if entry not in self.item.ports:
             self.item.ports.append(entry)
         else:
             log.warning("Port '%s/%s' already set, ignoring.",
                         attrs["port"], attrs["protocol"])
Exemplo n.º 3
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)
        if name == "ipset":
            if "type" in attrs:
                if attrs["type"] not in IPSET_TYPES:
                    raise FirewallError(errors.INVALID_TYPE, "%s" % attrs["type"])
                self.item.type = attrs["type"]
            if "version" in attrs:
                self.item.version = attrs["version"]
        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "option":
            value = ""
            if "value" in attrs:
                value = attrs["value"]

            if attrs["name"] not in \
               [ "family", "timeout", "hashsize", "maxelem" ]:
                raise FirewallError(
                    errors.INVALID_OPTION,
                    "Unknown option '%s'" % attrs["name"])
            if self.item.type == "hash:mac" and attrs["name"] in [ "family" ]:
                raise FirewallError(
                    errors.INVALID_OPTION,
                    "Unsupported option '%s' for type '%s'" % \
                    (attrs["name"], self.item.type))
            if attrs["name"] in [ "family", "timeout", "hashsize", "maxelem" ] \
               and not value:
                raise FirewallError(
                    errors.INVALID_OPTION,
                    "Missing mandatory value of option '%s'" % attrs["name"])
            if attrs["name"] in [ "timeout", "hashsize", "maxelem" ]:
                try:
                    int_value = int(value)
                except ValueError:
                    raise FirewallError(
                        errors.INVALID_VALUE,
                        "Option '%s': Value '%s' is not an integer" % \
                        (attrs["name"], value))
                if int_value < 0:
                    raise FirewallError(
                        errors.INVALID_VALUE,
                        "Option '%s': Value '%s' is negative" % \
                        (attrs["name"], value))
            if attrs["name"] == "family" and value not in [ "inet", "inet6" ]:
                raise FirewallError(errors.INVALID_FAMILY, value)
            if attrs["name"] not in self.item.options:
                self.item.options[attrs["name"]] = value
            else:
                log.warning("Option %s already set, ignoring.", attrs["name"])
Exemplo n.º 4
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)

        if name == "direct":
            if self.direct:
                raise FirewallError(errors.PARSE_ERROR,
                                    "More than one direct tag.")
            self.direct = True

        elif name == "chain":
            if not self.direct:
                log.error("Parse Error: chain outside of direct")
                return
            ipv = attrs["ipv"]
            table = attrs["table"]
            chain = attrs["chain"]
            self.item.add_chain(u2b_if_py2(ipv), u2b_if_py2(table),
                                u2b_if_py2(chain))

        elif name == "rule":
            if not self.direct:
                log.error("Parse Error: rule outside of direct")
                return
            ipv = attrs["ipv"]
            if ipv not in ["ipv4", "ipv6", "eb"]:
                raise FirewallError(errors.INVALID_IPV,
                                    "'%s' not from {'ipv4'|'ipv6'|'eb'}" % ipv)
            table = attrs["table"]
            chain = attrs["chain"]
            try:
                priority = int(attrs["priority"])
            except ValueError:
                log.error("Parse Error: %s is not a valid priority" %
                          attrs["priority"])
                return
            self._rule = [
                u2b_if_py2(ipv),
                u2b_if_py2(table),
                u2b_if_py2(chain), priority
            ]

        elif name == "passthrough":
            if not self.direct:
                log.error("Parse Error: command outside of direct")
                return
            ipv = attrs["ipv"]
            self._passthrough = [u2b_if_py2(ipv)]

        else:
            log.error('Unknown XML element %s' % name)
            return
Exemplo n.º 5
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)
        if name == "ipset":
            if "type" in attrs:
                self.item.type = attrs["type"]
            if "version" in attrs:
                self.item.version = attrs["version"]
        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "option":
            value = ""
            if "value" in attrs:
                value = attrs["value"]

            if attrs["name"] not in \
               [ "family", "timeout", "hashsize", "maxelem" ]:
                raise FirewallError(
                    errors.INVALID_OPTION,
                    "Unknown option '%s'" % attrs["name"])
            if self.item.type == "hash:mac" and attrs["name"] in [ "family" ]:
                raise FirewallError(
                    errors.INVALID_OPTION,
                    "Unsupported option '%s' for type '%s'" % \
                    (attrs["name"], self.item.type))
            if attrs["name"] in [ "family", "timeout", "hashsize", "maxelem" ] \
               and not value:
                raise FirewallError(
                    errors.INVALID_OPTION,
                    "Missing mandatory value of option '%s'" % attrs["name"])
            if attrs["name"] in [ "timeout", "hashsize", "maxelem" ]:
                try:
                    int_value = int(value)
                except ValueError:
                    raise FirewallError(
                        errors.INVALID_VALUE,
                        "Option '%s': Value '%s' is not an integer" % \
                        (attrs["name"], value))
                if int_value < 0:
                    raise FirewallError(
                        errors.INVALID_VALUE,
                        "Option '%s': Value '%s' is negative" % \
                        (attrs["name"], value))
            if attrs["name"] == "family" and value not in [ "inet", "inet6" ]:
                raise FirewallError(errors.INVALID_FAMILY, value)
            if attrs["name"] not in self.item.options:
                self.item.options[attrs["name"]] = value
            else:
                log.warning("Option %s already set, ignoring.", attrs["name"])
Exemplo n.º 6
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)

        if name == "direct":
            if self.direct:
                raise FirewallError(errors.PARSE_ERROR,
                                    "More than one direct tag.")
            self.direct = True

        elif name == "chain":
            if not self.direct:
                log.error("Parse Error: chain outside of direct")
                return
            ipv = attrs["ipv"]
            table = attrs["table"]
            chain = attrs["chain"]
            self.item.add_chain(u2b_if_py2(ipv), u2b_if_py2(table),
                                u2b_if_py2(chain))

        elif name == "rule":
            if not self.direct:
                log.error("Parse Error: rule outside of direct")
                return
            ipv = attrs["ipv"]
            if ipv not in [ "ipv4", "ipv6", "eb" ]:
                raise FirewallError(errors.INVALID_IPV,
                                    "'%s' not from {'ipv4'|'ipv6'|'eb'}" % ipv)
            table = attrs["table"]
            chain = attrs["chain"]
            try:
                priority = int(attrs["priority"])
            except ValueError:
                log.error("Parse Error: %s is not a valid priority" %
                          attrs["priority"])
                return
            self._rule = [ u2b_if_py2(ipv), u2b_if_py2(table),
                           u2b_if_py2(chain), priority ]

        elif name == "passthrough":
            if not self.direct:
                log.error("Parse Error: command outside of direct")
                return
            ipv = attrs["ipv"]
            self._passthrough = [ u2b_if_py2(ipv) ]

        else:
            log.error('Unknown XML element %s' % name)
            return
Exemplo n.º 7
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)

        if name == "icmptype":
            if "name" in attrs:
                log.warning("Ignoring deprecated attribute name='%s'" % attrs["name"])
            if "version" in attrs:
                self.item.version = attrs["version"]
        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "destination":
            for x in ["ipv4", "ipv6"]:
                if x in attrs and attrs[x].lower() in ["yes", "true"]:
                    self.item.destination.append(str(x))
Exemplo n.º 8
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)

        if name == "whitelist":
            if self.whitelist:
                raise FirewallError(errors.PARSE_ERROR,
                                    "More than one whitelist.")
            self.whitelist = True

        elif name == "command":
            if not self.whitelist:
                log.error("Parse Error: command outside of whitelist")
                return
            command = attrs["name"]
            self.item.add_command(command)

        elif name == "user":
            if not self.whitelist:
                log.error("Parse Error: user outside of whitelist")
                return
            if "id" in attrs:
                try:
                    uid = int(attrs["id"])
                except ValueError:
                    log.error("Parse Error: %s is not a valid uid" %
                              attrs["id"])
                    return
                self.item.add_uid(uid)
            elif "name" in attrs:
                self.item.add_user(attrs["name"])

        elif name == "selinux":
            if not self.whitelist:
                log.error("Parse Error: selinux outside of whitelist")
                return
            if "context" not in attrs:
                log.error("Parse Error: no context")
                return
            self.item.add_context(attrs["context"])

        else:
            log.error('Unknown XML element %s' % name)
            return
Exemplo n.º 9
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        self.item.parser_check_element_attrs(name, attrs)

        if name == "icmptype":
            if "name" in attrs:
                log.warning("Ignoring deprecated attribute name='%s'" %
                            attrs["name"])
            if "version" in attrs:
                self.item.version = attrs["version"]
        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "destination":
            for x in ["ipv4", "ipv6"]:
                if x in attrs and \
                        attrs[x].lower() in [ "yes", "true" ]:
                    self.item.destination.append(str(x))
Exemplo n.º 10
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        if self._rule_error:
            return

        self.item.parser_check_element_attrs(name, attrs)

        if common_startElement(self, name, attrs):
            return

        elif name == "policy":
            if "version" in attrs:
                self.item.version = attrs["version"]
            if "priority" in attrs:
                self.item.priority = int(attrs["priority"])
            if "target" in attrs:
                target = attrs["target"]
                if target not in POLICY_TARGETS:
                    raise FirewallError(errors.INVALID_TARGET, target)
                if target:
                    self.item.target = target

        elif name == "ingress-zone":
            if attrs["name"] not in self.item.ingress_zones:
                self.item.ingress_zones.append(attrs["name"])
            else:
                log.warning("Ingress zone '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "egress-zone":
            if attrs["name"] not in self.item.egress_zones:
                self.item.egress_zones.append(attrs["name"])
            else:
                log.warning("Egress zone '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "source":
            if not self._rule:
                log.warning('Invalid rule: Source outside of rule')
                self._rule_error = True
                return

            if self._rule.source:
                log.warning(
                    "Invalid rule: More than one source in rule '%s', ignoring.",
                    str(self._rule))
                self._rule_error = True
                return
            invert = False
            if "invert" in attrs and \
                    attrs["invert"].lower() in [ "yes", "true" ]:
                invert = True
            addr = mac = ipset = None
            if "address" in attrs:
                addr = attrs["address"]
            if "mac" in attrs:
                mac = attrs["mac"]
            if "ipset" in attrs:
                ipset = attrs["ipset"]
            self._rule.source = rich.Rich_Source(addr,
                                                 mac,
                                                 ipset,
                                                 invert=invert)
            return

        else:
            log.warning("Unknown XML element '%s'", name)
            return
Exemplo n.º 11
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        if self._rule_error:
            return

        self.item.parser_check_element_attrs(name, attrs)

        if name == "zone":
            if "name" in attrs:
                log.warning("Ignoring deprecated attribute name='%s'",
                            attrs["name"])
            if "version" in attrs:
                self.item.version = attrs["version"]
            if "immutable" in attrs:
                log.warning("Ignoring deprecated attribute immutable='%s'",
                            attrs["immutable"])
            if "target" in attrs:
                target = attrs["target"]
                if target not in ZONE_TARGETS:
                    raise FirewallError(errors.INVALID_TARGET, target)
                if target != "" and target != DEFAULT_ZONE_TARGET:
                    self.item.target = target

        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "service":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Service(attrs["name"])
                return
            if attrs["name"] not in self.item.services:
                self.item.services.append(attrs["name"])
            else:
                log.warning("Service '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "port":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Port(attrs["port"],
                                                    attrs["protocol"])
                return
            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
            if entry not in self.item.ports:
                self.item.ports.append(entry)
            else:
                log.warning("Port '%s/%s' already set, ignoring.",
                            attrs["port"], attrs["protocol"])

        elif name == "protocol":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Protocol(attrs["value"])
            else:
                check_protocol(attrs["value"])
                if attrs["value"] not in self.item.protocols:
                    self.item.protocols.append(attrs["value"])
                else:
                    log.warning("Protocol '%s' already set, ignoring.",
                                attrs["value"])
        elif name == "icmp-block":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_IcmpBlock(attrs["name"])
                return
            if attrs["name"] not in self.item.icmp_blocks:
                self.item.icmp_blocks.append(attrs["name"])
            else:
                log.warning("icmp-block '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "icmp-type":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_IcmpType(attrs["name"])
                return
            else:
                log.warning("Invalid rule: icmp-block '%s' outside of rule",
                            attrs["name"])

        elif name == "masquerade":
            if "enabled" in attrs and \
               attrs["enabled"].lower() in [ "no", "false" ] :
                log.warning("Ignoring deprecated attribute enabled='%s'",
                            attrs["enabled"])
                return

            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Masquerade()
            else:
                if self.item.masquerade:
                    log.warning("Masquerade already set, ignoring.")
                else:
                    self.item.masquerade = True

        elif name == "forward-port":
            to_port = ""
            if "to-port" in attrs:
                to_port = attrs["to-port"]
            to_addr = ""
            if "to-addr" in attrs:
                to_addr = attrs["to-addr"]

            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_ForwardPort(
                    attrs["port"], attrs["protocol"], to_port, to_addr)
                return

            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            if to_port:
                check_port(to_port)
            if to_addr:
                if not checkIP(to_addr) and not checkIP6(to_addr):
                    raise FirewallError(errors.INVALID_ADDR,
                                        "to-addr '%s' is not a valid address" \
                                        % to_addr)
            entry = (portStr(attrs["port"], "-"), attrs["protocol"],
                     portStr(to_port, "-"), str(to_addr))
            if entry not in self.item.forward_ports:
                self.item.forward_ports.append(entry)
            else:
                log.warning("Forward port %s/%s%s%s already set, ignoring.",
                            attrs["port"], attrs["protocol"],
                            " >%s" % to_port if to_port else "",
                            " @%s" % to_addr if to_addr else "")

        elif name == "source-port":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_SourcePort(
                    attrs["port"], attrs["protocol"])
                return
            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
            if entry not in self.item.source_ports:
                self.item.source_ports.append(entry)
            else:
                log.warning("Source port '%s/%s' already set, ignoring.",
                            attrs["port"], attrs["protocol"])

        elif name == "interface":
            if self._rule:
                log.warning('Invalid rule: interface use in rule.')
                self._rule_error = True
                return
            # zone bound to interface
            if "name" not in attrs:
                log.warning('Invalid interface: Name missing.')
                self._rule_error = True
                return
            if attrs["name"] not in self.item.interfaces:
                self.item.interfaces.append(attrs["name"])
            else:
                log.warning("Interface '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "source":
            if self._rule:
                if self._rule.source:
                    log.warning(
                        "Invalid rule: More than one source in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                invert = False
                if "invert" in attrs and \
                        attrs["invert"].lower() in [ "yes", "true" ]:
                    invert = True
                addr = mac = ipset = None
                if "address" in attrs:
                    addr = attrs["address"]
                if "mac" in attrs:
                    mac = attrs["mac"]
                if "ipset" in attrs:
                    ipset = attrs["ipset"]
                self._rule.source = rich.Rich_Source(addr,
                                                     mac,
                                                     ipset,
                                                     invert=invert)
                return
            # zone bound to source
            if "address" not in attrs and "ipset" not in attrs:
                log.warning('Invalid source: No address no ipset.')
                return
            if "address" in attrs and "ipset" in attrs:
                log.warning('Invalid source: Address and ipset.')
                return
            if "family" in attrs:
                log.warning("Ignoring deprecated attribute family='%s'",
                            attrs["family"])
            if "invert" in attrs:
                log.warning('Invalid source: Invertion not allowed here.')
                return
            if "address" in attrs:
                if not checkIPnMask(attrs["address"]) and \
                   not checkIP6nMask(attrs["address"]) and \
                   not check_mac(attrs["address"]):
                    raise FirewallError(errors.INVALID_ADDR, attrs["address"])
            if "ipset" in attrs:
                entry = "ipset:%s" % attrs["ipset"]
                if entry not in self.item.sources:
                    self.item.sources.append(entry)
                else:
                    log.warning("Source '%s' already set, ignoring.",
                                attrs["address"])
            if "address" in attrs:
                entry = attrs["address"]
                if entry not in self.item.sources:
                    self.item.sources.append(entry)
                else:
                    log.warning("Source '%s' already set, ignoring.",
                                attrs["address"])

        elif name == "destination":
            if not self._rule:
                log.warning('Invalid rule: Destination outside of rule')
                self._rule_error = True
                return
            if self._rule.destination:
                log.warning(
                    "Invalid rule: More than one destination in rule '%s', ignoring.",
                    str(self._rule))
                return
            invert = False
            if "invert" in attrs and \
                    attrs["invert"].lower() in [ "yes", "true" ]:
                invert = True
            self._rule.destination = rich.Rich_Destination(
                attrs["address"], invert)

        elif name in ["accept", "reject", "drop", "mark"]:
            if not self._rule:
                log.warning('Invalid rule: Action outside of rule')
                self._rule_error = True
                return
            if self._rule.action:
                log.warning('Invalid rule: More than one action')
                self._rule_error = True
                return
            if name == "accept":
                self._rule.action = rich.Rich_Accept()
            elif name == "reject":
                _type = None
                if "type" in attrs:
                    _type = attrs["type"]
                self._rule.action = rich.Rich_Reject(_type)
            elif name == "drop":
                self._rule.action = rich.Rich_Drop()
            elif name == "mark":
                _set = attrs["set"]
                self._rule.action = rich.Rich_Mark(_set)
            self._limit_ok = self._rule.action

        elif name == "log":
            if not self._rule:
                log.warning('Invalid rule: Log outside of rule')
                return
            if self._rule.log:
                log.warning('Invalid rule: More than one log')
                return
            level = None
            if "level" in attrs:
                level = attrs["level"]
                if level not in [
                        "emerg", "alert", "crit", "error", "warning", "notice",
                        "info", "debug"
                ]:
                    log.warning('Invalid rule: Invalid log level')
                    self._rule_error = True
                    return
            prefix = attrs["prefix"] if "prefix" in attrs else None
            self._rule.log = rich.Rich_Log(prefix, level)
            self._limit_ok = self._rule.log

        elif name == "audit":
            if not self._rule:
                log.warning('Invalid rule: Audit outside of rule')
                return
            if self._rule.audit:
                log.warning(
                    "Invalid rule: More than one audit in rule '%s', ignoring.",
                    str(self._rule))
                self._rule_error = True
                return
            self._rule.audit = rich.Rich_Audit()
            self._limit_ok = self._rule.audit

        elif name == "rule":
            family = None
            if "family" in attrs:
                family = attrs["family"]
                if family not in ["ipv4", "ipv6"]:
                    log.warning('Invalid rule: Rule family "%s" invalid',
                                attrs["family"])
                    self._rule_error = True
                    return
            self._rule = rich.Rich_Rule(family)

        elif name == "limit":
            if not self._limit_ok:
                log.warning(
                    'Invalid rule: Limit outside of action, log and audit')
                self._rule_error = True
                return
            if self._limit_ok.limit:
                log.warning(
                    "Invalid rule: More than one limit in rule '%s', ignoring.",
                    str(self._rule))
                self._rule_error = True
                return
            value = attrs["value"]
            self._limit_ok.limit = rich.Rich_Limit(value)

        elif name == "icmp-block-inversion":
            if self.item.icmp_block_inversion:
                log.warning("Icmp-Block-Inversion already set, ignoring.")
            else:
                self.item.icmp_block_inversion = True

        else:
            log.warning("Unknown XML element '%s'", name)
            return
Exemplo n.º 12
0
 def startElement(self, name, attrs):
     IO_Object_ContentHandler.startElement(self, name, attrs)
     self.item.parser_check_element_attrs(name, attrs)
     if name == "service":
         if "name" in attrs:
             log.warning("Ignoring deprecated attribute name='%s'",
                         attrs["name"])
         if "version" in attrs:
             self.item.version = attrs["version"]
     elif name == "short":
         pass
     elif name == "description":
         pass
     elif name == "port":
         if attrs["port"] != "":
             check_port(attrs["port"])
             check_tcpudp(attrs["protocol"])
             entry = (attrs["port"], attrs["protocol"])
             if entry not in self.item.ports:
                 self.item.ports.append(entry)
             else:
                 log.warning("Port '%s/%s' already set, ignoring.",
                             attrs["port"], attrs["protocol"])
         else:
             check_protocol(attrs["protocol"])
             if attrs["protocol"] not in self.item.protocols:
                 self.item.protocols.append(attrs["protocol"])
             else:
                 log.warning("Protocol '%s' already set, ignoring.",
                             attrs["protocol"])
     elif name == "protocol":
         check_protocol(attrs["value"])
         if attrs["value"] not in self.item.protocols:
             self.item.protocols.append(attrs["value"])
         else:
             log.warning("Protocol '%s' already set, ignoring.",
                         attrs["value"])
     elif name == "source-port":
         check_port(attrs["port"])
         check_tcpudp(attrs["protocol"])
         entry = (attrs["port"], attrs["protocol"])
         if entry not in self.item.source_ports:
             self.item.source_ports.append(entry)
         else:
             log.warning("SourcePort '%s/%s' already set, ignoring.",
                         attrs["port"], attrs["protocol"])
     elif name == "destination":
         for x in ["ipv4", "ipv6"]:
             if x in attrs:
                 check_address(x, attrs[x])
                 if x in self.item.destination:
                     log.warning(
                         "Destination address for '%s' already set, ignoring",
                         x)
                 else:
                     self.item.destination[x] = attrs[x]
     elif name == "module":
         module = attrs["name"]
         if module.startswith("nf_conntrack_"):
             module = module.replace("nf_conntrack_", "")
             if "_" in module:
                 module = module.replace("_", "-")
         if module not in self.item.modules:
             self.item.modules.append(module)
         else:
             log.warning("Module '%s' already set, ignoring.", module)
     elif name == "include":
         if attrs["service"] not in self.item.includes:
             self.item.includes.append(attrs["service"])
         else:
             log.warning("Include '%s' already set, ignoring.",
                         attrs["service"])
     elif name == "helper":
         if attrs["name"] not in self.item.helpers:
             self.item.helpers.append(attrs["name"])
         else:
             log.warning("Helper '%s' already set, ignoring.",
                         attrs["name"])
Exemplo n.º 13
0
 def startElement(self, name, attrs):
     IO_Object_ContentHandler.startElement(self, name, attrs)
     self.item.parser_check_element_attrs(name, attrs)
     if name == "service":
         if "name" in attrs:
             log.warning("Ignoring deprecated attribute name='%s'",
                         attrs["name"])
         if "version" in attrs:
             self.item.version = attrs["version"]
     elif name == "short":
         pass
     elif name == "description":
         pass
     elif name == "port":
         if attrs["port"] != "":
             check_port(attrs["port"])
             check_tcpudp(attrs["protocol"])
             entry = (attrs["port"], attrs["protocol"])
             if entry not in self.item.ports:
                 self.item.ports.append(entry)
             else:
                 log.warning("Port '%s/%s' already set, ignoring.",
                             attrs["port"], attrs["protocol"])
         else:
             check_protocol(attrs["protocol"])
             if attrs["protocol"] not in self.item.protocols:
                 self.item.protocols.append(attrs["protocol"])
             else:
                 log.warning("Protocol '%s' already set, ignoring.",
                             attrs["protocol"])
     elif name == "protocol":
         check_protocol(attrs["value"])
         if attrs["value"] not in self.item.protocols:
             self.item.protocols.append(attrs["value"])
         else:
             log.warning("Protocol '%s' already set, ignoring.",
                         attrs["value"])
     elif name == "source-port":
         check_port(attrs["port"])
         check_tcpudp(attrs["protocol"])
         entry = (attrs["port"], attrs["protocol"])
         if entry not in self.item.source_ports:
             self.item.source_ports.append(entry)
         else:
             log.warning("SourcePort '%s/%s' already set, ignoring.",
                         attrs["port"], attrs["protocol"])
     elif name == "destination":
         for x in [ "ipv4", "ipv6" ]:
             if x in attrs:
                 check_address(x, attrs[x])
                 if x in self.item.destination:
                     log.warning("Destination address for '%s' already set, ignoring",
                                 x)
                 else:
                     self.item.destination[x] = attrs[x]
     elif name == "module":
         if attrs["name"].startswith("nf_conntrack_") and \
            len(attrs["name"].replace("nf_conntrack_", "")) > 0:
             if attrs["name"] not in self.item.modules:
                 self.item.modules.append(attrs["name"])
             else:
                 log.warning("Module '%s' already set, ignoring.",
                             attrs["name"])
         else:
             log.warning("Invalid module '%s'", attrs["name"])
Exemplo n.º 14
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        if self._rule_error:
            return

        self.item.parser_check_element_attrs(name, attrs)

        if name == "policy":
            if "version" in attrs:
                self.item.version = attrs["version"]
            if "priority" in attrs:
                self.item.priority = int(attrs["priority"])
            target = attrs["target"]
            if target not in POLICY_TARGETS:
                raise FirewallError(errors.INVALID_TARGET, target)

        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "service":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Service(attrs["name"])
                return
            if attrs["name"] not in self.item.services:
                self.item.services.append(attrs["name"])
            else:
                log.warning("Service '%s' already set, ignoring.",
                            attrs["name"])
        elif name == "ingress-zone":
            if attrs["name"] not in self.item.ingress_zones:
                self.item.ingress_zones.append(attrs["name"])
            else:
                log.warning("Ingress zone '%s' already set, ignoring.",
                            attrs["name"])
        elif name == "egress-zone":
            if attrs["name"] not in self.item.egress_zones:
                self.item.egress_zones.append(attrs["name"])
            else:
                log.warning("Egress zone '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "port":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Port(attrs["port"],
                                                    attrs["protocol"])
                return
            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
            if entry not in self.item.ports:
                self.item.ports.append(entry)
            else:
                log.warning("Port '%s/%s' already set, ignoring.",
                            attrs["port"], attrs["protocol"])

        elif name == "protocol":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Protocol(attrs["value"])
            else:
                check_protocol(attrs["value"])
                if attrs["value"] not in self.item.protocols:
                    self.item.protocols.append(attrs["value"])
                else:
                    log.warning("Protocol '%s' already set, ignoring.",
                                attrs["value"])
        elif name == "icmp-block":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_IcmpBlock(attrs["name"])
                return
            if attrs["name"] not in self.item.icmp_blocks:
                self.item.icmp_blocks.append(attrs["name"])
            else:
                log.warning("icmp-block '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "icmp-type":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_IcmpType(attrs["name"])
                return
            else:
                log.warning("Invalid rule: icmp-block '%s' outside of rule",
                            attrs["name"])

        elif name == "masquerade":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_Masquerade()
            else:
                if self.item.masquerade:
                    log.warning("Masquerade already set, ignoring.")
                else:
                    self.item.masquerade = True

        elif name == "forward-port":
            to_port = ""
            if "to-port" in attrs:
                to_port = attrs["to-port"]
            to_addr = ""
            if "to-addr" in attrs:
                to_addr = attrs["to-addr"]

            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_ForwardPort(
                    attrs["port"], attrs["protocol"], to_port, to_addr)
                return

            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            if to_port:
                check_port(to_port)
            if to_addr:
                if not checkIP(to_addr) and not checkIP6(to_addr):
                    raise FirewallError(errors.INVALID_ADDR,
                                        "to-addr '%s' is not a valid address" \
                                        % to_addr)
            entry = (portStr(attrs["port"], "-"), attrs["protocol"],
                     portStr(to_port, "-"), str(to_addr))
            if entry not in self.item.forward_ports:
                self.item.forward_ports.append(entry)
            else:
                log.warning("Forward port %s/%s%s%s already set, ignoring.",
                            attrs["port"], attrs["protocol"],
                            " >%s" % to_port if to_port else "",
                            " @%s" % to_addr if to_addr else "")

        elif name == "source-port":
            if self._rule:
                if self._rule.element:
                    log.warning(
                        "Invalid rule: More than one element in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = rich.Rich_SourcePort(
                    attrs["port"], attrs["protocol"])
                return
            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
            if entry not in self.item.source_ports:
                self.item.source_ports.append(entry)
            else:
                log.warning("Source port '%s/%s' already set, ignoring.",
                            attrs["port"], attrs["protocol"])

        elif name == "destination":
            if not self._rule:
                log.warning('Invalid rule: Destination outside of rule')
                self._rule_error = True
                return
            if self._rule.destination:
                log.warning(
                    "Invalid rule: More than one destination in rule '%s', ignoring.",
                    str(self._rule))
                return
            invert = False
            if "invert" in attrs and \
                    attrs["invert"].lower() in [ "yes", "true" ]:
                invert = True
            self._rule.destination = rich.Rich_Destination(
                attrs["address"], invert)

        elif name in ["accept", "reject", "drop", "mark"]:
            if not self._rule:
                log.warning('Invalid rule: Action outside of rule')
                self._rule_error = True
                return
            if self._rule.action:
                log.warning('Invalid rule: More than one action')
                self._rule_error = True
                return
            if name == "accept":
                self._rule.action = rich.Rich_Accept()
            elif name == "reject":
                _type = None
                if "type" in attrs:
                    _type = attrs["type"]
                self._rule.action = rich.Rich_Reject(_type)
            elif name == "drop":
                self._rule.action = rich.Rich_Drop()
            elif name == "mark":
                _set = attrs["set"]
                self._rule.action = rich.Rich_Mark(_set)
            self._limit_ok = self._rule.action

        elif name == "log":
            if not self._rule:
                log.warning('Invalid rule: Log outside of rule')
                return
            if self._rule.log:
                log.warning('Invalid rule: More than one log')
                return
            level = None
            if "level" in attrs:
                level = attrs["level"]
                if level not in [
                        "emerg", "alert", "crit", "error", "warning", "notice",
                        "info", "debug"
                ]:
                    log.warning('Invalid rule: Invalid log level')
                    self._rule_error = True
                    return
            prefix = attrs["prefix"] if "prefix" in attrs else None
            self._rule.log = rich.Rich_Log(prefix, level)
            self._limit_ok = self._rule.log

        elif name == "audit":
            if not self._rule:
                log.warning('Invalid rule: Audit outside of rule')
                return
            if self._rule.audit:
                log.warning(
                    "Invalid rule: More than one audit in rule '%s', ignoring.",
                    str(self._rule))
                self._rule_error = True
                return
            self._rule.audit = rich.Rich_Audit()
            self._limit_ok = self._rule.audit

        elif name == "rule":
            family = None
            priority = 0
            if "family" in attrs:
                family = attrs["family"]
                if family not in ["ipv4", "ipv6"]:
                    log.warning('Invalid rule: Rule family "%s" invalid',
                                attrs["family"])
                    self._rule_error = True
                    return
            if "priority" in attrs:
                priority = int(attrs["priority"])
            self._rule = rich.Rich_Rule(family=family, priority=priority)

        elif name == "limit":
            if not self._limit_ok:
                log.warning(
                    'Invalid rule: Limit outside of action, log and audit')
                self._rule_error = True
                return
            if self._limit_ok.limit:
                log.warning(
                    "Invalid rule: More than one limit in rule '%s', ignoring.",
                    str(self._rule))
                self._rule_error = True
                return
            value = attrs["value"]
            self._limit_ok.limit = rich.Rich_Limit(value)

        else:
            log.warning("Unknown XML element '%s'", name)
            return
Exemplo n.º 15
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        if self._rule_error:
            return

        self.item.parser_check_element_attrs(name, attrs)

        if common_startElement(self, name, attrs):
            return

        elif name == "zone":
            if "name" in attrs:
                log.warning("Ignoring deprecated attribute name='%s'",
                            attrs["name"])
            if "version" in attrs:
                self.item.version = attrs["version"]
            if "immutable" in attrs:
                log.warning("Ignoring deprecated attribute immutable='%s'",
                            attrs["immutable"])
            if "target" in attrs:
                target = attrs["target"]
                if target not in ZONE_TARGETS:
                    raise FirewallError(errors.INVALID_TARGET, target)
                if target != "" and target != DEFAULT_ZONE_TARGET:
                    self.item.target = target

        elif name == "forward":
            if self.item.forward:
                log.warning("Forward already set, ignoring.")
            else:
                self.item.forward = True

        elif name == "interface":
            if self._rule:
                log.warning('Invalid rule: interface use in rule.')
                self._rule_error = True
                return
            # zone bound to interface
            if "name" not in attrs:
                log.warning('Invalid interface: Name missing.')
                self._rule_error = True
                return
            if attrs["name"] not in self.item.interfaces:
                self.item.interfaces.append(attrs["name"])
            else:
                log.warning("Interface '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "source":
            if self._rule:
                if self._rule.source:
                    log.warning(
                        "Invalid rule: More than one source in rule '%s', ignoring.",
                        str(self._rule))
                    self._rule_error = True
                    return
                invert = False
                if "invert" in attrs and \
                        attrs["invert"].lower() in [ "yes", "true" ]:
                    invert = True
                addr = mac = ipset = None
                if "address" in attrs:
                    addr = attrs["address"]
                if "mac" in attrs:
                    mac = attrs["mac"]
                if "ipset" in attrs:
                    ipset = attrs["ipset"]
                self._rule.source = rich.Rich_Source(addr,
                                                     mac,
                                                     ipset,
                                                     invert=invert)
                return
            # zone bound to source
            if "address" not in attrs and "ipset" not in attrs:
                log.warning('Invalid source: No address no ipset.')
                return
            if "address" in attrs and "ipset" in attrs:
                log.warning('Invalid source: Address and ipset.')
                return
            if "family" in attrs:
                log.warning("Ignoring deprecated attribute family='%s'",
                            attrs["family"])
            if "invert" in attrs:
                log.warning('Invalid source: Invertion not allowed here.')
                return
            if "address" in attrs:
                if not checkIPnMask(attrs["address"]) and \
                   not checkIP6nMask(attrs["address"]) and \
                   not check_mac(attrs["address"]):
                    raise FirewallError(errors.INVALID_ADDR, attrs["address"])
            if "ipset" in attrs:
                entry = "ipset:%s" % attrs["ipset"]
                if entry not in self.item.sources:
                    self.item.sources.append(entry)
                else:
                    log.warning("Source '%s' already set, ignoring.",
                                attrs["address"])
            if "address" in attrs:
                entry = attrs["address"]
                if entry not in self.item.sources:
                    self.item.sources.append(entry)
                else:
                    log.warning("Source '%s' already set, ignoring.",
                                attrs["address"])

        elif name == "icmp-block-inversion":
            if self.item.icmp_block_inversion:
                log.warning("Icmp-Block-Inversion already set, ignoring.")
            else:
                self.item.icmp_block_inversion = True

        else:
            log.warning("Unknown XML element '%s'", name)
            return
Exemplo n.º 16
0
    def startElement(self, name, attrs):
        IO_Object_ContentHandler.startElement(self, name, attrs)
        if self._rule_error:
            return

        self.item.parser_check_element_attrs(name, attrs)

        if name == "zone":
            if "name" in attrs:
                log.warning("Ignoring deprecated attribute name='%s'",
                            attrs["name"])
            if "version" in attrs:
                self.item.version = attrs["version"]
            if "immutable" in attrs:
                log.warning("Ignoring deprecated attribute immutable='%s'",
                            attrs["immutable"])
            if "target" in attrs:
                target = attrs["target"]
                if target not in ZONE_TARGETS:
                    raise FirewallError(errors.INVALID_TARGET, target)
                if target != "" and target != DEFAULT_ZONE_TARGET:
                    self.item.target = target

        elif name == "short":
            pass
        elif name == "description":
            pass
        elif name == "service":
            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_Service(attrs["name"])
                return
            if attrs["name"] not in self.item.services:
                self.item.services.append(attrs["name"])
            else:
                log.warning("Service '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "port":
            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_Port(attrs["port"],
                                               attrs["protocol"])
                return
            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
            if entry not in self.item.ports:
                self.item.ports.append(entry)
            else:
                log.warning("Port '%s/%s' already set, ignoring.",
                            attrs["port"], attrs["protocol"])

        elif name == "protocol":
            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_Protocol(attrs["value"])
            else:
                check_protocol(attrs["value"])
                if attrs["value"] not in self.item.protocols:
                    self.item.protocols.append(attrs["value"])
                else:
                    log.warning("Protocol '%s' already set, ignoring.",
                                attrs["value"])
        elif name == "icmp-block":
            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_IcmpBlock(attrs["name"])
                return
            if attrs["name"] not in self.item.icmp_blocks:
                self.item.icmp_blocks.append(attrs["name"])
            else:
                log.warning("icmp-block '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "masquerade":
            if "enabled" in attrs and \
               attrs["enabled"].lower() in [ "no", "false" ] :
                log.warning("Ignoring deprecated attribute enabled='%s'",
                            attrs["enabled"])
                return

            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_Masquerade()
            else:
                if self.item.masquerade:
                    log.warning("Masquerade already set, ignoring.")
                else:
                    self.item.masquerade = True

        elif name == "forward-port":
            to_port = ""
            if "to-port" in attrs:
                to_port = attrs["to-port"]
            to_addr = ""
            if "to-addr" in attrs:
                to_addr = attrs["to-addr"]

            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_ForwardPort(attrs["port"],
                                                      attrs["protocol"],
                                                      to_port, to_addr)
                return

            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            if to_port:
                check_port(to_port)
            if to_addr:
                if not checkIP(to_addr):
                    raise FirewallError(errors.INVALID_ADDR,
                                        "to-addr '%s' is not a valid address" \
                                        % to_addr)
            entry = (portStr(attrs["port"], "-"), attrs["protocol"],
                     portStr(to_port, "-"), str(to_addr))
            if entry not in self.item.forward_ports:
                self.item.forward_ports.append(entry)
            else:
                log.warning("Forward port %s/%s%s%s already set, ignoring.",
                            attrs["port"], attrs["protocol"],
                            " >%s" % to_port if to_port else "",
                            " @%s" % to_addr if to_addr else "")

        elif name == "source-port":
            if self._rule:
                if self._rule.element:
                    log.warning("Invalid rule: More than one element in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                self._rule.element = Rich_SourcePort(attrs["port"],
                                                     attrs["protocol"])
                return
            check_port(attrs["port"])
            check_tcpudp(attrs["protocol"])
            entry = (portStr(attrs["port"], "-"), attrs["protocol"])
            if entry not in self.item.source_ports:
                self.item.source_ports.append(entry)
            else:
                log.warning("Source port '%s/%s' already set, ignoring.",
                            attrs["port"], attrs["protocol"])

        elif name == "interface":
            if self._rule:
                log.warning('Invalid rule: interface use in rule.')
                self._rule_error = True
                return
            # zone bound to interface
            if "name" not in attrs:
                log.warning('Invalid interface: Name missing.')
                self._rule_error = True
                return
            if attrs["name"] not in self.item.interfaces:
                self.item.interfaces.append(attrs["name"])
            else:
                log.warning("Interface '%s' already set, ignoring.",
                            attrs["name"])

        elif name == "source":
            if self._rule:
                if self._rule.source:
                    log.warning("Invalid rule: More than one source in rule '%s', ignoring.",
                                str(self._rule))
                    self._rule_error = True
                    return
                invert = False
                if "invert" in attrs and \
                        attrs["invert"].lower() in [ "yes", "true" ]:
                    invert = True
                addr = mac = ipset = None
                if "address" in attrs:
                    addr = attrs["address"]
                if "mac" in attrs:
                    mac = attrs["mac"]
                if "ipset" in attrs:
                    ipset = attrs["ipset"]
                self._rule.source = Rich_Source(addr, mac, ipset, invert=invert)
                return
            # zone bound to source
            if "address" not in attrs and not "ipset" in attrs:
                log.warning('Invalid source: No address no ipset.')
                return
            if "address" in attrs and "ipset" in attrs:
                log.warning('Invalid source: Address and ipset.')
                return
            if "family" in attrs:
                log.warning("Ignoring deprecated attribute family='%s'",
                            attrs["family"])
            if "invert" in attrs:
                log.warning('Invalid source: Invertion not allowed here.')
                return
            if "address" in attrs:
                if not checkIPnMask(attrs["address"]) and \
                   not checkIP6nMask(attrs["address"]) and \
                   not check_mac(attrs["address"]):
                    raise FirewallError(errors.INVALID_ADDR, attrs["address"])
            if "ipset" in attrs:
                entry = "ipset:%s" % attrs["ipset"]
                if entry not in self.item.sources:
                    self.item.sources.append(entry)
                else:
                    log.warning("Source '%s' already set, ignoring.",
                                attrs["address"])
            if "address" in attrs:
                entry = attrs["address"]
                if entry not in self.item.sources:
                    self.item.sources.append(entry)
                else:
                    log.warning("Source '%s' already set, ignoring.",
                                attrs["address"])

        elif name == "destination":
            if not self._rule:
                log.warning('Invalid rule: Destination outside of rule')
                self._rule_error = True
                return
            if self._rule.destination:
                log.warning("Invalid rule: More than one destination in rule '%s', ignoring.",
                            str(self._rule))
                return
            invert = False
            if "invert" in attrs and \
                    attrs["invert"].lower() in [ "yes", "true" ]:
                invert = True
            self._rule.destination = Rich_Destination(attrs["address"],
                                                      invert)

        elif name in [ "accept", "reject", "drop", "mark" ]:
            if not self._rule:
                log.warning('Invalid rule: Action outside of rule')
                self._rule_error = True
                return
            if self._rule.action:
                log.warning('Invalid rule: More than one action')
                self._rule_error = True
                return
            if name == "accept":
                self._rule.action = Rich_Accept()
            elif name == "reject":
                _type = None
                if "type" in attrs:
                    _type = attrs["type"]
                self._rule.action = Rich_Reject(_type)
            elif name == "drop":
                self._rule.action = Rich_Drop()
            elif name == "mark":
                _set = attrs["set"]
                self._rule.action = Rich_Mark(_set)
            self._limit_ok = self._rule.action

        elif name == "log":
            if not self._rule:
                log.warning('Invalid rule: Log outside of rule')
                return
            if self._rule.log:
                log.warning('Invalid rule: More than one log')
                return
            level = None
            if "level" in attrs:
                level = attrs["level"]
                if level not in [ "emerg", "alert", "crit", "error",
                                  "warning", "notice", "info", "debug" ]:
                    log.warning('Invalid rule: Invalid log level')
                    self._rule_error = True
                    return
            prefix = attrs["prefix"] if "prefix" in attrs else None
            self._rule.log = Rich_Log(prefix, level)
            self._limit_ok = self._rule.log

        elif name == "audit":
            if not self._rule:
                log.warning('Invalid rule: Audit outside of rule')
                return
            if self._rule.audit:
                log.warning("Invalid rule: More than one audit in rule '%s', ignoring.",
                            str(self._rule))
                self._rule_error = True
                return            
            self._rule.audit = Rich_Audit()
            self._limit_ok = self._rule.audit

        elif name == "rule":
            family = None
            if "family" in attrs:
                family = attrs["family"]
                if family not in [ "ipv4", "ipv6" ]:
                    log.warning('Invalid rule: Rule family "%s" invalid',
                                attrs["family"])
                    self._rule_error = True
                    return
            self._rule = Rich_Rule(family)

        elif name == "limit":
            if not self._limit_ok:
                log.warning('Invalid rule: Limit outside of action, log and audit')
                self._rule_error = True
                return
            if self._limit_ok.limit:
                log.warning("Invalid rule: More than one limit in rule '%s', ignoring.",
                            str(self._rule))
                self._rule_error = True
                return
            value = attrs["value"]
            self._limit_ok.limit = Rich_Limit(value)

        elif name == "icmp-block-inversion":
            if self.item.icmp_block_inversion:
                log.warning("Icmp-Block-Inversion already set, ignoring.")
            else:
                self.item.icmp_block_inversion = True

        else:
            log.warning("Unknown XML element '%s'", name)
            return