Exemplo n.º 1
0
    def querySourcePort(self, port, protocol, sender=None):  # pylint: disable=W0613
        port = dbus_to_python(port, str)
        protocol = dbus_to_python(protocol, str)
        log.debug1("%s.querySourcePort('%s', '%s')", self._log_prefix, port,
                   protocol)
        for (_port, _protocol) in self.getSettings()[14]:
            if portInPortRange(port, _port) and protocol == _protocol:
                return True

        return False
Exemplo n.º 2
0
    def queryPort(self, port, protocol, sender=None):  # pylint: disable=W0613
        port = dbus_to_python(port, str)
        protocol = dbus_to_python(protocol, str)
        log.debug1("%s.queryPort('%s', '%s')", self._log_prefix, port,
                   protocol)
        if (port, protocol) in self.getSettings()[6]:
            return True
        else:
            # It might be a single port query that is inside a range
            for (_port, _protocol) in self.getSettings()[6]:
                if portInPortRange(port, _port) and protocol == _protocol:
                    return True

        return False
Exemplo n.º 3
0
 def addPort(self, port, protocol, sender=None):
     port = dbus_to_python(port, str)
     protocol = dbus_to_python(protocol, str)
     log.debug1("%s.addPort('%s', '%s')", self._log_prefix, port, protocol)
     self.parent.accessCheck(sender)
     settings = list(self.getSettings())
     existing_port_ids = list(
         filter(lambda x: x[1] == protocol, settings[6]))
     for port_id in existing_port_ids:
         if portInPortRange(port, port_id[0]):
             raise FirewallError(errors.ALREADY_ENABLED,
                                 "%s:%s" % (port, protocol))
     added_ranges, removed_ranges = coalescePortRange(
         port, [_port for (_port, _protocol) in existing_port_ids])
     for range in removed_ranges:
         settings[6].remove((portStr(range, "-"), protocol))
     for range in added_ranges:
         settings[6].append((portStr(range, "-"), protocol))
     self.update(settings)
Exemplo n.º 4
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"])

        # coalesce and warn about overlapping ranges
        new_port_id = (portStr(attrs["port"], "-"), attrs["protocol"])
        existing_port_ids = list(filter(lambda x: x[1] == attrs["protocol"], obj.item.ports))
        for port_id in existing_port_ids:
            if portInPortRange(new_port_id[0], port_id[0]):
                # the range is wholly contained already, so just warn
                _name = obj.item.derived_from_zone if isinstance(obj.item, Policy) else obj.item.name
                log.warning(FirewallError(errors.ALREADY_ENABLED,
                                    "'%s:%s' already in '%s'" % (new_port_id[0], attrs["protocol"], _name)))
                break # for
        else:
            # the range can be coalesced into the existing set
            added_ranges, removed_ranges = coalescePortRange(new_port_id[0], [_port for (_port, _protocol) in existing_port_ids])

            for _range in removed_ranges:
                entry = (portStr(_range, "-"), attrs["protocol"])
                obj.item.ports.remove(entry)
            for _range in added_ranges:
                entry = (portStr(_range, "-"), attrs["protocol"])
                obj.item.ports.append(entry)

    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"])

        # coalesce and warn about overlapping ranges
        new_port_id = (portStr(attrs["port"], "-"), attrs["protocol"])
        existing_port_ids = list(filter(lambda x: x[1] == attrs["protocol"], obj.item.source_ports))
        for port_id in existing_port_ids:
            if portInPortRange(new_port_id[0], port_id[0]):
                # the range is wholly contained already, so just warn
                _name = obj.item.derived_from_zone if isinstance(obj.item, Policy) else obj.item.name
                log.warning(FirewallError(errors.ALREADY_ENABLED,
                                    "'%s:%s' already in '%s'" % (new_port_id[0], attrs["protocol"], _name)))
                break # for
        else:
            # the range can be coalesced into the existing set
            added_ranges, removed_ranges = coalescePortRange(new_port_id[0], [_port for (_port, _protocol) in existing_port_ids])

            for _range in removed_ranges:
                entry = (portStr(_range, "-"), attrs["protocol"])
                obj.item.source_ports.remove(entry)
            for _range in added_ranges:
                entry = (portStr(_range, "-"), attrs["protocol"])
                obj.item.source_ports.append(entry)

    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