Ejemplo n.º 1
0
    def _check_config(self, config, item, all_config):
        if item == "ports":
            for port in config:
                if port[0] != "":
                    check_port(port[0])
                    check_tcpudp(port[1])
                else:
                    # only protocol
                    check_protocol(port[1])

        elif item == "protocols":
            for proto in config:
                check_protocol(proto)

        elif item == "source_ports":
            for port in config:
                check_port(port[0])
                check_tcpudp(port[1])

        elif item == "destination":
            for destination in config:
                if destination not in ["ipv4", "ipv6"]:
                    raise FirewallError(errors.INVALID_DESTINATION,
                                        "'%s' not in {'ipv4'|'ipv6'}" % \
                                        destination)
                check_address(destination, config[destination])

        elif item == "modules":
            for module in config:
                if module.startswith("nf_conntrack_"):
                    module = module.replace("nf_conntrack_", "")
                    if "_" in module:
                        module = module.replace("_", "-")
                if len(module) < 2:
                    raise FirewallError(errors.INVALID_MODULE, module)
Ejemplo n.º 2
0
    def _check_config(self, config, item):
        if item == "ports":
            for port in config:
                if port[0] != "":
                    check_port(port[0])
                    check_tcpudp(port[1])
                else:
                    # only protocol
                    check_protocol(port[1])

        elif item == "protocols":
            for proto in config:
                check_protocol(proto)

        elif item == "source_ports":
            for port in config:
                check_port(port[0])
                check_tcpudp(port[1])

        elif item == "destination":
            for destination in config:
                if destination not in [ "ipv4", "ipv6" ]:
                    raise FirewallError(errors.INVALID_DESTINATION,
                                        "'%s' not in {'ipv4'|'ipv6'}" % \
                                        destination)
                check_address(destination, config[destination])

        elif item == "modules":
            for module in config:
                if not module.startswith("nf_conntrack_"):
                    raise FirewallError(errors.INVALID_MODULE, module)
                elif len(module.replace("nf_conntrack_", "")) < 1:
                    raise FirewallError(errors.INVALID_MODULE, module)
Ejemplo n.º 3
0
def common_check_config(obj, config, item, all_config):
    if item == "services" and obj.fw_config:
        existing_services = obj.fw_config.get_services()
        for service in config:
            if service not in existing_services:
                raise FirewallError(errors.INVALID_SERVICE,
                                    "'%s' not among existing services" % \
                                    service)
    elif item == "ports":
        for port in config:
            check_port(port[0])
            check_tcpudp(port[1])
    elif item == "protocols":
        for proto in config:
            check_protocol(proto)
    elif item == "icmp_blocks" and obj.fw_config:
        existing_icmptypes = obj.fw_config.get_icmptypes()
        for icmptype in config:
            if icmptype not in existing_icmptypes:
                raise FirewallError(errors.INVALID_ICMPTYPE,
                                    "'%s' not among existing icmp types" % \
                                    icmptype)
    elif item == "forward_ports":
        for fwd_port in config:
            check_port(fwd_port[0])
            check_tcpudp(fwd_port[1])
            if not fwd_port[2] and not fwd_port[3]:
                raise FirewallError(
                    errors.INVALID_FORWARD,
                    "'%s' is missing to-port AND to-addr " % fwd_port)
            if fwd_port[2]:
                check_port(fwd_port[2])
            if fwd_port[3]:
                if not checkIP(fwd_port[3]) and not checkIP6(fwd_port[3]):
                    raise FirewallError(
                        errors.INVALID_ADDR,
                        "to-addr '%s' is not a valid address" % fwd_port[3])
    elif item == "source_ports":
        for port in config:
            check_port(port[0])
            check_tcpudp(port[1])
    elif item in ["rules_str", "rich_rules"]:
        for rule in config:
            obj_rich = rich.Rich_Rule(rule_str=rule)
            if obj.fw_config and obj_rich.element and (
                    isinstance(obj_rich.element, rich.Rich_IcmpBlock)
                    or isinstance(obj_rich.element, rich.Rich_IcmpType)):
                existing_icmptypes = obj.fw_config.get_icmptypes()
                if obj_rich.element.name not in existing_icmptypes:
                    raise FirewallError(errors.INVALID_ICMPTYPE,
                                        "'%s' not among existing icmp types" % \
                                        obj_rich.element.name)
                elif obj_rich.family:
                    ict = obj.fw_config.get_icmptype(obj_rich.element.name)
                    if ict.destination and obj_rich.family not in ict.destination:
                        raise FirewallError(errors.INVALID_ICMPTYPE,
                                            "rich rule family '%s' conflicts with icmp type '%s'" % \
                                            (obj_rich.family, obj_rich.element.name))
