# -*- coding: utf-8 -*- # # Copyright (C) 2016 Red Hat, Inc. # # Authors: # Thomas Woerner <twoerner@redhat.com> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # """Transaction classes for firewalld""" __all__ = [ "FirewallTransaction", "FirewallZoneTransaction" ] from firewall.core.logger import log from firewall import errors from firewall.errors import FirewallError from firewall.fw_types import LastUpdatedOrderedDict class SimpleFirewallTransaction(object): """Base class for FirewallTransaction and FirewallZoneTransaction""" def __init__(self, fw): self.fw = fw self.rules = { } # [ ( backend.name, [ rule,.. ] ),.. ] self.pre_funcs = [ ] # [ (func, args),.. ] self.post_funcs = [ ] # [ (func, args),.. ] self.fail_funcs = [ ] # [ (func, args),.. ] def clear(self): self.rules.clear() del self.pre_funcs[:] del self.post_funcs[:] del self.fail_funcs[:] def add_rule(self, backend, rule): self.rules.setdefault(backend.name, [ ]).append(rule) def add_rules(self, backend, rules): for rule in rules: self.add_rule(backend, rule) def query_rule(self, backend, rule): return backend.name in self.rules and rule in self.rules[backend.name] def remove_rule(self, backend, rule): if backend.name in self.rules and rule in self.rules[backend.name]: self.rules[backend.name].remove(rule) def add_pre(self, func, *args): self.pre_funcs.append((func, args)) def add_post(self, func, *args): self.post_funcs.append((func, args)) def add_fail(self, func, *args): self.fail_funcs.append((func, args)) def prepare(self, enable, rules=None, modules=None): log.debug4("%s.prepare(%s, %s)" % (type(self), enable, "...")) if rules is None: rules = { } if modules is None: modules = [ ] if not enable: # reverse rule order for cleanup for backend_name in self.rules: for rule in reversed(self.rules[backend_name]): rules.setdefault(backend_name, [ ]).append( self.fw.get_backend_by_name(backend_name).reverse_rule(rule)) else: for backend_name in self.rules: rules.setdefault(backend_name, [ ]).extend(self.rules[backend_name]) return rules, modules def execute(self, enable): log.debug4("%s.execute(%s)" % (type(self), enable)) rules, modules = self.prepare(enable) # pre self.pre() # stage 1: apply rules error = False errorMsg = "" done = [ ] for backend_name in rules: try: self.fw.rules(backend_name, rules[backend_name]) except Exception as msg: error = True errorMsg = msg log.error(msg) else: done.append(backend_name) # stage 2: load modules if not error: module_return = self.fw.handle_modules(modules, enable) if module_return: # Debug log about issues loading modules, but don't error. The # modules may be builtin or CONFIG_MODULES=n, in which case # modprobe will fail. Or we may be running inside a container # that doesn't have sufficient privileges. Unfortunately there # is no way for us to know. (status, msg) = module_return if status: log.debug1(msg) # error case: revert rules if error: undo_rules = { } for backend_name in done: undo_rules[backend_name] = [ ] for rule in reversed(rules[backend_name]): undo_rules[backend_name].append( self.fw.get_backend_by_name(backend_name).reverse_rule(rule)) for backend_name in undo_rules: try: self.fw.rules(backend_name, undo_rules[backend_name]) except Exception as msg: log.error(msg) # call failure functions for (func, args) in self.fail_funcs: try: func(*args) except Exception as msg: log.error("Calling fail func %s(%s) failed: %s" % \ (func, args, msg)) raise FirewallError(errors.COMMAND_FAILED, errorMsg) # post self.post() def pre(self): log.debug4("%s.pre()" % type(self)) for (func, args) in self.pre_funcs: try: func(*args) except Exception as msg: log.error("Calling pre func %s(%s) failed: %s" % \ (func, args, msg)) def post(self): log.debug4("%s.post()" % type(self)) for (func, args) in self.post_funcs: try: func(*args) except Exception as msg: log.error("Calling post func %s(%s) failed: %s" % \ (func, args, msg)) # class FirewallTransaction class FirewallTransaction(SimpleFirewallTransaction): """General FirewallTransaction, contains also zone transactions""" def __init__(self, fw): super(FirewallTransaction, self).__init__(fw) self.zone_transactions = LastUpdatedOrderedDict() # { zone: transaction, .. } def clear(self): super(FirewallTransaction, self).clear() self.zone_transactions.clear() def zone_transaction(self, zone): if zone not in self.zone_transactions: self.zone_transactions[zone] = FirewallZoneTransaction( self.fw, zone, self) return self.zone_transactions[zone] def prepare(self, enable, rules=None, modules=None): log.debug4("%s.prepare(%s, %s)" % (type(self), enable, "...")) rules, modules = super(FirewallTransaction, self).prepare( enable, rules, modules) for zone in self.zone_transactions: try: self.zone_transactions[zone].prepare(enable, rules) for module in self.zone_transactions[zone].modules: if module not in modules: modules.append(module) except FirewallError as msg: log.error("Failed to prepare transaction rules for zone '%s'", str(msg)) return rules, modules def pre(self): log.debug4("%s.pre()" % type(self)) super(FirewallTransaction, self).pre() for zone in self.zone_transactions: self.zone_transactions[zone].pre() def post(self): log.debug4("%s.post()" % type(self)) super(FirewallTransaction, self).post() for zone in self.zone_transactions: self.zone_transactions[zone].post() # class FirewallZoneTransaction class FirewallZoneTransaction(SimpleFirewallTransaction): """Zone transaction with additional chain and module interface""" def __init__(self, fw, zone, fw_transaction=None): super(FirewallZoneTransaction, self).__init__(fw) self.zone = zone self.fw_transaction = fw_transaction self.chains = [ ] # [ (table, chain),.. ] self.modules = [ ] # [ module,.. ] def clear(self): # calling clear on a zone_transaction that was spawned from a # FirewallTransaction needs to clear the fw_transaction and all the # other zones otherwise we end up with a partially cleared transaction. if self.fw_transaction: super(FirewallTransaction, self.fw_transaction).clear() for zone in self.fw_transaction.zone_transactions.keys(): super(FirewallZoneTransaction, self.fw_transaction.zone_transactions[zone]).clear() del self.fw_transaction.zone_transactions[zone].chains[:] del self.fw_transaction.zone_transactions[zone].modules[:] else: super(FirewallZoneTransaction, self).clear() del self.chains[:] del self.modules[:] def prepare(self, enable, rules=None, modules=None): log.debug4("%s.prepare(%s, %s)" % (type(self), enable, "...")) rules, modules = super(FirewallZoneTransaction, self).prepare( enable, rules, modules) for module in self.modules: if module not in modules: modules.append(module) return rules, modules def execute(self, enable): # calling execute on a zone_transaction that was spawned from a # FirewallTransaction should execute the FirewallTransaction as it may # have prerequisite rules if self.fw_transaction: self.fw_transaction.execute(enable) else: super(FirewallZoneTransaction, self).execute(enable) def add_chain(self, table, chain): table_chain = (table, chain) if table_chain not in self.chains: self.fw.zone.gen_chain_rules(self.zone, True, [table_chain], self) self.chains.append(table_chain) def remove_chain(self, table, chain): table_chain = (table, chain) if table_chain in self.chains: self.chains.remove(table_chain) def add_chains(self, chains): for table_chain in chains: if table_chain not in self.chains: self.add_chain(table_chain[0], table_chain[1]) def remove_chains(self, chains): for table_chain in chains: if table_chain in self.chains: self.chains.remove(table_chain) def add_module(self, module): if module not in self.modules: self.modules.append(module) def remove_module(self, module): if module in self.modules: self.modules.remove(module) def add_modules(self, modules): for module in modules: self.add_module(module) def remove_modules(self, modules): for module in modules: self.remove_module(module)
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
io | Folder | 0755 |
|
|
.__init__.pyo.40009 | File | 145 B | 0644 |
|
.base.pyo.40009 | File | 1.29 KB | 0644 |
|
.ebtables.pyo.40009 | File | 9.04 KB | 0644 |
|
.fw.pyo.40009 | File | 30.67 KB | 0644 |
|
.fw_config.pyo.40009 | File | 30.69 KB | 0644 |
|
.fw_direct.pyo.40009 | File | 14.77 KB | 0644 |
|
.fw_helper.pyo.40009 | File | 2.57 KB | 0644 |
|
.fw_icmptype.pyo.40009 | File | 3 KB | 0644 |
|
.fw_ifcfg.pyo.40009 | File | 1.84 KB | 0644 |
|
.fw_ipset.pyo.40009 | File | 9.02 KB | 0644 |
|
.fw_nm.pyo.40009 | File | 5.93 KB | 0644 |
|
.fw_policies.pyo.40009 | File | 2.94 KB | 0644 |
|
.fw_service.pyo.40009 | File | 2.14 KB | 0644 |
|
.fw_test.pyo.40009 | File | 17.45 KB | 0644 |
|
.fw_transaction.pyo.40009 | File | 10.96 KB | 0644 |
|
.fw_zone.pyo.40009 | File | 57.31 KB | 0644 |
|
.helper.pyo.40009 | File | 222 B | 0644 |
|
.icmp.pyo.40009 | File | 2.89 KB | 0644 |
|
.ipXtables.pyo.40009 | File | 34.8 KB | 0644 |
|
.ipset.pyo.40009 | File | 9.15 KB | 0644 |
|
.logger.pyo.40009 | File | 27.43 KB | 0644 |
|
.modules.pyo.40009 | File | 3.56 KB | 0644 |
|
.nftables.pyo.40009 | File | 38.56 KB | 0644 |
|
.prog.pyo.40009 | File | 988 B | 0644 |
|
.rich.pyo.40009 | File | 23.73 KB | 0644 |
|
.watcher.pyo.40009 | File | 3.55 KB | 0644 |
|
__init__.py | File | 0 B | 0644 |
|
__init__.pyc | File | 145 B | 0644 |
|
__init__.pyo | File | 145 B | 0644 |
|
base.py | File | 1.94 KB | 0644 |
|
base.pyc | File | 1.29 KB | 0644 |
|
base.pyo | File | 1.29 KB | 0644 |
|
ebtables.py | File | 9.13 KB | 0644 |
|
ebtables.pyc | File | 9.04 KB | 0644 |
|
ebtables.pyo | File | 9.04 KB | 0644 |
|
fw.py | File | 43.71 KB | 0644 |
|
fw.pyc | File | 30.67 KB | 0644 |
|
fw.pyo | File | 30.67 KB | 0644 |
|
fw_config.py | File | 35.99 KB | 0644 |
|
fw_config.pyc | File | 30.69 KB | 0644 |
|
fw_config.pyo | File | 30.69 KB | 0644 |
|
fw_direct.py | File | 20.12 KB | 0644 |
|
fw_direct.pyc | File | 14.77 KB | 0644 |
|
fw_direct.pyo | File | 14.77 KB | 0644 |
|
fw_helper.py | File | 1.79 KB | 0644 |
|
fw_helper.pyc | File | 2.57 KB | 0644 |
|
fw_helper.pyo | File | 2.57 KB | 0644 |
|
fw_icmptype.py | File | 2.77 KB | 0644 |
|
fw_icmptype.pyc | File | 3 KB | 0644 |
|
fw_icmptype.pyo | File | 3 KB | 0644 |
|
fw_ifcfg.py | File | 2.5 KB | 0644 |
|
fw_ifcfg.pyc | File | 1.84 KB | 0644 |
|
fw_ifcfg.pyo | File | 1.84 KB | 0644 |
|
fw_ipset.py | File | 8.96 KB | 0644 |
|
fw_ipset.pyc | File | 9.02 KB | 0644 |
|
fw_ipset.pyo | File | 9.02 KB | 0644 |
|
fw_nm.py | File | 6.49 KB | 0644 |
|
fw_nm.pyc | File | 5.93 KB | 0644 |
|
fw_nm.pyo | File | 5.93 KB | 0644 |
|
fw_policies.py | File | 2.74 KB | 0644 |
|
fw_policies.pyc | File | 2.94 KB | 0644 |
|
fw_policies.pyo | File | 2.94 KB | 0644 |
|
fw_service.py | File | 1.6 KB | 0644 |
|
fw_service.pyc | File | 2.14 KB | 0644 |
|
fw_service.pyo | File | 2.14 KB | 0644 |
|
fw_test.py | File | 22.06 KB | 0644 |
|
fw_test.pyc | File | 17.45 KB | 0644 |
|
fw_test.pyo | File | 17.45 KB | 0644 |
|
fw_transaction.py | File | 10.54 KB | 0644 |
|
fw_transaction.pyc | File | 10.96 KB | 0644 |
|
fw_transaction.pyo | File | 10.96 KB | 0644 |
|
fw_zone.py | File | 75.6 KB | 0644 |
|
fw_zone.pyc | File | 57.31 KB | 0644 |
|
fw_zone.pyo | File | 57.31 KB | 0644 |
|
helper.py | File | 804 B | 0644 |
|
helper.pyc | File | 222 B | 0644 |
|
helper.pyo | File | 222 B | 0644 |
|
icmp.py | File | 3.03 KB | 0644 |
|
icmp.pyc | File | 2.89 KB | 0644 |
|
icmp.pyo | File | 2.89 KB | 0644 |
|
ipXtables.py | File | 47.68 KB | 0644 |
|
ipXtables.pyc | File | 34.8 KB | 0644 |
|
ipXtables.pyo | File | 34.8 KB | 0644 |
|
ipset.py | File | 9.1 KB | 0644 |
|
ipset.pyc | File | 9.15 KB | 0644 |
|
ipset.pyo | File | 9.15 KB | 0644 |
|
logger.py | File | 30.31 KB | 0644 |
|
logger.pyc | File | 27.43 KB | 0644 |
|
logger.pyo | File | 27.43 KB | 0644 |
|
modules.py | File | 3.63 KB | 0644 |
|
modules.pyc | File | 3.56 KB | 0644 |
|
modules.pyo | File | 3.56 KB | 0644 |
|
nftables.py | File | 60.55 KB | 0644 |
|
nftables.pyc | File | 38.56 KB | 0644 |
|
nftables.pyo | File | 38.56 KB | 0644 |
|
prog.py | File | 1.47 KB | 0644 |
|
prog.pyc | File | 988 B | 0644 |
|
prog.pyo | File | 988 B | 0644 |
|
rich.py | File | 29.34 KB | 0644 |
|
rich.pyc | File | 23.73 KB | 0644 |
|
rich.pyo | File | 23.73 KB | 0644 |
|
watcher.py | File | 3.15 KB | 0644 |
|
watcher.pyc | File | 3.55 KB | 0644 |
|
watcher.pyo | File | 3.55 KB | 0644 |
|