Пример #1
0
    def __cmd_sequence(self, cmd_type, option, action_method, query_method,
                       parse_method, message, start_args=None, end_args=None,
                       no_exit=False):
        if self.fw is not None:
            self.fw.authorizeAll()
        items = [ ]
        _errors = 0
        for item in option:
            if parse_method is not None:
                try:
                    item = parse_method(item)
                except Exception as msg:
                    if len(option) > 1:
                        self.print_warning("Warning: %s" % msg)
                        _errors += 1
                        continue
                    else:
                        code = FirewallError.get_code(str(msg))
                        self.print_and_exit("Error: %s" % msg, code)
                        _errors += 1

            items.append(item)

        for item in items:
            call_item = [ ]
            if start_args is not None:
                call_item += start_args
            if not isinstance(item, list) and not isinstance(item, tuple):
                call_item.append(item)
            else:
                call_item += item
            if end_args is not None:
                call_item += end_args
            self.deactivate_exception_handler()
            try:
                action_method(*call_item)
            except DBusException as msg:
                code = FirewallError.get_code(msg.get_dbus_message())
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg.get_dbus_message())
                else:
                    self.print_and_exit("Error: %s" % msg.get_dbus_message(),
                                        code)
                _errors += 1
            except Exception as msg:
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg)
                    _errors += 1
                    continue
                else:
                    code = FirewallError.get_code(str(msg))
                    self.print_and_exit("Error: %s" % msg, code)
                    _errors += 1
            self.activate_exception_handler()

        if _errors == len(option) and not no_exit:
            sys.exit(errors.UNKNOWN_ERROR)
Пример #2
0
    def __query_sequence(self, option, query_method, parse_method, message, # pylint: disable=R0913
                         start_args=None, no_exit=False):
        items = [ ]
        for item in option:
            if parse_method is not None:
                try:
                    item = parse_method(item)
                except Exception as msg:
                    if len(option) > 1:
                        self.print_warning("Warning: %s" % msg)
                        continue
                    else:
                        code = FirewallError.get_code(str(msg))
                        self.print_and_exit("Error: %s" % msg, code)
            items.append(item)

        for item in items:
            call_item = [ ]
            if start_args is not None:
                call_item += start_args
            if not isinstance(item, list) and not isinstance(item, tuple):
                call_item.append(item)
            else:
                call_item += item
            self.deactivate_exception_handler()
            try:
                res = query_method(*call_item)
            except DBusException as msg:
                self.fail_if_not_authorized(msg.get_dbus_name())
                code = FirewallError.get_code(msg.get_dbus_message())
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg.get_dbus_message())
                    continue
                else:
                    self.print_and_exit("Error: %s" % msg.get_dbus_message(),
                                        code)
            except Exception as msg:
                code = FirewallError.get_code(str(msg))
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg)
                else:
                    self.print_and_exit("Error: %s" % msg, code)
            self.activate_exception_handler()
            if len(option) > 1:
                self.print_msg("%s: %s" % (message % item, ("no", "yes")[res]))
            else:
                self.print_query_result(res)
        if not no_exit:
            sys.exit(0)
Пример #3
0
 def __query_sequence(self, option, query_method, parse_method, message,
                      start_args=[]):
     items = [ ]
     for item in option:
         if parse_method != None:
             items.append(parse_method(item))
         else:
             items.append(item)
     for item in items:
         call_item = start_args[:]
         if not isinstance(item, list) and not isinstance(item, tuple):
             call_item.append(item)
         else:
             call_item += item
         try:
             res = query_method(*call_item)
         except DBusException as msg:
             code = FirewallError.get_code(msg)
             if len(option) > 1:
                 self.print_warning("Warning: %s" % msg.get_dbus_message())
             else:
                 self.print_and_exit("Error: %s" % msg.get_dbus_message(),
                                     code)
             continue
         if len(option) > 1:
             self.print_msg("%s: %s" % (message % item, ("no", "yes")[res]))
         else:
             self.print_query_result(res)
     sys.exit(0)
Пример #4
0
 def exception_handler(self, exception_message):
     if not self.__use_exception_handler:
         raise
     self.fail_if_not_authorized(exception_message)
     code = FirewallError.get_code(str(exception_message))
     if code in [ errors.ALREADY_ENABLED, errors.NOT_ENABLED,
                  errors.ZONE_ALREADY_SET, errors.ALREADY_SET ]:
         self.print_warning("Warning: %s" % exception_message)
     else:
         self.print_and_exit("Error: %s" % exception_message, code)
Пример #5
0
 def exception_handler(self, exception_message):
     if "NotAuthorizedException" in exception_message:
         msg = """Authorization failed.
 Make sure polkit agent is running or run the application as superuser."""
         self.print_and_exit(msg, errors.NOT_AUTHORIZED)
     else:
         code = FirewallError.get_code(exception_message)
         if code in [ errors.ALREADY_ENABLED, errors.NOT_ENABLED,
                      errors.ZONE_ALREADY_SET ]:
             self.print_warning("Warning: %s" % exception_message)
         else:
             self.print_and_exit("Error: %s" % exception_message, code)