Ejemplo n.º 4
0
 def _check_config(self, config, item):
     if item == "services" and self.fw_config:
         existing_services = self.fw_config.get_services()
         for service in config:
             if service not in existing_services:
                 raise FirewallError(errors.INVALID_SERVICE,
                                     "'%s' not among existing services" % \
                                     service)
     elif item == "ports":
         for port in config:
             check_port(port[0])
             check_tcpudp(port[1])
     elif item == "protocols":
         for proto in config:
             check_protocol(proto)
     elif item == "icmp_blocks" and self.fw_config:
         existing_icmptypes = self.fw_config.get_icmptypes()
         for icmptype in config:
             if icmptype not in existing_icmptypes:
                 raise FirewallError(errors.INVALID_ICMPTYPE,
                                     "'%s' not among existing icmp types" % \
                                     icmptype)
     elif item == "forward_ports":
         for fwd_port in config:
             check_port(fwd_port[0])
             check_tcpudp(fwd_port[1])
             if not fwd_port[2] and not fwd_port[3]:
                 raise FirewallError(
                     errors.INVALID_FORWARD,
                     "'%s' is missing to-port AND to-addr " % fwd_port)
             if fwd_port[2]:
                 check_port(fwd_port[2])
             if fwd_port[3]:
                 if not checkIP(fwd_port[3]) and not checkIP6(fwd_port[3]):
                     raise FirewallError(
                         errors.INVALID_ADDR,
                         "to-addr '%s' is not a valid address" %
                         fwd_port[3])
     elif item == "source_ports":
         for port in config:
             check_port(port[0])
             check_tcpudp(port[1])
     elif item == "target":
         if config not in ZONE_TARGETS:
             raise FirewallError(errors.INVALID_TARGET, config)
     elif item == "interfaces":
         for interface in config:
             if not checkInterface(interface):
                 raise FirewallError(errors.INVALID_INTERFACE, interface)
     elif item == "sources":
         for source in config:
             if not checkIPnMask(source) and not checkIP6nMask(source) and \
                not check_mac(source) and not source.startswith("ipset:"):
                 raise FirewallError(errors.INVALID_ADDR, source)
     elif item == "rules_str":
         for rule in config:
             rich.Rich_Rule(rule_str=rule)
Ejemplo n.º 5
0
 def _check_config(self, config, item):
     if item == "services" and self.fw_config:
         existing_services = self.fw_config.get_services()
         for service in config:
             if not service in existing_services:
                 raise FirewallError(errors.INVALID_SERVICE,
                                     "'%s' not among existing services" % \
                                     service)
     elif item == "ports":
         for port in config:
             check_port(port[0])
             check_tcpudp(port[1])
     elif item == "protocols":
         for proto in config:
             check_protocol(proto)
     elif item == "icmp_blocks" and self.fw_config:
         existing_icmptypes = self.fw_config.get_icmptypes()
         for icmptype in config:
             if not icmptype in existing_icmptypes:
                 raise FirewallError(errors.INVALID_ICMPTYPE,
                                     "'%s' not among existing icmp types" % \
                                     icmptype)
     elif item == "forward_ports":
         for fwd_port in config:
             check_port(fwd_port[0])
             check_tcpudp(fwd_port[1])
             if not fwd_port[2] and not fwd_port[3]:
                 raise FirewallError(
                     errors.INVALID_FORWARD,
                     "'%s' is missing to-port AND to-addr " % fwd_port)
             if fwd_port[2]:
                 check_port(fwd_port[2])
             if fwd_port[3]:
                 if not checkIP(fwd_port[3]):
                     raise FirewallError(
                         errors.INVALID_ADDR,
                         "to-addr '%s' is not a valid address" % fwd_port[3])
     elif item == "source_ports":
         for port in config:
             check_port(port[0])
             check_tcpudp(port[1])
     elif item == "target":
         if config not in ZONE_TARGETS:
             raise FirewallError(errors.INVALID_TARGET, config)
     elif item == "interfaces":
         for interface in config:
             if not checkInterface(interface):
                 raise FirewallError(errors.INVALID_INTERFACE, interface)
     elif item == "sources":
         for source in config:
             if not checkIPnMask(source) and not checkIP6nMask(source) and \
                not check_mac(source) and not source.startswith("ipset:"):
                 raise FirewallError(errors.INVALID_ADDR, source)
     elif item == "rules_str":
         for rule in config:
             Rich_Rule(rule_str=rule)
Ejemplo n.º 6
0
 def _check_config(self, config, item):
     if item == "services" and self.fw_config:
         existing_services = self.fw_config.get_services()
         for service in config:
             if service not in existing_services:
                 raise FirewallError(errors.INVALID_SERVICE,
                                     "'%s' not among existing services" % \
                                     service)
     elif item == "ports":
         for port in config:
             check_port(port[0])
             check_tcpudp(port[1])
     elif item == "protocols":
         for proto in config:
             check_protocol(proto)
     elif item == "icmp_blocks" and self.fw_config:
         existing_icmptypes = self.fw_config.get_icmptypes()
         for icmptype in config:
             if icmptype not in existing_icmptypes:
                 raise FirewallError(errors.INVALID_ICMPTYPE,
                                     "'%s' not among existing icmp types" % \
                                     icmptype)
     elif item == "forward_ports":
         for fwd_port in config:
             check_port(fwd_port[0])
             check_tcpudp(fwd_port[1])
             if not fwd_port[2] and not fwd_port[3]:
                 raise FirewallError(
                     errors.INVALID_FORWARD,
                     "'%s' is missing to-port AND to-addr " % fwd_port)
             if fwd_port[2]:
                 check_port(fwd_port[2])
             if fwd_port[3]:
                 if not checkIP(fwd_port[3]) and not checkIP6(fwd_port[3]):
                     raise FirewallError(
                         errors.INVALID_ADDR,
                         "to-addr '%s' is not a valid address" %
                         fwd_port[3])
     elif item == "source_ports":
         for port in config:
             check_port(port[0])
             check_tcpudp(port[1])
     elif item == "target":
         if config not in POLICY_TARGETS:
             raise FirewallError(errors.INVALID_TARGET, config)
     elif item == "rules_str":
         for rule in config:
             rich.Rich_Rule(rule_str=rule)
     elif item in ["ingress-zone", "egress-zone"] and self.fw_config:
         existing_zones = self.fw_config.get_zones()
         for zone in config:
             if zone not in existing_zones:
                 raise FirewallError(errors.INVALID_SERVICE,
                                     "'%s' not among existing zones" % zone)