Пример #6
0
 def addSourcePort(self, port, protocol, sender=None):
     port = dbus_to_python(port, str)
     protocol = dbus_to_python(protocol, str)
     log.debug1("%s.addSourcePort('%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[14]))
     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[14].remove((portStr(range, "-"), protocol))
     for range in added_ranges:
         settings[14].append((portStr(range, "-"), protocol))
     self.update(settings)
Пример #7
0
    def set_default_zone(self, zone):
        _zone = self.check_zone(zone)
        if _zone != self._default_zone:
            _old_dz = self._default_zone
            self._default_zone = _zone
            self._firewalld_conf.set("DefaultZone", _zone)
            self._firewalld_conf.write()

            # remove old default zone from ZONES and add new default zone
            self.zone.change_default_zone(_old_dz, _zone)

            # Move interfaces from old default zone to the new one.
            _old_dz_settings = self.zone.get_settings(_old_dz)
            for iface, settings in list(_old_dz_settings["interfaces"].items()):
                if settings["__default__"]:
                    # move only those that were added to default zone
                    # (not those that were added to specific zone same as default)
                    self.zone.change_zone_of_interface("", iface)
        else:
            raise FirewallError(errors.ZONE_ALREADY_SET, _zone)
Пример #8
0
 def _impl(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except FirewallError as error:
         code = FirewallError.get_code(str(error))
         if code in [
                 errors.ALREADY_ENABLED, errors.NOT_ENABLED,
                 errors.ZONE_ALREADY_SET, errors.ALREADY_SET
         ]:
             log.warning(str(error))
         else:
             log.debug1(traceback.format_exc())
             log.error(str(error))
         raise FirewallDBusException(str(error))
     except DBusException as ex:
         # only log DBusExceptions once
         raise ex
     except Exception as ex:
         log.exception()
         raise FirewallDBusException(str(ex))
Пример #9
0
    def parse_forward_port(self, value):
        port = None
        protocol = None
        toport = None
        toaddr = None
        args = value.split(":")
        for arg in args:
            try:
                (opt, val) = arg.split("=")
                if opt == "port":
                    port = val
                elif opt == "proto":
                    protocol = val
                elif opt == "toport":
                    toport = val
                elif opt == "toaddr":
                    toaddr = val
            except ValueError:
                raise FirewallError(errors.INVALID_FORWARD,
                                    "invalid forward port arg '%s'" % (arg))
        if not port:
            raise FirewallError(errors.INVALID_FORWARD, "missing port")
        if not protocol:
            raise FirewallError(errors.INVALID_FORWARD, "missing protocol")
        if not (toport or toaddr):
            raise FirewallError(errors.INVALID_FORWARD, "missing destination")

        if not check_port(port):
            raise FirewallError(errors.INVALID_PORT, port)
        if protocol not in [ "tcp", "udp", "sctp", "dccp" ]:
            raise FirewallError(errors.INVALID_PROTOCOL,
                                "'%s' not in {'tcp'|'udp'|'sctp'|'dccp'}" % \
                                protocol)
        if toport and not check_port(toport):
            raise FirewallError(errors.INVALID_PORT, toport)
        if toaddr and not check_single_address("ipv4", toaddr):
            raise FirewallError(errors.INVALID_ADDR, toaddr)

        return (port, protocol, toport, toaddr)
Пример #10
0
def dbus_handle_exceptions(func, *args, **kwargs):
    """Decorator to handle exceptions, log and report them into D-Bus

    :Raises DBusException: on a firewall error code problems.
    """
    try:
        return func(*args, **kwargs)
    except FirewallError as error:
        code = FirewallError.get_code(str(error))
        if code in [ errors.ALREADY_ENABLED, errors.NOT_ENABLED,
                     errors.ZONE_ALREADY_SET, errors.ALREADY_SET ]:
            log.warning(str(error))
        else:
            log.error(str(error))
        raise FirewallDBusException(str(error))
    except DBusException as ex:
        # only log DBusExceptions once
        raise ex
    except Exception as ex:
        log.exception()
        raise FirewallDBusException(str(ex))
Пример #11
0
    def new_service(self, name, conf):
        try:
            self.get_service(name)
        except:
            pass
        else:
            raise FirewallError(errors.NAME_CONFLICT,
                                "new_service(): '%s'" % name)

        x = Service()
        x.check_name(name)
        x.import_config(conf)
        x.name = name
        x.filename = "%s.xml" % name
        x.path = config.ETC_FIREWALLD_SERVICES
        # It is not possible to add a new one with a name of a buitin
        x.builtin = False
        x.default = True

        service_writer(x)
        self.add_service(x)
        return x
Пример #12
0
def icmptype_reader(filename, path):
    icmptype = IcmpType()
    if not filename.endswith(".xml"):
        raise FirewallError(errors.INVALID_NAME,
                            "%s is missing .xml suffix" % filename)
    icmptype.name = filename[:-4]
    icmptype.check_name(icmptype.name)
    icmptype.filename = filename
    icmptype.path = path
    icmptype.builtin = False if path.startswith(ETC_FIREWALLD) else True
    icmptype.default = icmptype.builtin
    handler = icmptype_ContentHandler(icmptype)
    parser = sax.make_parser()
    parser.setContentHandler(handler)
    name = "%s/%s" % (path, filename)
    with open(name, "r") as f:
        parser.parse(f)
    del handler
    del parser
    if PY2:
        icmptype.encode_strings()
    return icmptype
Пример #13
0
    def reverse_passthrough(self, args):
        """ Reverse valid passthough rule """

        replace_args = {
            # Append
            "-A": "-D",
            "--append": "--delete",
            # Insert
            "-I": "-D",
            "--insert": "--delete",
            # New chain
            "-N": "-X",
            "--new-chain": "--delete-chain",
        }

        ret_args = args[:]

        for x in replace_args:
            try:
                idx = ret_args.index(x)
            except ValueError:
                continue

            if x in [ "-I", "--insert" ]:
                # With insert rulenum, then remove it if it is a number
                # Opt at position idx, chain at position idx+1, [rulenum] at
                # position idx+2
                try:
                    int(ret_args[idx+2])
                except ValueError:
                    pass
                else:
                    ret_args.pop(idx+2)

            ret_args[idx] = replace_args[x]
            return ret_args

        raise FirewallError(errors.INVALID_PASSTHROUGH,
                            "no '-A', '-I' or '-N' arg")
Пример #14
0
 def _rich_rule_to_policies(self, zone, rule):
     zone = self._fw.check_zone(zone)
     if type(rule.action) == Rich_Mark:
         return [self.policy_name_from_zones(zone, "ANY")]
     elif type(rule.element) in [
             Rich_Service, Rich_Port, Rich_Protocol, Rich_SourcePort
     ]:
         return [self.policy_name_from_zones(zone, "HOST")]
     elif type(rule.element) in [Rich_IcmpBlock, Rich_IcmpType]:
         return [
             self.policy_name_from_zones(zone, "HOST"),
             self.policy_name_from_zones(zone, "ANY")
         ]
     elif type(rule.element) in [Rich_ForwardPort]:
         return [self.policy_name_from_zones(zone, "ANY")]
     elif type(rule.element) in [Rich_Masquerade]:
         return [self.policy_name_from_zones("ANY", zone)]
     elif rule.element is None:
         return [self.policy_name_from_zones(zone, "HOST")]
     else:
         raise FirewallError("Rich rule type (%s) not handled." %
                             (type(rule.element)))
Пример #15
0
    def policy_from_chain(self, chain):
        x = self.zone_from_chain(chain)
        if x is None:
            return None

        (zone, _chain) = x
        # derived from _get_table_chains_for_zone_dispatch()
        if _chain in ["PREROUTING", "FORWARD_IN"]:
            fromZone = zone
            toZone = "ANY"
        elif _chain in ["INPUT"]:
            fromZone = zone
            toZone = "HOST"
        elif _chain in ["POSTROUTING", "FORWARD_OUT"]:
            fromZone = "ANY"
            toZone = zone
        else:
            raise FirewallError(
                errors.INVALID_CHAIN,
                "chain '%s' can't be mapped to a policy" % (chain))

        return (self.policy_name_from_zones(fromZone, toZone), _chain)
Пример #16
0
def service_reader(filename, path):
    service = Service()
    if not filename.endswith(".xml"):
        raise FirewallError(errors.INVALID_NAME,
                            "'%s' is missing .xml suffix" % filename)
    service.name = filename[:-4]
    service.check_name(service.name)
    service.filename = filename
    service.path = path
    service.builtin = False if path.startswith(ETC_FIREWALLD) else True
    service.default = service.builtin
    handler = service_ContentHandler(service)
    parser = sax.make_parser()
    parser.setContentHandler(handler)
    name = "%s/%s" % (path, filename)
    with open(name, "r") as f:
        parser.parse(f)
    del handler
    del parser
    if PY2:
        service.encode_strings()
    return service
Пример #17
0
    def new_service(self, name, conf):
        if name in self._services or name in self._builtin_services:
            raise FirewallError(errors.NAME_CONFLICT,
                                "new_service(): '%s'" % name)

        conf_dict = {}
        for i, value in enumerate(conf):
            conf_dict[Service.IMPORT_EXPORT_STRUCTURE[i][0]] = value

        x = Service()
        x.check_name(name)
        x.import_config_dict(conf_dict)
        x.name = name
        x.filename = "%s.xml" % name
        x.path = config.ETC_FIREWALLD_SERVICES
        # It is not possible to add a new one with a name of a buitin
        x.builtin = False
        x.default = True

        service_writer(x)
        self.add_service(x)
        return x
Пример #18
0
    def rules(self, ipv, rules):
        _rules = rules[:]

        backend = self.get_ipv_backend(ipv)
        if not backend:
            raise FirewallError(errors.INVALID_IPV,
                                "'%s' is not a valid backend" % ipv)

        if not self.is_ipv_enabled(ipv):
            return ""

        if self._individual_calls or \
           not backend.restore_command_exists or \
           (ipv == "eb" and not self.ebtables_backend.restore_noflush_option):
            for i,rule in enumerate(_rules):
                # remove leading and trailing '"' for use with execve
                j = 0
                while j < len(rule):
                    x = rule[j]
                    if len(x) > 2 and x[0] == '"' and x[-1] == '"':
                        rule[j] = x[1:-1]
                    j += 1

                try:
                    backend.set_rule(rule)
                except Exception as msg:
                    log.error("Failed to apply rules. A firewall reload might solve the issue if the firewall has been modified using ip*tables or ebtables.")
                    log.error(msg)
                    for rule in reversed(_rules[:i]):
                        try:
                            backend.set_rule(backend.reverse_rule(rule))
                        except Exception:
                            # ignore errors here
                            pass
                    return False
            return True
        else:
            return backend.set_rules(_rules, log_denied=self._log_denied)
Пример #19
0
    def _check_config(self, config, item, all_config, all_io_objects):
        common_check_config(self, config, item, all_config, all_io_objects)

        if self.name in all_io_objects["policies"]:
            raise FirewallError(
                errors.NAME_CONFLICT,
                "Zone '{}': Can't have the same name as a policy.".format(
                    self.name))

        if item == "target":
            if config not in ZONE_TARGETS:
                raise FirewallError(
                    errors.INVALID_TARGET,
                    "Zone '{}': invalid target '{}'".format(self.name, config))
        elif item == "interfaces":
            for interface in config:
                if not checkInterface(interface):
                    raise FirewallError(
                        errors.INVALID_INTERFACE,
                        "Zone '{}': invalid interface '{}'".format(
                            self.name, interface))
                for zone in all_io_objects["zones"]:
                    if zone == self.name:
                        continue
                    if interface in all_io_objects["zones"][zone].interfaces:
                        raise FirewallError(
                            errors.INVALID_INTERFACE,
                            "Zone '{}': interface '{}' already bound to zone '{}'"
                            .format(self.name, interface, zone))
        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,
                        "Zone '{}': invalid source '{}'".format(
                            self.name, source))
                for zone in all_io_objects["zones"]:
                    if zone == self.name:
                        continue
                    if source in all_io_objects["zones"][zone].sources:
                        raise FirewallError(
                            errors.INVALID_ADDR,
                            "Zone '{}': source '{}' already bound to zone '{}'"
                            .format(self.name, source, zone))
Пример #20
0
    def check_entry(entry, options, ipset_type):
        family = "ipv4"
        if "family" in options:
            if options["family"] == "inet6":
                family = "ipv6"

        if ipset_type == "hash:ip":
            if "-" in entry:
                splits = entry.split("-")
                if len(splits) != 2:
                    raise FirewallError(
                        errors.INVALID_ENTRY,
                        "entry '%s' does not match ipset type '%s'" % \
                        (entry, ipset_type))
                for split in splits:
                    if (family == "ipv4" and not checkIP(split)) or \
                       (family == "ipv6" and not checkIP6(split)):
                        raise FirewallError(
                            errors.INVALID_ENTRY,
                            "entry '%s' does not match ipset type '%s'" % \
                            (entry, ipset_type))
            else:
                if (family == "ipv4" and not checkIPnMask(entry)) or \
                   (family == "ipv6" and not checkIP6nMask(entry)):
                    raise FirewallError(
                        errors.INVALID_ENTRY,
                        "entry '%s' does not match ipset type '%s'" % \
                        (entry, ipset_type))
        elif ipset_type == "hash:net":
            if (family == "ipv4" and not checkIPnMask(entry)) or \
               (family == "ipv6" and not checkIP6nMask(entry)):
                raise FirewallError(
                    errors.INVALID_ENTRY,
                    "entry '%s' does not match ipset type '%s'" % \
                    (entry, ipset_type))
        elif ipset_type == "hash:mac":
            # ipset does not allow to add 00:00:00:00:00:00
            if not check_mac(entry) or entry == "00:00:00:00:00:00":
                raise FirewallError(
                    errors.INVALID_ENTRY,
                    "entry '%s' does not match ipset type '%s'" % \
                    (entry, ipset_type))
        else:
            raise FirewallError(errors.INVALID_IPSET,
                                "ipset type '%s' not usable" % ipset_type)
Пример #21
0
    def remove_forward(self, zone, use_transaction=None):
        _zone = self._fw.check_zone(zone)
        self._fw.check_panic()
        _obj = self._zones[_zone]

        if not _obj.forward:
            raise FirewallError(errors.NOT_ENABLED,
                                "forward not enabled in '%s'" % _zone)

        if use_transaction is None:
            transaction = self.new_transaction()
        else:
            transaction = use_transaction

        if _obj.applied:
            self._forward(False, _zone, transaction)

        transaction.add_post(self.__unregister_forward, _obj)

        if use_transaction is None:
            transaction.execute(True)

        return _zone
Пример #22
0
def ipset_reader(filename, path):
    ipset = IPSet()
    if not filename.endswith(".xml"):
        raise FirewallError(errors.INVALID_NAME,
                            "'%s' is missing .xml suffix" % filename)
    ipset.name = filename[:-4]
    ipset.check_name(ipset.name)
    ipset.filename = filename
    ipset.path = path
    ipset.builtin = False if path.startswith(ETC_FIREWALLD) else True
    ipset.default = ipset.builtin
    handler = ipset_ContentHandler(ipset)
    parser = sax.make_parser()
    parser.setContentHandler(handler)
    name = "%s/%s" % (path, filename)
    with open(name, "r") as f:
        parser.parse(f)
    del handler
    del parser
    if "timeout" in ipset.options and len(ipset.entries) > 0:
        # no entries visible for ipsets with timeout
        log.warning("ipset '%s': timeout option is set, entries are ignored",
                    ipset.name)
        del ipset.entries[:]
    i = 0
    while i < len(ipset.entries):
        try:
            ipset.check_entry(ipset.entries[i], ipset.options, ipset.type)
        except FirewallError as e:
            log.warning("%s, ignoring.", e)
            ipset.entries.pop(i)
        else:
            i += 1
    if PY2:
        ipset.encode_strings()

    return ipset
Пример #23
0
    def check(self):
        if self.family is not None and self.family not in ["ipv4", "ipv6"]:
            raise FirewallError(errors.INVALID_FAMILY, self.family)
        if self.family is None:
            if (self.source is not None and self.source.addr is not None) or \
               self.destination is not None:
                raise FirewallError(errors.MISSING_FAMILY)
            if type(self.element) == Rich_ForwardPort:
                raise FirewallError(errors.MISSING_FAMILY)

        if self.element is None:
            if self.action is None:
                raise FirewallError(errors.INVALID_RULE,
                                    "no element, no action")
            if self.source is None:
                raise FirewallError(errors.INVALID_RULE,
                                    "no element, no source")
            if self.destination is not None:
                raise FirewallError(errors.INVALID_RULE, "destination action")

        if type(self.element) not in [
                Rich_IcmpBlock, Rich_ForwardPort, Rich_Masquerade
        ]:
            if self.log is None and self.audit is None and \
                    self.action is None:
                raise FirewallError(errors.INVALID_RULE,
                                    "no action, no log, no audit")

        # source
        if self.source is not None:
            if self.source.addr is not None:
                if self.family is None:
                    raise FirewallError(errors.INVALID_FAMILY)
                if self.source.mac is not None:
                    raise FirewallError(errors.INVALID_RULE, "address and mac")
                if not functions.check_address(self.family, self.source.addr):
                    raise FirewallError(errors.INVALID_ADDR,
                                        str(self.source.addr))

            elif self.source.mac is not None:
                if not functions.check_mac(self.source.mac):
                    raise FirewallError(errors.INVALID_MAC,
                                        str(self.source.mac))

            elif self.source.ipset is not None:
                if not check_ipset_name(self.source.ipset):
                    raise FirewallError(errors.INVALID_IPSET,
                                        str(self.source.ipset))

            else:
                raise FirewallError(errors.INVALID_RULE, "invalid source")

        # destination
        if self.destination is not None:
            if self.family is None:
                raise FirewallError(errors.INVALID_FAMILY)
            if self.destination.addr is None or \
                    not functions.check_address(self.family,
                                                self.destination.addr):
                raise FirewallError(errors.INVALID_ADDR,
                                    str(self.destination.addr))

        # service
        if type(self.element) == Rich_Service:
            # service availability needs to be checked in Firewall, here is no
            # knowledge about this, therefore only simple check
            if self.element.name is None or len(self.element.name) < 1:
                raise FirewallError(errors.INVALID_SERVICE,
                                    str(self.element.name))

        # port
        elif type(self.element) == Rich_Port:
            if not functions.check_port(self.element.port):
                raise FirewallError(errors.INVALID_PORT, self.element.port)
            if self.element.protocol not in ["tcp", "udp"]:
                raise FirewallError(errors.INVALID_PROTOCOL,
                                    self.element.protocol)

        # protocol
        elif type(self.element) == Rich_Protocol:
            if not functions.checkProtocol(self.element.value):
                raise FirewallError(errors.INVALID_PROTOCOL,
                                    self.element.value)

        # masquerade
        elif type(self.element) == Rich_Masquerade:
            if self.action is not None:
                raise FirewallError(errors.INVALID_RULE,
                                    "masquerade and action")
            if self.source is not None and self.source.mac is not None:
                raise FirewallError(errors.INVALID_RULE,
                                    "masquerade and mac source")

        # icmp-block
        elif type(self.element) == Rich_IcmpBlock:
            # icmp type availability needs to be checked in Firewall, here is no
            # knowledge about this, therefore only simple check
            if self.element.name is None or len(self.element.name) < 1:
                raise FirewallError(errors.INVALID_ICMPTYPE,
                                    str(self.element.name))
            if self.action:
                raise FirewallError(errors.INVALID_RULE,
                                    "icmp-block and action")

        # forward-port
        elif type(self.element) == Rich_ForwardPort:
            if not functions.check_port(self.element.port):
                raise FirewallError(errors.INVALID_PORT, self.element.port)
            if self.element.protocol not in ["tcp", "udp"]:
                raise FirewallError(errors.INVALID_PROTOCOL,
                                    self.element.protocol)
            if self.element.to_port == "" and self.element.to_address == "":
                raise FirewallError(errors.INVALID_PORT, self.element.to_port)
            if self.element.to_port != "" and \
                    not functions.check_port(self.element.to_port):
                raise FirewallError(errors.INVALID_PORT, self.element.to_port)
            if self.element.to_address != "" and \
                    not functions.check_single_address(self.family,
                                                       self.element.to_address):
                raise FirewallError(errors.INVALID_ADDR,
                                    self.element.to_address)
            if self.family is None:
                raise FirewallError(errors.INVALID_FAMILY)
            if self.action is not None:
                raise FirewallError(errors.INVALID_RULE,
                                    "forward-port and action")

        # other element and not empty?
        elif self.element is not None:
            raise FirewallError(errors.INVALID_RULE,
                                "Unknown element %s" % type(self.element))

        # log
        if self.log is not None:
            if self.log.level and \
               self.log.level not in [ "emerg", "alert", "crit", "error",
                                       "warning", "notice", "info", "debug" ]:
                raise FirewallError(errors.INVALID_LOG_LEVEL, self.log.level)

            if self.log.limit is not None:
                self.log.limit.check()

        # audit
        if self.audit is not None:
            if type(self.action) not in [Rich_Accept, Rich_Reject, Rich_Drop]:
                raise FirewallError(errors.INVALID_AUDIT_TYPE,
                                    type(self.action))

            if self.audit.limit is not None:
                self.audit.limit.check()

        # action
        if self.action is not None:
            if type(self.action) == Rich_Reject:
                self.action.check(self.family)
            elif type(self.action) == Rich_Mark:
                self.action.check()

            if self.action.limit is not None:
                self.action.limit.check()
Пример #24
0
 def check_icmptype(self, icmptype):
     if icmptype not in self._icmptypes:
         raise FirewallError(errors.INVALID_ICMPTYPE, icmptype)
Пример #25
0
 def check_name(self, name):
     """Check ipset name"""
     if len(name) > IPSET_MAXNAMELEN:
         raise FirewallError(errors.INVALID_NAME,
                             "ipset name '%s' is not valid" % name)
Пример #26
0
    def _import_from_string(self, rule_str):
        if not rule_str:
            raise FirewallError(errors.INVALID_RULE, 'empty rule')

        self.family = None
        self.source = None
        self.destination = None
        self.element = None
        self.log = None
        self.audit = None
        self.action = None

        tokens = self._lexer(rule_str)
        if tokens and tokens[0].get('element') == 'EOL':
            raise FirewallError(errors.INVALID_RULE, 'empty rule')

        attrs = {}  # attributes of elements
        in_elements = []  # stack with elements we are in
        index = 0  # index into tokens
        while not (tokens[index].get('element') == 'EOL'
                   and in_elements == ['rule']):
            element = tokens[index].get('element')
            attr_name = tokens[index].get('attr_name')
            attr_value = tokens[index].get('attr_value')
            #print ("in_elements: ", in_elements)
            #print ("index: %s, element: %s, attribute: %s=%s" % (index, element, attr_name, attr_value))
            if attr_name:  # attribute
                if attr_name not in [
                        'family', 'address', 'mac', 'ipset', 'invert', 'value',
                        'port', 'protocol', 'to-port', 'to-addr', 'name',
                        'prefix', 'level', 'type', 'set'
                ]:
                    raise FirewallError(errors.INVALID_RULE,
                                        "bad attribute '%s'" % attr_name)
            else:  # element
                if element in [
                        'rule', 'source', 'destination', 'protocol', 'service',
                        'port', 'icmp-block', 'masquerade', 'forward-port',
                        'log', 'audit', 'accept', 'drop', 'reject', 'mark',
                        'limit', 'not', 'NOT', 'EOL'
                ]:
                    if element == 'source' and self.source:
                        raise FirewallError(errors.INVALID_RULE,
                                            "more than one 'source' element")
                    elif element == 'destination' and self.destination:
                        raise FirewallError(
                            errors.INVALID_RULE,
                            "more than one 'destination' element")
                    elif element in [
                            'protocol', 'service', 'port', 'icmp-block',
                            'masquerade', 'forward-port'
                    ] and self.element:
                        raise FirewallError(
                            errors.INVALID_RULE,
                            "more than one element. There cannot be both '%s' and '%s' in one rule."
                            % (element, self.element))
                    elif element == 'log' and self.log:
                        raise FirewallError(errors.INVALID_RULE,
                                            "more than one 'log' element")
                    elif element == 'audit' and self.audit:
                        raise FirewallError(errors.INVALID_RULE,
                                            "more than one 'audit' element")
                    elif element in ['accept', 'drop', 'reject', 'mark'
                                     ] and self.action:
                        raise FirewallError(
                            errors.INVALID_RULE,
                            "more than one 'action' element. There cannot be both '%s' and '%s' in one rule."
                            % (element, self.action))
                else:
                    raise FirewallError(errors.INVALID_RULE,
                                        "unknown element %s" % element)

            in_element = in_elements[len(in_elements) -
                                     1] if len(in_elements) > 0 else ''

            if in_element == '':
                if not element and attr_name:
                    if attr_name == 'family':
                        raise FirewallError(
                            errors.INVALID_RULE,
                            "'family' outside of rule. Use 'rule family=...'.")
                    else:
                        raise FirewallError(
                            errors.INVALID_RULE,
                            "'%s' outside of any element. Use 'rule <element> %s= ...'."
                            % (attr_name, attr_name))
                elif 'rule' not in element:
                    raise FirewallError(
                        errors.INVALID_RULE,
                        "'%s' outside of rule. Use 'rule ... %s ...'." %
                        (element, element))
                else:
                    in_elements.append('rule')  # push into stack
            elif in_element == 'rule':
                if attr_name == 'family':
                    if attr_value not in ['ipv4', 'ipv6']:
                        raise FirewallError(
                            errors.INVALID_RULE,
                            "'family' attribute cannot have '%s' value. Use 'ipv4' or 'ipv6' instead."
                            % attr_value)
                    self.family = attr_value
                elif attr_name:
                    if attr_name == 'protocol':
                        err_msg = "wrong 'protocol' usage. Use either 'rule protocol value=...' or  'rule [forward-]port protocol=...'."
                    else:
                        err_msg = "attribute '%s' outside of any element. Use 'rule <element> %s= ...'." % (
                            attr_name, attr_name)
                    raise FirewallError(errors.INVALID_RULE, err_msg)
                else:
                    in_elements.append(element)  # push into stack
            elif in_element == 'source':
                if attr_name in ['address', 'mac', 'ipset', 'invert']:
                    attrs[attr_name] = attr_value
                elif element in ['not', 'NOT']:
                    attrs['invert'] = True
                else:
                    self.source = Rich_Source(attrs.get('address'),
                                              attrs.get('mac'),
                                              attrs.get('ipset'),
                                              attrs.get('invert'))
                    in_elements.pop()  # source
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'destination':
                if attr_name in ['address', 'invert']:
                    attrs[attr_name] = attr_value
                elif element in ['not', 'NOT']:
                    attrs['invert'] = True
                else:
                    self.destination = Rich_Destination(
                        attrs.get('address'), attrs.get('invert'))
                    in_elements.pop()  # destination
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'protocol':
                if attr_name == 'value':
                    self.element = Rich_Protocol(attr_value)
                    in_elements.pop()  # protocol
                else:
                    raise FirewallError(errors.INVALID_RULE,
                                        "invalid 'protocol' element")
            elif in_element == 'service':
                if attr_name == 'name':
                    self.element = Rich_Service(attr_value)
                    in_elements.pop()  # service
                else:
                    raise FirewallError(errors.INVALID_RULE,
                                        "invalid 'service' element")
            elif in_element == 'port':
                if attr_name in ['port', 'protocol']:
                    attrs[attr_name] = attr_value
                else:
                    self.element = Rich_Port(attrs.get('port'),
                                             attrs.get('protocol'))
                    in_elements.pop()  # port
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'icmp-block':
                if attr_name == 'name':
                    self.element = Rich_IcmpBlock(attr_value)
                    in_elements.pop()  # icmp-block
                else:
                    raise FirewallError(errors.INVALID_RULE,
                                        "invalid 'icmp-block' element")
            elif in_element == 'masquerade':
                self.element = Rich_Masquerade()
                in_elements.pop()
                attrs.clear()
                index = index - 1  # return token to input
            elif in_element == 'forward-port':
                if attr_name in ['port', 'protocol', 'to-port', 'to-addr']:
                    attrs[attr_name] = attr_value
                else:
                    self.element = Rich_ForwardPort(attrs.get('port'),
                                                    attrs.get('protocol'),
                                                    attrs.get('to-port'),
                                                    attrs.get('to-addr'))
                    in_elements.pop()  # forward-port
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'log':
                if attr_name in ['prefix', 'level']:
                    attrs[attr_name] = attr_value
                elif element == 'limit':
                    in_elements.append('limit')
                else:
                    self.log = Rich_Log(attrs.get('prefix'),
                                        attrs.get('level'), attrs.get('limit'))
                    in_elements.pop()  # log
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'audit':
                if element == 'limit':
                    in_elements.append('limit')
                else:
                    self.audit = Rich_Audit(attrs.get('limit'))
                    in_elements.pop()  # audit
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'accept':
                if element == 'limit':
                    in_elements.append('limit')
                else:
                    self.action = Rich_Accept(attrs.get('limit'))
                    in_elements.pop()  # accept
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'drop':
                if element == 'limit':
                    in_elements.append('limit')
                else:
                    self.action = Rich_Drop(attrs.get('limit'))
                    in_elements.pop()  # drop
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'reject':
                if attr_name == 'type':
                    attrs[attr_name] = attr_value
                elif element == 'limit':
                    in_elements.append('limit')
                else:
                    self.action = Rich_Reject(attrs.get('type'),
                                              attrs.get('limit'))
                    in_elements.pop()  # accept
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'mark':
                if attr_name == 'set':
                    attrs[attr_name] = attr_value
                elif element == 'limit':
                    in_elements.append('limit')
                else:
                    self.action = Rich_Mark(attrs.get('set'),
                                            attrs.get('limit'))
                    in_elements.pop()  # accept
                    attrs.clear()
                    index = index - 1  # return token to input
            elif in_element == 'limit':
                if attr_name == 'value':
                    attrs['limit'] = Rich_Limit(attr_value)
                    in_elements.pop()  # limit
                else:
                    raise FirewallError(errors.INVALID_RULE,
                                        "invalid 'limit' element")

            index = index + 1

        self.check()
Пример #27
0
 def _rule_validate(self, rule):
     for str in ["%%REJECT%%", "%%ICMP%%", "%%LOGTYPE%%"]:
         if str in rule:
             raise FirewallError(INVALID_IPV,
                     "'%s' invalid for ebtables" % str)
Пример #28
0
 def check_type(self, type_name):
     """Check ipset type"""
     if len(type_name) > IPSET_MAXNAMELEN or type_name not in IPSET_TYPES:
         raise FirewallError(
             errors.INVALID_TYPE,
             "ipset type name '%s' is not valid" % type_name)
Пример #29
0
 def check_ipset(self, name):
     if name not in self.get_ipsets():
         raise FirewallError(errors.INVALID_IPSET, name)
Пример #30
0
 def add_ipset(self, obj):
     if obj.type not in self._fw.ipset_supported_types:
         raise FirewallError(errors.INVALID_TYPE,
                             "'%s' is not supported by ipset." % obj.type)
     self._ipsets[obj.name] = obj
Пример #31
0
 def check_ip(self, ip):
     if not functions.checkIP(ip):
         raise FirewallError(errors.INVALID_ADDR, ip)
Пример #32
0
 def check_applied_obj(self, obj):
     if not obj.applied:
         raise FirewallError(errors.NOT_APPLIED, obj.name)
Пример #33
0
 def check_port(self, port):
     if not functions.check_port(port):
         raise FirewallError(errors.INVALID_PORT, port)
Пример #34
0
 def check_interface(self, interface):
     if not functions.checkInterface(interface):
         raise FirewallError(errors.INVALID_INTERFACE, interface)
Пример #35
0
 def check_panic(self):
     if self._panic:
         raise FirewallError(errors.PANIC_MODE)
Пример #36
0
    def __cmd_sequence(self, cmd_type, option, action_method, query_method, # pylint: disable=W0613, R0913, R0914
                       parse_method, message, start_args=None, end_args=None, # pylint: disable=W0613
                       no_exit=False):
        if self.fw is not None:
            self.fw.authorizeAll()
        items = [ ]
        _errors = 0
        _error_codes = [ ]
        for item in option:
            if parse_method is not None:
                try:
                    item = parse_method(item)
                except Exception as msg:
                    code = FirewallError.get_code(str(msg))
                    if len(option) > 1:
                        self.print_warning("Warning: %s" % msg)
                    else:
                        self.print_and_exit("Error: %s" % msg, code)
                    if code not in _error_codes:
                        _error_codes.append(code)
                    _errors += 1
                    continue

            items.append(item)

        for item in items:
            call_item = [ ]
            if start_args is not None:
                call_item += start_args
            if not isinstance(item, list) and not isinstance(item, tuple):
                call_item.append(item)
            else:
                call_item += item
            if end_args is not None:
                call_item += end_args
            self.deactivate_exception_handler()
            try:
                action_method(*call_item)
            except (DBusException, Exception) as msg:
                if isinstance(msg, DBusException):
                    self.fail_if_not_authorized(msg.get_dbus_name())
                    msg = msg.get_dbus_message()
                else:
                    msg = str(msg)
                code = FirewallError.get_code(msg)
                if code in [ errors.ALREADY_ENABLED, errors.NOT_ENABLED,
                             errors.ZONE_ALREADY_SET, errors.ALREADY_SET ]:
                    code = 0
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg)
                elif code == 0:
                    self.print_warning("Warning: %s" % msg)
                    return
                else:
                    self.print_and_exit("Error: %s" % msg, code)
                if code not in _error_codes:
                    _error_codes.append(code)
                _errors += 1
            self.activate_exception_handler()

        if not no_exit:
            if len(option) > _errors or 0 in _error_codes:
                # There have been more options than errors or there
                # was at least one error code 0, return.
                return
            elif len(_error_codes) == 1:
                # Exactly one error code, use it.
                sys.exit(_error_codes[0])
            elif len(_error_codes) > 1:
                # There is more than error, exit using
                # UNKNOWN_ERROR. This could happen within sequences
                # where parsing failed with different errors like
                # INVALID_PORT and INVALID_PROTOCOL.
                sys.exit(errors.UNKNOWN_ERROR)