Ejemplo n.º 7
0
def common_startElement(obj, name, attrs):
    if name == "short":
        pass
    elif name == "description":
        pass

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

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

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

    elif name == "tcp-mss-clamp":
        if obj._rule:
            if obj._rule.element:
                log.warning(
                    "Invalid rule: More than one element in rule '%s', ignoring.",
                    str(obj._rule))
                obj._rule_error = True
                return True
            _value = "pmtu"
            if "value" in attrs:
                _value = attrs["value"]
            obj._rule.element = rich.Rich_Tcp_Mss_Clamp(_value)
        else:
            log.warning("Invalid rule: tcp-mss-clamp '%s' outside of rule",
                        attrs["value"])

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

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

    elif name == "masquerade":
        if obj._rule:
            if obj._rule.element:
                log.warning(
                    "Invalid rule: More than one element in rule '%s', ignoring.",
                    str(obj._rule))
                obj._rule_error = True
                return True
            obj._rule.element = rich.Rich_Masquerade()
        else:
            if obj.item.masquerade:
                log.warning("Masquerade already set, ignoring.")
            else:
                obj.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 obj._rule:
            if obj._rule.element:
                log.warning(
                    "Invalid rule: More than one element in rule '%s', ignoring.",
                    str(obj._rule))
                obj._rule_error = True
                return True
            obj._rule.element = rich.Rich_ForwardPort(attrs["port"],
                                                      attrs["protocol"],
                                                      to_port, to_addr)
            return True

        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 obj.item.forward_ports:
            obj.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 obj._rule:
            if obj._rule.element:
                log.warning(
                    "Invalid rule: More than one element in rule '%s', ignoring.",
                    str(obj._rule))
                obj._rule_error = True
                return True
            obj._rule.element = rich.Rich_SourcePort(attrs["port"],
                                                     attrs["protocol"])
            return True
        check_port(attrs["port"])
        check_tcpudp(attrs["protocol"])
        entry = (portStr(attrs["port"], "-"), attrs["protocol"])
        if entry not in obj.item.source_ports:
            obj.item.source_ports.append(entry)
        else:
            log.warning("Source port '%s/%s' already set, ignoring.",
                        attrs["port"], attrs["protocol"])

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

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

    elif name == "log":
        if not obj._rule:
            log.warning('Invalid rule: Log outside of rule')
            return True
        if obj._rule.log:
            log.warning('Invalid rule: More than one log')
            return True
        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')
                obj._rule_error = True
                return True
        prefix = None
        if "prefix" in attrs:
            prefix = attrs["prefix"]
            if not prefix or len(prefix) > 127:
                log.warning('Invalid rule: Invalid log prefix')
                obj._rule_error = True
                return True
        obj._rule.log = rich.Rich_Log(prefix, level)
        obj._limit_ok = obj._rule.log

    elif name == "nflog":
        if not obj._rule:
            log.warning('Invalid rule: Log outside of rule')
            return True
        if obj._rule.log:
            log.warning('Invalid rule: More than one log')
            return True
        group = None
        if "group" in attrs:
            group = attrs["group"]
            if not checkUINT16(group):
                log.warning('Invalid rule: Invalid nflog group value')
                obj._rule_error = True
                return True
        prefix = None
        if "prefix" in attrs:
            prefix = attrs["prefix"]
            if not prefix or len(prefix) > 127:
                log.warning('Invalid rule: Invalid nflog prefix')
                obj._rule_error = True
                return True
        threshold = None
        if "queue-size" in attrs:
            threshold = attrs["queue-size"]
            if not checkUINT16(threshold):
                log.warning('Invalid rule: Invalid nflog queue-size')
                obj._rule_error = True
                return True
        obj._rule.log = rich.Rich_NFLog(group, prefix, threshold)
        obj._limit_ok = obj._rule.log

    elif name == "audit":
        if not obj._rule:
            log.warning('Invalid rule: Audit outside of rule')
            return True
        if obj._rule.audit:
            log.warning(
                "Invalid rule: More than one audit in rule '%s', ignoring.",
                str(obj._rule))
            obj._rule_error = True
            return True
        obj._rule.audit = rich.Rich_Audit()
        obj._limit_ok = obj._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"])
                obj._rule_error = True
                return True
        if "priority" in attrs:
            priority = int(attrs["priority"])
        obj._rule = rich.Rich_Rule(family=family, priority=priority)

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

    return True