Пример #37
0
    def __cmd_sequence(self, cmd_type, option, action_method, query_method,
                       parse_method, message, start_args=None, end_args=None,
                       no_exit=False):
        warn_type = {
            "add": "ALREADY_ENABLED",
            "remove": "NOT_ENABLED",
        }
        items = [ ]
        _errors = 0
        for item in option:
            if parse_method is not None:
                try:
                    item = parse_method(item)
                except Exception as msg:
                    if len(option) > 1:
                        self.print_warning("Warning: %s" % msg)
                        continue
                    else:
                        code = FirewallError.get_code(msg)
                        self.print_and_exit("Error: %s" % msg, code)

            call_item = [ ]
            if start_args is not None:
                call_item += start_args
            if not isinstance(item, list) and not isinstance(item, tuple):
                call_item.append(item)
            else:
                call_item += item
            self.deactivate_exception_handler()
            try:
                if cmd_type == "add" and not query_method(*call_item):
                    items.append(item)
                elif cmd_type == "remove" and query_method(*call_item):
                    items.append(item)
                else:
                    if len(option) > 1:
                        self.print_warning("Warning: %s: %s" % \
                                           (warn_type[cmd_type],
                                            message % item))
                    else:
                        code = FirewallError.get_code(warn_type[cmd_type])
                        self.print_and_exit("Error: %s: %s" % \
                                            (warn_type[cmd_type],
                                             message % item), code)
                    _errors += 1
            except DBusException as msg:
                code = FirewallError.get_code(msg)
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg.get_dbus_message())
                    continue
                else:
                    self.print_and_exit("Error: %s" % msg.get_dbus_message(),
                                        code)
                _errors += 1
            self.activate_exception_handler()

        for item in items:
            call_item = [ ]
            if start_args is not None:
                call_item += start_args
            if not isinstance(item, list) and not isinstance(item, tuple):
                call_item.append(item)
            else:
                call_item += item
            if end_args is not None:
                call_item += end_args
            try:
                action_method(*call_item)
            except DBusException as msg:
                code = FirewallError.get_code(msg)
                if len(option) > 1:
                    self.print_warning("Warning: %s" % msg.get_dbus_message())
                else:
                    self.print_and_exit("Error: %s" % msg.get_dbus_message(),
                                        code)
                _errors += 1

        if _errors == len(option) and not no_exit:
            sys.exit(0)