Ejemplo n.º 8
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
Ejemplo 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 == "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"])
Ejemplo n.º 10
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"])
Ejemplo n.º 11
0
def common_check_config(obj, config, item, all_config, all_io_objects):
    obj_type = "Policy" if isinstance(obj, Policy) else "Zone"

    if item == "services" and "services" in all_io_objects:
        existing_services = all_io_objects["services"]
        for service in config:
            if service not in existing_services:
                raise FirewallError(errors.INVALID_SERVICE,
                        "{} '{}': '{}' not among existing services".format(
                            obj_type, obj.name, service))
    elif item == "ports":
        for port in config:
            check_port(port[0])
            check_tcpudp(port[1])
    elif item == "protocols":
        for proto in config:
            check_protocol(proto)
    elif item == "icmp_blocks" and "icmptypes" in all_io_objects:
        existing_icmptypes = all_io_objects["icmptypes"]
        for icmptype in config:
            if icmptype not in existing_icmptypes:
                ex = FirewallError(errors.INVALID_ICMPTYPE,
                        "{} '{}': '{}' not among existing ICMP types".format(
                            obj_type, obj.name, icmptype))
                if icmptype in all_io_objects.get("icmptypes_unsupported", {}):
                    log.debug1("{} (unsupported)".format(ex))
                else:
                    raise ex

    elif item == "forward_ports":
        for fwd_port in config:
            check_port(fwd_port[0])
            check_tcpudp(fwd_port[1])
            if not fwd_port[2] and not fwd_port[3]:
                raise FirewallError(errors.INVALID_FORWARD,
                    "{} '{}': '{}' is missing to-port AND to-addr ".format(
                        obj_type, obj.name, fwd_port))
            if fwd_port[2]:
                check_port(fwd_port[2])
            if fwd_port[3]:
                if not checkIP(fwd_port[3]) and not checkIP6(fwd_port[3]):
                    raise FirewallError(errors.INVALID_ADDR,
                        "{} '{}': to-addr '{}' is not a valid address".format(
                            obj_type, obj.name, fwd_port[3]))
    elif item == "source_ports":
        for port in config:
            check_port(port[0])
            check_tcpudp(port[1])
    elif item in ["rules_str", "rich_rules"]:
        for rule in config:
            obj_rich = rich.Rich_Rule(rule_str=rule)
            if obj_rich.element and "icmptypes" in all_io_objects and \
              (isinstance(obj_rich.element, rich.Rich_IcmpBlock) or
               isinstance(obj_rich.element, rich.Rich_IcmpType)):
                existing_icmptypes = all_io_objects["icmptypes"]
                if obj_rich.element.name not in existing_icmptypes:
                    ex = FirewallError(errors.INVALID_ICMPTYPE,
                            "{} '{}': '{}' not among existing ICMP types".format(
                                obj_type, obj.name, obj_rich.element.name))
                    if obj_rich.element.name in all_io_objects.get("icmptypes_unsupported", {}):
                        log.debug1("{} (unsupported)".format(ex))
                    else:
                        raise ex
                elif obj_rich.family:
                    ict = all_io_objects["icmptypes"][obj_rich.element.name]
                    if ict.destination and obj_rich.family not in ict.destination:
                        ex = FirewallError(errors.INVALID_ICMPTYPE,
                                           "{} '{}': rich rule family '{}' conflicts with icmp type '{}'".format(
                                           obj_type, obj.name, obj_rich.family, obj_rich.element.name))
                        ict_unsupported = all_io_objects.get("icmptypes_unsupported", {}).get(obj_rich.element.name)
                        if ict_unsupported and ict_unsupported.destination and \
                           obj_rich.family in ict_unsupported.destination:
                            log.debug1("{} (unsupported)".format(ex))
                        else:
                            raise ex
Ejemplo n.º 12
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
Ejemplo n.º 13
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